Previous (Introduction)
Table of Contents (Introduction)
Next (Plant)
When thinking of the living resources in Surface Tension, I didn't simply want the plants and animals to seem like they were thinking, I actually wanted to program them so they really were thinking. Grand Theft Auto uses statistical generation to make the world seem alive. In older versions of the game, you can see this when you look at the world and see some car and pedestrian objects. When you look away for a few seconds and look back, the cars and people will be different objects. The corvette you were planning on stealing may have been replaced by a police car!
Grand Theft Auto is a great game, and in later versions the memory they have to work with in the PS4 is much more than that of the PS2, so the statistical generation of objects is much less of a problem for the player. I think I'll be forced to use statistical generation later, but right now I want to code a living world where objects don't spontaneously appear and disappear based on what the players can see. One reason I'm choosing this strategy, is because this is an MMO- and I want to assume that every section of the map is being viewed by at least one player at all times- worst case scenario for performance. If the game can load now under those conditions, I (hopefully) won't be surprised in the future when it cannot.
This is a (bad?) decision that later forces me into premature optimization.
I got my idea for this AI structure when reading Michio Kaku's book, "The Future of the Mind", where he talks about the different levels of intelligence measured by feedback loops. This is what I came up with.
Here is the base AI that all of the living resources have:
So, every AI instance has a method to create feedback loops and a method to cycle through those feedback loops.
A brain has 2 hemispheres that function independently, sharing some information when needed. How a real brain decides which hemisphere to use to make a conscious decision or whether to use both or not, is something I don't quite understand. In any case, this is the code for the Brain in Surface Tension:
The brain has the ability to store memories and make decisions. It also has a right and a left AI- each with the ability to create independent feedback loops. The brain has it's own createFeedback method which will create the same feedback loop on both left and right. Finally, the brain has a cycle method that will cycle through the right, then the left, and return a decision based on the weight of that decision- where a higher weight will be chosen as the decision to execute. The result of that decision is returned.
There is also a way to sync memories from one side of the brain to the other. Memories are not shared between the left and right sides.
Now, every living resource with a brain will have at least 4 feedback loops (Remember and Decision feedback loops assigned to both right and left).
So, this is the base for the AI. Next I'll talk about setting up the basis for all plants and the basis for all herbs. What do plants have to think about? They are required to reproduce automatically, how will they do that?
Previous (Introduction)
Table of Contents (Introduction)
Next (Plant)
Table of Contents (Introduction)
Next (Plant)
When thinking of the living resources in Surface Tension, I didn't simply want the plants and animals to seem like they were thinking, I actually wanted to program them so they really were thinking. Grand Theft Auto uses statistical generation to make the world seem alive. In older versions of the game, you can see this when you look at the world and see some car and pedestrian objects. When you look away for a few seconds and look back, the cars and people will be different objects. The corvette you were planning on stealing may have been replaced by a police car!
Grand Theft Auto is a great game, and in later versions the memory they have to work with in the PS4 is much more than that of the PS2, so the statistical generation of objects is much less of a problem for the player. I think I'll be forced to use statistical generation later, but right now I want to code a living world where objects don't spontaneously appear and disappear based on what the players can see. One reason I'm choosing this strategy, is because this is an MMO- and I want to assume that every section of the map is being viewed by at least one player at all times- worst case scenario for performance. If the game can load now under those conditions, I (hopefully) won't be surprised in the future when it cannot.
This is a (bad?) decision that later forces me into premature optimization.
I got my idea for this AI structure when reading Michio Kaku's book, "The Future of the Mind", where he talks about the different levels of intelligence measured by feedback loops. This is what I came up with.
Here is the base AI that all of the living resources have:
Code:
[COLOR=#008000][B]function[/B][/COLOR] Ai() {
[COLOR=#BA2121]"use strict"[/COLOR];
[COLOR=#008000][B]var[/B][/COLOR] self [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]this[/B][/COLOR];
[COLOR=#008000][B]var[/B][/COLOR] feedbackLoops [COLOR=#666666]=[/COLOR] [];
self.alive [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]true[/B][/COLOR];
[COLOR=#008000][B]function[/B][/COLOR] doFeedback(fn) {
[COLOR=#008000][B]if[/B][/COLOR] (self.alive) {
fn.cycle();
}
}
self.createFeedback [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] (Fn) {
feedbackLoops.push([COLOR=#008000][B]new[/B][/COLOR] Fn(self));
};
self.cycle [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] () {
feedbackLoops.forEach(doFeedback);
};
}
module.exports [COLOR=#666666]=[/COLOR] Ai;
So, every AI instance has a method to create feedback loops and a method to cycle through those feedback loops.
A brain has 2 hemispheres that function independently, sharing some information when needed. How a real brain decides which hemisphere to use to make a conscious decision or whether to use both or not, is something I don't quite understand. In any case, this is the code for the Brain in Surface Tension:
Code:
[COLOR=#008000][B]var[/B][/COLOR] Ai [COLOR=#666666]=[/COLOR] require([COLOR=#BA2121]'./ai'[/COLOR]);
module.exports [COLOR=#666666]=[/COLOR] ([COLOR=#008000][B]function[/B][/COLOR] () {
[COLOR=#BA2121]"use strict"[/COLOR];
[COLOR=#008000][B]function[/B][/COLOR] nil() {
[COLOR=#008000][B]return[/B][/COLOR];
}
[COLOR=#008000][B]function[/B][/COLOR] Decision(ai) {
[COLOR=#008000][B]var[/B][/COLOR] self [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]this[/B][/COLOR];
ai.decisions [COLOR=#666666]=[/COLOR] [];
ai.addDecision [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] (dec) {
[COLOR=#008000][B]var[/B][/COLOR] decision [COLOR=#666666]=[/COLOR] {
title[COLOR=#666666]:[/COLOR] dec.title [COLOR=#666666]||[/COLOR] [COLOR=#BA2121]"unknown"[/COLOR],
weight[COLOR=#666666]:[/COLOR] dec.weight [COLOR=#666666]||[/COLOR] [COLOR=#666666]0[/COLOR],
args[COLOR=#666666]:[/COLOR] dec.args [COLOR=#666666]||[/COLOR] [],
action[COLOR=#666666]:[/COLOR] dec.action [COLOR=#666666]||[/COLOR] nil
};
ai.decisions.push(decision);
};
self.cycle [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] () {
ai.decisions [COLOR=#666666]=[/COLOR] [{
weight[COLOR=#666666]:[/COLOR] [COLOR=#666666]0[/COLOR],
action[COLOR=#666666]:[/COLOR] nil,
title[COLOR=#666666]:[/COLOR] [COLOR=#BA2121]"do nothing"[/COLOR]
}];
};
}
[COLOR=#008000][B]function[/B][/COLOR] Remember(ai) {
[COLOR=#008000][B]var[/B][/COLOR] self [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]this[/B][/COLOR];
ai.memories [COLOR=#666666]=[/COLOR] {};
self.cycle [COLOR=#666666]=[/COLOR] nil;
}
[COLOR=#008000][B]return[/B][/COLOR] [COLOR=#008000][B]function[/B][/COLOR] Brain() {
[COLOR=#008000][B]var[/B][/COLOR] self [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]this[/B][/COLOR];
self.right [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]new[/B][/COLOR] Ai();
self.left [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]new[/B][/COLOR] Ai();
self.left.sync [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] (prop) {
[COLOR=#008000][B]var[/B][/COLOR] chain [COLOR=#666666]=[/COLOR] prop.split([COLOR=#BA2121]'.'[/COLOR]);
[COLOR=#008000][B]var[/B][/COLOR] i;
[COLOR=#008000][B]var[/B][/COLOR] l [COLOR=#666666]=[/COLOR] self.left;
[COLOR=#008000][B]var[/B][/COLOR] r [COLOR=#666666]=[/COLOR] self.right;
[COLOR=#008000][B]for[/B][/COLOR] (i [COLOR=#666666]=[/COLOR] [COLOR=#666666]0[/COLOR]; i [COLOR=#666666]<[/COLOR] chain.length [COLOR=#666666]-[/COLOR] [COLOR=#666666]1[/COLOR]; i [COLOR=#666666]+=[/COLOR] [COLOR=#666666]1[/COLOR]) {
r [COLOR=#666666]=[/COLOR] r[chain[i]];
l [COLOR=#666666]=[/COLOR] l[chain[i]];
}
r[chain[chain.length [COLOR=#666666]-[/COLOR] [COLOR=#666666]1[/COLOR]]] [COLOR=#666666]=[/COLOR] l[chain[chain.length [COLOR=#666666]-[/COLOR] [COLOR=#666666]1[/COLOR]]];
};
self.right.sync [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] (prop) {
[COLOR=#008000][B]var[/B][/COLOR] chain [COLOR=#666666]=[/COLOR] prop.split([COLOR=#BA2121]'.'[/COLOR]);
[COLOR=#008000][B]var[/B][/COLOR] i;
[COLOR=#008000][B]var[/B][/COLOR] l [COLOR=#666666]=[/COLOR] self.left;
[COLOR=#008000][B]var[/B][/COLOR] r [COLOR=#666666]=[/COLOR] self.right;
[COLOR=#008000][B]for[/B][/COLOR] (i [COLOR=#666666]=[/COLOR] [COLOR=#666666]0[/COLOR]; i [COLOR=#666666]<[/COLOR] chain.length [COLOR=#666666]-[/COLOR] [COLOR=#666666]1[/COLOR]; i [COLOR=#666666]+=[/COLOR] [COLOR=#666666]1[/COLOR]) {
r [COLOR=#666666]=[/COLOR] r[chain[i]];
l [COLOR=#666666]=[/COLOR] l[chain[i]];
}
l[chain[chain.length [COLOR=#666666]-[/COLOR] [COLOR=#666666]1[/COLOR]]] [COLOR=#666666]=[/COLOR] r[chain[chain.length [COLOR=#666666]-[/COLOR] [COLOR=#666666]1[/COLOR]]];
};
[COLOR=#008000][B]function[/B][/COLOR] findDecision(list) {
[COLOR=#008000][B]var[/B][/COLOR] i;
[COLOR=#008000][B]var[/B][/COLOR] decision [COLOR=#666666]=[/COLOR] list[[COLOR=#666666]0[/COLOR]];
[COLOR=#008000][B]for[/B][/COLOR] (i [COLOR=#666666]=[/COLOR] [COLOR=#666666]0[/COLOR]; i [COLOR=#666666]<[/COLOR] list.length; i [COLOR=#666666]+=[/COLOR] [COLOR=#666666]1[/COLOR]) {
[COLOR=#008000][B]if[/B][/COLOR] (decision.weight [COLOR=#666666]<[/COLOR] list[i].weight) {
decision [COLOR=#666666]=[/COLOR] list[i];
}
}
[COLOR=#008000][B]return[/B][/COLOR] decision;
}
[COLOR=#008000][B]function[/B][/COLOR] decide() {
[COLOR=#008000][B]var[/B][/COLOR] decision;
[COLOR=#008000][B]var[/B][/COLOR] context;
[COLOR=#008000][B]var[/B][/COLOR] lDecision [COLOR=#666666]=[/COLOR] findDecision(self.left.decisions);
[COLOR=#008000][B]var[/B][/COLOR] rDecision [COLOR=#666666]=[/COLOR] findDecision(self.right.decisions);
[COLOR=#008000][B]if[/B][/COLOR] ([COLOR=#666666]![/COLOR]self.left.alive [COLOR=#666666]||[/COLOR] [COLOR=#666666]![/COLOR]self.right.alive) {
[COLOR=#008000][B]return[/B][/COLOR];
}
[COLOR=#008000][B]if[/B][/COLOR] (lDecision.weight [COLOR=#666666]<[/COLOR] rDecision.weight) {
decision [COLOR=#666666]=[/COLOR] rDecision;
context [COLOR=#666666]=[/COLOR] [COLOR=#BA2121]"right"[/COLOR];
} [COLOR=#008000][B]else[/B][/COLOR] {
decision [COLOR=#666666]=[/COLOR] lDecision;
context [COLOR=#666666]=[/COLOR] [COLOR=#BA2121]"left"[/COLOR];
}
self[context].memories.lastAction [COLOR=#666666]=[/COLOR] decision.title;
[COLOR=#008000][B]return[/B][/COLOR] decision.action.apply(self[context], decision.args);
}
self.createFeedback [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] (fn) {
self.right.createFeedback(fn);
self.left.createFeedback(fn);
};
self.cycle [COLOR=#666666]=[/COLOR] [COLOR=#008000][B]function[/B][/COLOR] () {
self.right.cycle();
self.left.cycle();
[COLOR=#008000][B]return[/B][/COLOR] decide();
};
self.createFeedback(Remember);
self.createFeedback(Decision);
};
}());
The brain has the ability to store memories and make decisions. It also has a right and a left AI- each with the ability to create independent feedback loops. The brain has it's own createFeedback method which will create the same feedback loop on both left and right. Finally, the brain has a cycle method that will cycle through the right, then the left, and return a decision based on the weight of that decision- where a higher weight will be chosen as the decision to execute. The result of that decision is returned.
There is also a way to sync memories from one side of the brain to the other. Memories are not shared between the left and right sides.
Now, every living resource with a brain will have at least 4 feedback loops (Remember and Decision feedback loops assigned to both right and left).
So, this is the base for the AI. Next I'll talk about setting up the basis for all plants and the basis for all herbs. What do plants have to think about? They are required to reproduce automatically, how will they do that?
Previous (Introduction)
Table of Contents (Introduction)
Next (Plant)
Last edited: