/****
* Classes
****/
var AI = Container.expand(function () {
var self = Container.call(this);
self.inheritTraits = function (parent) {
this.food = parent.food * 0.5;
this.speed = parent.speed;
this.agility = parent.agility;
this.strength = parent.strength;
this.intelligence = parent.intelligence;
};
var ais = [];
self.foods = [];
self.aiGraphics = self.attachAsset('ai', {
anchorX: 0.5,
anchorY: 0.5
});
self.food = 10;
self.generation = 1;
self.family = [];
self.generationText = new Text2(self.generation.toString(), {
size: 50,
fill: '#ffffff'
});
self.generationText.anchor.set(.5, 0);
self.addChild(self.generationText);
self.eat = function (food) {
if (food.amount > 0) {
var familyNeedsFood = this.family.some(function (member) {
return member.food < 1;
});
if (!familyNeedsFood) {
this.food += food.consume(1);
}
}
};
self.share = function (otherAI) {
var decision = this.neuralNetwork.feedForward([this.food, otherAI.food, this.fieldOfView]);
if (decision > 0) {
if (this.food > 10) {
var shareAmount = this.food * 0.1;
this.food -= shareAmount;
this.family.forEach(function (member) {
member.food += shareAmount / this.family.length;
});
}
}
};
self.survive = function () {
this.food -= 0.01;
if (this.food < 0) {
this.destroy();
var index = ais.indexOf(this);
if (index > -1) {
ais.splice(index, 1);
}
}
};
self.neuralNetwork = new NeuralNetwork();
self.neuralNetwork.weights = [Math.random(), Math.random()];
self.neuralNetwork.bias = Math.random();
self.direction = Math.random() * 2 * Math.PI;
self.fieldOfView = Math.random() * Math.PI;
self.viewDistance = Math.random() * 500;
self.speed = Math.random() * 5;
self.reproductionThreshold = 2;
self.generation = 1;
self.agility = Math.random() * 5;
self.strength = Math.random() * 5;
self.intelligence = Math.random() * 5;
self._move_migrated = function () {
var nearestFood = null;
var nearestFoodDistance = Infinity;
for (var i = 0; i < this.foods.length; i++) {
var dx = this.foods[i].x - this.x;
var dy = this.foods[i].y - this.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var angle = Math.atan2(dy, dx);
var deltaAngle = Math.abs(this.direction - angle);
if (distance < this.viewDistance && deltaAngle < this.fieldOfView / 2 && distance < nearestFoodDistance) {
nearestFood = this.foods[i];
nearestFoodDistance = distance;
}
}
if (nearestFood) {
var dx = nearestFood.x - this.x;
var dy = nearestFood.y - this.y;
self.direction = Math.atan2(dy, dx);
} else {
if (Math.random() < 0.05) {
self.direction += Math.random() * 0.2 - 0.1;
}
}
var speed = 5;
var newX = self.x + Math.cos(self.direction) * speed;
var newY = self.y + Math.sin(self.direction) * speed;
if (newX < 0) {
newX = 0;
self.direction = Math.PI - self.direction;
} else if (newX > 2048) {
newX = 2048;
self.direction = Math.PI - self.direction;
}
if (newY < 0) {
newY = 0;
self.direction = -self.direction;
} else if (newY > 2732) {
newY = 2732;
self.direction = -self.direction;
}
self.x = newX;
self.y = newY;
};
self.reproduce = function () {
if (this.food > 10) {
var child = new AI();
child.neuralNetwork = this.neuralNetwork.clone();
for (var i = 0; i < child.neuralNetwork.weights.length; i++) {
if (Math.random() < 0.1) {
child.neuralNetwork.weights[i] += Math.random() * 0.2 - 0.1;
}
}
if (Math.random() < 0.1) {
child.neuralNetwork.bias += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.fieldOfView += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.viewDistance += Math.random() * 100 - 50;
}
if (Math.random() < 0.1) {
child.speed += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.reproductionThreshold += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.agility += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.strength += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.intelligence += Math.random() * 0.2 - 0.1;
}
child.inheritTraits(this);
this.food -= 10;
ais.push(child);
this.family.push(child);
child.direction = Math.random() * 2 * Math.PI;
child.generation = this.generation + 1;
return child;
}
return null;
};
});
var Food = Container.expand(function () {
var self = Container.call(this);
var foodGraphics = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.amount = 10;
self.consume = function (amount) {
this.amount -= amount;
return amount;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var NeuralNetwork = function NeuralNetwork() {
var self = this;
self.weights = [];
self.bias = 0;
self.clone = function () {
var clone = new NeuralNetwork();
clone.weights = this.weights.slice();
clone.bias = this.bias;
return clone;
};
self.feedForward = function (inputs) {
var sum = 0;
for (var i = 0; i < inputs.length; i++) {
sum += inputs[i] * this.weights[i];
}
return sum + this.bias;
};
};
var ais = [];
var foods = [];
for (var i = 0; i < 3; i++) {
var ai = new AI();
ai.x = Math.random() * 2048;
ai.y = Math.random() * 2732;
ais.push(ai);
game.addChild(ai);
var food = new Food();
food.x = Math.random() * 2048;
food.y = Math.random() * 2732;
foods.push(food);
game.addChild(food);
}
LK.on('tick', function () {
for (var i = 0; i < ais.length; i++) {
var ai = ais[i];
ai._move_migrated();
ai.survive();
ai.generationText.setText(ai.generation.toString());
for (var j = 0; j < foods.length; j++) {
var food = foods[j];
if (ai.intersects(food)) {
ai.eat(food);
food.consume(1);
if (food.amount <= 0) {
food.destroy();
foods.splice(j, 1);
j--;
}
}
}
for (var j = i + 1; j < ais.length; j++) {
var otherAI = ais[j];
if (ai.intersects(otherAI)) {
var decision = ai.neuralNetwork.feedForward([ai.food, otherAI.food]);
if (decision > 0) {
ai.share(otherAI);
}
}
}
if (ai.food <= 0) {
var index = ais.indexOf(ai);
if (index > -1) {
ais.splice(index, 1);
}
ai.destroy();
i--;
if (ais.length === 0) {
LK.showGameOver();
}
}
}
if (LK.ticks % 600 == 0) {
for (var i = 0; i < ais.length; i++) {
var ai = ais[i];
var child = ai.reproduce();
if (child) {
child.x = ai.x;
child.y = ai.y;
game.addChild(child);
ais.push(child);
}
}
}
if (LK.ticks % 120 == 0) {
var food = new Food();
food.x = Math.random() * 2048;
food.y = Math.random() * 2732;
foods.push(food);
game.addChild(food);
}
}); /****
* Classes
****/
var AI = Container.expand(function () {
var self = Container.call(this);
self.inheritTraits = function (parent) {
this.food = parent.food * 0.5;
this.speed = parent.speed;
this.agility = parent.agility;
this.strength = parent.strength;
this.intelligence = parent.intelligence;
};
var ais = [];
self.foods = [];
self.aiGraphics = self.attachAsset('ai', {
anchorX: 0.5,
anchorY: 0.5
});
self.food = 10;
self.generation = 1;
self.family = [];
self.generationText = new Text2(self.generation.toString(), {
size: 50,
fill: '#ffffff'
});
self.generationText.anchor.set(.5, 0);
self.addChild(self.generationText);
self.eat = function (food) {
if (food.amount > 0) {
var familyNeedsFood = this.family.some(function (member) {
return member.food < 1;
});
if (!familyNeedsFood) {
this.food += food.consume(1);
}
}
};
self.share = function (otherAI) {
var decision = this.neuralNetwork.feedForward([this.food, otherAI.food, this.fieldOfView]);
if (decision > 0) {
if (this.food > 10) {
var shareAmount = this.food * 0.1;
this.food -= shareAmount;
this.family.forEach(function (member) {
member.food += shareAmount / this.family.length;
});
}
}
};
self.survive = function () {
this.food -= 0.01;
if (this.food < 0) {
this.destroy();
var index = ais.indexOf(this);
if (index > -1) {
ais.splice(index, 1);
}
}
};
self.neuralNetwork = new NeuralNetwork();
self.neuralNetwork.weights = [Math.random(), Math.random()];
self.neuralNetwork.bias = Math.random();
self.direction = Math.random() * 2 * Math.PI;
self.fieldOfView = Math.random() * Math.PI;
self.viewDistance = Math.random() * 500;
self.speed = Math.random() * 5;
self.reproductionThreshold = 2;
self.generation = 1;
self.agility = Math.random() * 5;
self.strength = Math.random() * 5;
self.intelligence = Math.random() * 5;
self._move_migrated = function () {
var nearestFood = null;
var nearestFoodDistance = Infinity;
for (var i = 0; i < this.foods.length; i++) {
var dx = this.foods[i].x - this.x;
var dy = this.foods[i].y - this.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var angle = Math.atan2(dy, dx);
var deltaAngle = Math.abs(this.direction - angle);
if (distance < this.viewDistance && deltaAngle < this.fieldOfView / 2 && distance < nearestFoodDistance) {
nearestFood = this.foods[i];
nearestFoodDistance = distance;
}
}
if (nearestFood) {
var dx = nearestFood.x - this.x;
var dy = nearestFood.y - this.y;
self.direction = Math.atan2(dy, dx);
} else {
if (Math.random() < 0.05) {
self.direction += Math.random() * 0.2 - 0.1;
}
}
var speed = 5;
var newX = self.x + Math.cos(self.direction) * speed;
var newY = self.y + Math.sin(self.direction) * speed;
if (newX < 0) {
newX = 0;
self.direction = Math.PI - self.direction;
} else if (newX > 2048) {
newX = 2048;
self.direction = Math.PI - self.direction;
}
if (newY < 0) {
newY = 0;
self.direction = -self.direction;
} else if (newY > 2732) {
newY = 2732;
self.direction = -self.direction;
}
self.x = newX;
self.y = newY;
};
self.reproduce = function () {
if (this.food > 10) {
var child = new AI();
child.neuralNetwork = this.neuralNetwork.clone();
for (var i = 0; i < child.neuralNetwork.weights.length; i++) {
if (Math.random() < 0.1) {
child.neuralNetwork.weights[i] += Math.random() * 0.2 - 0.1;
}
}
if (Math.random() < 0.1) {
child.neuralNetwork.bias += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.fieldOfView += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.viewDistance += Math.random() * 100 - 50;
}
if (Math.random() < 0.1) {
child.speed += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.reproductionThreshold += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.agility += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.strength += Math.random() * 0.2 - 0.1;
}
if (Math.random() < 0.1) {
child.intelligence += Math.random() * 0.2 - 0.1;
}
child.inheritTraits(this);
this.food -= 10;
ais.push(child);
this.family.push(child);
child.direction = Math.random() * 2 * Math.PI;
child.generation = this.generation + 1;
return child;
}
return null;
};
});
var Food = Container.expand(function () {
var self = Container.call(this);
var foodGraphics = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.amount = 10;
self.consume = function (amount) {
this.amount -= amount;
return amount;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
var NeuralNetwork = function NeuralNetwork() {
var self = this;
self.weights = [];
self.bias = 0;
self.clone = function () {
var clone = new NeuralNetwork();
clone.weights = this.weights.slice();
clone.bias = this.bias;
return clone;
};
self.feedForward = function (inputs) {
var sum = 0;
for (var i = 0; i < inputs.length; i++) {
sum += inputs[i] * this.weights[i];
}
return sum + this.bias;
};
};
var ais = [];
var foods = [];
for (var i = 0; i < 3; i++) {
var ai = new AI();
ai.x = Math.random() * 2048;
ai.y = Math.random() * 2732;
ais.push(ai);
game.addChild(ai);
var food = new Food();
food.x = Math.random() * 2048;
food.y = Math.random() * 2732;
foods.push(food);
game.addChild(food);
}
LK.on('tick', function () {
for (var i = 0; i < ais.length; i++) {
var ai = ais[i];
ai._move_migrated();
ai.survive();
ai.generationText.setText(ai.generation.toString());
for (var j = 0; j < foods.length; j++) {
var food = foods[j];
if (ai.intersects(food)) {
ai.eat(food);
food.consume(1);
if (food.amount <= 0) {
food.destroy();
foods.splice(j, 1);
j--;
}
}
}
for (var j = i + 1; j < ais.length; j++) {
var otherAI = ais[j];
if (ai.intersects(otherAI)) {
var decision = ai.neuralNetwork.feedForward([ai.food, otherAI.food]);
if (decision > 0) {
ai.share(otherAI);
}
}
}
if (ai.food <= 0) {
var index = ais.indexOf(ai);
if (index > -1) {
ais.splice(index, 1);
}
ai.destroy();
i--;
if (ais.length === 0) {
LK.showGameOver();
}
}
}
if (LK.ticks % 600 == 0) {
for (var i = 0; i < ais.length; i++) {
var ai = ais[i];
var child = ai.reproduce();
if (child) {
child.x = ai.x;
child.y = ai.y;
game.addChild(child);
ais.push(child);
}
}
}
if (LK.ticks % 120 == 0) {
var food = new Food();
food.x = Math.random() * 2048;
food.y = Math.random() * 2732;
foods.push(food);
game.addChild(food);
}
});