From b813dfa4c45706e4c5e190181cdbbd1d06bbaa4d Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 18 Dec 2021 10:34:19 -0600 Subject: [PATCH 1/8] max fps and active tab css --- dist/css/style.css | 4 ++++ dist/index.html | 2 +- src/Controllers/ControlPanel.js | 9 +++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/dist/css/style.css b/dist/css/style.css index a0624dc..1178ec3 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -134,6 +134,10 @@ button:active{ background-color: #81d2c7; color: black; } +.open-tab { + background-color: #66a39b; + color: black; +} .tab { grid-template-columns: repeat(2, 1fr); diff --git a/dist/index.html b/dist/index.html index 5585f26..d5a5c9a 100644 --- a/dist/index.html +++ b/dist/index.html @@ -59,7 +59,7 @@
-

About

+

About

Editor

Simulation Controls

Stats

diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index fcbe8b3..a7369a5 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -114,11 +114,14 @@ class ControlPanel { defineEngineSpeedControls(){ this.slider = document.getElementById("slider"); this.slider.oninput = function() { - this.fps = this.slider.value + const max_fps = 300; + this.fps = this.slider.value; + if (this.fps>=max_fps) this.fps = 1000; if (this.engine.running) { this.changeEngineSpeed(this.fps); } - $('#fps').text("Target FPS: "+this.fps); + let text = this.fps >= max_fps ? 'MAX' : this.fps; + $('#fps').text("Target FPS: "+text); }.bind(this); $('.pause-button').click(function() { $('.pause-button').find("i").toggleClass("fa fa-pause"); @@ -177,6 +180,8 @@ class ControlPanel { $('.tab').css('display', 'none'); var tab = '#'+this.id+'.tab'; $(tab).css('display', 'grid'); + $('.tabnav-item').removeClass('open-tab') + $('#'+this.id+'.tabnav-item').addClass('open-tab'); self.engine.organism_editor.is_active = (this.id == 'editor'); self.stats_panel.stopAutoRender(); if (this.id === 'stats') { From 09ed9edb07d4eed22daf79e68b009005a038965d Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 18 Dec 2021 11:06:55 -0600 Subject: [PATCH 2/8] created world controls tab --- dist/css/style.css | 16 +++++++++--- dist/index.html | 64 +++++++++++++++++++++++++++++----------------- 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/dist/css/style.css b/dist/css/style.css index 1178ec3..823001a 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -57,11 +57,15 @@ body{ img { image-rendering: -moz-crisp-edges; - image-rendering: -webkit-crisp-edges; - image-rendering: pixelated; - image-rendering: crisp-edges; - width: 60%; + image-rendering: -webkit-crisp-edges; + image-rendering: pixelated; + image-rendering: crisp-edges; + object-fit: cover; + width: 85%; + max-width: 500px; + max-height: 40%; border-radius: 10px; + overflow: hidden; } button { @@ -260,4 +264,8 @@ button:active{ } #maximize-hot-control { right: 10px; +} + +.grid-size-in { + width: 75px; } \ No newline at end of file diff --git a/dist/index.html b/dist/index.html index d5a5c9a..ec40fda 100644 --- a/dist/index.html +++ b/dist/index.html @@ -24,9 +24,9 @@ -
-

Simulation Speed

+ Life Engine +

Simulation Speed

@@ -34,26 +34,6 @@

-
- -
- - -
-

Auto reset count:

-

Grid Size

- - - - -
- - - - -
-
-
@@ -61,15 +41,15 @@

About

Editor

+

World Controls

Simulation Controls

Stats

-

Challenges

+
- Life Engine

The Life Engine is a virtual ecosystem that allows organisms to grow, spread, and compete.

Each organism is made up by a structure of cells, which provide different benefits based on their color.

@@ -177,6 +157,42 @@
+
+
+

Grid Size

+ + + + +
+ + + + +
+
+ +

Reset Options

+ + +
+

Auto reset count:

+ + + +
+
+
+ +
+ + +
+

Simulation Controls

From fe2d6aae7c2cc0f45385c4c8eff09614d0449772 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 18 Dec 2021 11:24:31 -0600 Subject: [PATCH 3/8] embed youtube vid --- dist/css/style.css | 8 ++++++++ dist/index.html | 18 +++++++----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/dist/css/style.css b/dist/css/style.css index 823001a..f0a008f 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -268,4 +268,12 @@ button:active{ .grid-size-in { width: 75px; +} + +#video { + height: 100%; + max-height: 190px; + margin: auto; + margin-bottom: 0; + padding-bottom: 0; } \ No newline at end of file diff --git a/dist/index.html b/dist/index.html index ec40fda..506957f 100644 --- a/dist/index.html +++ b/dist/index.html @@ -50,12 +50,9 @@
+

The Life Engine

The Life Engine is a virtual ecosystem that allows organisms to grow, spread, and compete.

-

Each organism is made up by a structure of cells, which provide different benefits based on their color.

- -
-
-

Cell Types

+

Each organism is made up of different colored cells. Hover over each color to learn what it does.

@@ -65,14 +62,13 @@
-
-
-

Hover over each color to learn what it does. For a more in depth explanation of the simulation, view the - readme and you can explore the source code. -

+

+
+
+
From c319ed9dc56da0ac317b55ec27110a21c57044f7 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 18 Dec 2021 11:53:30 -0600 Subject: [PATCH 4/8] world config + improved wall clearing --- dist/index.html | 13 ++++++------- src/Controllers/ControlPanel.js | 7 ++++--- src/Controllers/EnvironmentController.js | 4 ++-- src/Environments/WorldEnvironment.js | 5 +++-- src/Grid/GridMap.js | 3 ++- src/Organism/Cell/GridCell.js | 2 +- src/WorldConfig.js | 6 ++++++ 7 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 src/WorldConfig.js diff --git a/dist/index.html b/dist/index.html index 506957f..e19e80c 100644 --- a/dist/index.html +++ b/dist/index.html @@ -51,7 +51,7 @@

The Life Engine

-

The Life Engine is a virtual ecosystem that allows organisms to grow, spread, and compete.

+

The Life Engine is a virtual ecosystem that allows organisms to reproduce, compete, and evolve.

Each organism is made up of different colored cells. Hover over each color to learn what it does.

@@ -169,17 +169,16 @@

Reset Options

- - -
-

Auto reset count:

- +
+ + +
+

Auto reset count:


diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index a7369a5..5e8030e 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 WorldConfig = require("../WorldConfig"); class ControlPanel { constructor(engine) { @@ -137,14 +138,14 @@ class ControlPanel { $('.headless').click(function() { $('.headless').find("i").toggleClass("fa fa-eye"); $('.headless').find("i").toggleClass("fa fa-eye-slash"); - if (Hyperparams.headless){ + if (WorldConfig.headless){ $('#headless-notification').css('display', 'none'); this.engine.env.renderFull(); } else { $('#headless-notification').css('display', 'block'); } - Hyperparams.headless = !Hyperparams.headless; + WorldConfig.headless = !WorldConfig.headless; }.bind(this)); } @@ -411,7 +412,7 @@ class ControlPanel { $('#fps-actual').text("Actual FPS: " + Math.floor(this.engine.actual_fps)); $('#reset-count').text("Auto reset count: " + this.engine.env.reset_count); this.stats_panel.updateDetails(); - if (Hyperparams.headless) + if (WorldConfig.headless) this.updateHeadlessIcon(delta_time); } diff --git a/src/Controllers/EnvironmentController.js b/src/Controllers/EnvironmentController.js index 5e8b963..17da00f 100644 --- a/src/Controllers/EnvironmentController.js +++ b/src/Controllers/EnvironmentController.js @@ -4,7 +4,7 @@ const Modes = require("./ControlModes"); const CellStates = require("../Organism/Cell/CellStates"); const Neighbors = require("../Grid/Neighbors"); const FossilRecord = require("../Stats/FossilRecord"); -const Hyperparams = require("../Hyperparameters"); +const WorldConfig = require("../WorldConfig"); const Perlin = require("../Utils/Perlin"); class EnvironmentController extends CanvasController{ @@ -98,7 +98,7 @@ class EnvironmentController extends CanvasController{ } performModeAction() { - if (Hyperparams.headless && this.mode != Modes.Drag) + if (WorldConfig.headless && this.mode != Modes.Drag) return; var mode = this.mode; var right_click = this.right_click; diff --git a/src/Environments/WorldEnvironment.js b/src/Environments/WorldEnvironment.js index fdf48c3..ed07327 100644 --- a/src/Environments/WorldEnvironment.js +++ b/src/Environments/WorldEnvironment.js @@ -6,6 +6,7 @@ const CellStates = require('../Organism/Cell/CellStates'); const EnvironmentController = require('../Controllers/EnvironmentController'); const Hyperparams = require('../Hyperparameters.js'); const FossilRecord = require('../Stats/FossilRecord'); +const WorldConfig = require('../WorldConfig'); class WorldEnvironment extends Environment{ constructor(cell_size) { @@ -45,7 +46,7 @@ class WorldEnvironment extends Environment{ } render() { - if (Hyperparams.headless) { + if (WorldConfig.headless) { this.renderer.cells_to_render.clear(); return; } @@ -136,7 +137,7 @@ class WorldEnvironment extends Environment{ return; this.organisms = []; - this.grid_map.fillGrid(CellStates.empty); + this.grid_map.fillGrid(CellStates.empty, !WorldConfig.clear_walls_on_reset); this.renderer.renderFullGrid(this.grid_map.grid); this.total_mutability = 0; this.total_ticks = 0; diff --git a/src/Grid/GridMap.js b/src/Grid/GridMap.js index 24f167c..84db4ca 100644 --- a/src/Grid/GridMap.js +++ b/src/Grid/GridMap.js @@ -21,9 +21,10 @@ class GridMap { } } - fillGrid(state) { + fillGrid(state, ignore_walls=false) { for (var col of this.grid) { for (var cell of col) { + if (ignore_walls && cell.state===CellStates.wall) continue; cell.setType(state); cell.owner = null; cell.cell_owner = null; diff --git a/src/Organism/Cell/GridCell.js b/src/Organism/Cell/GridCell.js index 10d637b..fd3bdff 100644 --- a/src/Organism/Cell/GridCell.js +++ b/src/Organism/Cell/GridCell.js @@ -5,7 +5,7 @@ const Hyperparams = require("../../Hyperparameters"); class Cell{ constructor(state, col, row, x, y){ this.owner = null; // owner organism - this.cell_owner = null; // owner cell of ^that organism + this.cell_owner = null; // specific body cell of the owner organism that occupies this grid cell this.setType(state); this.col = col; this.row = row; diff --git a/src/WorldConfig.js b/src/WorldConfig.js new file mode 100644 index 0000000..91910d3 --- /dev/null +++ b/src/WorldConfig.js @@ -0,0 +1,6 @@ +const WorldConfig = { + headless: false, + clear_walls_on_reset: false, +} + +module.exports = WorldConfig; \ No newline at end of file From adc826d6a6f9a87251e899a05497e687ee92d423 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 18 Dec 2021 12:49:47 -0600 Subject: [PATCH 5/8] wall reset param works --- dist/index.html | 8 ++--- src/Controllers/ControlPanel.js | 53 ++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/dist/index.html b/dist/index.html index e19e80c..935c500 100644 --- a/dist/index.html +++ b/dist/index.html @@ -33,7 +33,7 @@

Target FPS: 60

- +
@@ -171,9 +171,9 @@

Reset Options


@@ -185,7 +185,7 @@
- +
diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index 5e8030e..83dc3a8 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -9,9 +9,9 @@ class ControlPanel { this.defineMinMaxControls(); this.defineHotkeys(); this.defineEngineSpeedControls(); - this.defineGridSizeControls(); this.defineTabNavigation(); this.defineHyperparameterControls(); + this.defineWorldControls(); this.defineModeControls(); this.defineChallenges(); this.fps = engine.fps; @@ -149,7 +149,28 @@ class ControlPanel { }.bind(this)); } - defineGridSizeControls() { + defineTabNavigation() { + this.tab_id = 'about'; + var self = this; + $('.tabnav-item').click(function() { + $('.tab').css('display', 'none'); + var tab = '#'+this.id+'.tab'; + $(tab).css('display', 'grid'); + $('.tabnav-item').removeClass('open-tab') + $('#'+this.id+'.tabnav-item').addClass('open-tab'); + self.engine.organism_editor.is_active = (this.id == 'editor'); + self.stats_panel.stopAutoRender(); + if (this.id === 'stats') { + self.stats_panel.startAutoRender(); + } + else if (this.id === 'editor') { + self.editor_controller.refreshDetailsPanel(); + } + self.tab_id = this.id; + }); + } + + defineWorldControls() { $('#fill-window').change(function() { if (this.checked) $('.col-row-input').css('display' ,'none'); @@ -172,27 +193,14 @@ class ControlPanel { this.stats_panel.reset(); }.bind(this)); - } - defineTabNavigation() { - this.tab_id = 'about'; - var self = this; - $('.tabnav-item').click(function() { - $('.tab').css('display', 'none'); - var tab = '#'+this.id+'.tab'; - $(tab).css('display', 'grid'); - $('.tabnav-item').removeClass('open-tab') - $('#'+this.id+'.tabnav-item').addClass('open-tab'); - self.engine.organism_editor.is_active = (this.id == 'editor'); - self.stats_panel.stopAutoRender(); - if (this.id === 'stats') { - self.stats_panel.startAutoRender(); - } - else if (this.id === 'editor') { - self.editor_controller.refreshDetailsPanel(); - } - self.tab_id = this.id; + $('#auto-reset').change(function() { + env.auto_reset = this.checked; }); + + $('#clear-walls-reset').change(function() { + WorldConfig.clear_walls_on_reset = this.checked; + }) } defineHyperparameterControls() { @@ -336,9 +344,6 @@ class ControlPanel { $('#random-walls').click( function() { this.env_controller.randomizeWalls(); }.bind(this)); - $('#auto-reset').change(function() { - env.auto_reset = this.checked; - }); $('#clear-walls').click( function() { this.engine.env.clearWalls(); }.bind(this)); From f6db669adb9ea41a9352d472b47995bd2c608614 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 18 Dec 2021 13:22:52 -0600 Subject: [PATCH 6/8] basic start state and auto reset/pause --- dist/index.html | 10 +++++---- src/Controllers/ControlPanel.js | 12 +++++++---- src/Environments/WorldEnvironment.js | 32 +++++++++++++++++++--------- src/WorldConfig.js | 3 +++ 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/dist/index.html b/dist/index.html index 935c500..cd08a34 100644 --- a/dist/index.html +++ b/dist/index.html @@ -33,7 +33,7 @@

Target FPS: 60

- +
@@ -169,16 +169,18 @@

Reset Options

- -
-

Auto reset count:

+ + +

diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index 83dc3a8..7bf1269 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -195,12 +195,18 @@ class ControlPanel { }.bind(this)); $('#auto-reset').change(function() { - env.auto_reset = this.checked; + WorldConfig.auto_reset = this.checked; + }); + $('#auto-pause').change(function() { + WorldConfig.auto_pause = this.checked; }); - $('#clear-walls-reset').change(function() { WorldConfig.clear_walls_on_reset = this.checked; }) + + $('#start-state').change ( function() { + WorldConfig.start_state = $("#start-state").val(); + }.bind(this)); } defineHyperparameterControls() { @@ -338,8 +344,6 @@ class ControlPanel { $('#clear-env').click( () => { env.reset(true, false); this.stats_panel.reset(); - env.auto_reset = false; - $('#auto-reset').prop('checked', false);; }); $('#random-walls').click( function() { this.env_controller.randomizeWalls(); diff --git a/src/Environments/WorldEnvironment.js b/src/Environments/WorldEnvironment.js index ed07327..5c3f9b9 100644 --- a/src/Environments/WorldEnvironment.js +++ b/src/Environments/WorldEnvironment.js @@ -19,7 +19,6 @@ class WorldEnvironment extends Environment{ this.organisms = []; this.walls = []; this.total_mutability = 0; - this.auto_reset = true; this.largest_cell_count = 0; this.reset_count = 0; this.total_ticks = 0; @@ -59,24 +58,37 @@ class WorldEnvironment extends Environment{ } removeOrganisms(org_indeces) { + let start_pop = this.organisms.length; for (var i of org_indeces.reverse()){ this.total_mutability -= this.organisms[i].mutability; this.organisms.splice(i, 1); } - if (this.organisms.length == 0 && this.auto_reset){ - this.reset_count++; - this.reset(false); + if (this.organisms.length === 0 && start_pop > 0) { + if (WorldConfig.auto_pause) + $('.pause-button')[0].click(); + else if(WorldConfig.auto_reset) { + this.reset_count++; + this.reset(false); + } } } OriginOfLife() { var center = this.grid_map.getCenter(); - var org = new Organism(center[0], center[1], this); - 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); + switch (WorldConfig.start_state){ + case 'simple-prod': + var org = new Organism(center[0], center[1], this); + 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); + break; + case 'random-orgs': + break; + case 'no-orgs': + break; + } } addOrganism(organism) { diff --git a/src/WorldConfig.js b/src/WorldConfig.js index 91910d3..1923453 100644 --- a/src/WorldConfig.js +++ b/src/WorldConfig.js @@ -1,6 +1,9 @@ const WorldConfig = { headless: false, clear_walls_on_reset: false, + start_state: 'simple-prod', + auto_reset: true, + auto_pause: false, } module.exports = WorldConfig; \ No newline at end of file From 653a6c3f31fcefae7b14e9cecc9c129c346f1e83 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Sat, 18 Dec 2021 13:37:15 -0600 Subject: [PATCH 7/8] consolidated rotation control --- dist/index.html | 9 +++------ src/Controllers/ControlPanel.js | 10 +++------- src/Hyperparameters.js | 3 +-- src/Organism/Organism.js | 4 ++-- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/dist/index.html b/dist/index.html index cd08a34..0835452 100644 --- a/dist/index.html +++ b/dist/index.html @@ -43,7 +43,7 @@

Editor

World Controls

Simulation Controls

-

Stats

+

Statistics

@@ -199,11 +199,8 @@
- - -
- - + +
diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index 7bf1269..f566692 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -217,11 +217,8 @@ class ControlPanel { Hyperparams.lifespanMultiplier = $('#lifespan-multiplier').val(); }.bind(this)); - $('#mover-rot').change(function() { - Hyperparams.moversCanRotate = this.checked; - }); - $('#offspring-rot').change(function() { - Hyperparams.offspringRotate = this.checked; + $('#rot-enabled').change(function() { + Hyperparams.rotationEnabled = this.checked; }); $('#insta-kill').change(function() { Hyperparams.instaKill = this.checked; @@ -278,8 +275,7 @@ class ControlPanel { Hyperparams.setDefaults(); $('#food-prod-prob').val(Hyperparams.foodProdProb); $('#lifespan-multiplier').val(Hyperparams.lifespanMultiplier); - $('#mover-rot').prop('checked', Hyperparams.moversCanRotate); - $('#offspring-rot').prop('checked', Hyperparams.offspringRotate); + $('#rot-enabled').prop('checked', Hyperparams.rotationEnabled); $('#insta-kill').prop('checked', Hyperparams.instaKill); $('#evolved-mutation').prop('checked', !Hyperparams.useGlobalMutability); $('#add-prob').val(Hyperparams.addProb); diff --git a/src/Hyperparameters.js b/src/Hyperparameters.js index 4199cd9..67ece3c 100644 --- a/src/Hyperparameters.js +++ b/src/Hyperparameters.js @@ -16,8 +16,7 @@ const Hyperparams = { this.changeProb = 33; this.removeProb = 33; - this.moversCanRotate = true; - this.offspringRotate = true; + this.rotationEnabled = true; this.foodBlocksReproduction = true; this.moversCanProduce = false; diff --git a/src/Organism/Organism.js b/src/Organism/Organism.js index 589bfb9..ef38f03 100644 --- a/src/Organism/Organism.js +++ b/src/Organism/Organism.js @@ -17,7 +17,7 @@ class Organism { 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.can_rotate = Hyperparams.rotationEnabled; this.move_count = 0; this.move_range = 4; this.ignore_brain_for = 0; @@ -63,7 +63,7 @@ class Organism { //produce mutated child //check nearby locations (is there room and a direct path) var org = new Organism(0, 0, this.env, this); - if(Hyperparams.offspringRotate){ + if(Hyperparams.rotationEnabled){ org.rotation = Directions.getRandomDirection(); } var prob = this.mutability; From 3f9a8a5ccd8d4c9d5b81b905cf2d6f4702deb80a Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Sat, 18 Dec 2021 13:52:09 -0600 Subject: [PATCH 8/8] Update Changelog.md --- Changelog.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index bf73909..844c04a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,14 +3,20 @@ ## 1.0.2 (current development) ### UI Enhancements: -- Button to generate random walls with perlin noise generator +- New tab for world controls + - Relocated grid controls, 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 + - 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 Enhancements: +- ### Bug Fixes: - Armor is no longer ignored when checking for clear reproduction space -- Thanks to contributors: