working eyes!

This commit is contained in:
MaxRobinsonTheGreat
2020-08-11 15:25:20 -06:00
parent 6003686a13
commit 3d3c6f8558
11 changed files with 233 additions and 50 deletions

2
dist/js/bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -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);
}

View File

@@ -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 :)

View File

@@ -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{

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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;

View 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;

View 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;

View 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
View 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;
}
}