Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions dist/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,29 @@ button:active{
height: 50px;
margin: 1px;
}
.cell-legend-type-living {
width: 50px;
height: 50px;
margin: 1px;
cursor: pointer;
}
/* p is white with a black outline */
.cell-legend-type-living p {
opacity: 0;
color: black;
font-size: 20px;
font-weight: bolder;
text-align: center;
transition: opacity 0.5s;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.cell-legend-type-living p:hover {
opacity: 1;
}
.cell-legend-hover {
border-color: black;
border: 5px;
Expand Down
18 changes: 7 additions & 11 deletions dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ <h3>Simulation Speed</h3>
<div class='left-half'>
<h3>The Life Engine</h3>
<p>The Life Engine is a virtual ecosystem that allows organisms to reproduce, compete, and evolve.</p>
<p>Each organism is made up of different colored cells. Hover over each color to learn what it does.</p>
<p>Each organism is made up of different colored cells. Hover over each color to learn what it does and change the cell cost by clicking it.</p>
<div id='cell-legend'>
<div class='cell-legend-type' id='mouth' title="Mouth: Eats adjacent food."></div>
<div class='cell-legend-type' id='producer' title="Producer: Produces adjacent food."></div>
<div class='cell-legend-type' id='mover' title="Mover: Allows for movement and rotation."></div>
<div class='cell-legend-type' id='killer' title="Killer: Harms organisms in adjacent cells."></div>
<div class='cell-legend-type' id='armor' title="Armor: Negates affects of killer cell."></div>
<div class='cell-legend-type' id='eye' title="Eye: Observes cells and decides movement."></div>
<div class='cell-legend-type-living' id='mouth' title="Mouth: Eats adjacent food."></div>
<div class='cell-legend-type-living' id='producer' title="Producer: Produces adjacent food."></div>
<div class='cell-legend-type-living' id='mover' title="Mover: Allows for movement and rotation."></div>
<div class='cell-legend-type-living' id='killer' title="Killer: Harms organisms in adjacent cells."></div>
<div class='cell-legend-type-living' id='armor' title="Armor: Negates affects of killer cell."></div>
<div class='cell-legend-type-living' id='eye' title="Eye: Observes cells and decides movement."></div>
<div class='cell-legend-type' id='food' title="Food: Not part of an organism. Once an organism has eaten enough food, it will reproduce."></div>
<div class='cell-legend-type' id='wall' title="Wall: Not part of an organism. Blocks movement and reproduction."></div>
</div><br>
Expand Down Expand Up @@ -209,10 +209,6 @@ <h2>Evolution Controls</h2>
<br>
<label for="food-drop-rate" title='Rate at which food is automatically generated and dropped in the world'>Auto food drop rate:</label>
<input type="number" id="food-drop-rate" value=0 max="1000">
<br>
<label for="extra-mover-cost" title='Additional food cost for movers to reproduce'>Extra mover reproduction cost:</label>
<input type="number" id="extra-mover-cost" value=0 max="1000" step="1">

</div>
<div class='right-half'>
<button id='reset-rules'>Reset all controls</button>
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 16 additions & 4 deletions src/Controllers/ControlPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,6 @@ class ControlPanel {
$('#food-drop-rate').change(function() {
Hyperparams.foodDropProb = $('#food-drop-rate').val();
});
$('#extra-mover-cost').change(function() {
Hyperparams.extraMoverFoodCost = parseInt($('#extra-mover-cost').val());
});

$('#evolved-mutation').change( function() {
if (this.checked) {
Expand Down Expand Up @@ -313,7 +310,6 @@ class ControlPanel {
$('#movers-produce').prop('checked', Hyperparams.moversCanProduce);
$('#food-blocks').prop('checked', Hyperparams.foodBlocksReproduction);
$('#food-drop-rate').val(Hyperparams.foodDropProb);
$('#extra-mover-cost').val(Hyperparams.extraMoverFoodCost);
$('#look-range').val(Hyperparams.lookRange);

if (!Hyperparams.useGlobalMutability) {
Expand Down Expand Up @@ -388,6 +384,22 @@ class ControlPanel {
this.engine.organism_editor.resetWithRandomOrgs(this.engine.env);
}.bind(this));

$('.cell-legend-type-living').click(function() {
if(Hyperparams.cost[this.id] != null) {
let val = parseFloat(prompt('Enter the reproduce cost(food count) of ' + this.id + ' cell:', Hyperparams.cost[this.id].toFixed(2)));

Hyperparams.cost[this.id] = isNaN(val) ? Hyperparams.cost[this.id] : Math.max(val, 0.001);

if(val != null) {//check and if not then add a p inside of .cell-legend-type-living with the cost of the cell or just set its text to the cost
if($(this).find('p').length > 0) {
$(this).find('p').text(Hyperparams.cost[this.id].toFixed(2));
} else {
$(this).append('<p>' + Hyperparams.cost[this.id].toFixed(2) + '</p>');
}
}
}
});

window.onbeforeunload = function (e) {
e = e || window.event;
let return_str = 'this will cause a confirmation on page close'
Expand Down
7 changes: 6 additions & 1 deletion src/Hyperparameters.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const Neighbors = require("./Grid/Neighbors");
const CellStates = require('./Organism/Cell/CellStates');

const Hyperparams = {
setDefaults: function() {
Expand All @@ -25,7 +26,11 @@ const Hyperparams = {

this.foodDropProb = 0;

this.extraMoverFoodCost = 0;
this.cost = {};

for (var cell of CellStates.living) {
this.cost[cell.name] = 1;
}
},

loadJsonObj(obj) {
Expand Down
10 changes: 10 additions & 0 deletions src/Organism/Anatomy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const CellStates = require("./Cell/CellStates");
const BodyCellFactory = require("./Cell/BodyCells/BodyCellFactory");
const Hyperparams = require("../Hyperparameters");

class Anatomy {
constructor(owner) {
Expand All @@ -9,6 +10,7 @@ class Anatomy {
this.is_mover = false;
this.has_eyes = false;
this.birth_distance = 4;
this.total_cost = 0;
}

canAddCellAt(c, r) {
Expand All @@ -23,6 +25,7 @@ class Anatomy {
addDefaultCell(state, c, r) {
var new_cell = BodyCellFactory.createDefault(this.owner, state, c, r);
this.cells.push(new_cell);
this.total_cost += Hyperparams.cost[state.name];
return new_cell;
}

Expand All @@ -32,12 +35,14 @@ class Anatomy {
}
var new_cell = BodyCellFactory.createRandom(this.owner, state, c, r);
this.cells.push(new_cell);
this.total_cost += Hyperparams.cost[state.name];
return new_cell;
}

addInheritCell(parent_cell) {
var new_cell = BodyCellFactory.createInherited(this.owner, parent_cell);
this.cells.push(new_cell);
this.total_cost += Hyperparams.cost[new_cell.state.name];
return new_cell;
}

Expand All @@ -58,6 +63,7 @@ class Anatomy {
var cell = this.cells[i];
if (cell.loc_col == c && cell.loc_row == r){
this.cells.splice(i, 1);
this.total_cost -= Hyperparams.cost[cell.state.name];
break;
}
}
Expand Down Expand Up @@ -107,6 +113,10 @@ class Anatomy {

return neighbors;
}

getTotalCost() {
return this.total_cost;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Massive performance difference. Now It has almost no effect on performance!

}
}

module.exports = Anatomy;
2 changes: 1 addition & 1 deletion src/Organism/Cell/BodyCells/MouthCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MouthCell extends BodyCell{
return;
if (n_cell.state == CellStates.food){
env.changeCell(n_cell.col, n_cell.row, CellStates.empty, null);
this.org.food_collected++;
this.org.food_collected += (n_cell.cell_owner && n_cell.cell_owner.food_value) ? n_cell.food_value : 1;
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/Organism/Organism.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Organism {

// amount of food required before it can reproduce
foodNeeded() {
return this.anatomy.is_mover ? this.anatomy.cells.length + Hyperparams.extraMoverFoodCost : this.anatomy.cells.length;
return this.anatomy.getTotalCost();
}

lifespan() {
Expand Down Expand Up @@ -261,7 +261,11 @@ class Organism {
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);
if(Hyperparams.cost[cell.state.name] > 0.001) {
this.env.changeCell(real_c, real_r, CellStates.food, {food_value: Hyperparams.cost[cell.state.name]});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMPORTANT BUG FIX: For example, when the cost of a cell is 0.35 (below 1), the organism spends 0.35 to reproduce that cell, but when that cell dies, it gives 1 food at position. This means 0.65 food that exist out of nothing in the system. To correct this gap, the food cell was given a food_value that was equal to the cost of the cell.

}else{
this.env.changeCell(real_c, real_r, CellStates.empty, null);
}
}
this.species.decreasePop();
this.living = false;
Expand Down
1 change: 1 addition & 0 deletions src/Rendering/ColorScheme.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ColorScheme {
for (var cell_type in color_scheme) {
$('#'+cell_type+'.cell-type ').css('background-color', color_scheme[cell_type]);
$('#'+cell_type+'.cell-legend-type').css('background-color', color_scheme[cell_type]);
$('#'+cell_type+'.cell-legend-type-living').css('background-color', color_scheme[cell_type]);

}
this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid);
Expand Down