working eyes!
This commit is contained in:
@@ -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;
|
||||
Reference in New Issue
Block a user