Separated anatomy from org / made species tracker
This commit is contained in:
443
dist/js/bundle.js
vendored
443
dist/js/bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -199,6 +199,7 @@ class ControlPanel {
|
||||
case "drop-org":
|
||||
self.setMode(Modes.Clone);
|
||||
self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg();
|
||||
self.env_controller.make_new_species = true;
|
||||
break;
|
||||
case "drag-view":
|
||||
self.setMode(Modes.Drag);
|
||||
|
||||
@@ -26,7 +26,7 @@ class EditorController extends CanvasController{
|
||||
mouseUp(){}
|
||||
|
||||
getCurLocalCell(){
|
||||
return this.env.organism.getLocalCell(this.mouse_c-this.env.organism.c, this.mouse_r-this.env.organism.r);
|
||||
return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c, this.mouse_r-this.env.organism.r);
|
||||
}
|
||||
|
||||
editOrganism() {
|
||||
@@ -49,7 +49,7 @@ class EditorController extends CanvasController{
|
||||
}
|
||||
|
||||
updateDetails() {
|
||||
$('.cell-count').text("Cell count: "+this.env.organism.cells.length);
|
||||
$('.cell-count').text("Cell count: "+this.env.organism.anatomy.cells.length);
|
||||
}
|
||||
|
||||
defineCellTypeSelection() {
|
||||
@@ -111,7 +111,7 @@ class EditorController extends CanvasController{
|
||||
this.clearDetailsPanel();
|
||||
var org = this.env.organism;
|
||||
|
||||
$('.cell-count').text("Cell count: "+org.cells.length);
|
||||
$('.cell-count').text("Cell count: "+org.anatomy.cells.length);
|
||||
$('#move-range').text("Move Range: "+org.move_range);
|
||||
$('#mutation-rate').text("Mutation Rate: "+org.mutability);
|
||||
if (Hyperparams.useGlobalMutability) {
|
||||
@@ -134,7 +134,7 @@ class EditorController extends CanvasController{
|
||||
this.clearDetailsPanel();
|
||||
var org = this.env.organism;
|
||||
|
||||
$('.cell-count').text("Cell count: "+org.cells.length);
|
||||
$('.cell-count').text("Cell count: "+org.anatomy.cells.length);
|
||||
if (this.setMoveRangeVisibility()){
|
||||
$('#move-range-edit').val(org.move_range);
|
||||
}
|
||||
@@ -149,7 +149,7 @@ class EditorController extends CanvasController{
|
||||
|
||||
setBrainPanelVisibility() {
|
||||
var org = this.env.organism;
|
||||
if (org.has_eyes && org.is_mover) {
|
||||
if (org.anatomy.has_eyes && org.anatomy.is_mover) {
|
||||
$('.brain-details').css('display', 'block');
|
||||
return true;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ class EditorController extends CanvasController{
|
||||
|
||||
setMoveRangeVisibility() {
|
||||
var org = this.env.organism;
|
||||
if (org.is_mover) {
|
||||
if (org.anatomy.is_mover) {
|
||||
$('#move-range-cont').css('display', 'block');
|
||||
$('#move-range').css('display', 'block');
|
||||
return true;
|
||||
|
||||
@@ -3,12 +3,15 @@ const Organism = require('../Organism/Organism');
|
||||
const Modes = require("./ControlModes");
|
||||
const CellStates = require("../Organism/Cell/CellStates");
|
||||
const Neighbors = require("../Grid/Neighbors");
|
||||
const FossilRecord = require("../Stats/FossilRecord");
|
||||
|
||||
class EnvironmentController extends CanvasController{
|
||||
constructor(env, canvas) {
|
||||
super(env, canvas);
|
||||
this.mode = Modes.Drag;
|
||||
this.org_to_clone = null;
|
||||
this.species_to_clone = null;
|
||||
this.make_new_species = false;
|
||||
this.defineZoomControls();
|
||||
this.scale = 1;
|
||||
}
|
||||
@@ -118,6 +121,14 @@ class EnvironmentController extends CanvasController{
|
||||
case Modes.Clone:
|
||||
if (this.org_to_clone != null){
|
||||
var new_org = new Organism(this.mouse_c, this.mouse_r, this.env, this.org_to_clone);
|
||||
if (this.make_new_species){
|
||||
this.species_to_clone = FossilRecord.addSpecies(new_org, null)
|
||||
this.make_new_species = false;
|
||||
}
|
||||
else {
|
||||
new_org.species = this.species_to_clone;
|
||||
this.species_to_clone.addPop();
|
||||
}
|
||||
if (new_org.isClear(this.mouse_c, this.mouse_r)){
|
||||
this.env.addOrganism(new_org)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ const GridMap = require('../Grid/GridMap');
|
||||
const Renderer = require('../Rendering/Renderer');
|
||||
const CellStates = require('../Organism/Cell/CellStates');
|
||||
const EditorController = require("../Controllers/EditorController");
|
||||
const Directions = require('../Organism/Directions');
|
||||
|
||||
class OrganismEditor extends Environment{
|
||||
constructor() {
|
||||
@@ -37,13 +36,13 @@ class OrganismEditor extends Environment{
|
||||
var center = this.grid_map.getCenter();
|
||||
var loc_c = c - center[0];
|
||||
var loc_r = r - center[1];
|
||||
var prev_cell = this.organism.getLocalCell(loc_c, loc_r)
|
||||
var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)
|
||||
if (prev_cell != null) {
|
||||
var new_cell = this.organism.replaceCell(state, prev_cell.loc_col, prev_cell.loc_row, false);
|
||||
var new_cell = this.organism.anatomy.replaceCell(state, prev_cell.loc_col, prev_cell.loc_row, false);
|
||||
this.changeCell(c, r, state, new_cell);
|
||||
}
|
||||
else if (this.organism.canAddCellAt(loc_c, loc_r)){
|
||||
this.changeCell(c, r, state, this.organism.addDefaultCell(state, loc_c, loc_r));
|
||||
else if (this.organism.anatomy.canAddCellAt(loc_c, loc_r)){
|
||||
this.changeCell(c, r, state, this.organism.anatomy.addDefaultCell(state, loc_c, loc_r));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +54,9 @@ class OrganismEditor extends Environment{
|
||||
alert("Cannot remove center cell");
|
||||
return;
|
||||
}
|
||||
var prev_cell = this.organism.getLocalCell(loc_c, loc_r)
|
||||
var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)
|
||||
if (prev_cell != null) {
|
||||
if (this.organism.removeCell(loc_c, loc_r)) {
|
||||
if (this.organism.anatomy.removeCell(loc_c, loc_r)) {
|
||||
this.changeCell(c, r, CellStates.empty, null);
|
||||
}
|
||||
}
|
||||
@@ -80,7 +79,7 @@ class OrganismEditor extends Environment{
|
||||
this.grid_map.fillGrid(CellStates.empty);
|
||||
var center = this.grid_map.getCenter();
|
||||
this.organism = new Organism(center[0], center[1], this, null);
|
||||
this.organism.addDefaultCell(CellStates.mouth, 0, 0);
|
||||
this.organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0);
|
||||
this.organism.updateGrid();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const Organism = require('../Organism/Organism');
|
||||
const CellStates = require('../Organism/Cell/CellStates');
|
||||
const EnvironmentController = require('../Controllers/EnvironmentController');
|
||||
const Hyperparams = require('../Hyperparameters.js');
|
||||
const Cell = require('../Organism/Cell/GridCell');
|
||||
const FossilRecord = require('../Stats/FossilRecord');
|
||||
|
||||
class WorldEnvironment extends Environment{
|
||||
constructor(cell_size) {
|
||||
@@ -21,9 +21,12 @@ class WorldEnvironment extends Environment{
|
||||
this.auto_reset = true;
|
||||
this.largest_cell_count = 0;
|
||||
this.reset_count = 0;
|
||||
this.total_ticks = 0;
|
||||
FossilRecord.setEnv(this);
|
||||
}
|
||||
|
||||
update(delta_time) {
|
||||
this.total_ticks ++;
|
||||
var to_remove = [];
|
||||
for (var i in this.organisms) {
|
||||
var org = this.organisms[i];
|
||||
@@ -56,21 +59,19 @@ class WorldEnvironment extends Environment{
|
||||
OriginOfLife() {
|
||||
var center = this.grid_map.getCenter();
|
||||
var org = new Organism(center[0], center[1], this);
|
||||
// org.addDefaultCell(CellStates.eye, 0, 0);
|
||||
// org.addDefaultCell(CellStates.mouth, 1, 1);
|
||||
// org.addDefaultCell(CellStates.mover, 1, -1);
|
||||
org.addDefaultCell(CellStates.mouth, 0, 0);
|
||||
org.addDefaultCell(CellStates.producer, 1, 1);
|
||||
org.addDefaultCell(CellStates.producer, -1, -1);
|
||||
org.anatomy.addDefaultCell(CellStates.mouth, 0, 0);
|
||||
org.anatomy.addDefaultCell(CellStates.producer, 1, 1);
|
||||
org.anatomy.addDefaultCell(CellStates.producer, -1, -1);
|
||||
this.addOrganism(org);
|
||||
FossilRecord.addSpecies(org, null);
|
||||
}
|
||||
|
||||
addOrganism(organism) {
|
||||
organism.updateGrid();
|
||||
this.total_mutability += organism.mutability;
|
||||
this.organisms.push(organism);
|
||||
if (organism.cells.length > this.largest_cell_count)
|
||||
this.largest_cell_count = organism.cells.length;
|
||||
if (organism.anatomy.cells.length > this.largest_cell_count)
|
||||
this.largest_cell_count = organism.anatomy.cells.length;
|
||||
}
|
||||
|
||||
averageMutability() {
|
||||
@@ -119,6 +120,7 @@ class WorldEnvironment extends Environment{
|
||||
this.grid_map.fillGrid(CellStates.empty);
|
||||
this.renderer.renderFullGrid(this.grid_map.grid);
|
||||
this.total_mutability = 0;
|
||||
this.total_ticks = 0;
|
||||
this.OriginOfLife();
|
||||
}
|
||||
|
||||
|
||||
96
src/Organism/Anatomy.js
Normal file
96
src/Organism/Anatomy.js
Normal file
@@ -0,0 +1,96 @@
|
||||
const CellStates = require("./Cell/CellStates");
|
||||
const BodyCellFactory = require("./Cell/BodyCells/BodyCellFactory");
|
||||
|
||||
class Anatomy {
|
||||
constructor(owner) {
|
||||
this.owner = owner;
|
||||
this.cells = [];
|
||||
this.is_producer = false;
|
||||
this.is_mover = false;
|
||||
this.has_eyes = false;
|
||||
this.birth_distance = 4;
|
||||
}
|
||||
|
||||
canAddCellAt(c, r) {
|
||||
for (var cell of this.cells) {
|
||||
if (cell.loc_col == c && cell.loc_row == r){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
addDefaultCell(state, c, r) {
|
||||
var new_cell = BodyCellFactory.createDefault(this.owner, state, c, r);
|
||||
this.cells.push(new_cell);
|
||||
return new_cell;
|
||||
}
|
||||
|
||||
addRandomizedCell(state, c, r) {
|
||||
if (state==CellStates.eye && !this.has_eyes) {
|
||||
this.owner.brain.randomizeDecisions();
|
||||
}
|
||||
var new_cell = BodyCellFactory.createRandom(this.owner, state, c, r);
|
||||
this.cells.push(new_cell);
|
||||
return new_cell;
|
||||
}
|
||||
|
||||
addInheritCell(parent_cell) {
|
||||
var new_cell = BodyCellFactory.createInherited(this.owner, parent_cell);
|
||||
this.cells.push(new_cell);
|
||||
return new_cell;
|
||||
}
|
||||
|
||||
replaceCell(state, c, r, randomize=true) {
|
||||
this.removeCell(c, r, true);
|
||||
if (randomize) {
|
||||
return this.addRandomizedCell(state, c, r);
|
||||
}
|
||||
else {
|
||||
return this.addDefaultCell(state, c, r);
|
||||
}
|
||||
}
|
||||
|
||||
removeCell(c, r, allow_center_removal=false) {
|
||||
if (c == 0 && r == 0 && !allow_center_removal)
|
||||
return false;
|
||||
for (var i=0; i<this.cells.length; i++) {
|
||||
var cell = this.cells[i];
|
||||
if (cell.loc_col == c && cell.loc_row == r){
|
||||
this.cells.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.checkTypeChange(cell.state);
|
||||
return true;
|
||||
}
|
||||
|
||||
getLocalCell(c, r) {
|
||||
for (var cell of this.cells) {
|
||||
if (cell.loc_col == c && cell.loc_row == r){
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
checkTypeChange() {
|
||||
this.is_producer = false;
|
||||
this.is_mover = false;
|
||||
this.has_eyes = false;
|
||||
for (var cell of this.cells) {
|
||||
if (cell.state == CellStates.producer)
|
||||
this.is_producer = true;
|
||||
if (cell.state == CellStates.mover)
|
||||
this.is_mover = true;
|
||||
if (cell.state == CellStates.eye)
|
||||
this.has_eyes = true;
|
||||
}
|
||||
}
|
||||
|
||||
getRandomCell() {
|
||||
return this.cells[Math.floor(Math.random() * this.cells.length)];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Anatomy;
|
||||
@@ -10,8 +10,8 @@ class BodyCell{
|
||||
this.loc_row = loc_row;
|
||||
|
||||
var distance = Math.max(Math.abs(loc_row)*2 + 2, Math.abs(loc_col)*2 + 2);
|
||||
if (this.org.birth_distance < distance) {
|
||||
this.org.birth_distance = distance;
|
||||
if (this.org.anatomy.birth_distance < distance) {
|
||||
this.org.anatomy.birth_distance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ const Observation = require("../../Perception/Observation")
|
||||
class EyeCell extends BodyCell{
|
||||
constructor(org, loc_col, loc_row){
|
||||
super(CellStates.eye, org, loc_col, loc_row);
|
||||
this.org.has_eyes = true;
|
||||
this.org.anatomy.has_eyes = true;
|
||||
}
|
||||
|
||||
initInherit(parent) {
|
||||
|
||||
@@ -4,7 +4,7 @@ const BodyCell = require("./BodyCell");
|
||||
class MoverCell extends BodyCell{
|
||||
constructor(org, loc_col, loc_row){
|
||||
super(CellStates.mover, org, loc_col, loc_row);
|
||||
this.org.is_mover = true;
|
||||
this.org.anatomy.is_mover = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ const Hyperparams = require("../../../Hyperparameters");
|
||||
class ProducerCell extends BodyCell{
|
||||
constructor(org, loc_col, loc_row){
|
||||
super(CellStates.producer, org, loc_col, loc_row);
|
||||
this.org.is_producer = true;
|
||||
this.org.anatomy.is_producer = true;
|
||||
}
|
||||
|
||||
performFunction() {
|
||||
if (this.org.is_mover && !Hyperparams.moversCanProduce)
|
||||
if (this.org.anatomy.is_mover && !Hyperparams.moversCanProduce)
|
||||
return;
|
||||
var env = this.org.env;
|
||||
var prob = Hyperparams.foodProdProb;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
const CellStates = require("../Organism/Cell/CellStates");
|
||||
const BodyCellFactory = require("./Cell/BodyCells/BodyCellFactory");
|
||||
const CellStates = require("./Cell/CellStates");
|
||||
const Neighbors = require("../Grid/Neighbors");
|
||||
const Hyperparams = require("../Hyperparameters");
|
||||
const Directions = require("./Directions");
|
||||
const Anatomy = require("./Anatomy");
|
||||
const Brain = require("./Perception/Brain");
|
||||
const FossilRecord = require("../Stats/FossilRecord");
|
||||
|
||||
class Organism {
|
||||
constructor(col, row, env, parent=null) {
|
||||
@@ -13,111 +14,31 @@ class Organism {
|
||||
this.lifetime = 0;
|
||||
this.food_collected = 0;
|
||||
this.living = true;
|
||||
this.cells = [];
|
||||
this.is_producer = false;
|
||||
this.is_mover = false;
|
||||
this.has_eyes = false;
|
||||
this.direction = Directions.down;
|
||||
this.rotation = Directions.up;
|
||||
this.anatomy = new Anatomy(this)
|
||||
this.direction = Directions.down; // direction of movement
|
||||
this.rotation = Directions.up; // direction of rotation
|
||||
this.can_rotate = Hyperparams.moversCanRotate;
|
||||
this.move_count = 0;
|
||||
this.move_range = 4;
|
||||
this.ignore_brain_for = 0;
|
||||
this.mutability = 5;
|
||||
this.damage = 0;
|
||||
this.birth_distance = 4;
|
||||
this.brain = new Brain(this);
|
||||
if (parent != null) {
|
||||
this.inherit(parent);
|
||||
}
|
||||
}
|
||||
|
||||
canAddCellAt(c, r) {
|
||||
for (var cell of this.cells) {
|
||||
if (cell.loc_col == c && cell.loc_row == r){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
addDefaultCell(state, c, r) {
|
||||
var new_cell = BodyCellFactory.createDefault(this, state, c, r);
|
||||
this.cells.push(new_cell);
|
||||
return new_cell;
|
||||
}
|
||||
|
||||
addRandomizedCell(state, c, r) {
|
||||
if (state==CellStates.eye && !this.has_eyes) {
|
||||
this.brain.randomizeDecisions();
|
||||
}
|
||||
var new_cell = BodyCellFactory.createRandom(this, state, c, r);
|
||||
this.cells.push(new_cell);
|
||||
return new_cell;
|
||||
}
|
||||
|
||||
addInheritCell(parent_cell) {
|
||||
var new_cell = BodyCellFactory.createInherited(this, parent_cell);
|
||||
this.cells.push(new_cell);
|
||||
return new_cell;
|
||||
}
|
||||
|
||||
replaceCell(state, c, r, randomize=true) {
|
||||
this.removeCell(c, r, true);
|
||||
if (randomize) {
|
||||
return this.addRandomizedCell(state, c, r);
|
||||
}
|
||||
else {
|
||||
return this.addDefaultCell(state, c, r);
|
||||
}
|
||||
}
|
||||
|
||||
removeCell(c, r, override_defense=false) {
|
||||
if (c == 0 && r == 0 && !override_defense)
|
||||
return false;
|
||||
for (var i=0; i<this.cells.length; i++) {
|
||||
var cell = this.cells[i];
|
||||
if (cell.loc_col == c && cell.loc_row == r){
|
||||
this.cells.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.checkTypeChange(cell.state);
|
||||
return true;
|
||||
}
|
||||
|
||||
getLocalCell(c, r) {
|
||||
for (var cell of this.cells) {
|
||||
if (cell.loc_col == c && cell.loc_row == r){
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
checkTypeChange() {
|
||||
this.is_producer = false;
|
||||
this.is_mover = false;
|
||||
this.has_eyes = false;
|
||||
for (var cell of this.cells) {
|
||||
if (cell.state == CellStates.producer)
|
||||
this.is_producer = true;
|
||||
if (cell.state == CellStates.mover)
|
||||
this.is_mover = true;
|
||||
if (cell.state == CellStates.eye)
|
||||
this.has_eyes = true;
|
||||
}
|
||||
}
|
||||
|
||||
inherit(parent) {
|
||||
this.move_range = parent.move_range;
|
||||
this.mutability = parent.mutability;
|
||||
this.species = parent.species;
|
||||
// this.birth_distance = parent.birth_distance;
|
||||
for (var c of parent.cells){
|
||||
for (var c of parent.anatomy.cells){
|
||||
//deep copy parent cells
|
||||
this.addInheritCell(c);
|
||||
this.anatomy.addInheritCell(c);
|
||||
}
|
||||
if(parent.is_mover) {
|
||||
if(parent.anatomy.is_mover) {
|
||||
for (var i in parent.brain.decisions) {
|
||||
this.brain.decisions[i] = parent.brain.decisions[i];
|
||||
}
|
||||
@@ -126,16 +47,16 @@ class Organism {
|
||||
|
||||
// amount of food required before it can reproduce
|
||||
foodNeeded() {
|
||||
return this.cells.length;
|
||||
return this.anatomy.cells.length;
|
||||
}
|
||||
|
||||
lifespan() {
|
||||
// console.log(Hyperparams.lifespanMultiplier)
|
||||
return this.cells.length * Hyperparams.lifespanMultiplier;
|
||||
return this.anatomy.cells.length * Hyperparams.lifespanMultiplier;
|
||||
}
|
||||
|
||||
maxHealth() {
|
||||
return this.cells.length;
|
||||
return this.anatomy.cells.length;
|
||||
}
|
||||
|
||||
reproduce() {
|
||||
@@ -159,9 +80,10 @@ class Organism {
|
||||
org.mutability = 1;
|
||||
}
|
||||
}
|
||||
var mutated = false;
|
||||
if (Math.random() * 100 <= prob) {
|
||||
if (org.is_mover && Math.random() * 100 <= 10) {
|
||||
if (org.has_eyes) {
|
||||
if (org.anatomy.is_mover && Math.random() * 100 <= 10) {
|
||||
if (org.anatomy.has_eyes) {
|
||||
org.brain.mutate();
|
||||
}
|
||||
org.move_range += Math.floor(Math.random() * 4) - 2;
|
||||
@@ -170,24 +92,31 @@ class Organism {
|
||||
};
|
||||
|
||||
}
|
||||
else
|
||||
org.mutate();
|
||||
else {
|
||||
mutated = org.mutate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var direction = Directions.getRandomScalar();
|
||||
var direction_c = direction[0];
|
||||
var direction_r = direction[1];
|
||||
var offset = (Math.floor(Math.random() * 3));
|
||||
var basemovement = this.birth_distance;
|
||||
var basemovement = this.anatomy.birth_distance;
|
||||
var new_c = this.c + (direction_c*basemovement) + (direction_c*offset);
|
||||
var new_r = this.r + (direction_r*basemovement) + (direction_r*offset);
|
||||
|
||||
// console.log(org.isClear(new_c, new_r, org.rotation, true))
|
||||
if (org.isClear(new_c, new_r, org.rotation, true) && org.isStraightPath(new_c, new_r, this.c, this.r, this)){
|
||||
org.c = new_c;
|
||||
org.r = new_r;
|
||||
this.env.addOrganism(org);
|
||||
org.updateGrid();
|
||||
if (mutated) {
|
||||
FossilRecord.addSpecies(org, this.species);
|
||||
}
|
||||
else {
|
||||
org.species.addPop();
|
||||
}
|
||||
}
|
||||
this.food_collected -= this.foodNeeded();
|
||||
|
||||
@@ -200,31 +129,31 @@ class Organism {
|
||||
// add cell
|
||||
// console.log("add cell")
|
||||
|
||||
var branch = this.cells[Math.floor(Math.random() * this.cells.length)];
|
||||
var branch = this.anatomy.getRandomCell();
|
||||
var state = CellStates.getRandomLivingType();//branch.state;
|
||||
var growth_direction = Neighbors.all[Math.floor(Math.random() * Neighbors.all.length)]
|
||||
var c = branch.loc_col+growth_direction[0];
|
||||
var r = branch.loc_row+growth_direction[1];
|
||||
if (this.canAddCellAt(c, r)){
|
||||
if (this.anatomy.canAddCellAt(c, r)){
|
||||
mutated = true;
|
||||
this.addRandomizedCell(state, c, r);
|
||||
this.anatomy.addRandomizedCell(state, c, r);
|
||||
}
|
||||
}
|
||||
else if (choice <= Hyperparams.addProb + Hyperparams.changeProb){
|
||||
// change cell
|
||||
var cell = this.cells[Math.floor(Math.random() * this.cells.length)];
|
||||
var cell = this.anatomy.getRandomCell();
|
||||
var state = CellStates.getRandomLivingType();
|
||||
// console.log("change cell", state)
|
||||
this.replaceCell(state, cell.loc_col, cell.loc_row);
|
||||
this.anatomy.replaceCell(state, cell.loc_col, cell.loc_row);
|
||||
mutated = true;
|
||||
}
|
||||
else if (choice <= Hyperparams.addProb + Hyperparams.changeProb + Hyperparams.removeProb){
|
||||
// remove cell
|
||||
// console.log("remove cell")
|
||||
|
||||
if(this.cells.length > 1) {
|
||||
var cell = this.cells[Math.floor(Math.random() * this.cells.length)];
|
||||
mutated = this.removeCell(cell.loc_col, cell.loc_row);
|
||||
if(this.anatomy.cells.length > 1) {
|
||||
var cell = this.anatomy.getRandomCell();
|
||||
mutated = this.anatomy.removeCell(cell.loc_col, cell.loc_row);
|
||||
}
|
||||
}
|
||||
return mutated;
|
||||
@@ -237,7 +166,7 @@ class Organism {
|
||||
var new_c = this.c + direction_c;
|
||||
var new_r = this.r + direction_r;
|
||||
if (this.isClear(new_c, new_r)) {
|
||||
for (var cell of this.cells) {
|
||||
for (var cell of this.anatomy.cells) {
|
||||
var real_c = this.c + cell.rotatedCol(this.rotation);
|
||||
var real_r = this.r + cell.rotatedRow(this.rotation);
|
||||
this.env.changeCell(real_c, real_r, CellStates.empty, null);
|
||||
@@ -258,7 +187,7 @@ class Organism {
|
||||
}
|
||||
var new_rotation = Directions.getRandomDirection();
|
||||
if(this.isClear(this.c, this.r, new_rotation)){
|
||||
for (var cell of this.cells) {
|
||||
for (var cell of this.anatomy.cells) {
|
||||
var real_c = this.c + cell.rotatedCol(this.rotation);
|
||||
var real_r = this.r + cell.rotatedRow(this.rotation);
|
||||
this.env.changeCell(real_c, real_r, CellStates.empty, null);
|
||||
@@ -277,7 +206,7 @@ class Organism {
|
||||
this.move_count = 0;
|
||||
}
|
||||
|
||||
// assumes either c1==c2 or r1==r2, returns true if there is a clear path from point a to b
|
||||
// assumes either c1==c2 or r1==r2, returns true if there is a clear path from point 1 to 2
|
||||
isStraightPath(c1, r1, c2, r2, parent){
|
||||
if (c1 == c2) {
|
||||
if (r1 > r2){
|
||||
@@ -314,11 +243,12 @@ class Organism {
|
||||
}
|
||||
|
||||
isClear(col, row, rotation=this.rotation, ignore_armor=false) {
|
||||
for(var loccell of this.cells) {
|
||||
for(var loccell of this.anatomy.cells) {
|
||||
var cell = this.getRealCell(loccell, col, row, rotation);
|
||||
if(cell==null) {
|
||||
if (cell==null) {
|
||||
return false;
|
||||
}
|
||||
// console.log(cell.owner == this)
|
||||
if (cell.owner==this || cell.state==CellStates.empty || (!Hyperparams.foodBlocksReproduction && cell.state==CellStates.food) || (ignore_armor && loccell.state==CellStates.armor && cell.state==CellStates.food)){
|
||||
continue;
|
||||
}
|
||||
@@ -335,16 +265,17 @@ class Organism {
|
||||
}
|
||||
|
||||
die() {
|
||||
for (var cell of this.cells) {
|
||||
for (var cell of this.anatomy.cells) {
|
||||
var real_c = this.c + cell.rotatedCol(this.rotation);
|
||||
var real_r = this.r + cell.rotatedRow(this.rotation);
|
||||
this.env.changeCell(real_c, real_r, CellStates.food, null);
|
||||
}
|
||||
this.species.decreasePop();
|
||||
this.living = false;
|
||||
}
|
||||
|
||||
updateGrid() {
|
||||
for (var cell of this.cells) {
|
||||
for (var cell of this.anatomy.cells) {
|
||||
var real_c = this.c + cell.rotatedCol(this.rotation);
|
||||
var real_r = this.r + cell.rotatedRow(this.rotation);
|
||||
this.env.changeCell(real_c, real_r, cell.state, cell);
|
||||
@@ -360,13 +291,13 @@ class Organism {
|
||||
if (this.food_collected >= this.foodNeeded()) {
|
||||
this.reproduce();
|
||||
}
|
||||
for (var cell of this.cells) {
|
||||
for (var cell of this.anatomy.cells) {
|
||||
cell.performFunction();
|
||||
if (!this.living)
|
||||
return this.living
|
||||
}
|
||||
|
||||
if (this.is_mover) {
|
||||
if (this.anatomy.is_mover) {
|
||||
this.move_count++;
|
||||
var changed_dir = false;
|
||||
if (this.ignore_brain_for == 0){
|
||||
|
||||
@@ -52,7 +52,7 @@ class Renderer {
|
||||
}
|
||||
|
||||
renderOrganism(org) {
|
||||
for(var org_cell of org.cells) {
|
||||
for(var org_cell of org.anatomy.cells) {
|
||||
var cell = org.getRealCell(org_cell);
|
||||
this.renderCell(cell);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ class Renderer {
|
||||
}
|
||||
|
||||
highlightOrganism(org) {
|
||||
for(var org_cell of org.cells) {
|
||||
for(var org_cell of org.anatomy.cells) {
|
||||
var cell = org.getRealCell(org_cell);
|
||||
this.cells_to_highlight.add(cell);
|
||||
}
|
||||
|
||||
49
src/Stats/FossilRecord.js
Normal file
49
src/Stats/FossilRecord.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const Species = require("./Species");
|
||||
|
||||
const FossilRecord = {
|
||||
init: function(){
|
||||
this.extant_species = [];
|
||||
this.extinct_species = [];
|
||||
|
||||
// if an organism has fewer than this cumulative pop, discard them
|
||||
this.discard_pop = 5;
|
||||
},
|
||||
|
||||
setEnv: function(env) {
|
||||
this.env = env;
|
||||
},
|
||||
|
||||
addSpecies: function(org, ancestor) {
|
||||
console.log("Adding Species")
|
||||
var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks)
|
||||
this.extant_species.push(new_species);
|
||||
org.species = new_species;
|
||||
return new_species;
|
||||
},
|
||||
|
||||
fossilize: function(species) {
|
||||
species.end_tick = this.env.total_ticks;
|
||||
for (i in this.extant_species) {
|
||||
var s = this.extant_species[i];
|
||||
if (s == species) {
|
||||
this.extant_species.splice(i, 1);
|
||||
if (species.cumulative_pop <= this.discard_pop) {
|
||||
return false;
|
||||
}
|
||||
this.extinct_species.push(s);
|
||||
console.log("Extant:", this.extant_species.length)
|
||||
console.log("Extinct:", this.extinct_species.length)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
clear_record: function() {
|
||||
this.species = [];
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
FossilRecord.init();
|
||||
|
||||
module.exports = FossilRecord;
|
||||
30
src/Stats/Species.js
Normal file
30
src/Stats/Species.js
Normal file
@@ -0,0 +1,30 @@
|
||||
class Species {
|
||||
constructor(anatomy, ancestor, start_tick) {
|
||||
this.anatomy = anatomy;
|
||||
this.ancestor = ancestor;
|
||||
this.population = 1;
|
||||
this.cumulative_pop = 1;
|
||||
this.start_tick = start_tick;
|
||||
this.end_tick = -1;
|
||||
this.color = '#asdfasdf';
|
||||
this.name = "crabuloid";
|
||||
this.extinct = false;
|
||||
}
|
||||
|
||||
addPop() {
|
||||
this.population++;
|
||||
this.cumulative_pop++;
|
||||
}
|
||||
|
||||
decreasePop() {
|
||||
this.population--;
|
||||
if (this.population <= 0) {
|
||||
this.extinct = true;
|
||||
console.log("Extinction");
|
||||
const FossilRecord = require("./FossilRecord");
|
||||
FossilRecord.fossilize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Species;
|
||||
Reference in New Issue
Block a user