more control panel stuff

This commit is contained in:
MaxRobinsonTheGreat
2020-07-12 18:48:51 -06:00
parent c39ece309d
commit 9f13068cda
10 changed files with 135 additions and 275 deletions

245
dist/bundle.js vendored

File diff suppressed because one or more lines are too long

18
dist/html/index.html vendored
View File

@@ -25,17 +25,29 @@
<h2>Stats</h2> <h2>Stats</h2>
<p id='org-count'>Organism count: </p> <p id='org-count'>Organism count: </p>
<p id='org-record'>Highest count: </p> <p id='org-record'>Highest count: </p>
<p id='avg-mut'>Average Mutation Rate: </p>
</div> </div>
<div id='hyperparameters' class='control-set'> <div id='hyperparameters' class='control-set'>
<h2>Hyperparameters</h2> <h2>Hyperparameters</h2>
<label for="food-prod-prob">Probability of producing food:</label> <label for="food-prod-prob">Probability of producing food:</label>
<input type="number" id="food-prod-prob" min=".001" max="100" value=1 step="1"> <input type="number" id="food-prod-prob" min=".001" max="100" value=4 step="1">
<label for="lifespan-multiplier">Lifespan multiplier:</label> <label for="lifespan-multiplier">Lifespan multiplier:</label>
<input type="number" id="lifespan-multiplier" min="1" max="10000" value=100 step="1"> <input type="number" id="lifespan-multiplier" min="1" max="10000" value=100 step="1">
<br/> <br/>
<label for="fixed-ratio">Use fixed ratio</label> <label for="fixed-ratio">Use fixed ratio</label>
<input type="checkbox" id="fixed-ratio" name="scales" checked> <input type="checkbox" id="fixed-ratio" name="scales" checked>
<br><br/>
<h4>Mutation Probabilities</h4>
<label for="add-prob">Add Cell:</label>
<input class="mut-prob" type="number" id="add-prob" min="0" max="100" value=33>
<br/>
<label for="change-prob">Change Cell:</label>
<input class="mut-prob" type="number" id="change-prob" min="0" max="100" value=33>
<br/>
<label for="remove-prob">Remove Cell:</label>
<input class="mut-prob" type="number" id="remove-prob" min="0" max="100" value=33>
<br/>
</div> </div>
<div id='abilities' class='control-set'> <div id='abilities' class='control-set'>
@@ -44,6 +56,10 @@
<button class='control-mode-button' id='wall-button'>Drop Wall</button> <button class='control-mode-button' id='wall-button'>Drop Wall</button>
<button class='control-mode-button' id='kill-button'>Kill Organism</button> <button class='control-mode-button' id='kill-button'>Kill Organism</button>
<button class='control-mode-button' id='none-button'>None</button> <button class='control-mode-button' id='none-button'>None</button>
<br><br/>
<button id='reset-env'>Reset Environment</button>
<button id='kill-all'>Kill All Organisms</button>
<button id='clear-walls'>Clear All Walls</button>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
const CellTypes = require("./CellTypes"); const CellTypes = require("./CellTypes");
var Hyperparams = require("./Hyperparameters"); const Hyperparams = require("./Hyperparameters");
// A cell exists in a grid system. // A cell exists in a grid system.
class Cell{ class Cell{
@@ -61,12 +61,12 @@ function growFood(self, env){
if (self.owner.is_mover) if (self.owner.is_mover)
return; return;
var prob = Hyperparams.foodProdProb; var prob = Hyperparams.foodProdProb;
// console.log(prob) if (Math.random() * 100 <= prob){
for (var loc of Hyperparams.growableNeighbors){ var loc = Hyperparams.growableNeighbors[Math.floor(Math.random() * Hyperparams.growableNeighbors.length)]
var c=loc[0]; var c=loc[0];
var r=loc[1]; var r=loc[1];
var cell = env.grid_map.cellAt(self.col+c, self.row+r); var cell = env.grid_map.cellAt(self.col+c, self.row+r);
if (cell != null && cell.type == CellTypes.empty && Math.random() * 100 <= prob){ if (cell != null && cell.type == CellTypes.empty){
env.changeCell(self.col+c, self.row+r, CellTypes.food, null); env.changeCell(self.col+c, self.row+r, CellTypes.food, null);
return; return;
} }

View File

@@ -8,7 +8,7 @@ const CellTypes = {
killer: 6, killer: 6,
armor: 7, armor: 7,
colors: ['#121D29', 'green', 'gray', 'orange', 'white', 'blue', 'red', 'purple'], colors: ['#121D29', 'green', 'gray', 'orange', 'white', 'blue', 'red', 'purple'],
getRandomLivingType: function(){ getRandomLivingType: function() {
return Math.floor(Math.random() * 5) + 3; return Math.floor(Math.random() * 5) + 3;
} }
} }

View File

@@ -1,5 +1,5 @@
var Hyperparams = require("./Hyperparameters"); const Hyperparams = require("./Hyperparameters");
var Modes = require("./ControlModes"); const Modes = require("./ControlModes");
const CellTypes = require("./CellTypes"); const CellTypes = require("./CellTypes");
class ControlPanel { class ControlPanel {
@@ -59,6 +59,25 @@ class ControlPanel {
Hyperparams.lifespanMultiplier = lifespan; Hyperparams.lifespanMultiplier = lifespan;
} }
}.bind(this)); }.bind(this));
$('.mut-prob').change( function() {
switch(this.id){
case "add-prob":
Hyperparams.addProb = this.value;
Hyperparams.balanceMutationProbs(1);
break;
case "change-prob":
Hyperparams.changeProb = this.value;
Hyperparams.balanceMutationProbs(2);
break;
case "remove-prob":
Hyperparams.removeProb = this.value;
Hyperparams.balanceMutationProbs(3);
break;
}
$('#add-prob').val(Math.floor(Hyperparams.addProb));
$('#change-prob').val(Math.floor(Hyperparams.changeProb));
$('#remove-prob').val(Math.floor(Hyperparams.removeProb));
});
} }
defineModeControls() { defineModeControls() {
@@ -81,6 +100,17 @@ class ControlPanel {
$(".control-mode-button" ).css( "background-color", "lightgray" ); $(".control-mode-button" ).css( "background-color", "lightgray" );
$("#"+this.id).css("background-color", "darkgray"); $("#"+this.id).css("background-color", "darkgray");
}); });
$('#reset-env').click( function() {
this.engine.env.reset();
}.bind(this));
$('#kill-all').click( function() {
this.engine.env.clearOrganisms();
}.bind(this));
$('#clear-walls').click( function() {
this.engine.env.clearWalls();
}.bind(this));
} }
changeEngineSpeed(change_val) { changeEngineSpeed(change_val) {
@@ -96,7 +126,7 @@ class ControlPanel {
if (org_count > this.organism_record) if (org_count > this.organism_record)
this.organism_record = org_count; this.organism_record = org_count;
$('#org-record').text("Highest count: " + this.organism_record); $('#org-record').text("Highest count: " + this.organism_record);
// this.env_controller.performModeAction(); $('#avg-mut').text("Average Mutation Rate: " + Math.round(this.engine.env.averageMutability() * 100) / 100);
} }
} }

View File

@@ -15,6 +15,8 @@ class Environment{
this.grid_map = new GridMap(this.grid_cols, this.grid_rows, cell_size); this.grid_map = new GridMap(this.grid_cols, this.grid_rows, cell_size);
this.renderer.renderFullGrid(); this.renderer.renderFullGrid();
this.organisms = []; this.organisms = [];
this.walls = [];
this.total_mutability = 0;
} }
update(delta_time) { update(delta_time) {
@@ -35,6 +37,7 @@ class Environment{
removeOrganisms(org_indeces) { removeOrganisms(org_indeces) {
for (var i of org_indeces.reverse()){ for (var i of org_indeces.reverse()){
this.total_mutability -= this.organisms[i].mutability;
this.organisms.splice(i, 1); this.organisms.splice(i, 1);
} }
} }
@@ -44,19 +47,47 @@ class Environment{
var org = new Organism(center[0], center[1], this); var org = new Organism(center[0], center[1], this);
org.addCell(CellTypes.mouth, 1, 1); org.addCell(CellTypes.mouth, 1, 1);
org.addCell(CellTypes.producer, 0, 0); org.addCell(CellTypes.producer, 0, 0);
// org.addCell(CellTypes.mouth, 1, -1); org.addCell(CellTypes.mouth, -1, -1);
this.addOrganism(org); this.addOrganism(org);
} }
addOrganism(organism) { addOrganism(organism) {
organism.updateGrid(); organism.updateGrid();
this.total_mutability += organism.mutability;
this.organisms.push(organism); this.organisms.push(organism);
} }
averageMutability() {
if (this.organisms.length < 1)
return 0;
return this.total_mutability / this.organisms.length;
}
changeCell(c, r, type, owner) { changeCell(c, r, type, owner) {
this.grid_map.setCellType(c, r, type); this.grid_map.setCellType(c, r, type);
this.grid_map.setCellOwner(c, r, owner); this.grid_map.setCellOwner(c, r, owner);
this.renderer.addToRender(this.grid_map.cellAt(c, r)); this.renderer.addToRender(this.grid_map.cellAt(c, r));
if(type == CellTypes.wall)
this.walls.push(this.grid_map.cellAt(c, r));
}
clearWalls() {
for(var wall of this.walls)
this.changeCell(wall.col, wall.row, CellTypes.empty, null);
}
clearOrganisms() {
for (var org of this.organisms)
org.die();
this.organisms = [];
}
reset() {
this.organisms = [];
this.grid_map.fillGrid(CellTypes.empty);
this.renderer.renderFullGrid();
this.total_mutability = 0;
this.OriginOfLife();
} }
} }

View File

@@ -1,4 +1,4 @@
var Modes = require("./ControlModes"); const Modes = require("./ControlModes");
const CellTypes = require("./CellTypes"); const CellTypes = require("./CellTypes");
class EnvironmentController{ class EnvironmentController{

View File

@@ -19,9 +19,10 @@ class GridMap {
} }
fillGrid(type) { fillGrid(type) {
for (var col of grid) { for (var col of this.grid) {
for (var cell of col){ for (var cell of col){
cell.setType(type); cell.setType(type);
cell.owner = null;
} }
} }
} }

View File

@@ -1,22 +1,47 @@
const Neighbors = require("./Neighbors"); const Neighbors = require("./Neighbors");
var Hyperparams = { const Hyperparams = {
lifespanMultiplier: 100, lifespanMultiplier: 100,
foodProdProb: 1, foodProdProb: 4,
foodProdProbScalar: 4,
killableNeighbors: Neighbors.adjacent, killableNeighbors: Neighbors.adjacent,
edibleNeighbors: Neighbors.adjacent, edibleNeighbors: Neighbors.adjacent,
growableNeighbors: Neighbors.adjacent, growableNeighbors: Neighbors.adjacent,
useGlobalMutability: false,
globalMutability: 0,
addProb: 33,
changeProb: 33,
removeProb: 33,
// calculates the optimal ratio where a producer cell is most likely to produce 1 food in its lifespan. // calculates the optimal ratio where a producer cell is most likely to produce 1 food in its lifespan * a scalar of my choice :)
calcProducerFoodRatio : function(lifespan_fixed=true) { calcProducerFoodRatio : function(lifespan_fixed=true) {
if (lifespan_fixed) { if (lifespan_fixed) {
// change the foodProdProb // change the foodProdProb
this.foodProdProb = 100 / this.lifespanMultiplier; this.foodProdProb = (100 / this.lifespanMultiplier) * this.foodProdProbScalar;
} }
else { else {
// change the lifespanMultiplier // change the lifespanMultiplier
this.lifespanMultiplier = Math.floor(100 / this.foodProdProb); this.lifespanMultiplier = Math.floor(100 / (this.foodProdProb/this.foodProdProbScalar));
}
},
balanceMutationProbs : function(choice) {
if (choice == 1) {
var remaining = 100 - this.addProb;
this.changeProb = remaining/2;
this.removeProb = remaining/2;
}
else if (choice == 2) {
var remaining = 100 - this.changeProb;
this.addProb = remaining/2;
this.removeProb = remaining/2;
}
else {
var remaining = 100 - this.removeProb;
this.changeProb = remaining/2;
this.addProb = remaining/2;
} }
} }
} }

View File

@@ -2,9 +2,8 @@ const CellTypes = require("./CellTypes");
const Cell = require("./Cell"); const Cell = require("./Cell");
const GridMap = require("./GridMap"); const GridMap = require("./GridMap");
const LocalCell = require("./LocalCell"); const LocalCell = require("./LocalCell");
const { producer } = require("./CellTypes");
const Neighbors = require("./Neighbors"); const Neighbors = require("./Neighbors");
var Hyperparams = require("./Hyperparameters"); const Hyperparams = require("./Hyperparameters");
const directions = [[0,1],[0,-1],[1,0],[-1,0]] const directions = [[0,1],[0,-1],[1,0],[-1,0]]
@@ -89,7 +88,10 @@ class Organism {
//produce mutated child //produce mutated child
//check nearby locations (is there room and a direct path) //check nearby locations (is there room and a direct path)
var org = new Organism(0, 0, this.env, this); var org = new Organism(0, 0, this.env, this);
if (Math.random() * 100 <= 3) { var prob = this.mutability;
if (Hyperparams.useGlobalMutability)
prob = Hyperparams.globalMutability;
if (Math.random() * 100 <= this.mutability) {
org.mutate(); org.mutate();
} }
if (Math.random() <= 0.5) if (Math.random() <= 0.5)
@@ -120,27 +122,25 @@ class Organism {
} }
mutate() { mutate() {
var choice = Math.floor(Math.random() * 3); var choice = Math.floor(Math.random() * 100);
if (choice == 0) { if (choice <= Hyperparams.addProb) {
// add cell // add cell
var type = CellTypes.getRandomLivingType(); var type = CellTypes.getRandomLivingType();
var num_to_add = Math.floor(Math.random() * 3) + 1; var num_to_add = Math.floor(Math.random() * 3) + 1;
// for (var i=0; i<num_to_add; i++){ var branch = this.cells[Math.floor(Math.random() * this.cells.length)];
var branch = this.cells[Math.floor(Math.random() * this.cells.length)]; var growth_direction = Neighbors.all[Math.floor(Math.random() * Neighbors.all.length)]
var growth_direction = Neighbors.all[Math.floor(Math.random() * Neighbors.all.length)] var c = branch.loc_col+growth_direction[0];
var c = branch.loc_col+growth_direction[0]; var r = branch.loc_row+growth_direction[1];
var r = branch.loc_row+growth_direction[1]; return this.addCell(type, c, r);
return this.addCell(type, c, r);
// }
} }
else if (choice == 1){ else if (choice <= Hyperparams.addProb + Hyperparams.changeProb){
// change cell // change cell
var cell = this.cells[Math.floor(Math.random() * this.cells.length)]; var cell = this.cells[Math.floor(Math.random() * this.cells.length)];
cell.type = CellTypes.getRandomLivingType(); cell.type = CellTypes.getRandomLivingType();
this.checkProducerMover(cell.type); this.checkProducerMover(cell.type);
return true; return true;
} }
else { else if (choice <= Hyperparams.addProb + Hyperparams.changeProb + Hyperparams.removeProb){
// remove cell // remove cell
if(this.cells.length > 1) { if(this.cells.length > 1) {
this.cells.splice(Math.floor(Math.random() * this.cells.length), 1); this.cells.splice(Math.floor(Math.random() * this.cells.length), 1);