diff --git a/F b/F
new file mode 100644
index 00000000..6a69f920
--- /dev/null
+++ b/F
@@ -0,0 +1 @@
+f
diff --git a/README.md b/README.md
index ee152a08..4e5265f6 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ Organism Cells are only found in organisms, and cannot exist on their own in the
- Killer - Red, harms organisms in directly adjacent cells (besides itself).
- Armor - Purple, negates the effects of killer cells.
- Eye - Light purple with a slit, allows the organism to see and move intelligently. See further description below.
+- Fin - Yellow, Allows creature to swim in water.
## Organisms
Organisms are structures of cells that eat food, reproduce, and die.
diff --git a/dist/css/style.css b/dist/css/style.css
index 1714871e..a08c3a99 100644
--- a/dist/css/style.css
+++ b/dist/css/style.css
@@ -172,6 +172,9 @@ button:active{
#clear-walls {
margin-top: 5px;
}
+#clear-water {
+ margin-top: 5px;
+}
#organism-options {
display: none;
}
diff --git a/dist/index.html b/dist/index.html
index 0166f539..26e226f6 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -23,8 +23,11 @@
+
-
+
+
+
Simulation Speed
@@ -78,11 +81,13 @@ Cell Types
+
+
Hover over each color to learn what it does. For a more in depth explanation of the simulation, view the
@@ -110,6 +115,7 @@
Cell Types
+
@@ -126,6 +132,7 @@
Cell Types
Organism Details
Cell count:
Move Range:
+
Is Aquatic:
Mutation Rate:
@@ -143,6 +150,10 @@
Edit Organism
+
+
+
+
@@ -156,6 +167,7 @@
Brain
+
@@ -269,6 +281,7 @@ Select a Challenge
+
diff --git a/src/Controllers/ControlModes.js b/src/Controllers/ControlModes.js
index 882e5001..e618ce94 100644
--- a/src/Controllers/ControlModes.js
+++ b/src/Controllers/ControlModes.js
@@ -6,7 +6,8 @@ const Modes = {
Select: 4,
Edit: 5,
Clone: 6,
- Drag: 7
+ Drag: 7,
+ WaterDrop: 8,
}
module.exports = Modes;
\ No newline at end of file
diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js
index 5ec9e548..d4e9fe69 100644
--- a/src/Controllers/ControlPanel.js
+++ b/src/Controllers/ControlPanel.js
@@ -288,6 +288,9 @@ class ControlPanel {
case "wall-drop":
self.setMode(Modes.WallDrop);
break;
+ case "water-drop":
+ self.setMode(Modes.WaterDrop);
+ break;
case "click-kill":
self.setMode(Modes.ClickKill);
break;
@@ -323,6 +326,11 @@ class ControlPanel {
if (confirm("Are you sure you want to clear all the walls?")) {
this.engine.env.clearWalls();
}
+ }.bind(this));
+ $('#clear-water').click( function() {
+ if (confirm("Are you sure you want to clear all the water?")) {
+ this.engine.env.clearWater();
+ }
}.bind(this));
$('#clear-editor').click( function() {
this.engine.organism_editor.clear();
diff --git a/src/Controllers/EditorController.js b/src/Controllers/EditorController.js
index f0c101e8..2d6f9c2b 100644
--- a/src/Controllers/EditorController.js
+++ b/src/Controllers/EditorController.js
@@ -44,10 +44,11 @@ class EditorController extends CanvasController{
}
else if (this.right_click)
this.env.removeCellFromOrg(this.mouse_c, this.mouse_r);
-
+
this.new_species = true;
this.setBrainPanelVisibility();
this.setMoveRangeVisibility();
+ this.setAquaticVisibility()
this.updateDetails();
}
@@ -68,6 +69,9 @@ class EditorController extends CanvasController{
case "mover":
self.edit_cell_type = CellStates.mover;
break;
+ case "fin":
+ self.edit_cell_type = CellStates.fin;
+ break;
case "killer":
self.edit_cell_type = CellStates.killer;
break;
@@ -93,9 +97,9 @@ class EditorController extends CanvasController{
$('#move-range-edit').change ( function() {
this.env.organism.move_range = parseInt($('#move-range-edit').val());
}.bind(this));
-
- $('#mutation-rate-edit').change ( function() {
- this.env.organism.mutability = parseInt($('#mutation-rate-edit').val());
+
+ $('#is-aquatic-edit').change(function() {
+ this.env.organism.is_aquatic = $('#is-aquatic-edit').is(":checked");
}.bind(this));
$('#observation-type-edit').change ( function() {
this.setBrainEditorValues($('#observation-type-edit').val());
@@ -127,9 +131,10 @@ class EditorController extends CanvasController{
$('.cell-count').text("Cell count: "+org.anatomy.cells.length);
$('#move-range').text("Move Range: "+org.move_range);
+ $('#is-aquatic').text("Is Aquatic: "+org.is_aquatic);
+
$('#mutation-rate').text("Mutation Rate: "+org.mutability);
-
- if (Hyperparams.useGlobalMutability) {
+ if (Hyperparams.useGlobalMutability) {
$('#mutation-rate').css('display', 'none');
}
else {
@@ -154,6 +159,10 @@ class EditorController extends CanvasController{
$('#move-range-edit').val(org.move_range);
}
+ if (this.setAquaticVisibility()){
+ $('#is-aquatic-edit').val(org.is_aquatic);
+ }
+
$('#mutation-rate-edit').val(org.mutability);
if (Hyperparams.useGlobalMutability) {
$('#mutation-rate-cont').css('display', 'none');
@@ -208,6 +217,20 @@ class EditorController extends CanvasController{
return false;
}
+ setAquaticVisibility() {
+ var org = this.env.organism;
+
+ if (org.anatomy.has_fins) {
+ $('#is-aquatic-cont').css('display', 'block');
+ $('#is-aquatic').css('display', 'block');
+ return true;
+ }
+ org.is_aquatic = false
+ $('#is-aquatic-cont').css('display', 'none');
+ $('#is-aquatic').css('display', 'none');
+ return false;
+ }
+
setBrainEditorValues(name) {
$('#observation-type-edit').val(name);
var reaction = this.env.organism.brain.decisions[name];
diff --git a/src/Controllers/EnvironmentController.js b/src/Controllers/EnvironmentController.js
index 73aa0fca..3ecef51a 100644
--- a/src/Controllers/EnvironmentController.js
+++ b/src/Controllers/EnvironmentController.js
@@ -99,6 +99,28 @@ class EnvironmentController extends CanvasController{
this.dropCellType(cell.col, cell.row, CellStates.empty, false);
}
break;
+ case Modes.WaterDrop:
+ if (left_click){
+ this.env.water_map[cell.col][cell.row] = true
+ for (var loc of Neighbors.allSelf){
+ var c=cell.col + loc[0];
+ var r=cell.row + loc[1];
+ this.env.water_map[c][r] = true
+ }
+
+ this.dropCellType(cell.col, cell.row, CellStates.water, true);
+
+ }
+ else if (right_click){
+ this.env.water_map[cell.col][cell.row] = false
+ for (var loc of Neighbors.allSelf){
+ var c=cell.col + loc[0];
+ var r=cell.row + loc[1];
+ this.env.water_map[c][r] = false
+ }
+ this.dropCellType(cell.col, cell.row, CellStates.empty, false);
+ }
+ break;
case Modes.ClickKill:
this.killNearOrganisms();
break;
diff --git a/src/Environments/OrganismEditor.js b/src/Environments/OrganismEditor.js
index b969774f..c5cb4b5b 100644
--- a/src/Environments/OrganismEditor.js
+++ b/src/Environments/OrganismEditor.js
@@ -59,6 +59,7 @@ class OrganismEditor extends Environment{
var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)
if (prev_cell != null) {
if (this.organism.anatomy.removeCell(loc_c, loc_r)) {
+
this.changeCell(c, r, CellStates.empty, null);
this.organism.species = new Species(this.organism.anatomy, null, 0);
}
diff --git a/src/Environments/WorldEnvironment.js b/src/Environments/WorldEnvironment.js
index da7bb404..846f9c92 100644
--- a/src/Environments/WorldEnvironment.js
+++ b/src/Environments/WorldEnvironment.js
@@ -12,11 +12,13 @@ class WorldEnvironment extends Environment{
super();
this.renderer = new Renderer('env-canvas', 'env', cell_size);
this.controller = new EnvironmentController(this, this.renderer.canvas);
- var grid_rows = Math.ceil(this.renderer.height / cell_size);
- var grid_cols = Math.ceil(this.renderer.width / cell_size);
- this.grid_map = new GridMap(grid_cols, grid_rows, cell_size);
+ this.grid_rows = Math.ceil(this.renderer.height / cell_size);
+ this.grid_cols = Math.ceil(this.renderer.width / cell_size);
+ this.grid_map = new GridMap(this.grid_cols, this.grid_rows, cell_size);
this.organisms = [];
this.walls = [];
+ this.water = [];
+ this.water_map = [];
this.total_mutability = 0;
this.auto_reset = true;
this.largest_cell_count = 0;
@@ -69,6 +71,17 @@ class WorldEnvironment extends Environment{
}
OriginOfLife() {
+
+ for (var c = 0; c < this.grid_cols; c++) {
+ if(this.water_map[c] == null){
+ this.water_map[c] = []
+ }
+ for (var r = 0; r < this.grid_rows; r++) {
+ this.water_map[c][r] = false
+
+ }
+ }
+
var center = this.grid_map.getCenter();
var org = new Organism(center[0], center[1], this);
org.anatomy.addDefaultCell(CellStates.mouth, 0, 0);
@@ -96,10 +109,19 @@ class WorldEnvironment extends Environment{
}
changeCell(c, r, state, owner) {
+ if(state == CellStates.empty){
+ if(this.water_map[c][r] == true){
+ state = CellStates.water
+ }
+ }
super.changeCell(c, r, state, owner);
this.renderer.addToRender(this.grid_map.cellAt(c, r));
if(state == CellStates.wall)
this.walls.push(this.grid_map.cellAt(c, r));
+ if(state == CellStates.water){
+ this.water.push(this.grid_map.cellAt(c, r));
+ this.water_map[c][r] = true
+ }
}
clearWalls() {
@@ -109,6 +131,15 @@ class WorldEnvironment extends Environment{
}
}
+
+ clearWater() {
+ for(var water of this.water){
+ this.water_map[water.col][water.row] = false
+ if (this.grid_map.cellAt(water.col, water.row).state == CellStates.water)
+ this.changeCell(water.col, water.row, CellStates.empty, null);
+ }
+ }
+
clearOrganisms() {
for (var org of this.organisms)
org.die();
@@ -123,7 +154,7 @@ class WorldEnvironment extends Environment{
var c=Math.floor(Math.random() * this.grid_map.cols);
var r=Math.floor(Math.random() * this.grid_map.rows);
- if (this.grid_map.cellAt(c, r).state == CellStates.empty){
+ if (this.grid_map.cellAt(c, r).state == CellStates.empty || this.grid_map.cellAt(c, r).state == CellStates.water){
this.changeCell(c, r, CellStates.food, null);
}
}
diff --git a/src/Organism/Anatomy.js b/src/Organism/Anatomy.js
index 8175024e..69932275 100644
--- a/src/Organism/Anatomy.js
+++ b/src/Organism/Anatomy.js
@@ -7,6 +7,7 @@ class Anatomy {
this.cells = [];
this.is_producer = false;
this.is_mover = false;
+ this.has_fins = false;
this.has_eyes = false;
this.birth_distance = 4;
}
@@ -77,6 +78,7 @@ class Anatomy {
checkTypeChange() {
this.is_producer = false;
this.is_mover = false;
+ this.has_fins = false;
this.has_eyes = false;
for (var cell of this.cells) {
if (cell.state == CellStates.producer)
@@ -85,6 +87,8 @@ class Anatomy {
this.is_mover = true;
if (cell.state == CellStates.eye)
this.has_eyes = true;
+ if (cell.state == CellStates.fin)
+ this.has_fins = true;
}
}
diff --git a/src/Organism/Cell/BodyCells/BodyCellFactory.js b/src/Organism/Cell/BodyCells/BodyCellFactory.js
index 577f609f..b841c7e8 100644
--- a/src/Organism/Cell/BodyCells/BodyCellFactory.js
+++ b/src/Organism/Cell/BodyCells/BodyCellFactory.js
@@ -1,6 +1,7 @@
const MouthCell = require("./MouthCell");
const ProducerCell = require("./ProducerCell");
const MoverCell = require("./MoverCell");
+const FinCell = require("./FinCell");
const KillerCell = require("./KillerCell");
const ArmorCell = require("./ArmorCell");
const EyeCell = require("./EyeCell");
@@ -13,6 +14,7 @@ const BodyCellFactory = {
type_map[CellStates.mouth.name] = MouthCell;
type_map[CellStates.producer.name] = ProducerCell;
type_map[CellStates.mover.name] = MoverCell;
+ type_map[CellStates.fin.name] = FinCell;
type_map[CellStates.killer.name] = KillerCell;
type_map[CellStates.armor.name] = ArmorCell;
type_map[CellStates.eye.name] = EyeCell;
diff --git a/src/Organism/Cell/BodyCells/FinCell.js b/src/Organism/Cell/BodyCells/FinCell.js
new file mode 100644
index 00000000..ef2420b7
--- /dev/null
+++ b/src/Organism/Cell/BodyCells/FinCell.js
@@ -0,0 +1,11 @@
+const CellStates = require("../CellStates");
+const BodyCell = require("./BodyCell");
+
+class FinCell extends BodyCell{
+ constructor(org, loc_col, loc_row){
+ super(CellStates.fin, org, loc_col, loc_row);
+ this.org.anatomy.has_fins = true;
+ }
+}
+
+module.exports = FinCell;
\ No newline at end of file
diff --git a/src/Organism/Cell/BodyCells/ProducerCell.js b/src/Organism/Cell/BodyCells/ProducerCell.js
index b6c4b3e4..9b306ba7 100644
--- a/src/Organism/Cell/BodyCells/ProducerCell.js
+++ b/src/Organism/Cell/BodyCells/ProducerCell.js
@@ -20,7 +20,7 @@ class ProducerCell extends BodyCell{
var loc_c=loc[0];
var loc_r=loc[1];
var cell = env.grid_map.cellAt(real_c+loc_c, real_r+loc_r);
- if (cell != null && cell.state == CellStates.empty){
+ if (cell != null && (cell.state == CellStates.empty || (cell.state == CellStates.water && this.org.anatomy.has_fins))){
env.changeCell(real_c+loc_c, real_r+loc_r, CellStates.food, null);
return;
}
diff --git a/src/Organism/Cell/CellStates.js b/src/Organism/Cell/CellStates.js
index 4a01aa76..a6764041 100644
--- a/src/Organism/Cell/CellStates.js
+++ b/src/Organism/Cell/CellStates.js
@@ -26,6 +26,13 @@ class Wall extends CellState {
super('wall');
}
}
+
+class Water extends CellState {
+ constructor() {
+ super('water');
+ }
+}
+
class Mouth extends CellState {
constructor() {
super('mouth');
@@ -41,6 +48,12 @@ class Mover extends CellState {
super('mover');
}
}
+
+class Fin extends CellState {
+ constructor() {
+ super('fin');
+ }
+}
class Killer extends CellState {
constructor() {
super('killer');
@@ -78,14 +91,16 @@ const CellStates = {
empty: new Empty(),
food: new Food(),
wall: new Wall(),
+ water: new Water(),
mouth: new Mouth(),
producer: new Producer(),
mover: new Mover(),
+ fin: new Fin(),
killer: new Killer(),
armor: new Armor(),
eye: new Eye(),
defineLists() {
- this.all = [this.empty, this.food, this.wall, this.mouth, this.producer, this.mover, this.killer, this.armor, this.eye]
+ this.all = [this.empty, this.food, this.wall, this.water, this.mouth, this.producer, this.mover, this.fin, this.killer, this.armor, this.eye]
this.living = [this.mouth, this.producer, this.mover, this.killer, this.armor, this.eye];
},
getRandomName: function() {
diff --git a/src/Organism/Organism.js b/src/Organism/Organism.js
index 672c3020..95ae12f8 100644
--- a/src/Organism/Organism.js
+++ b/src/Organism/Organism.js
@@ -20,6 +20,7 @@ class Organism {
this.can_rotate = Hyperparams.moversCanRotate;
this.move_count = 0;
this.move_range = 4;
+ this.is_aquatic = false;
this.ignore_brain_for = 0;
this.mutability = 5;
this.damage = 0;
@@ -31,6 +32,7 @@ class Organism {
inherit(parent) {
this.move_range = parent.move_range;
+ this.is_aquatic = parent.is_aquatic && parent.anatomy.has_fins;
this.mutability = parent.mutability;
this.species = parent.species;
// this.birth_distance = parent.birth_distance;
@@ -80,9 +82,21 @@ class Organism {
org.mutability = 1;
}
}
+
+ if(!org.anatomy.has_fins){
+ org.is_aquatic = false
+ }
+
+
var mutated = false;
if (Math.random() * 100 <= prob) {
- if (org.anatomy.is_mover && Math.random() * 100 <= 10) {
+ if (org.anatomy.has_fins && Math.random() * 100 <= 5) {
+ if(Math.random() * 100 < 60){
+ org.is_aquatic = true
+ }else{
+ org.is_aquatic = false
+ }
+ }else if (org.anatomy.is_mover && Math.random() * 100 <= 10) {
if (org.anatomy.has_eyes) {
org.brain.mutate();
}
@@ -234,7 +248,7 @@ class Organism {
}
isPassableCell(cell, parent){
- return cell != null && (cell.state == CellStates.empty || cell.owner == this || cell.owner == parent || cell.state == CellStates.food);
+ return cell != null && ((cell.state == CellStates.empty && !this.is_aquatic) || cell.owner == this || cell.owner == parent || (this.anatomy.has_fins && cell.state == CellStates.water) || cell.state == CellStates.food);
}
isClear(col, row, rotation=this.rotation, ignore_armor=false) {
@@ -243,8 +257,11 @@ class Organism {
if (cell==null) {
return false;
}
+
+ //console.log(this)
+
// 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)){
+ if (cell.owner==this || (this.anatomy.has_fins && cell.state == CellStates.water) || (cell.state == CellStates.empty && !this.is_aquatic) || (!Hyperparams.foodBlocksReproduction && cell.state==CellStates.food) || (ignore_armor && loccell.state==CellStates.armor && cell.state==CellStates.food)){
continue;
}
return false;
diff --git a/src/Organism/Perception/Brain.js b/src/Organism/Perception/Brain.js
index e52d8a31..19d88e48 100644
--- a/src/Organism/Perception/Brain.js
+++ b/src/Organism/Perception/Brain.js
@@ -24,9 +24,11 @@ class Brain {
this.decisions[CellStates.empty.name] = Decision.neutral;
this.decisions[CellStates.food.name] = Decision.chase;
this.decisions[CellStates.wall.name] = Decision.neutral;
+ this.decisions[CellStates.water.name] = Decision.neutral;
this.decisions[CellStates.mouth.name] = Decision.neutral;
this.decisions[CellStates.producer.name] = Decision.neutral;
this.decisions[CellStates.mover.name] = Decision.neutral;
+ this.decisions[CellStates.fin.name] = Decision.neutral;
this.decisions[CellStates.killer.name] = Decision.retreat;
this.decisions[CellStates.armor.name] = Decision.neutral;
this.decisions[CellStates.eye.name] = Decision.neutral;
@@ -37,6 +39,7 @@ class Brain {
this.decisions[CellStates.mouth.name] = Decision.getRandom();
this.decisions[CellStates.producer.name] = Decision.getRandom();
this.decisions[CellStates.mover.name] = Decision.getRandom();
+ this.decisions[CellStates.fin.name] = Decision.getRandom();
this.decisions[CellStates.armor.name] = Decision.getRandom();
this.decisions[CellStates.eye.name] = Decision.getRandom();
}
diff --git a/src/Rendering/ColorScheme.js b/src/Rendering/ColorScheme.js
index 30ce7f90..b61af99c 100644
--- a/src/Rendering/ColorScheme.js
+++ b/src/Rendering/ColorScheme.js
@@ -4,9 +4,11 @@ var color_scheme = {
"empty":"#0E1318",
"food":"#2F7AB7",
"wall":"gray",
+ "water":"#0a47a3",
"mouth":"#DEB14D",
"producer":"#15DE59",
"mover":"#60D4FF",
+ "fin":"#d9d029",
"killer":"#F82380",
"armor":"#7230DB",
"eye":"#B6C1EA",