From 869cc85d049268f99cf9c206e882ee997d7d86a3 Mon Sep 17 00:00:00 2001 From: Chris Gallegos Date: Sun, 21 Nov 2021 01:36:20 -0800 Subject: [PATCH 1/5] Randomized Creature Generation Adds a random organism generator that is accessible through the editor control panel. This generator gives the user to generate an entire world of random organisms for selection to act upon. --- dist/css/style.css | 3 + dist/index.html | 19 ++++++ src/Controllers/ControlModes.js | 3 +- src/Controllers/ControlPanel.js | 53 ++++++++++++---- src/Controllers/EditorController.js | 6 ++ src/Controllers/EnvironmentController.js | 36 ++++++----- src/Environments/OrganismEditor.js | 33 ++++++++++ src/Environments/WorldEnvironment.js | 6 +- src/Organism/Anatomy.js | 16 +++++ src/Organism/Cell/CellStates.js | 1 + src/Organism/Perception/Brain.js | 2 + src/Organism/RandomOrganismGenerator.js | 77 ++++++++++++++++++++++++ 12 files changed, 227 insertions(+), 28 deletions(-) create mode 100644 src/Organism/RandomOrganismGenerator.js diff --git a/dist/css/style.css b/dist/css/style.css index f98f464..86af6b0 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -169,6 +169,9 @@ button:hover{ .edit-mode-btn#drag-view { background-color: #81d2c7; } +.randomize-button { + margin-top: 5px; +} #clear-walls { margin-top: 5px; } diff --git a/dist/index.html b/dist/index.html index f833752..bd57ef2 100644 --- a/dist/index.html +++ b/dist/index.html @@ -100,6 +100,7 @@
+
@@ -169,6 +170,24 @@
+
diff --git a/src/Controllers/ControlModes.js b/src/Controllers/ControlModes.js index 882e500..97ecfa2 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, + Randomize: 8, } module.exports = Modes; \ No newline at end of file diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index ab5eaa5..7d92c53 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -1,6 +1,7 @@ const Hyperparams = require("../Hyperparameters"); const Modes = require("./ControlModes"); const StatsPanel = require("../Stats/StatsPanel"); +const RandomOrganismGenerator = require("../Organism/RandomOrganismGenerator") class ControlPanel { constructor(engine) { @@ -21,7 +22,7 @@ class ControlPanel { this.stats_panel = new StatsPanel(this.engine.env); this.headless_opacity = 1; this.opacity_change_rate = -0.8; - this.paused=false; + //this.paused=false; } defineMinMaxControls(){ @@ -84,17 +85,12 @@ class ControlPanel { } $('#fps').text("Target FPS: "+this.fps); }.bind(this); + $('.pause-button').click(function() { - $('.pause-button').find("i").toggleClass("fa fa-pause"); - $('.pause-button').find("i").toggleClass("fa fa-play"); - this.paused = !this.paused; - if (this.engine.running) { - this.engine.stop(); - } - else if (!this.engine.running){ - this.engine.start(this.fps); - } + // toggle pause + this.setPaused(this.engine.running); }.bind(this)); + $('.headless').click(function() { $('.headless').find("i").toggleClass("fa fa-eye"); $('.headless').find("i").toggleClass("fa fa-eye-slash"); @@ -263,6 +259,9 @@ class ControlPanel { self.setMode(Modes.Edit); self.editor_controller.setEditorPanel(); break; + case "randomize": + self.setMode(Modes.Randomize); + self.editor_controller.setRandomizePanel(); case "drop-org": self.setMode(Modes.Clone); self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg(); @@ -298,6 +297,24 @@ class ControlPanel { this.engine.organism_editor.clear(); this.editor_controller.setEditorPanel(); }.bind(this)); + document.getElementById("random-width").addEventListener('input', function() { + var width = 2 * this.value + 1; + $('#random-width-display').text(width); + RandomOrganismGenerator.organismLayers = this.value; + }); + document.getElementById("cell-spawn-chance").addEventListener("input", function() { + var value = parseFloat(this.value); + $('#spawn-chance-display').text((value * 100).toFixed(1) + "%"); + RandomOrganismGenerator.cellSpawnChance = value; + }); + $('#generate-random').click( function() { + this.engine.organism_editor.createRandom(); + }.bind(this)); + + $('#create-random-world').click( function() { + this.setPaused(true); + this.engine.organism_editor.createRandomWorld(this.engine.env); + }.bind(this)); } defineChallenges() { @@ -307,6 +324,20 @@ class ControlPanel { }); } + setPaused(paused) { + + if (paused) { + $('.pause-button').find("i").removeClass("fa-pause"); + $('.pause-button').find("i").addClass("fa-play"); + this.engine.stop(); + } + else if (!paused) { + $('.pause-button').find("i").addClass("fa-pause"); + $('.pause-button').find("i").removeClass("fa-play"); + this.engine.start(this.fps); + } + } + setMode(mode) { this.env_controller.mode = mode; this.editor_controller.mode = mode; @@ -325,7 +356,7 @@ class ControlPanel { } updateHeadlessIcon(delta_time) { - if (this.paused) + if (this.engine.running) return; var op = this.headless_opacity + (this.opacity_change_rate*delta_time/1000); if (op <= 0.4){ diff --git a/src/Controllers/EditorController.js b/src/Controllers/EditorController.js index e7c2152..2a47afa 100644 --- a/src/Controllers/EditorController.js +++ b/src/Controllers/EditorController.js @@ -108,6 +108,7 @@ class EditorController extends CanvasController{ clearDetailsPanel() { $('#organism-details').css('display', 'none'); $('#edit-organism-details').css('display', 'none'); + $('#randomize-organism-details').css('display', 'none'); } setDetailsPanel() { @@ -193,6 +194,11 @@ class EditorController extends CanvasController{ var reaction = this.env.organism.brain.decisions[name]; $('#reaction-edit').val(reaction); } + + setRandomizePanel() { + this.clearDetailsPanel(); + $('#randomize-organism-details').css('display', 'block'); + } } module.exports = EditorController; diff --git a/src/Controllers/EnvironmentController.js b/src/Controllers/EnvironmentController.js index 451d2a9..cf0c644 100644 --- a/src/Controllers/EnvironmentController.js +++ b/src/Controllers/EnvironmentController.js @@ -122,21 +122,7 @@ 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.add_new_species){ - FossilRecord.addSpeciesObj(new_org.species); - new_org.species.start_tick = this.env.total_ticks; - this.add_new_species = false; - new_org.species.population = 0; - } - else if (this.org_to_clone.species.extinct){ - FossilRecord.resurrect(this.org_to_clone.species); - } - - if (new_org.isClear(this.mouse_c, this.mouse_r)){ - this.env.addOrganism(new_org); - new_org.species.addPop(); - } + this.dropOrganism(this.org_to_clone, this.mouse_c, this.mouse_r); } break; case Modes.Drag: @@ -151,6 +137,26 @@ class EnvironmentController extends CanvasController{ } } + dropOrganism(organism, col, row) { + + // close the organism and drop it in the world + var new_org = new Organism(col, row, this.env, organism); + if (this.add_new_species){ + FossilRecord.addSpeciesObj(new_org.species); + new_org.species.start_tick = this.env.total_ticks; + this.add_new_species = false; + new_org.species.population = 0; + } + else if (this.org_to_clone.species.extinct){ + FossilRecord.resurrect(this.org_to_clone.species); + } + + if (new_org.isClear(this.mouse_c, this.mouse_r)){ + this.env.addOrganism(new_org); + new_org.species.addPop(); + } + } + dropCellType(col, row, state, killBlocking=false) { for (var loc of Neighbors.allSelf){ var c=col + loc[0]; diff --git a/src/Environments/OrganismEditor.js b/src/Environments/OrganismEditor.js index b969774..c9d48e1 100644 --- a/src/Environments/OrganismEditor.js +++ b/src/Environments/OrganismEditor.js @@ -5,6 +5,7 @@ const Renderer = require('../Rendering/Renderer'); const CellStates = require('../Organism/Cell/CellStates'); const EditorController = require("../Controllers/EditorController"); const Species = require('../Stats/Species'); +const RandomOrganismGenerator = require('../Organism/RandomOrganismGenerator') class OrganismEditor extends Environment{ constructor() { @@ -87,6 +88,38 @@ class OrganismEditor extends Environment{ this.organism.updateGrid(); this.organism.species = new Species(this.organism.anatomy, null, 0); } + + createRandom() { + + this.grid_map.fillGrid(CellStates.empty); + + this.organism = RandomOrganismGenerator.generate(this); + this.organism.updateGrid(); + this.organism.species = new Species(this.organism.anatomy, null, 0); + } + + createRandomWorld(worldEnvironment) { + + worldEnvironment.clear(); + + var numOrganismCols = Math.floor(worldEnvironment.grid_map.cols / this.grid_map.cols); + var numOrganismRows = Math.floor(worldEnvironment.grid_map.rows / this.grid_map.rows); + var center = this.grid_map.getCenter(); + + for (var x = 0; x < numOrganismCols; x++) { + for (var y = 0; y < numOrganismRows; y++) { + + var newOrganism = RandomOrganismGenerator.generate(this); + //newOrganism.updateGrid(); + newOrganism.species = new Species(newOrganism.anatomy, null, 0); + + var col = x * this.grid_map.cols + center[0]; + var row = y * this.grid_map.rows + center[1]; + worldEnvironment.controller.add_new_species = true; + worldEnvironment.controller.dropOrganism(newOrganism, col, row); + } + } + } } module.exports = OrganismEditor; \ No newline at end of file diff --git a/src/Environments/WorldEnvironment.js b/src/Environments/WorldEnvironment.js index da7bb40..1470b0e 100644 --- a/src/Environments/WorldEnvironment.js +++ b/src/Environments/WorldEnvironment.js @@ -131,13 +131,17 @@ class WorldEnvironment extends Environment{ } reset() { + this.clear(); + this.OriginOfLife(); + } + + clear() { this.organisms = []; this.grid_map.fillGrid(CellStates.empty); this.renderer.renderFullGrid(this.grid_map.grid); this.total_mutability = 0; this.total_ticks = 0; FossilRecord.clear_record(); - this.OriginOfLife(); } resizeGridColRow(cell_size, cols, rows) { diff --git a/src/Organism/Anatomy.js b/src/Organism/Anatomy.js index 8175024..b1c3cb6 100644 --- a/src/Organism/Anatomy.js +++ b/src/Organism/Anatomy.js @@ -91,6 +91,22 @@ class Anatomy { getRandomCell() { return this.cells[Math.floor(Math.random() * this.cells.length)]; } + + getNeighborsOfCell(col, row) { + + var neighbors = []; + + for (var x = -1; x <= 1; x++) { + for (var y = -1; y <= 1; y++) { + + var neighbor = this.getLocalCell(col + x, row + y); + if (neighbor) + neighbors.push(neighbor) + } + } + + return neighbors; + } } module.exports = Anatomy; \ No newline at end of file diff --git a/src/Organism/Cell/CellStates.js b/src/Organism/Cell/CellStates.js index 4a01aa7..9bf54f8 100644 --- a/src/Organism/Cell/CellStates.js +++ b/src/Organism/Cell/CellStates.js @@ -95,6 +95,7 @@ const CellStates = { return this.living[Math.floor(Math.random() * this.living.length)]; } } + CellStates.defineLists(); module.exports = CellStates; diff --git a/src/Organism/Perception/Brain.js b/src/Organism/Perception/Brain.js index e52d8a3..6aba956 100644 --- a/src/Organism/Perception/Brain.js +++ b/src/Organism/Perception/Brain.js @@ -79,4 +79,6 @@ class Brain { } } +Brain.Decision = Decision; + module.exports = Brain; \ No newline at end of file diff --git a/src/Organism/RandomOrganismGenerator.js b/src/Organism/RandomOrganismGenerator.js new file mode 100644 index 0000000..3379e6f --- /dev/null +++ b/src/Organism/RandomOrganismGenerator.js @@ -0,0 +1,77 @@ +const CellStates = require("./Cell/CellStates"); +const Organism = require("./Organism"); +const Brain = require("./Perception/Brain") + +class RandomOrganismGenerator { + + static generate(env) { + + var center = env.grid_map.getCenter(); + var organism = new Organism(center[0], center[1], env, null); + organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0); + + var outermostLayer = RandomOrganismGenerator.organismLayers; + var x, y; + + // iterate from center to edge of organism + // layer 0 is the central cell of the organism + for (var layer = 1; layer <= outermostLayer; layer++) { + + var someCellSpawned = false; + var spawnChance = RandomOrganismGenerator.cellSpawnChance * 1 - ((layer - 1) / outermostLayer); + + // top + y = -layer; + for (x = -layer; x <= layer; x++) + someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); + + // bottom + y = layer; + for (x = -layer; x <= layer; x++) + someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); + + // left + x = -layer; + for (y = -layer + 1; y <= layer - 1; y++) + someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); + + // right + x = layer; + for (y = -layer + 1; y < layer - 1; y++) + someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); + + if (!someCellSpawned) + break; + } + + // randomize the organism's brain + var decisions = organism.brain.decisions; + decisions[CellStates.empty.name] = Brain.Decision.getRandom(); + decisions[CellStates.food.name] = Brain.Decision.getRandom(); + decisions[CellStates.wall.name] = Brain.Decision.getRandom(); + decisions[CellStates.mouth.name] = Brain.Decision.getRandom(); + decisions[CellStates.producer.name] = Brain.Decision.getRandom(); + decisions[CellStates.mover.name] = Brain.Decision.getRandom(); + decisions[CellStates.killer.name] = Brain.Decision.getRandom(); + decisions[CellStates.armor.name] = Brain.Decision.getRandom(); + decisions[CellStates.eye.name] = Brain.Decision.getRandom(); + + return organism; + } + + static trySpawnCell(organism, x, y, spawnChance) { + + var neighbors = organism.anatomy.getNeighborsOfCell(x, y); + if (neighbors.length && Math.random() < spawnChance) { + organism.anatomy.addRandomizedCell(CellStates.getRandomLivingType(), x, y); + return true; + } + return false; + } + +} + +RandomOrganismGenerator.organismLayers = 2; +RandomOrganismGenerator.cellSpawnChance = 0.75; + +module.exports = RandomOrganismGenerator; \ No newline at end of file From 6abb82bcdaf1682d6cbe698b12990a0716e30656 Mon Sep 17 00:00:00 2001 From: Chris Gallegos Date: Sun, 21 Nov 2021 02:12:39 -0800 Subject: [PATCH 2/5] fix setPaused function --- src/Controllers/ControlPanel.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index 7d92c53..2174bf8 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -90,7 +90,7 @@ class ControlPanel { // toggle pause this.setPaused(this.engine.running); }.bind(this)); - + $('.headless').click(function() { $('.headless').find("i").toggleClass("fa fa-eye"); $('.headless').find("i").toggleClass("fa fa-eye-slash"); @@ -327,14 +327,18 @@ class ControlPanel { setPaused(paused) { if (paused) { + $('.pause-button').find("i").removeClass("fa-pause"); $('.pause-button').find("i").addClass("fa-play"); - this.engine.stop(); + if (this.engine.running) + this.engine.stop(); } else if (!paused) { + $('.pause-button').find("i").addClass("fa-pause"); $('.pause-button').find("i").removeClass("fa-play"); - this.engine.start(this.fps); + if (!this.engine.running) + this.engine.start(this.fps); } } From 0bdea0843cbf81d08e6188ce28d3180cdefd1d16 Mon Sep 17 00:00:00 2001 From: Chris Gallegos Date: Wed, 24 Nov 2021 00:55:59 -0800 Subject: [PATCH 3/5] Tabs to spaces --- src/Organism/RandomOrganismGenerator.js | 100 ++++++++++++------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/Organism/RandomOrganismGenerator.js b/src/Organism/RandomOrganismGenerator.js index 3379e6f..da945af 100644 --- a/src/Organism/RandomOrganismGenerator.js +++ b/src/Organism/RandomOrganismGenerator.js @@ -4,70 +4,70 @@ const Brain = require("./Perception/Brain") class RandomOrganismGenerator { - static generate(env) { + static generate(env) { - var center = env.grid_map.getCenter(); - var organism = new Organism(center[0], center[1], env, null); - organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0); + var center = env.grid_map.getCenter(); + var organism = new Organism(center[0], center[1], env, null); + organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0); - var outermostLayer = RandomOrganismGenerator.organismLayers; - var x, y; + var outermostLayer = RandomOrganismGenerator.organismLayers; + var x, y; - // iterate from center to edge of organism - // layer 0 is the central cell of the organism - for (var layer = 1; layer <= outermostLayer; layer++) { + // iterate from center to edge of organism + // layer 0 is the central cell of the organism + for (var layer = 1; layer <= outermostLayer; layer++) { - var someCellSpawned = false; - var spawnChance = RandomOrganismGenerator.cellSpawnChance * 1 - ((layer - 1) / outermostLayer); + var someCellSpawned = false; + var spawnChance = RandomOrganismGenerator.cellSpawnChance * 1 - ((layer - 1) / outermostLayer); - // top - y = -layer; - for (x = -layer; x <= layer; x++) - someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); + // top + y = -layer; + for (x = -layer; x <= layer; x++) + someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); - // bottom - y = layer; - for (x = -layer; x <= layer; x++) - someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); + // bottom + y = layer; + for (x = -layer; x <= layer; x++) + someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); - // left - x = -layer; - for (y = -layer + 1; y <= layer - 1; y++) - someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); + // left + x = -layer; + for (y = -layer + 1; y <= layer - 1; y++) + someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); - // right - x = layer; - for (y = -layer + 1; y < layer - 1; y++) - someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); + // right + x = layer; + for (y = -layer + 1; y < layer - 1; y++) + someCellSpawned = RandomOrganismGenerator.trySpawnCell(organism, x, y, spawnChance); - if (!someCellSpawned) - break; - } + if (!someCellSpawned) + break; + } - // randomize the organism's brain - var decisions = organism.brain.decisions; - decisions[CellStates.empty.name] = Brain.Decision.getRandom(); - decisions[CellStates.food.name] = Brain.Decision.getRandom(); - decisions[CellStates.wall.name] = Brain.Decision.getRandom(); - decisions[CellStates.mouth.name] = Brain.Decision.getRandom(); + // randomize the organism's brain + var decisions = organism.brain.decisions; + decisions[CellStates.empty.name] = Brain.Decision.getRandom(); + decisions[CellStates.food.name] = Brain.Decision.getRandom(); + decisions[CellStates.wall.name] = Brain.Decision.getRandom(); + decisions[CellStates.mouth.name] = Brain.Decision.getRandom(); decisions[CellStates.producer.name] = Brain.Decision.getRandom(); - decisions[CellStates.mover.name] = Brain.Decision.getRandom(); - decisions[CellStates.killer.name] = Brain.Decision.getRandom(); - decisions[CellStates.armor.name] = Brain.Decision.getRandom(); - decisions[CellStates.eye.name] = Brain.Decision.getRandom(); + decisions[CellStates.mover.name] = Brain.Decision.getRandom(); + decisions[CellStates.killer.name] = Brain.Decision.getRandom(); + decisions[CellStates.armor.name] = Brain.Decision.getRandom(); + decisions[CellStates.eye.name] = Brain.Decision.getRandom(); - return organism; - } + return organism; + } - static trySpawnCell(organism, x, y, spawnChance) { + static trySpawnCell(organism, x, y, spawnChance) { - var neighbors = organism.anatomy.getNeighborsOfCell(x, y); - if (neighbors.length && Math.random() < spawnChance) { - organism.anatomy.addRandomizedCell(CellStates.getRandomLivingType(), x, y); - return true; - } - return false; - } + var neighbors = organism.anatomy.getNeighborsOfCell(x, y); + if (neighbors.length && Math.random() < spawnChance) { + organism.anatomy.addRandomizedCell(CellStates.getRandomLivingType(), x, y); + return true; + } + return false; + } } From d6ce0cdcd8f831e1904247485eff4b65ca5c1ea6 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Mon, 20 Dec 2021 18:42:49 -0600 Subject: [PATCH 4/5] cleaned random creature generation --- Changelog.md | 22 ++++++--- dist/css/style.css | 7 +-- dist/index.html | 62 +++++------------------- src/Controllers/ControlModes.js | 1 - src/Controllers/ControlPanel.js | 45 +++++------------ src/Controllers/EnvironmentController.js | 23 +++++---- src/Environments/OrganismEditor.js | 31 +++++------- src/Environments/WorldEnvironment.js | 23 +++------ src/Organism/Organism.js | 2 +- src/Organism/Perception/Brain.js | 6 ++- src/Organism/RandomOrganismGenerator.js | 13 +---- src/Stats/Charts/ChartController.js | 41 ++++++++++------ src/Stats/FossilRecord.js | 3 +- src/WorldConfig.js | 1 - 14 files changed, 110 insertions(+), 170 deletions(-) diff --git a/Changelog.md b/Changelog.md index 844c04a..c6df355 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,23 +3,29 @@ ## 1.0.2 (current development) ### UI Enhancements: -- New tab for world controls - - Relocated grid controls, auto reset to this tab +- New tab "World Controls" + - Relocated grid controls and auto reset to this tab - Button to generate random walls with perlin noise - - Options for starting state, including simple producer and empty state - - Option to not clear walls when resetting + - Button to reset the environment with many randomly generated organisms + - Option to not clear walls on reset - Option to pause on total extinction -- Combined `Movers can rotate` and `Offspring rotate` simulation controls into `Rotation enabled` -- Can now drag view while rendering is off +- "Simulation controls" tab renamed to "Evolution Controls" +- Button to save/load Evolution Controls in a `.json` file +- Button to randomize the organism in the editor window +- Can now use drag view tool while rendering is off +- Reorganized "About" tab and left panel, embedded explanation video ### Simulation Enhancements: -- +- New evolution control `Extra Mover Reproduction Cost`, which adds additional food cost for movers to reproduce +- Combined `Movers can rotate` and `Offspring rotate` evolution controls into `Rotation enabled` +- Fully max out simulation speed when slider is all the way to the right ### Bug Fixes: - Armor is no longer ignored when checking for clear reproduction space +- Chart data is now properly loaded/discarded when paused -Thanks to contributors: +Thanks to contributors: @Chrispykins @M4YX0R ## 1.0.1 (12/4/2021) diff --git a/dist/css/style.css b/dist/css/style.css index 0a1747d..5c7d20c 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -178,9 +178,6 @@ button:active{ .edit-mode-btn.selected { background-color: #81d2c7; } -.randomize-button { - margin-top: 5px; -} #clear-walls { margin-top: 5px; } @@ -278,4 +275,8 @@ button:active{ margin: auto; margin-bottom: 0; padding-bottom: 0; +} + +#reset-with-editor-org{ + margin-top: 5px; } \ No newline at end of file diff --git a/dist/index.html b/dist/index.html index 829704c..d2fe274 100644 --- a/dist/index.html +++ b/dist/index.html @@ -42,9 +42,8 @@

About

Editor

World Controls

-

Simulation Controls

+

Evolution Controls

Statistics

-
@@ -79,7 +78,6 @@ -
@@ -97,6 +95,8 @@
+ +
@@ -126,7 +126,7 @@ -
+

Brain

@@ -151,25 +151,8 @@

Move Away From: killer

- - + +
@@ -185,23 +168,20 @@
-

Reset Options

- -

Auto reset count:


+ + +
+


@@ -211,7 +191,7 @@
-

Simulation Controls

+

Evolution Controls


@@ -255,8 +235,8 @@
- - + +
@@ -283,22 +263,6 @@
-
-
-

Challenges

- - - - - - -
-
-

Select a Challenge

-
-

Challenge yourself to create interesting ecosystems and organisms. There is no formal way to win or lose, its just for fun!

-
-
diff --git a/src/Controllers/ControlModes.js b/src/Controllers/ControlModes.js index 97ecfa2..3213e4e 100644 --- a/src/Controllers/ControlModes.js +++ b/src/Controllers/ControlModes.js @@ -7,7 +7,6 @@ const Modes = { Edit: 5, Clone: 6, Drag: 7, - Randomize: 8, } module.exports = Modes; \ No newline at end of file diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index fc86ce6..37f0aff 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -14,7 +14,6 @@ class ControlPanel { this.defineHyperparameterControls(); this.defineWorldControls(); this.defineModeControls(); - this.defineChallenges(); this.fps = engine.fps; this.organism_record=0; this.env_controller = this.engine.env.controller; @@ -198,11 +197,15 @@ class ControlPanel { }); $('#clear-walls-reset').change(function() { WorldConfig.clear_walls_on_reset = this.checked; - }) - - $('#start-state').change ( function() { - WorldConfig.start_state = $("#start-state").val(); - }.bind(this)); + }); + $('#reset-with-editor-org').click( () => { + let env = this.engine.env; + if (!env.reset(true, false)) return; + let center = env.grid_map.getCenter(); + let org = this.editor_controller.env.getCopyOfOrg(); + this.env_controller.add_new_species = true; + this.env_controller.dropOrganism(org, center[0], center[1]) + }); } defineHyperparameterControls() { @@ -226,7 +229,6 @@ class ControlPanel { Hyperparams.foodDropProb = $('#food-drop-rate').val(); }); $('#extra-mover-cost').change(function() { - console.log(parseInt($('#extra-mover-cost').val())) Hyperparams.extraMoverFoodCost = parseInt($('#extra-mover-cost').val()); }); @@ -346,9 +348,6 @@ class ControlPanel { case "edit": self.setMode(Modes.Edit); break; - case "randomize": - self.setMode(Modes.Randomize); - self.editor_controller.setRandomizePanel(); case "drop-org": self.setMode(Modes.Clone); break; @@ -358,7 +357,6 @@ class ControlPanel { $('.edit-mode-btn').removeClass('selected'); $('.'+this.id).addClass('selected'); }); - $('.reset-view').click( function(){ this.env_controller.resetView(); }.bind(this)); @@ -382,25 +380,13 @@ class ControlPanel { this.engine.organism_editor.clear(); this.editor_controller.setEditorPanel(); }.bind(this)); - document.getElementById("random-width").addEventListener('input', function() { - var width = 2 * this.value + 1; - $('#random-width-display').text(width); - RandomOrganismGenerator.organismLayers = this.value; - }); - document.getElementById("cell-spawn-chance").addEventListener("input", function() { - var value = parseFloat(this.value); - $('#spawn-chance-display').text((value * 100).toFixed(1) + "%"); - RandomOrganismGenerator.cellSpawnChance = value; - }); $('#generate-random').click( function() { this.engine.organism_editor.createRandom(); + this.editor_controller.refreshDetailsPanel(); }.bind(this)); - - $('#create-random-world').click( function() { - this.setPaused(true); - this.engine.organism_editor.createRandomWorld(this.engine.env); + $('.reset-random').click( function() { + this.engine.organism_editor.resetWithRandomOrgs(this.engine.env); }.bind(this)); - }.bind(this)) window.onbeforeunload = function (e) { e = e || window.event; @@ -412,13 +398,6 @@ class ControlPanel { }; } - defineChallenges() { - $('.challenge-btn').click(function() { - $('#challenge-title').text($(this).text()); - $('#challenge-description').text($(this).val()); - }); - } - setPaused(paused) { if (paused) { diff --git a/src/Controllers/EnvironmentController.js b/src/Controllers/EnvironmentController.js index ea16248..93f3ddb 100644 --- a/src/Controllers/EnvironmentController.js +++ b/src/Controllers/EnvironmentController.js @@ -169,20 +169,23 @@ class EnvironmentController extends CanvasController{ // close the organism and drop it in the world var new_org = new Organism(col, row, this.env, organism); - if (this.add_new_species){ - FossilRecord.addSpeciesObj(new_org.species); - new_org.species.start_tick = this.env.total_ticks; - this.add_new_species = false; - new_org.species.population = 0; - } - else if (this.org_to_clone.species.extinct){ - FossilRecord.resurrect(this.org_to_clone.species); - } - if (new_org.isClear(this.mouse_c, this.mouse_r)){ + if (new_org.isClear(col, row)) { + if (this.add_new_species){ + FossilRecord.addSpeciesObj(new_org.species); + new_org.species.start_tick = this.env.total_ticks; + this.add_new_species = false; + new_org.species.population = 0; + } + else if (this.org_to_clone.species.extinct){ + FossilRecord.resurrect(this.org_to_clone.species); + } + this.env.addOrganism(new_org); new_org.species.addPop(); + return true; } + return false; } dropCellType(col, row, state, killBlocking=false) { diff --git a/src/Environments/OrganismEditor.js b/src/Environments/OrganismEditor.js index c9d48e1..6aadc0b 100644 --- a/src/Environments/OrganismEditor.js +++ b/src/Environments/OrganismEditor.js @@ -90,7 +90,6 @@ class OrganismEditor extends Environment{ } createRandom() { - this.grid_map.fillGrid(CellStates.empty); this.organism = RandomOrganismGenerator.generate(this); @@ -98,26 +97,20 @@ class OrganismEditor extends Environment{ this.organism.species = new Species(this.organism.anatomy, null, 0); } - createRandomWorld(worldEnvironment) { + resetWithRandomOrgs(env) { + let reset_confirmed = env.reset(true, false); + if (!reset_confirmed) return; + let numOrganisms = parseInt($('#num-random-orgs').val()); - worldEnvironment.clear(); + let size = Math.ceil(8); - var numOrganismCols = Math.floor(worldEnvironment.grid_map.cols / this.grid_map.cols); - var numOrganismRows = Math.floor(worldEnvironment.grid_map.rows / this.grid_map.rows); - var center = this.grid_map.getCenter(); - - for (var x = 0; x < numOrganismCols; x++) { - for (var y = 0; y < numOrganismRows; y++) { - - var newOrganism = RandomOrganismGenerator.generate(this); - //newOrganism.updateGrid(); - newOrganism.species = new Species(newOrganism.anatomy, null, 0); - - var col = x * this.grid_map.cols + center[0]; - var row = y * this.grid_map.rows + center[1]; - worldEnvironment.controller.add_new_species = true; - worldEnvironment.controller.dropOrganism(newOrganism, col, row); - } + for (let i=0; i0) { - newest_t = this.data[0].dataPoints[this.data[0].dataPoints.length-1].x; - newest_t = this.data[0].dataPoints[0].x; + let record_size = FossilRecord.tick_record.length; + let data_points = this.data[0].dataPoints; + let newest_t = -1; + if (data_points.length>0) { + newest_t = this.data[0].dataPoints[data_points.length-1].x; } - if (newest_t < FossilRecord.tick_record[r_len-1]) { - this.addNewest(); + let to_add = 0; + let cur_t = FossilRecord.tick_record[record_size-1]; + // first count up the number of new datapoints the chart is missing + while (cur_t !== newest_t) { + to_add++; + cur_t = FossilRecord.tick_record[record_size-to_add-1] } - if (oldest_t < FossilRecord.tick_record[0]) { + // then add them in order + this.addNewest(to_add) + + // remove oldest datapoints until the chart is the same size as the saved records + while (data_points.length > FossilRecord.tick_record.length) { this.removeOldest(); } } - addNewest() { - var i = FossilRecord.tick_record.length-1; - this.addDataPoint(i); - } - - addDataPoint(i) { - alert("Must override addDataPoint") + addNewest(to_add) { + for (let i=to_add; i>0; i--) { + let j = FossilRecord.tick_record.length-i; + this.addDataPoint(j); + } } removeOldest() { @@ -75,6 +80,10 @@ class ChartController { } } + addDataPoint(i) { + alert("Must override addDataPoint") + } + clear() { this.data.length = 0; this.chart.render(); diff --git a/src/Stats/FossilRecord.js b/src/Stats/FossilRecord.js index c33b822..3189f7a 100644 --- a/src/Stats/FossilRecord.js +++ b/src/Stats/FossilRecord.js @@ -82,8 +82,7 @@ const FossilRecord = { this.species_counts.push(this.extant_species.length); this.av_mut_rates.push(this.env.averageMutability()); this.calcCellCountAverages(); - - if (this.tick_record.length > this.record_size_limit) { + while (this.tick_record.length > this.record_size_limit) { this.tick_record.shift(); this.pop_counts.shift(); this.species_counts.shift(); diff --git a/src/WorldConfig.js b/src/WorldConfig.js index 1923453..2c8f432 100644 --- a/src/WorldConfig.js +++ b/src/WorldConfig.js @@ -1,7 +1,6 @@ const WorldConfig = { headless: false, clear_walls_on_reset: false, - start_state: 'simple-prod', auto_reset: true, auto_pause: false, } From 46ae4e8618292026d51a37d04d6ba76afcf1dc6d Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Tue, 21 Dec 2021 18:46:26 -0600 Subject: [PATCH 5/5] fixed headless icon bug --- src/Controllers/ControlPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index 37f0aff..f57b94b 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -444,7 +444,7 @@ class ControlPanel { } updateHeadlessIcon(delta_time) { - if (this.engine.running) + if (!this.engine.running) return; const min_opacity = 0.4; var op = this.headless_opacity + (this.opacity_change_rate*delta_time/1000);