Merge pull request #146 from MaxRobinsonTheGreat/develop

Develop
This commit is contained in:
Max Robinson
2022-09-17 20:30:45 -05:00
committed by GitHub
32 changed files with 4656 additions and 93 deletions

View File

@@ -1,5 +1,20 @@
# Changelog
## 1.0.4 (9/17/2022)
### UI Enhancements:
- Added "Community Creations" button
- Updated icons
- Standardized Colors
### Simulation Enhancements:
- Added ability to load premade organisms and worlds from backend
- Added SeeThroughSelf param that allows eyes to see through their own cells
### Bug Fixes:
- Mutation rate now properly saves and loads with world
## 1.0.3 (4/15/2022)
### UI Enhancements:

View File

@@ -3,6 +3,8 @@ This is the readme for my evolution simulator, The Life Engine.
FOR FEATURE REQUESTS, USE THE DISCUSSIONS TAB. FOR BUG REPORTS, USE THE ISSUES TAB. :)
# The Life Engine
[Play here!](https://thelifeengine.net/)
The life engine is a cellular automaton designed to simulate the long term processes of biological evolution. It allows organisms to eat, reproduce, mutate, and adapt.
Unlike genetic algorithms, the life engine does not manually select the most "fit" organism for some given task, but rather allows true natural selection to
run its course. Organisms that survive, successfully produce offspring, and out-compete their neighbors naturally propogate througout the environment.
@@ -10,7 +12,26 @@ run its course. Organisms that survive, successfully produce offspring, and out-
This is the second version of the [original evolution simulator](https://github.com/MaxRobinsonTheGreat/EvolutionSimulator), which I started in high school.
# Rules
# How to Run and Modify the Code
- [Install node and npm](https://nodejs.org/en/download/)
- Clone this repository
- In terminal/powershell, go to the repository and run `npm install`
- Run `npm run build` (or `npm run build-watch` for a better developer experience)
- If you get a `Can't resolve jquery` error message run `npm install --save jquery`
- Open `dist/index.html` in your browser. The simulation should start running.
To load custom creations (found in `/dist/assets`), you must have a simple web server that serves all files in the dist directory. I do this with python:
- [Install python](https://www.python.org/downloads/)
- run `python -m http.server --directory dist` from the repository root
- Open `http://localhost:8000/` in your browser
### Npm build commands
- Production mode (minified): `npm run build`
- Watch mode (dev mode that auto-builds when you save a file): `npm run build-watch`
- Dev mode (better error messages): `npm run build-dev`
# How the Simulation Works
## The Environment
The environment is a simple grid system made up of cells, which at every tick have a certain type. The environment is populated by organisms, which are structures of multiple cells.
@@ -56,11 +77,3 @@ Organims can also rotate around a central pivot cell. This cell can never be rem
## Eyes and Brains
Any organism can evolve eyes, but when an organism has both eyes and mover cells it is given a brain. The eye, unlike other cells, has a direction, which is denoted by the direction of the slit in the cell. It "looks" forward in this direction and "sees" the first non-empty cell within a certain range. It checks the type of the cell and informs the brain, which then decideds how to move. The brain can either ignore (keep moving in whatever direction), chase (move towards the observed cell), or retreat (move in the opposite direction of the observed cell). The brain maps different observed cell types to different actions. For instance, the brain will chase when it sees food and retreat when it sees a killer cell. These behaviors can mutate over time.
## Building
If you want to change the source code and then play, use any of the following commands to build the project:
To build minified: `npm run build`
To build in dev mode: `npm run build-dev`
To build in dev/watch mode: `npm run build-watch`
You can then open `dist/index.html` in your browser.

View File

@@ -0,0 +1 @@
{"c":7,"r":7,"lifetime":0,"food_collected":0,"living":true,"direction":2,"rotation":0,"can_rotate":true,"move_count":0,"move_range":4,"ignore_brain_for":0,"mutability":5,"damage":0,"anatomy":{"birth_distance":16,"is_producer":false,"is_mover":true,"has_eyes":true,"cells":[{"loc_col":-1,"loc_row":-1,"direction":0,"state":{"name":"eye"}},{"loc_col":1,"loc_row":-1,"direction":0,"state":{"name":"eye"}},{"loc_col":0,"loc_row":-3,"state":{"name":"armor"}},{"loc_col":0,"loc_row":-5,"state":{"name":"killer"}},{"loc_col":0,"loc_row":-7,"state":{"name":"killer"}},{"loc_col":2,"loc_row":-4,"state":{"name":"armor"}},{"loc_col":3,"loc_row":-2,"state":{"name":"armor"}},{"loc_col":-2,"loc_row":-4,"state":{"name":"armor"}},{"loc_col":-3,"loc_row":-2,"state":{"name":"armor"}},{"loc_col":-2,"loc_row":0,"state":{"name":"killer"}},{"loc_col":2,"loc_row":0,"state":{"name":"killer"}},{"loc_col":0,"loc_row":1,"direction":2,"state":{"name":"eye"}},{"loc_col":0,"loc_row":0,"state":{"name":"mover"}},{"loc_col":1,"loc_row":4,"state":{"name":"killer"}},{"loc_col":-1,"loc_row":4,"state":{"name":"killer"}}]},"brain":{"decisions":{"empty":0,"food":1,"wall":0,"mouth":2,"producer":2,"mover":2,"killer":1,"armor":2,"eye":2}},"species_name":"0nrwql39i6"}

1
dist/assets/organisms/Napoleon.json vendored Normal file
View File

@@ -0,0 +1 @@
{"c":7,"r":7,"lifetime":0,"food_collected":0,"living":true,"direction":2,"rotation":0,"can_rotate":true,"move_count":0,"move_range":4,"ignore_brain_for":0,"mutability":5,"damage":0,"anatomy":{"birth_distance":8,"is_producer":false,"is_mover":true,"has_eyes":true,"cells":[{"loc_col":0,"loc_row":0,"direction":0,"state":{"name":"eye"}},{"loc_col":0,"loc_row":1,"direction":3,"state":{"name":"eye"}},{"loc_col":1,"loc_row":1,"direction":1,"state":{"name":"eye"}},{"loc_col":1,"loc_row":-2,"state":{"name":"killer"}},{"loc_col":-1,"loc_row":-2,"state":{"name":"killer"}},{"loc_col":3,"loc_row":0,"state":{"name":"killer"}},{"loc_col":-3,"loc_row":0,"state":{"name":"killer"}},{"loc_col":-2,"loc_row":2,"state":{"name":"killer"}},{"loc_col":2,"loc_row":2,"state":{"name":"killer"}},{"loc_col":1,"loc_row":2,"state":{"name":"mover"}},{"loc_col":1,"loc_row":3,"state":{"name":"armor"}},{"loc_col":0,"loc_row":3,"state":{"name":"armor"}},{"loc_col":-1,"loc_row":3,"state":{"name":"armor"}},{"loc_col":-2,"loc_row":-1,"state":{"name":"armor"}},{"loc_col":2,"loc_row":-1,"state":{"name":"armor"}}]},"brain":{"decisions":{"empty":0,"food":2,"wall":0,"mouth":2,"producer":2,"mover":2,"killer":1,"armor":2,"eye":2}},"species_name":"k5rjhsat1z"}

View File

@@ -0,0 +1 @@
{"c":7,"r":7,"lifetime":0,"food_collected":0,"living":true,"direction":2,"rotation":0,"can_rotate":true,"move_count":0,"move_range":4,"ignore_brain_for":0,"mutability":5,"damage":0,"anatomy":{"birth_distance":10,"is_producer":true,"is_mover":false,"has_eyes":false,"cells":[{"loc_col":0,"loc_row":0,"state":{"name":"producer"}},{"loc_col":1,"loc_row":-1,"state":{"name":"producer"}},{"loc_col":-1,"loc_row":-1,"state":{"name":"producer"}},{"loc_col":1,"loc_row":1,"state":{"name":"producer"}},{"loc_col":-1,"loc_row":1,"state":{"name":"producer"}},{"loc_col":0,"loc_row":-2,"state":{"name":"mouth"}},{"loc_col":-2,"loc_row":0,"state":{"name":"mouth"}},{"loc_col":2,"loc_row":0,"state":{"name":"mouth"}},{"loc_col":0,"loc_row":2,"state":{"name":"mouth"}},{"loc_col":2,"loc_row":-2,"state":{"name":"killer"}},{"loc_col":-2,"loc_row":-2,"state":{"name":"killer"}},{"loc_col":-2,"loc_row":2,"state":{"name":"killer"}},{"loc_col":2,"loc_row":2,"state":{"name":"killer"}}]},"species_name":"te6jbz54t5"}

View File

@@ -0,0 +1 @@
{"c":7,"r":7,"lifetime":0,"food_collected":0,"living":true,"direction":2,"rotation":0,"can_rotate":true,"move_count":0,"move_range":2,"ignore_brain_for":0,"mutability":7,"damage":0,"anatomy":{"birth_distance":4,"is_producer":false,"is_mover":true,"has_eyes":true,"cells":[{"loc_col":-1,"loc_row":1,"state":{"name":"mouth"}},{"loc_col":0,"loc_row":0,"direction":3,"state":{"name":"eye"}},{"loc_col":0,"loc_row":-1,"direction":0,"state":{"name":"eye"}},{"loc_col":1,"loc_row":0,"direction":1,"state":{"name":"eye"}},{"loc_col":0,"loc_row":1,"state":{"name":"mover"}},{"loc_col":1,"loc_row":1,"direction":2,"state":{"name":"eye"}},{"loc_col":-1,"loc_row":-1,"direction":3,"state":{"name":"eye"}},{"loc_col":1,"loc_row":-1,"state":{"name":"armor"}}]},"brain":{"decisions":{"empty":0,"food":2,"wall":0,"mouth":1,"producer":1,"mover":1,"killer":1,"armor":1,"eye":1}},"species_name":"8y7z6hfjal"}

34
dist/assets/organisms/_list.json vendored Normal file
View File

@@ -0,0 +1,34 @@
[
{
"name": "Purple Flower",
"file": "purple_flower"
},
{
"name": "Rosa Finalis",
"file": "RosaFinalis"
},
{
"name": "Quadratus Anxius",
"file": "The_Anxious_Square"
},
{
"name": "Hunter",
"file": "hunter"
},
{
"name": "Small Bush Killer",
"file": "smallbushkiller"
},
{
"name": "Fly Catcher",
"file": "flycatcher"
},
{
"name": "Heart Locket",
"file": "HeartLocket"
},
{
"name": "Napoleon",
"file": "Napoleon"
}
]

1
dist/assets/organisms/flycatcher.json vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/assets/organisms/hunter.json vendored Normal file
View File

@@ -0,0 +1 @@
{"c":7,"r":7,"lifetime":0,"food_collected":0,"living":true,"direction":2,"rotation":0,"can_rotate":true,"move_count":0,"move_range":2,"ignore_brain_for":0,"mutability":3,"damage":0,"anatomy":{"birth_distance":4,"is_producer":false,"is_mover":true,"has_eyes":true,"cells":[{"loc_col":1,"loc_row":0,"direction":0,"state":{"name":"eye"}},{"loc_col":-1,"loc_row":0,"direction":0,"state":{"name":"eye"}},{"loc_col":0,"loc_row":0,"state":{"name":"mover"}},{"loc_col":0,"loc_row":-1,"state":{"name":"mouth"}},{"loc_col":0,"loc_row":1,"state":{"name":"killer"}}]},"brain":{"decisions":{"empty":0,"food":2,"wall":0,"mouth":0,"producer":2,"mover":0,"killer":1,"armor":0,"eye":0}}}

View File

@@ -0,0 +1 @@
{"c":7,"r":7,"lifetime":0,"food_collected":0,"living":true,"direction":2,"rotation":0,"can_rotate":true,"move_count":0,"move_range":4,"ignore_brain_for":0,"mutability":5,"damage":0,"anatomy":{"birth_distance":6,"is_producer":true,"is_mover":false,"has_eyes":false,"cells":[{"loc_col":0,"loc_row":0,"state":{"name":"mouth"}},{"loc_col":-1,"loc_row":-2,"state":{"name":"armor"}},{"loc_col":-2,"loc_row":-1,"state":{"name":"armor"}},{"loc_col":1,"loc_row":-2,"state":{"name":"armor"}},{"loc_col":2,"loc_row":-1,"state":{"name":"armor"}},{"loc_col":2,"loc_row":1,"state":{"name":"armor"}},{"loc_col":1,"loc_row":2,"state":{"name":"armor"}},{"loc_col":-2,"loc_row":1,"state":{"name":"armor"}},{"loc_col":-1,"loc_row":2,"state":{"name":"armor"}},{"loc_col":-1,"loc_row":-1,"state":{"name":"producer"}},{"loc_col":1,"loc_row":-1,"state":{"name":"producer"}},{"loc_col":1,"loc_row":1,"state":{"name":"producer"}},{"loc_col":-1,"loc_row":1,"state":{"name":"producer"}}]},"brain":{"decisions":{"empty":0,"food":2,"wall":0,"mouth":0,"producer":0,"mover":0,"killer":1,"armor":0,"eye":0}}}

View File

@@ -0,0 +1 @@
{"c":7,"r":7,"lifetime":0,"food_collected":0,"living":true,"direction":2,"rotation":0,"can_rotate":true,"move_count":0,"move_range":1,"ignore_brain_for":0,"mutability":10,"damage":0,"anatomy":{"birth_distance":4,"is_producer":false,"is_mover":true,"has_eyes":true,"cells":[{"loc_col":0,"loc_row":0,"state":{"name":"mover"}},{"loc_col":0,"loc_row":-1,"state":{"name":"mouth"}},{"loc_col":0,"loc_row":1,"state":{"name":"killer"}},{"loc_col":1,"loc_row":0,"direction":0,"state":{"name":"eye"}},{"loc_col":-1,"loc_row":0,"state":{"name":"killer"}}]},"brain":{"decisions":{"empty":0,"food":2,"wall":0,"mouth":0,"producer":0,"mover":0,"killer":1,"armor":0,"eye":1}},"species_name":"sdkambtti7"}

File diff suppressed because one or more lines are too long

1
dist/assets/worlds/Trailblazer3.json vendored Normal file

File diff suppressed because one or more lines are too long

38
dist/assets/worlds/_list.json vendored Normal file
View File

@@ -0,0 +1,38 @@
[
{
"name": "Colony",
"file": "colony"
},
{
"name": "Ephemeral World",
"file": "ephemeral"
},
{
"name": "Trailblazer",
"file": "Trailblazer3"
},
{
"name": "Scarcity",
"file": "scarcity"
},
{
"name": "High Def Sweepers",
"file": "world_HighDefSweepers_start"
},
{
"name": "Shrub Swamp",
"file": "shrubland"
},
{
"name": "Computer (unprogrammed)",
"file": "computer_unprogrammed"
},
{
"name": "Computer (fibonacci)",
"file": "compV2_fixed_labeled_fibofancy"
},
{
"name": "Life Engine of Nurgle",
"file": "Life_Engine_of_Nurgle"
}
]

1
dist/assets/worlds/colony.json vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
dist/assets/worlds/ephemeral.json vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/assets/worlds/scarcity.json vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/assets/worlds/shrubland.json vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

72
dist/css/style.css vendored
View File

@@ -1,5 +1,16 @@
:root {
/* Colors */
--border:#3a4b68;
--panel-bg:#e1e3ec;
--btn: #9099c2;
--btn-hover: #81d2c7;
--btn-click: #595e77;
--tab: #416788;
--tab-active: #66a39b;
}
body{
background: #3a4b68;
background: var(--border);
margin: 0;
padding: 0;
height: 100%;
@@ -36,7 +47,7 @@ body{
width: 100%;
bottom: 0;
position: fixed;
background-color: #3a4b68;
background-color: var(--border);
display: none;
grid-template-columns: repeat(3, 1fr);
/* opacity: 0.8; */
@@ -51,7 +62,7 @@ body{
padding: 5px;
border: 10px;
border-radius: 15px;
background-color: #e1e3ec;
background-color: var(--panel-bg);
grid-row: 1;
}
@@ -71,7 +82,7 @@ img {
button {
border: none;
color: black;
background-color: #9099c2;
background-color: var(--btn);
border-radius: 8px;
padding: 5px 5px;
text-align: center;
@@ -82,15 +93,15 @@ button {
margin: 2px;
}
button:hover{
background-color: #81d2c7;
background-color: var(--btn-hover);
}
button:active{
background-color: #595e77;
background-color: var(--btn-click);
}
input,select {
border-radius: 5px;
border: 2px solid #9099c2;
border: 2px solid var(--btn);
padding: 2px;
background-color: white;
outline: none;
@@ -136,7 +147,7 @@ input:hover,input:active {
.tabnav {
overflow: hidden;
background-color: #416788;
background-color: var(--tab);
border-radius: 15px;
}
.tabnav p {
@@ -149,11 +160,11 @@ input:hover,input:active {
user-select: none;
}
.tabnav p:hover {
background-color: #81d2c7;
background-color: var(--btn-hover);
color: black;
}
.open-tab {
background-color: #66a39b;
background-color: var(--tab-active);
color: black;
}
@@ -190,7 +201,7 @@ input:hover,input:active {
margin-top: 5px;
}
.edit-mode-btn.selected {
background-color: #81d2c7;
background-color: var(--btn-hover);
}
#clear-walls {
margin-top: 5px;
@@ -236,10 +247,6 @@ input:hover,input:active {
height: 50px;
margin: 1px;
}
.cell-legend-hover {
border-color: black;
border: 5px;
}
#editor-mode-cont{
padding-top: 20px;
}
@@ -254,6 +261,11 @@ input:hover,input:active {
width: 100%;
}
.community-section {
position: fixed;
right: 10px;
top: 10px;
}
.hot-controls {
position: fixed;
@@ -291,6 +303,34 @@ input:hover,input:active {
padding-bottom: 0;
}
#reset-with-editor-org{
#reset-with-editor-org {
margin-top: 5px;
}
.load-panel {
width: 300px;
background-color: var(--panel-bg);
position: fixed;
display: none;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border-style: solid;
border-width: 0px;
border-radius: 10px;
box-shadow: 0 0 0 10px var(--border);
padding: 10px;
}
#close-load-btn {
float: right;
}
#load-panel-title {
white-space: nowrap;
}
#load-panel-title * {
display: inline;
}

43
dist/index.html vendored
View File

@@ -5,9 +5,8 @@
<title>The Life Engine</title>
<link rel="icon" href="./img/icon.png">
<link rel="stylesheet" href="./css/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css">
<script type="text/javascript" src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</head>
<body>
<script src="./js/bundle.js"></script>
@@ -22,7 +21,7 @@
<button class="edit-mode-btn drag-view" id="drag-view" title="Drag View. Hotkey: S"><i class="fa fa-arrows"></i></button>
<button class="edit-mode-btn wall-drop" id="wall-drop" title="Drop/Remove Wall. Hotkey: D"><i class="fa fa-th"></i></button>
<button class="edit-mode-btn food-drop selected" id="food-drop" title="Drop/Remove Food. Hotkey: F"><i class="fa fa-cutlery"></i></button>
<button class="edit-mode-btn click-kill" id="click-kill" title="Click to kill. Hotkey: G"><i class="fa fa-bolt"></i></button>
<button class="edit-mode-btn click-kill" id="click-kill" title="Click to kill. Hotkey: G"><i class="fa fa-skull"></i></button>
</div>
<img src="./img/title.png" alt="Life Engine">
<h3>Simulation Speed</h3>
@@ -66,20 +65,21 @@
<iframe id="video" src="https://www.youtube.com/embed/iSAKEnRfles"></iframe>
</div>
<div class='icon-links'>
<a href=https://github.com/MaxRobinsonTheGreat/EvolutionSimulatorV2 title='View the code'><i class="fa fa-github"></i></a>
<a href="https://twitter.com/max_romana"><i class="fa fa-twitter"></i></a>
<a href=https://github.com/MaxRobinsonTheGreat/EvolutionSimulatorV2 title='View the code'><i class="fa-brands fa-github"></i></a>
<a href="https://discord.gg/ZsrAAByEnr" title='Join the community'><i class="fa-brands fa-discord"></i></a>
<a href=" https://www.patreon.com/emergentgarden" title='Support the project'><i class="fa-brands fa-patreon"></i></a>
</div>
</div>
<div id='editor' class='tab'>
<div class='left-half' id='editor-panel'>
<div class='editor-buttons'>
<button class="edit-mode-btn select" id="select" title="Select organism from world. Hotkey: Z"><i class="fa fa-hand-pointer-o"></i></button>
<button class="edit-mode-btn edit" id="edit" title="Edit organism. Hotkey: X"><i class="fa fa-pencil"></i></button>
<button class="edit-mode-btn select" id="select" title="Select organism from world. Hotkey: Z"><i class="fa-regular fa-hand-pointer"></i></button>
<button class="edit-mode-btn edit" id="edit" title="Edit organism. Hotkey: X"><i class="fa fa-pen-to-square"></i></button>
<button class="edit-mode-btn drop-org" id="drop-org" title="Drop organism in world. Hotkey: C"><i class="fa fa-plus"></i></button>
<button id="save-org" title="Save Organism"><i class="fa fa-save"></i></button>
<button id="load-org" title="Load Organism"><i class="fa fa-upload"></i></button>
<input id="upload-org" style="display: none;" type="file">
</div>
<div id='editor-env'>
<canvas id='editor-canvas'></canvas>
@@ -197,7 +197,6 @@
<button id='load-env' title="Load world save file">Load World</button>
<label for="override-controls" title='Override the current evolution controls with those from the loaded world'>Override Evolution Controls</label>
<input type="checkbox" id="override-controls" checked>
<input id="upload-env" style="display: none;" type="file">
</div>
</div>
<div id='hyperparameters' class='tab'>
@@ -218,11 +217,15 @@
<label for="look-range" title='How far an eye cell can see (in number of cells)'>Look range:</label>
<input type="number" id="look-range" min="1" max="50" value=20 step="1">
<br>
<label for="see-through-self" title='Allows eyes to see through an organisms own cells'>See through self:</label>
<input type="checkbox" id="see-through-self">
<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'>
@@ -231,7 +234,7 @@
<label for="evolved-mutation" title='When on, each organism has its own mutation rate that can increase or decrease. When off, all organisms have the same mutation rate.'>Use evolved mutation rate</label>
<input type="checkbox" id="evolved-mutation" checked> </br>
<label class="global-mutation-in" for="global-mutation">Global mutation rate: </label>
<input class="global-mutation-in" type="number" id="global-mutation" min="1" max="100" value=5 step="1">
<input class="global-mutation-in" type="number" id="global-mutation" min="0" max="100" value=5 step="1">
<h4 title='When an organism mutates, it can choose from one of the following mutation types.'>Mutation Type Probabilities</h4>
<label for="add-prob" title='A new cell will stem from an existing one'>Add Cell:</label>
<input class="mut-prob" type="number" id="add-prob" min="0" max="100" value=33>
@@ -267,21 +270,35 @@
<option value="mut-rate">Mutation Rate</option>
</select>
<p id='chart-note'></p>
</div>
<div class='right-half'>
<div id="chartContainer"></div>
</div>
</div>
</div>
</div>
<div class='load-panel'>
<div class="load-panel-title">
<button id='close-load-btn'><i class="fa fa-times"></i></button>
<h2 id="load-title">Community Creations</h2>
</div><br>
Worlds<br>
<select id="worlds-load-dropdown"></select>
<button id='load-env-btn'>Load</button><br>
Organisms<br>
<select id="organisms-load-dropdown"></select>
<button id='load-org-btn'>Load</button><br><br>
<input id="upload-json" style="display: none;" type="file">
</div>
<div class='community-section'>
<button id="community-creations-btn" title="See worlds and organisms made by the community">Community Creations <i class="fa fa-users"></i></button>
</div>
<div class='hot-controls'>
<button class="reset-view" title="Reset View. Hotkey: A"><i class="fa fa-video-camera"></i></button>
<button class="edit-mode-btn drag-view" id="drag-view" title="Drag View. Hotkey: S"><i class="fa fa-arrows"></i></button>
<button class="edit-mode-btn wall-drop" id="wall-drop" title="Drop/Remove Wall. Hotkey: D"><i class="fa fa-th"></i></button>
<button class="edit-mode-btn food-drop selected" id="food-drop" title="Drop/Remove Food. Hotkey: F"><i class="fa fa-cutlery"></i></button>
<button class="edit-mode-btn click-kill" id="click-kill" title="Click to kill. Hotkey: G"><i class="fa fa-bolt"></i></button>
<button class="edit-mode-btn click-kill" id="click-kill" title="Click to kill. Hotkey: G"><i class="fa fa-skull"></i></button>
<button class="headless" title="Toggle rendering. Hotkey: H"><i class="fa fa-eye-slash"></i></button>
<button class='pause-button' title="Play/Pause. Hotkey: Spacebar"><i class="fa fa-pause"></i></button>
</div>

4307
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,5 +24,7 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
},
"dependencies": {}
"dependencies": {
"jquery": "^3.6.1"
}
}

View File

@@ -2,6 +2,7 @@ const Hyperparams = require("../Hyperparameters");
const Modes = require("./ControlModes");
const StatsPanel = require("../Stats/StatsPanel");
const WorldConfig = require("../WorldConfig");
const LoadController = require("./LoadController");
class ControlPanel {
constructor(engine) {
@@ -24,10 +25,11 @@ class ControlPanel {
this.opacity_change_rate = -0.8;
this.paused=false;
this.setHyperparamDefaults();
LoadController.control_panel = this;
}
defineMinMaxControls(){
this.control_panel_active = true;
this.control_panel_active = false;
this.no_hud = false;
$('#minimize').click ( () => {
$('.control-panel').css('display', 'none');
@@ -100,10 +102,13 @@ class ControlPanel {
};
$('.control-panel').css('display', control_panel_display);
$('.hot-controls').css('display', hot_control_display);
$('.community-section').css('display', 'block');
}
else {
$('.control-panel').css('display', 'none');
$('.hot-controls').css('display', 'none');
$('.community-section').css('display', 'none');
LoadController.close();
}
this.no_hud = !this.no_hud;
break;
@@ -219,7 +224,9 @@ class ControlPanel {
this.setPaused(false);
});
$('#load-env').click(() => {
$('#upload-env').click();
LoadController.loadJson((env)=>{
this.loadEnv(env);
});
});
$('#upload-env').change((e)=>{
let files = e.target.files;
@@ -227,14 +234,8 @@ class ControlPanel {
let reader = new FileReader();
reader.onload = (e) => {
try {
let was_running = this.engine.running;
this.setPaused(true);
let env = JSON.parse(e.target.result);
this.engine.env.loadRaw(env);
if (was_running)
this.setPaused(false);
this.updateHyperparamUIValues();
this.env_controller.resetView();
this.loadEnv(env);
} catch(except) {
console.error(except)
alert('Failed to load world');
@@ -245,6 +246,20 @@ class ControlPanel {
});
}
loadEnv(env) {
if (this.tab_id == 'stats')
this.stats_panel.stopAutoRender();
let was_running = this.engine.running;
this.setPaused(true);
this.engine.env.loadRaw(env);
if (was_running)
this.setPaused(false);
this.updateHyperparamUIValues();
this.env_controller.resetView();
if (this.tab_id == 'stats')
this.stats_panel.startAutoRender();
}
defineHyperparameterControls() {
$('#food-prod-prob').change(function() {
Hyperparams.foodProdProb = $('#food-prod-prob').val();
@@ -262,6 +277,9 @@ class ControlPanel {
$('#look-range').change(function() {
Hyperparams.lookRange = $('#look-range').val();
});
$('#see-through-self').change(function() {
Hyperparams.seeThroughSelf = this.checked;
});
$('#food-drop-rate').change(function() {
Hyperparams.foodDropProb = $('#food-drop-rate').val();
});
@@ -352,6 +370,8 @@ class ControlPanel {
$('#food-drop-rate').val(Hyperparams.foodDropProb);
$('#extra-mover-cost').val(Hyperparams.extraMoverFoodCost);
$('#look-range').val(Hyperparams.lookRange);
$('#see-through-self').prop('checked', Hyperparams.seeThroughSelf);
$('#global-mutation').val(Hyperparams.globalMutability);
if (!Hyperparams.useGlobalMutability) {
$('.global-mutation-in').css('display', 'none');
@@ -436,9 +456,7 @@ class ControlPanel {
}
setPaused(paused) {
if (paused) {
$('.pause-button').find("i").removeClass("fa-pause");
$('.pause-button').find("i").addClass("fa-play");
if (this.engine.running)

View File

@@ -4,6 +4,7 @@ const CellStates = require("../Organism/Cell/CellStates");
const Directions = require("../Organism/Directions");
const Hyperparams = require("../Hyperparameters");
const Species = require("../Stats/Species");
const LoadController = require("./LoadController");
class EditorController extends CanvasController{
constructor(env, canvas) {
@@ -119,36 +120,25 @@ class EditorController extends CanvasController{
downloadEl.click();
});
$('#load-org').click(() => {
$('#upload-org').click();
});
$('#upload-org').change((e)=>{
let files = e.target.files;
if (!files.length) {return;};
let reader = new FileReader();
reader.onload = (e) => {
try {
let org=JSON.parse(e.target.result);
this.env.clear();
this.env.organism.loadRaw(org);
this.refreshDetailsPanel();
this.env.organism.updateGrid();
this.env.renderFull();
this.env.organism.species = new Species(this.env.organism.anatomy, null, 0);
if (org.species_name)
this.env.organism.species.name = org.species_name;
if (this.mode === Modes.Clone)
$('#drop-org').click();
// have to clear the value so change() will be triggered if the same file is uploaded again
$('#upload-org')[0].value = '';
} catch(except) {
console.error(except)
alert('Failed to load organism');
}
};
reader.readAsText(files[0]);
LoadController.loadJson((org)=>{
this.loadOrg(org);
});
});
}
loadOrg(org) {
this.env.clear();
this.env.organism.loadRaw(org);
this.refreshDetailsPanel();
this.env.organism.updateGrid();
this.env.renderFull();
this.env.organism.species = new Species(this.env.organism.anatomy, null, 0);
if (org.species_name)
this.env.organism.species.name = org.species_name;
if (this.mode === Modes.Clone)
$('#drop-org').click();
}
clearDetailsPanel() {
$('#organism-details').css('display', 'none');
$('#edit-organism-details').css('display', 'none');

View File

@@ -0,0 +1,94 @@
const LoadController = {
init() {
$('#close-load-btn').click(()=>{
this.close();
});
$('#load-custom-btn').click(()=>{
$('#upload-json').click();
});
$('#community-creations-btn').click(()=>{
this.open();
});
$('#load-env-btn').click(async ()=>{
let file = $('#worlds-load-dropdown').val();
const base = `./assets/worlds/`;
let resp = await fetch(base+file+'.json');
let json = await resp.json();
this.control_panel.loadEnv(json);
this.close();
});
$('#load-org-btn').click(async ()=>{
let file = $('#organisms-load-dropdown').val();
const base = `./assets/organisms/`;
let resp = await fetch(base+file+'.json');
let json = await resp.json();
this.control_panel.editor_controller.loadOrg(json);
this.close();
$('#maximize').click();
$('#editor').click();
});
this.loadDropdown('worlds');
this.loadDropdown('organisms');
},
async loadDropdown(name) {
const base = `./assets/${name}/`;
let list = [];
try {
let resp = await fetch(base+'_list.json');
list = await resp.json();
} catch(e) {
console.error('Failed to load list: ', e);
}
let id = `#${name}-load-dropdown`
$(id).empty();
for (let opt of list) {
$(id).append(
`<option value="${opt.file}">
${opt.name}
</option>`
);
}
},
async open() {
$('.load-panel').css('display','block');
},
loadJson(callback) {
$('#upload-json').change((e)=>{
let files = e.target.files;
if (!files.length) {return;};
let reader = new FileReader();
reader.onload = (e) => {
try {
let json=JSON.parse(e.target.result);
callback(json);
this.close();
} catch(e) {
console.error(e)
alert('Failed to load');
}
$('#upload-json')[0].value = '';
};
reader.readAsText(files[0]);
});
$('#upload-json').click();
},
close() {
$('.load-panel').css('display','none');
$('#load-selected-btn').off('click');
$('#upload-json').off('change');
}
}
$(document).ready(() => {
LoadController.init();
});
module.exports = LoadController;

View File

@@ -22,6 +22,7 @@ const Hyperparams = {
this.instaKill = false;
this.lookRange = 20;
this.seeThroughSelf = false;
this.foodDropProb = 0;

View File

@@ -69,7 +69,10 @@ class EyeCell extends BodyCell{
if (cell == null) {
break;
}
if (cell.state != CellStates.empty){
if (cell.owner === this.org && Hyperparams.seeThroughSelf) {
continue;
}
if (cell.state !== CellStates.empty) {
var distance = Math.abs(start_col-col) + Math.abs(start_row-row);
return new Observation(cell, distance, direction);
}

View File

@@ -5,8 +5,7 @@ import Engine from './Engine';
$('document').ready(function(){
let isMobile = mobileCheck();
if (isMobile) {
alert("Though the simulation still works on mobile, most features are disabled. Try it on desktop for the full experience!");
$('.control-panel').css('display', 'none');
alert("Welcome to the Life Engine! Be aware the website is not built for mobile, so try on desktop for the best experience!");
}
var engine = new Engine();
engine.start(60);