working eyes!
This commit is contained in:
@@ -54,9 +54,10 @@ class WorldEnvironment extends Environment{
|
||||
OriginOfLife() {
|
||||
var center = this.grid_map.getCenter();
|
||||
var org = new Organism(center[0], center[1], this);
|
||||
org.addCell(CellTypes.eye, 0, 0);
|
||||
org.addCell(CellTypes.mouth, -1, -1);
|
||||
org.addCell(CellTypes.mover, 1, 1);
|
||||
org.addCell(CellTypes.mouth, 0, 0);
|
||||
// org.addCell(CellTypes.eye, 2, 2);
|
||||
org.addCell(CellTypes.producer, -1, -1);
|
||||
org.addCell(CellTypes.producer, 1, 1);
|
||||
this.addOrganism(org);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,26 +2,28 @@ const Neighbors = require("./Grid/Neighbors");
|
||||
|
||||
const Hyperparams = {
|
||||
setDefaults: function() {
|
||||
this.lifespanMultiplier= 100;
|
||||
this.foodProdProb= 4;
|
||||
this.foodProdProbScalar= 4;
|
||||
this.killableNeighbors= Neighbors.adjacent;
|
||||
this.edibleNeighbors= Neighbors.adjacent;
|
||||
this.growableNeighbors= Neighbors.adjacent;
|
||||
this.lifespanMultiplier = 100;
|
||||
this.foodProdProb = 4;
|
||||
this.foodProdProbScalar = 4;
|
||||
this.killableNeighbors = Neighbors.adjacent;
|
||||
this.edibleNeighbors = Neighbors.adjacent;
|
||||
this.growableNeighbors = Neighbors.adjacent;
|
||||
|
||||
this.useGlobalMutability= false;
|
||||
this.globalMutability= 5;
|
||||
this.addProb= 33;
|
||||
this.changeProb= 33;
|
||||
this.removeProb= 33;
|
||||
this.useGlobalMutability = false;
|
||||
this.globalMutability = 5;
|
||||
this.addProb = 33;
|
||||
this.changeProb = 33;
|
||||
this.removeProb = 33;
|
||||
|
||||
this.moversCanRotate= true;
|
||||
this.offspringRotate= true;
|
||||
this.moversCanRotate = true;
|
||||
this.offspringRotate = true;
|
||||
|
||||
this.foodBlocksReproduction= true;
|
||||
this.moversCanProduce= false;
|
||||
this.foodBlocksReproduction = true;
|
||||
this.moversCanProduce = false;
|
||||
|
||||
this.instaKill= false;
|
||||
this.instaKill = false;
|
||||
|
||||
this.lookRange = 5;
|
||||
},
|
||||
|
||||
// calculates the optimal ratio where a producer cell is most likely to produce 1 food in its lifespan * a scalar of my choice :)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const CellTypes = require("./CellTypes");
|
||||
const Directions = require("../Directions");
|
||||
const Hyperparams = require("../../Hyperparameters");
|
||||
const Eye = require("../Eye.js");
|
||||
const Eye = require("../Perception/Eye.js");
|
||||
|
||||
// A local cell is a lightweight container for a cell in an organism. It does not directly exist in the grid
|
||||
class LocalCell{
|
||||
|
||||
@@ -3,12 +3,24 @@ const Directions = {
|
||||
right:1,
|
||||
down:2,
|
||||
left:3,
|
||||
scalars:[[0,-1],[0,1],[-1,0],[1,0]],
|
||||
scalars:[[0,-1],[1,0],[0,1],[-1,0]],
|
||||
getRandomDirection: function() {
|
||||
return Math.floor(Math.random() * 4);
|
||||
},
|
||||
getRandomScalar: function() {
|
||||
return this.scalars[Math.floor(Math.random() * this.scalars.length)];
|
||||
},
|
||||
getOppositeDirection: function(dir) {
|
||||
switch(dir){
|
||||
case this.up:
|
||||
return this.down;
|
||||
case this.down:
|
||||
return this.up;
|
||||
case this.left:
|
||||
return this.right;
|
||||
case this.right:
|
||||
return this.left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
const Directions = require("./Directions");
|
||||
|
||||
class Eye {
|
||||
constructor(loc_cell, direction=-1) {
|
||||
this.direction = direction;
|
||||
if (direction == -1){
|
||||
this.direction = Directions.getRandomDirection();
|
||||
}
|
||||
this.loc_cell = loc_cell
|
||||
}
|
||||
|
||||
getAbsoluteDirection(parent_dir) {
|
||||
var dir = parent_dir + this.direction;
|
||||
if (dir > 3)
|
||||
dir -= 4;
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Eye;
|
||||
@@ -5,7 +5,8 @@ const LocalCell = require("./Cell/LocalCell");
|
||||
const Neighbors = require("../Grid/Neighbors");
|
||||
const Hyperparams = require("../Hyperparameters");
|
||||
const Directions = require("./Directions");
|
||||
const Eye = require("./Eye");
|
||||
const Eye = require("./Perception/Eye");
|
||||
const Brain = require("./Perception/Brain");
|
||||
|
||||
const directions = [[0,1],[0,-1],[1,0],[-1,0]]
|
||||
|
||||
@@ -20,7 +21,7 @@ class Organism {
|
||||
this.cells = [];
|
||||
this.is_producer = false;
|
||||
this.is_mover = false;
|
||||
this.direction = Directions.up;
|
||||
this.direction = Directions.down;
|
||||
this.rotation = Directions.up;
|
||||
this.can_rotate = Hyperparams.moversCanRotate;
|
||||
this.move_count = 0;
|
||||
@@ -28,6 +29,7 @@ class Organism {
|
||||
this.mutability = 5;
|
||||
this.damage = 0;
|
||||
this.birth_distance = 4;
|
||||
this.brain = new Brain(this);
|
||||
if (parent != null) {
|
||||
this.inherit(parent);
|
||||
}
|
||||
@@ -334,18 +336,23 @@ class Organism {
|
||||
this.reproduce();
|
||||
}
|
||||
for (var cell of this.cells) {
|
||||
this.getRealCell(cell).performFunction(this.env);
|
||||
if (!this.living){
|
||||
return this.living
|
||||
if (cell.type == CellTypes.eye){
|
||||
var obs = cell.eye.look(this.getRealCol(cell), this.getRealRow(cell), this.rotation, this.env);
|
||||
this.brain.observe(obs);
|
||||
}
|
||||
if (cell.type == CellTypes.eye && cell.eye == null){
|
||||
console.log("whoe nellie");
|
||||
else {
|
||||
this.getRealCell(cell).performFunction(this.env);
|
||||
if (!this.living){
|
||||
return this.living
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.is_mover) {
|
||||
this.move_count++;
|
||||
var changed_dir = this.brain.decide();
|
||||
var moved = this.attemptMove();
|
||||
if (this.move_count > this.move_range){
|
||||
if ((this.move_count > this.move_range && !changed_dir) || !moved){
|
||||
this.attemptRotate();
|
||||
}
|
||||
}
|
||||
@@ -359,6 +366,13 @@ class Organism {
|
||||
return this.env.grid_map.cellAt(real_c, real_r);
|
||||
}
|
||||
|
||||
getRealCol(local_cell) {
|
||||
return this.c + local_cell.rotatedCol(this.rotation);
|
||||
}
|
||||
getRealRow(local_cell) {
|
||||
return this.r + local_cell.rotatedRow(this.rotation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = Organism;
|
||||
|
||||
63
src/Organism/Perception/Brain.js
Normal file
63
src/Organism/Perception/Brain.js
Normal file
@@ -0,0 +1,63 @@
|
||||
const CellTypes = require("../Cell/CellTypes");
|
||||
const Hyperparams = require("../../Hyperparameters");
|
||||
const Directions = require("../Directions");
|
||||
|
||||
const Decision = {
|
||||
neutral: 0,
|
||||
retreat: 1,
|
||||
chase: 2
|
||||
}
|
||||
|
||||
class Brain {
|
||||
constructor(owner){
|
||||
this.owner = owner;
|
||||
this.observations = [];
|
||||
|
||||
// corresponds to CellTypes
|
||||
this.decisions = [
|
||||
Decision.neutral, // empty
|
||||
Decision.chase, // food
|
||||
Decision.neutral, // wall
|
||||
Decision.neutral, // mouth
|
||||
Decision.neutral, // producer
|
||||
Decision.neutral, // mover
|
||||
Decision.retreat, // killer
|
||||
Decision.neutral, // armor
|
||||
Decision.neutral, // eye
|
||||
];
|
||||
}
|
||||
|
||||
observe(observation){
|
||||
this.observations.push(observation);
|
||||
}
|
||||
|
||||
decide(){
|
||||
var decision = Decision.neutral;
|
||||
var closest = Hyperparams.lookRange + 1;
|
||||
var move_direction = 0;
|
||||
for (var obs of this.observations) {
|
||||
if (obs.cell == null || obs.cell.owner == this.owner){
|
||||
continue;
|
||||
}
|
||||
if (obs.distance < closest){
|
||||
decision = this.decisions[obs.cell.type];
|
||||
move_direction = obs.direction;
|
||||
closest = obs.distance;
|
||||
}
|
||||
}
|
||||
this.observations = [];
|
||||
if (decision == Decision.chase) {
|
||||
this.owner.direction = move_direction;
|
||||
this.owner.move_count = 0;
|
||||
return true;
|
||||
}
|
||||
else if (decision == Decision.retreat) {
|
||||
this.owner.direction = Directions.getOppositeDirection(move_direction);
|
||||
this.owner.move_count = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Brain;
|
||||
59
src/Organism/Perception/Eye.js
Normal file
59
src/Organism/Perception/Eye.js
Normal file
@@ -0,0 +1,59 @@
|
||||
const Directions = require("../Directions");
|
||||
const Hyperparams = require("../../Hyperparameters");
|
||||
const CellTypes = require("../Cell/CellTypes");
|
||||
const Observation = require("./Observation")
|
||||
|
||||
class Eye {
|
||||
constructor(loc_cell, direction=-1) {
|
||||
this.direction = direction;
|
||||
if (direction == -1){
|
||||
this.direction = Directions.getRandomDirection();
|
||||
}
|
||||
this.loc_cell = loc_cell
|
||||
}
|
||||
|
||||
getAbsoluteDirection(parent_dir) {
|
||||
var dir = parent_dir + this.direction;
|
||||
if (dir > 3)
|
||||
dir -= 4;
|
||||
return dir;
|
||||
}
|
||||
|
||||
look(start_col, start_row, rotation, env) {
|
||||
var direction = this.getAbsoluteDirection(rotation);
|
||||
var addCol = 0;
|
||||
var addRow = 0;
|
||||
switch(direction) {
|
||||
case Directions.up:
|
||||
addRow = -1;
|
||||
break;
|
||||
case Directions.down:
|
||||
addRow = 1;
|
||||
break;
|
||||
case Directions.right:
|
||||
addCol = 1;
|
||||
break;
|
||||
case Directions.left:
|
||||
addCol = -1;
|
||||
break;
|
||||
}
|
||||
var col=start_col;
|
||||
var row=start_row;
|
||||
var cell = null;
|
||||
for (var i=0; i<Hyperparams.lookRange; i++){
|
||||
col+=addCol;
|
||||
row+=addRow;
|
||||
cell = env.grid_map.cellAt(col, row);
|
||||
if (cell == null){
|
||||
break;
|
||||
}
|
||||
if (cell.type != CellTypes.empty){
|
||||
var distance = Math.abs(start_col-col) + Math.abs(start_row-row);
|
||||
return new Observation(cell, distance, direction);
|
||||
}
|
||||
}
|
||||
return new Observation(cell, Hyperparams.lookRange, direction);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Eye;
|
||||
9
src/Organism/Perception/Observation.js
Normal file
9
src/Organism/Perception/Observation.js
Normal file
@@ -0,0 +1,9 @@
|
||||
class Observation {
|
||||
constructor(cell, distance, direction){
|
||||
this.cell = cell;
|
||||
this.distance = distance;
|
||||
this.direction = direction;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Observation;
|
||||
43
src/Util/LinkedList.js
Normal file
43
src/Util/LinkedList.js
Normal file
@@ -0,0 +1,43 @@
|
||||
class LinkedList {
|
||||
constructor() {
|
||||
this.head = null;
|
||||
this.size = 0;
|
||||
}
|
||||
push(obj) {
|
||||
var el = new Element(obj, null, this.head);
|
||||
if (this.head != null){
|
||||
this.head.prev = el;
|
||||
}
|
||||
this.head = el;
|
||||
this.size ++;
|
||||
}
|
||||
clear() {
|
||||
var cur = this.head;
|
||||
while(cur != null){
|
||||
this.remove(cur);
|
||||
cur = cur.next;
|
||||
}
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
remove(element){
|
||||
if (element.prev != null){
|
||||
element.prev.next = element.next;
|
||||
}
|
||||
else if (this.head == element){
|
||||
this.head = element.next;
|
||||
}
|
||||
if (element.next != null){
|
||||
element.next.prev = element.prev;
|
||||
}
|
||||
this.size--;
|
||||
}
|
||||
}
|
||||
|
||||
class Element {
|
||||
constructor(obj, prev, next){
|
||||
this.obj = obj;
|
||||
this.prev = prev;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user