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, }