From d26f19510002fc94edb055e5c675054d90ecf57e Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Thu, 4 Feb 2021 17:27:47 -0700 Subject: [PATCH 1/9] Separated anatomy from org / made species tracker --- dist/js/bundle.js | 443 +++++++++++++++++++- src/Controllers/ControlPanel.js | 1 + src/Controllers/EditorController.js | 12 +- src/Controllers/EnvironmentController.js | 11 + src/Environments/OrganismEditor.js | 15 +- src/Environments/WorldEnvironment.js | 20 +- src/Organism/Anatomy.js | 96 +++++ src/Organism/Cell/BodyCells/BodyCell.js | 4 +- src/Organism/Cell/BodyCells/EyeCell.js | 2 +- src/Organism/Cell/BodyCells/MoverCell.js | 2 +- src/Organism/Cell/BodyCells/ProducerCell.js | 4 +- src/Organism/Organism.js | 161 ++----- src/Rendering/Renderer.js | 4 +- src/Stats/FossilRecord.js | 49 +++ src/Stats/Species.js | 30 ++ 15 files changed, 707 insertions(+), 147 deletions(-) create mode 100644 src/Organism/Anatomy.js create mode 100644 src/Stats/FossilRecord.js create mode 100644 src/Stats/Species.js diff --git a/dist/js/bundle.js b/dist/js/bundle.js index 1e05899..6bf7d4c 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1 +1,442 @@ -!function(e){var t={};function i(s){if(t[s])return t[s].exports;var r=t[s]={i:s,l:!1,exports:{}};return e[s].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=t,i.d=function(e,t,s){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:s})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(s,r,function(t){return e[t]}.bind(null,r));return s},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=13)}([function(e,t){class i{constructor(e){this.name=e,this.color="black"}render(e,t,i){e.fillStyle=this.color,e.fillRect(t.x,t.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(e,t,i){if(e.fillStyle=this.color,e.fillRect(t.x,t.y,i,i),1!=i){var s=i/2,r=-i/8,o=-s,n=i/2+i/4,l=i/4;e.translate(t.x+s,t.y+s),e.rotate(90*t.cell_owner.getAbsoluteDirection()*Math.PI/180),e.fillStyle=this.slit_color,e.fillRect(r,o,l,n),e.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),e.exports=s},function(e,t,i){const s=i(4),r={setDefaults:function(){this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(e){if(1==e){var t=100-this.addProb;this.changeProb=t/2,this.removeProb=t/2}else if(2==e){t=100-this.changeProb;this.addProb=t/2,this.removeProb=t/2}else{t=100-this.removeProb;this.changeProb=t/2,this.addProb=t/2}}};r.setDefaults(),e.exports=r},function(e,t){const i={up:0,right:1,down:2,left:3,scalars:[[0,-1],[1,0],[0,1],[-1,0]],getRandomDirection:function(){return Math.floor(4*Math.random())},getRandomScalar:function(){return this.scalars[Math.floor(Math.random()*this.scalars.length)]},getOppositeDirection:function(e){switch(e){case this.up:return this.down;case this.down:return this.up;case this.left:return this.right;case this.right:return this.left}},rotateRight:function(e){return++e>3&&(e=0),e}};e.exports=i},function(e,t,i){i(0);const s=i(2);e.exports=class{constructor(e,t,i,s){this.state=e,this.org=t,this.loc_col=i,this.loc_row=s;var r=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.birth_distance1){c=this.cells[Math.floor(Math.random()*this.cells.length)];t=this.removeCell(c.loc_col,c.loc_row)}return t}attemptMove(){var e=l.scalars[this.direction],t=e[0],i=e[1],r=this.c+t,o=this.r+i;if(this.isClear(r,o)){for(var n of this.cells){var a=this.c+n.rotatedCol(this.rotation),h=this.r+n.rotatedRow(this.rotation);this.env.changeCell(a,h,s.empty,null)}return this.c=r,this.r=o,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=l.getRandomDirection(),this.move_count=0,!0;var e=l.getRandomDirection();if(this.isClear(this.c,this.r,e)){for(var t of this.cells){var i=this.c+t.rotatedCol(this.rotation),r=this.r+t.rotatedRow(this.rotation);this.env.changeCell(i,r,s.empty,null)}return this.rotation=e,this.direction=l.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(e){this.direction=e,this.move_count=0}isStraightPath(e,t,i,s,r){if(e==i){if(t>s){var o=s;s=t,t=o}for(var n=t;n!=s;n++){var l=this.env.grid_map.cellAt(e,n);if(!this.isPassableCell(l,r))return!1}return!0}if(e>i){o=i;i=e,e=o}for(n=e;n!=i;n++){l=this.env.grid_map.cellAt(n,t);if(!this.isPassableCell(l,r))return!1}return!0}isPassableCell(e,t){return null!=e&&(e.state==s.empty||e.owner==this||e.owner==t||e.state==s.food)}isClear(e,t,i=this.rotation,r=!1){for(var o of this.cells){var l=this.getRealCell(o,e,t,i);if(null==l)return!1;if(!(l.owner==this||l.state==s.empty||!n.foodBlocksReproduction&&l.state==s.food||r&&o.state==s.armor&&l.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||n.instaKill)&&this.die()}die(){for(var e of this.cells){var t=this.c+e.rotatedCol(this.rotation),i=this.r+e.rotatedRow(this.rotation);this.env.changeCell(t,i,s.food,null)}this.living=!1}updateGrid(){for(var e of this.cells){var t=this.c+e.rotatedCol(this.rotation),i=this.r+e.rotatedRow(this.rotation);this.env.changeCell(t,i,e.state,e)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var e of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.cells))if(e.performFunction(),!this.living)return this.living;if(this.is_mover){this.move_count++;var t=!1;0==this.ignore_brain_for?t=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!t||!i)this.attemptRotate()||(this.changeDirection(l.getRandomDirection()),t&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(e,t=this.c,i=this.r,s=this.rotation){var r=t+e.rotatedCol(s),o=i+e.rotatedRow(s);return this.env.grid_map.cellAt(r,o)}}e.exports=h},function(e,t){e.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(e,t){e.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(e,t,i,s){this.grid_map.setCellType(e,t,i),this.grid_map.setCellOwner(e,t,s)}}},function(e,t,i){i(0),i(2);e.exports=class{constructor(e,t,i){this.cell_size=i,this.canvas=document.getElementById(e),this.ctx=this.canvas.getContext("2d"),this.fillWindow(t),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(e){this.fillShape($("#"+e).height(),$("#"+e).width())}fillShape(e,t){this.canvas.width=t,this.canvas.height=e,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(e){for(var t of e)for(var i of t)this.renderCell(i)}renderCells(){for(var e of this.cells_to_render)this.renderCell(e);this.cells_to_render.clear()}renderCell(e){e.state.render(this.ctx,e,this.cell_size)}renderOrganism(e){for(var t of e.cells){var i=e.getRealCell(t);this.renderCell(i)}}addToRender(e){this.highlighted_cells.has(e)&&this.cells_to_highlight.add(e),this.cells_to_render.add(e)}renderHighlights(){for(var e of this.cells_to_highlight)this.renderCellHighlight(e),this.highlighted_cells.add(e);this.cells_to_highlight.clear()}highlightOrganism(e){for(var t of e.cells){var i=e.getRealCell(t);this.cells_to_highlight.add(i)}}highlightCell(e){this.cells_to_highlight.add(e)}renderCellHighlight(e,t="yellow"){this.renderCell(e),this.ctx.fillStyle=t,this.ctx.globalAlpha=.5,this.ctx.fillRect(e.x,e.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(e)}clearAllHighlights(e=!1){for(var t of this.highlighted_cells)this.renderCell(t);this.highlighted_cells.clear(),e&&this.cells_to_highlight.clear()}}},function(e,t,i){const s=i(10),r=i(0);e.exports=class{constructor(e,t,i){this.resize(e,t,i)}resize(e,t,i){this.grid=[],this.cols=e,this.rows=t,this.cell_size=i;for(var o=0;o=0&&t>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(e,t){var i=Math.floor(e/this.cell_size),s=Math.floor(t/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(e,t,i){i(0),i(1);e.exports=class{constructor(e,t,i,s,r){this.owner=null,this.cell_owner=null,this.setType(e),this.col=t,this.row=i,this.x=s,this.y=r}setType(e){this.state=e}}},function(e,t){e.exports=class{constructor(e,t){this.env=e,this.canvas=t,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(e){this.control_panel=e}defineEvents(){this.canvas.addEventListener("mousemove",e=>{this.updateMouseLocation(e.offsetX,e.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(e){e.preventDefault(),this.updateMouseLocation(e.offsetX,e.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(e){e.preventDefault(),this.updateMouseLocation(e.offsetX,e.offsetY),0==e.button&&(this.left_click=!0),2==e.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(e){e.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(e,t){var i=this.cur_cell,s=this.cur_org;this.mouse_x=e,this.mouse_y=t;var r=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=r[0],this.mouse_r=r[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(e,t,i){const s=i(14),r=i(25),o=i(26),n=i(28);e.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new o,this.controlpanel=new r(this),this.colorscheme=new n(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(e=60){e<=0&&(e=1),e>300&&(e=300),this.fps=e,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/e),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(e,t,i){"use strict";i.r(t);var s=i(12),r=i.n(s);$("document").ready((function(){(function(){let e=!1;return function(t){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substr(0,4)))&&(e=!0)}(navigator.userAgent||navigator.vendor||window.opera),e})()&&(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")),(new r.a).start(60)}))},function(e,t,i){const s=i(7),r=i(8),o=i(9),n=i(5),l=i(0),a=i(24),h=i(1);i(10);e.exports=class extends s{constructor(e){super(),this.renderer=new r("env-canvas","env",e),this.controller=new a(this,this.renderer.canvas);var t=Math.floor(this.renderer.height/e),i=Math.floor(this.renderer.width/e);this.grid_map=new o(i,t,e),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0}update(e){var t=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||t.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(t)}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(e){for(var t of e.reverse())this.total_mutability-=this.organisms[t].mutability,this.organisms.splice(t,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var e=this.grid_map.getCenter(),t=new n(e[0],e[1],this);t.addDefaultCell(l.mouth,0,0),t.addDefaultCell(l.producer,1,1),t.addDefaultCell(l.producer,-1,-1),this.addOrganism(t)}addOrganism(e){e.updateGrid(),this.total_mutability+=e.mutability,this.organisms.push(e),e.cells.length>this.largest_cell_count&&(this.largest_cell_count=e.cells.length)}averageMutability(){return this.organisms.length<1?0:this.total_mutability/this.organisms.length}changeCell(e,t,i,s){super.changeCell(e,t,i,s),this.renderer.addToRender(this.grid_map.cellAt(e,t)),i==l.wall&&this.walls.push(this.grid_map.cellAt(e,t))}clearWalls(){for(var e of this.walls)this.grid_map.cellAt(e.col,e.row).state==l.wall&&this.changeCell(e.col,e.row,l.empty,null)}clearOrganisms(){for(var e of this.organisms)e.die();this.organisms=[]}generateFood(){for(var e=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),t=h.foodDropProb,i=0;i3&&(e-=4),e}performFunction(){var e=this.look();this.org.brain.observe(e)}look(){var e=this.org.env,t=this.getAbsoluteDirection(),i=0,r=0;switch(t){case n.up:r=-1;break;case n.down:r=1;break;case n.right:i=1;break;case n.left:i=-1}for(var a=this.getRealCol(),h=this.getRealRow(),c=a,d=h,u=null,g=0;gthis.organism_record&&(this.organism_record=e),$("#org-record").text("Highest count: "+this.organism_record),$("#avg-mut").text("Average Mutation Rate: "+Math.round(100*this.engine.env.averageMutability())/100),$("#largest-org").text("Largest Organism: "+this.engine.env.largest_cell_count+" cells"),$("#reset-count").text("Auto reset count: "+this.engine.env.reset_count)}}},function(e,t,i){const s=i(7),r=i(5),o=i(9),n=i(8),l=i(0),a=i(27);i(2);e.exports=class extends s{constructor(){super(),this.is_active=!0;this.renderer=new n("editor-canvas","editor-env",13),this.controller=new a(this,this.renderer.canvas),this.grid_map=new o(15,15,13),this.clear()}update(){this.is_active&&this.renderer.renderHighlights()}changeCell(e,t,i,s){super.changeCell(e,t,i,s),this.renderFull()}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}addCellToOrg(e,t,i){var s=this.grid_map.getCenter(),r=e-s[0],o=t-s[1],n=this.organism.getLocalCell(r,o);if(null!=n){var l=this.organism.replaceCell(i,n.loc_col,n.loc_row,!1);this.changeCell(e,t,i,l)}else this.organism.canAddCellAt(r,o)&&this.changeCell(e,t,i,this.organism.addDefaultCell(i,r,o))}removeCellFromOrg(e,t){var i=this.grid_map.getCenter(),s=e-i[0],r=t-i[1];0!=s||0!=r?null!=this.organism.getLocalCell(s,r)&&this.organism.removeCell(s,r)&&this.changeCell(e,t,l.empty,null):alert("Cannot remove center cell")}setOrganismToCopyOf(e){this.grid_map.fillGrid(l.empty);var t=this.grid_map.getCenter();this.organism=new r(t[0],t[1],this,e),this.organism.updateGrid(),this.controller.updateDetails()}getCopyOfOrg(){return new r(0,0,null,this.organism)}clear(){this.grid_map.fillGrid(l.empty);var e=this.grid_map.getCenter();this.organism=new r(e[0],e[1],this,null),this.organism.addDefaultCell(l.mouth,0,0),this.organism.updateGrid()}}},function(e,t,i){const s=i(11),r=i(6),o=i(0),n=i(2),l=i(1);e.exports=class extends s{constructor(e,t){super(e,t),this.mode=r.None,this.edit_cell_type=null,this.highlight_org=!1,this.defineCellTypeSelection(),this.defineEditorDetails()}mouseMove(){(this.right_click||this.left_click)&&this.editOrganism()}mouseDown(){this.editOrganism()}mouseUp(){}getCurLocalCell(){return this.env.organism.getLocalCell(this.mouse_c-this.env.organism.c,this.mouse_r-this.env.organism.r)}editOrganism(){if(null!=this.edit_cell_type&&this.mode==r.Edit){if(this.left_click)if(this.edit_cell_type==o.eye&&this.cur_cell.state==o.eye){var e=this.getCurLocalCell();e.direction=n.rotateRight(e.direction),this.env.renderFull()}else this.env.addCellToOrg(this.mouse_c,this.mouse_r,this.edit_cell_type);this.right_click&&this.env.removeCellFromOrg(this.mouse_c,this.mouse_r),this.setBrainPanelVisibility(),this.setMoveRangeVisibility(),this.updateDetails()}}updateDetails(){$(".cell-count").text("Cell count: "+this.env.organism.cells.length)}defineCellTypeSelection(){var e=this;$(".cell-type").click((function(){switch(this.id){case"mouth":e.edit_cell_type=o.mouth;break;case"producer":e.edit_cell_type=o.producer;break;case"mover":e.edit_cell_type=o.mover;break;case"killer":e.edit_cell_type=o.killer;break;case"armor":e.edit_cell_type=o.armor;break;case"eye":e.edit_cell_type=o.eye}$(".cell-type").css("border-color","black");var t="#"+this.id+".cell-type";$(t).css("border-color","yellow")}))}defineEditorDetails(){this.details_html=$("#organism-details"),this.edit_details_html=$("#edit-organism-details"),this.decision_names=["ignore","move away","move towards"],$("#move-range-edit").change(function(){this.env.organism.move_range=parseInt($("#move-range-edit").val())}.bind(this)),$("#observation-type-edit").change(function(){this.setBrainEditorValues($("#observation-type-edit").val()),this.setBrainDetails()}.bind(this)),$("#reaction-edit").change(function(){var e=$("#observation-type-edit").val(),t=parseInt($("#reaction-edit").val());this.env.organism.brain.decisions[e]=t,this.setBrainDetails()}.bind(this))}clearDetailsPanel(){$("#organism-details").css("display","none"),$("#edit-organism-details").css("display","none")}setDetailsPanel(){this.clearDetailsPanel();var e=this.env.organism;$(".cell-count").text("Cell count: "+e.cells.length),$("#move-range").text("Move Range: "+e.move_range),$("#mutation-rate").text("Mutation Rate: "+e.mutability),l.useGlobalMutability?$("#mutation-rate").css("display","none"):$("#mutation-rate").css("display","block"),this.setMoveRangeVisibility(),this.setBrainPanelVisibility()&&this.setBrainDetails(),$("#organism-details").css("display","block")}setEditorPanel(){this.clearDetailsPanel();var e=this.env.organism;$(".cell-count").text("Cell count: "+e.cells.length),this.setMoveRangeVisibility()&&$("#move-range-edit").val(e.move_range),this.setBrainPanelVisibility()&&this.setBrainEditorValues($("#observation-type-edit").val()),$("#cell-selections").css("display","grid"),$("#edit-organism-details").css("display","block")}setBrainPanelVisibility(){var e=this.env.organism;return e.has_eyes&&e.is_mover?($(".brain-details").css("display","block"),!0):($(".brain-details").css("display","none"),!1)}setBrainDetails(){var e=[],t=[];for(var i in this.env.organism.brain.decisions){var s=this.env.organism.brain.decisions[i];1==s?t.push(i):2==s&&e.push(i)}$(".chase-types").text("Move Towards: "+e),$(".retreat-types").text("Move Away From: "+t)}setMoveRangeVisibility(){return this.env.organism.is_mover?($("#move-range-cont").css("display","block"),$("#move-range").css("display","block"),!0):($("#move-range-cont").css("display","none"),$("#move-range").css("display","none"),!1)}setBrainEditorValues(e){$("#observation-type-edit").val(e);var t=this.env.organism.brain.decisions[e];$("#reaction-edit").val(t)}}},function(e,t,i){const s=i(0);var r={empty:"#0E1318",food:"#2F7AB7",wall:"gray",mouth:"#DEB14D",producer:"#15DE59",mover:"#60D4FF",killer:"#F82380",armor:"#7230DB",eye:"#B6C1EA","eye-slit":"#0E1318"};e.exports=class{constructor(e,t){this.world_env=e,this.editor_env=t}loadColorScheme(){for(var e of s.all)e.color=r[e.name];for(var t in s.eye.slit_color=r["eye-slit"],r)$("#"+t+".cell-type ").css("background-color",r[t]),$("#"+t+".cell-legend-type").css("background-color",r[t]);this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid),this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid)}}}]); \ No newline at end of file +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./src/Controllers/CanvasController.js": +/*!*********************************************!*\ + !*** ./src/Controllers/CanvasController.js ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("\r\n\r\nclass CanvasController{\r\n constructor(env, canvas) {\r\n this.env = env;\r\n this.canvas = canvas;\r\n this.mouse_x;\r\n this.mouse_y;\r\n this.mouse_c;\r\n this.mouse_r;\r\n this.left_click = false;\r\n this.right_click = false;\r\n this.cur_cell = null;\r\n this.cur_org = null;\r\n this.highlight_org = true;\r\n this.defineEvents();\r\n }\r\n\r\n setControlPanel(panel){\r\n this.control_panel = panel;\r\n }\r\n\r\n defineEvents() {\r\n this.canvas.addEventListener('mousemove', e => {\r\n this.updateMouseLocation(e.offsetX, e.offsetY)\r\n this.mouseMove();\r\n });\r\n\r\n this.canvas.addEventListener('mouseup', function(evt) {\r\n evt.preventDefault();\r\n this.updateMouseLocation(evt.offsetX, evt.offsetY)\r\n this.mouseUp();\r\n this.left_click=false;\r\n this.right_click=false;\r\n }.bind(this));\r\n\r\n this.canvas.addEventListener('mousedown', function(evt) {\r\n evt.preventDefault();\r\n this.updateMouseLocation(evt.offsetX, evt.offsetY)\r\n if (evt.button == 0) {\r\n this.left_click = true;\r\n }\r\n if (evt.button == 2) \r\n this.right_click = true;\r\n this.mouseDown();\r\n }.bind(this));\r\n\r\n this.canvas.addEventListener('contextmenu', function(evt) {\r\n evt.preventDefault();\r\n });\r\n\r\n this.canvas.addEventListener('mouseleave', function(){\r\n this.right_click = false;\r\n this.left_click = false;\r\n this.env.renderer.clearAllHighlights(true);\r\n }.bind(this));\r\n\r\n }\r\n\r\n updateMouseLocation(offsetX, offsetY) {\r\n var prev_cell = this.cur_cell;\r\n var prev_org = this.cur_org;\r\n\r\n this.mouse_x = offsetX;\r\n this.mouse_y = offsetY;\r\n var colRow = this.env.grid_map.xyToColRow(this.mouse_x, this.mouse_y);\r\n this.mouse_c = colRow[0];\r\n this.mouse_r = colRow[1];\r\n this.cur_cell = this.env.grid_map.cellAt(this.mouse_c, this.mouse_r);\r\n this.cur_org = this.cur_cell.owner;\r\n\r\n if (this.cur_org != prev_org || this.cur_cell != prev_cell) {\r\n this.env.renderer.clearAllHighlights(true);\r\n if (this.cur_org != null && this.highlight_org) {\r\n this.env.renderer.highlightOrganism(this.cur_org);\r\n }\r\n else if (this.cur_cell != null) {\r\n this.env.renderer.highlightCell(this.cur_cell, true);\r\n }\r\n }\r\n }\r\n\r\n mouseMove() {\r\n alert(\"mouse move must be overridden\");\r\n }\r\n\r\n mouseDown() {\r\n alert(\"mouse down must be overridden\");\r\n }\r\n\r\n mouseUp(){\r\n alert(\"mouse up must be overridden\")\r\n }\r\n}\r\n\r\nmodule.exports = CanvasController;\n\n//# sourceURL=webpack:///./src/Controllers/CanvasController.js?"); + +/***/ }), + +/***/ "./src/Controllers/ControlModes.js": +/*!*****************************************!*\ + !*** ./src/Controllers/ControlModes.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("const Modes = {\r\n None: 0,\r\n FoodDrop: 1,\r\n WallDrop: 2,\r\n ClickKill: 3,\r\n Select: 4,\r\n Edit: 5,\r\n Clone: 6,\r\n Drag: 7\r\n}\r\n\r\nmodule.exports = Modes;\n\n//# sourceURL=webpack:///./src/Controllers/ControlModes.js?"); + +/***/ }), + +/***/ "./src/Controllers/ControlPanel.js": +/*!*****************************************!*\ + !*** ./src/Controllers/ControlPanel.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\n\r\nclass ControlPanel {\r\n constructor(engine) {\r\n this.engine = engine;\r\n this.defineMinMaxControls();\r\n this.defineEngineSpeedControls();\r\n this.defineGridSizeControls();\r\n this.defineTabNavigation();\r\n this.defineHyperparameterControls();\r\n this.defineModeControls();\r\n this.defineChallenges();\r\n this.fps = engine.fps;\r\n this.organism_record=0;\r\n this.env_controller = this.engine.env.controller;\r\n this.editor_controller = this.engine.organism_editor.controller;\r\n this.env_controller.setControlPanel(this);\r\n this.editor_controller.setControlPanel(this);\r\n }\r\n\r\n defineMinMaxControls(){\r\n $('#minimize').click ( function() {\r\n $('.control-panel').css('display', 'none');\r\n $('.hot-controls').css('display', 'block');\r\n });\r\n $('#maximize').click ( function() {\r\n $('.control-panel').css('display', 'grid');\r\n $('.hot-controls').css('display', 'none');\r\n });\r\n }\r\n\r\n defineEngineSpeedControls(){\r\n this.slider = document.getElementById(\"slider\");\r\n this.slider.oninput = function() {\r\n this.fps = this.slider.value\r\n if (this.engine.running) {\r\n this.changeEngineSpeed(this.fps);\r\n \r\n }\r\n $('#fps').text(\"Target FPS: \"+this.fps);\r\n }.bind(this);\r\n $('.pause-button').click(function() {\r\n $('.pause-button').find(\"i\").toggleClass(\"fa fa-pause\");\r\n $('.pause-button').find(\"i\").toggleClass(\"fa fa-play\");\r\n if (this.engine.running) {\r\n this.engine.stop();\r\n }\r\n else if (!this.engine.running){\r\n this.engine.start(this.fps);\r\n }\r\n }.bind(this));\r\n }\r\n\r\n defineGridSizeControls() {\r\n $('#fill-window').change(function() {\r\n if (this.checked)\r\n $('.col-row-input').css('display' ,'none');\r\n else\r\n $('.col-row-input').css('display' ,'block');\r\n });\r\n\r\n $('#resize').click(function() {\r\n var cell_size = $('#cell-size').val();\r\n var fill_window = $('#fill-window').is(\":checked\");\r\n if (fill_window) {\r\n this.engine.env.resizeFillWindow(cell_size);\r\n }\r\n else {\r\n var cols = $('#col-input').val();\r\n var rows = $('#row-input').val();\r\n this.engine.env.resizeGridColRow(cell_size, cols, rows);\r\n }\r\n \r\n }.bind(this));\r\n }\r\n\r\n defineTabNavigation() {\r\n var self = this;\r\n $('.tabnav-item').click(function() {\r\n $('.tab').css('display', 'none');\r\n var tab = '#'+this.id+'.tab';\r\n self.engine.organism_editor.is_active = (this.id == 'editor');\r\n $(tab).css('display', 'grid');\r\n });\r\n }\r\n\r\n defineHyperparameterControls() {\r\n $('#food-prod-prob').change(function() {\r\n var food_prob = \r\n Hyperparams.foodProdProb = $('#food-prod-prob').val();;\r\n }.bind(this));\r\n $('#lifespan-multiplier').change(function() {\r\n Hyperparams.lifespanMultiplier = $('#lifespan-multiplier').val();\r\n }.bind(this));\r\n\r\n $('#mover-rot').change(function() {\r\n Hyperparams.moversCanRotate = this.checked;\r\n });\r\n $('#offspring-rot').change(function() {\r\n Hyperparams.offspringRotate = this.checked;\r\n });\r\n $('#insta-kill').change(function() {\r\n Hyperparams.instaKill = this.checked;\r\n });\r\n $('#look-range').change(function() {\r\n Hyperparams.lookRange = $('#look-range').val();\r\n });\r\n $('#food-drop-rate').change(function() {\r\n Hyperparams.foodDropProb = $('#food-drop-rate').val();\r\n });\r\n\r\n $('#evolved-mutation').change( function() {\r\n if (this.checked) {\r\n $('.global-mutation-in').css('display', 'none');\r\n $('#avg-mut').css('display', 'block');\r\n }\r\n else {\r\n $('.global-mutation-in').css('display', 'block');\r\n $('#avg-mut').css('display', 'none');\r\n }\r\n Hyperparams.useGlobalMutability = !this.checked;\r\n });\r\n $('#global-mutation').change( function() {\r\n Hyperparams.globalMutability = $('#global-mutation').val();\r\n });\r\n $('.mut-prob').change( function() {\r\n switch(this.id){\r\n case \"add-prob\":\r\n Hyperparams.addProb = this.value;\r\n Hyperparams.balanceMutationProbs(1);\r\n break;\r\n case \"change-prob\":\r\n Hyperparams.changeProb = this.value;\r\n Hyperparams.balanceMutationProbs(2);\r\n break;\r\n case \"remove-prob\":\r\n Hyperparams.removeProb = this.value;\r\n Hyperparams.balanceMutationProbs(3);\r\n break;\r\n }\r\n $('#add-prob').val(Math.floor(Hyperparams.addProb));\r\n $('#change-prob').val(Math.floor(Hyperparams.changeProb));\r\n $('#remove-prob').val(Math.floor(Hyperparams.removeProb));\r\n });\r\n $('#movers-produce').change( function() {\r\n Hyperparams.moversCanProduce = this.checked;\r\n });\r\n $('#food-blocks').change( function() {\r\n Hyperparams.foodBlocksReproduction = this.checked; \r\n });\r\n $('#reset-rules').click( function() {\r\n Hyperparams.setDefaults();\r\n $('#food-prod-prob').val(Hyperparams.foodProdProb);\r\n $('#lifespan-multiplier').val(Hyperparams.lifespanMultiplier);\r\n $('#mover-rot').prop('checked', Hyperparams.moversCanRotate);\r\n $('#offspring-rot').prop('checked', Hyperparams.offspringRotate);\r\n $('#insta-kill').prop('checked', Hyperparams.instaKill);\r\n $('#evolved-mutation').prop('checked', !Hyperparams.useGlobalMutability);\r\n $('#add-prob').val(Hyperparams.addProb);\r\n $('#change-prob').val(Hyperparams.changeProb);\r\n $('#remove-prob').val(Hyperparams.removeProb);\r\n $('#movers-produce').prop('checked', Hyperparams.moversCanProduce);\r\n $('#food-blocks').prop('checked', Hyperparams.foodBlocksReproduction);\r\n if (!Hyperparams.useGlobalMutability) {\r\n $('.global-mutation-in').css('display', 'none');\r\n $('#avg-mut').css('display', 'block');\r\n }\r\n else {\r\n $('.global-mutation-in').css('display', 'block');\r\n $('#avg-mut').css('display', 'none');\r\n }\r\n });\r\n }\r\n\r\n defineModeControls() {\r\n var self = this;\r\n $('.edit-mode-btn').click( function() {\r\n $('#cell-selections').css('display', 'none');\r\n $('#organism-options').css('display', 'none');\r\n self.editor_controller.setDetailsPanel();\r\n switch(this.id){\r\n case \"food-drop\":\r\n self.setMode(Modes.FoodDrop);\r\n break;\r\n case \"wall-drop\":\r\n self.setMode(Modes.WallDrop);\r\n break;\r\n case \"click-kill\":\r\n self.setMode(Modes.ClickKill);\r\n break;\r\n case \"select\":\r\n self.setMode(Modes.Select);\r\n break;\r\n case \"edit\":\r\n self.setMode(Modes.Edit);\r\n self.editor_controller.setEditorPanel();\r\n break;\r\n case \"drop-org\":\r\n self.setMode(Modes.Clone);\r\n self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg();\r\n self.env_controller.make_new_species = true;\r\n break;\r\n case \"drag-view\":\r\n self.setMode(Modes.Drag);\r\n }\r\n $('.edit-mode-btn').css('background-color', '#9099c2');\r\n $('#'+this.id).css('background-color', '#81d2c7');\r\n });\r\n\r\n $('.reset-view').click( function(){\r\n this.env_controller.resetView();\r\n }.bind(this));\r\n\r\n var env = this.engine.env;\r\n $('#reset-env').click( function() {\r\n this.engine.env.reset();\r\n }.bind(this));\r\n $('#auto-reset').change(function() {\r\n env.auto_reset = this.checked;\r\n });\r\n $('#clear-walls').click( function() {\r\n if (confirm(\"Are you sure you want to clear all the walls?\")) {\r\n this.engine.env.clearWalls();\r\n }\r\n }.bind(this));\r\n $('#clear-editor').click( function() {\r\n this.engine.organism_editor.clear();\r\n this.editor_controller.setEditorPanel();\r\n }.bind(this));\r\n }\r\n\r\n defineChallenges() {\r\n $('.challenge-btn').click(function() {\r\n $('#challenge-title').text($(this).text());\r\n $('#challenge-description').text($(this).val());\r\n });\r\n }\r\n\r\n setMode(mode) {\r\n this.env_controller.mode = mode;\r\n this.editor_controller.mode = mode;\r\n }\r\n\r\n setEditorOrganism(org) {\r\n this.engine.organism_editor.setOrganismToCopyOf(org);\r\n this.editor_controller.clearDetailsPanel();\r\n this.editor_controller.setDetailsPanel();\r\n }\r\n\r\n changeEngineSpeed(change_val) {\r\n this.engine.stop();\r\n this.engine.start(change_val)\r\n this.fps = this.engine.fps;\r\n }\r\n\r\n update() {\r\n $('#fps-actual').text(\"Actual FPS: \" + Math.floor(this.engine.actual_fps));\r\n var org_count = this.engine.env.organisms.length;\r\n $('#org-count').text(\"Organism count: \" + org_count);\r\n if (org_count > this.organism_record) \r\n this.organism_record = org_count;\r\n $('#org-record').text(\"Highest count: \" + this.organism_record);\r\n $('#avg-mut').text(\"Average Mutation Rate: \" + Math.round(this.engine.env.averageMutability() * 100) / 100);\r\n $('#largest-org').text(\"Largest Organism: \" + this.engine.env.largest_cell_count + \" cells\");\r\n $('#reset-count').text(\"Auto reset count: \" + this.engine.env.reset_count);\r\n }\r\n\r\n}\r\n\r\n\r\nmodule.exports = ControlPanel;\n\n//# sourceURL=webpack:///./src/Controllers/ControlPanel.js?"); + +/***/ }), + +/***/ "./src/Controllers/EditorController.js": +/*!*********************************************!*\ + !*** ./src/Controllers/EditorController.js ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CanvasController = __webpack_require__(/*! ./CanvasController */ \"./src/Controllers/CanvasController.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Directions = __webpack_require__(/*! ../Organism/Directions */ \"./src/Organism/Directions.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\n\r\nclass EditorController extends CanvasController{\r\n constructor(env, canvas) {\r\n super(env, canvas);\r\n this.mode = Modes.None;\r\n this.edit_cell_type = null;\r\n this.highlight_org = false;\r\n this.defineCellTypeSelection();\r\n this.defineEditorDetails();\r\n }\r\n\r\n mouseMove() {\r\n if (this.right_click || this.left_click)\r\n this.editOrganism();\r\n }\r\n\r\n mouseDown() {\r\n this.editOrganism();\r\n }\r\n\r\n mouseUp(){}\r\n\r\n getCurLocalCell(){\r\n return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c, this.mouse_r-this.env.organism.r);\r\n }\r\n\r\n editOrganism() {\r\n if (this.edit_cell_type == null || this.mode != Modes.Edit)\r\n return;\r\n if (this.left_click){\r\n if(this.edit_cell_type == CellStates.eye && this.cur_cell.state == CellStates.eye) {\r\n var loc_cell = this.getCurLocalCell();\r\n loc_cell.direction = Directions.rotateRight(loc_cell.direction);\r\n this.env.renderFull();\r\n }\r\n else\r\n this.env.addCellToOrg(this.mouse_c, this.mouse_r, this.edit_cell_type);\r\n }\r\n if (this.right_click)\r\n this.env.removeCellFromOrg(this.mouse_c, this.mouse_r);\r\n this.setBrainPanelVisibility();\r\n this.setMoveRangeVisibility();\r\n this.updateDetails();\r\n }\r\n\r\n updateDetails() {\r\n $('.cell-count').text(\"Cell count: \"+this.env.organism.anatomy.cells.length);\r\n }\r\n\r\n defineCellTypeSelection() {\r\n var self = this;\r\n $('.cell-type').click( function() {\r\n switch(this.id){\r\n case \"mouth\":\r\n self.edit_cell_type = CellStates.mouth;\r\n break;\r\n case \"producer\":\r\n self.edit_cell_type = CellStates.producer;\r\n break;\r\n case \"mover\":\r\n self.edit_cell_type = CellStates.mover;\r\n break;\r\n case \"killer\":\r\n self.edit_cell_type = CellStates.killer;\r\n break;\r\n case \"armor\":\r\n self.edit_cell_type = CellStates.armor;\r\n break;\r\n case \"eye\":\r\n self.edit_cell_type = CellStates.eye;\r\n break;\r\n }\r\n $(\".cell-type\" ).css( \"border-color\", \"black\" );\r\n var selected = '#'+this.id+'.cell-type';\r\n $(selected).css(\"border-color\", \"yellow\");\r\n });\r\n }\r\n\r\n defineEditorDetails() {\r\n this.details_html = $('#organism-details');\r\n this.edit_details_html = $('#edit-organism-details');\r\n\r\n this.decision_names = [\"ignore\", \"move away\", \"move towards\"];\r\n\r\n $('#move-range-edit').change ( function() {\r\n this.env.organism.move_range = parseInt($('#move-range-edit').val());\r\n }.bind(this));\r\n $('#observation-type-edit').change ( function() {\r\n this.setBrainEditorValues($('#observation-type-edit').val());\r\n this.setBrainDetails();\r\n }.bind(this));\r\n $('#reaction-edit').change ( function() {\r\n var obs = $('#observation-type-edit').val();\r\n var decision = parseInt($('#reaction-edit').val());\r\n this.env.organism.brain.decisions[obs] = decision;\r\n this.setBrainDetails();\r\n }.bind(this));\r\n }\r\n\r\n clearDetailsPanel() {\r\n $('#organism-details').css('display', 'none');\r\n $('#edit-organism-details').css('display', 'none');\r\n }\r\n\r\n setDetailsPanel() {\r\n this.clearDetailsPanel();\r\n var org = this.env.organism;\r\n \r\n $('.cell-count').text(\"Cell count: \"+org.anatomy.cells.length);\r\n $('#move-range').text(\"Move Range: \"+org.move_range);\r\n $('#mutation-rate').text(\"Mutation Rate: \"+org.mutability);\r\n if (Hyperparams.useGlobalMutability) {\r\n $('#mutation-rate').css('display', 'none');\r\n }\r\n else {\r\n $('#mutation-rate').css('display', 'block');\r\n }\r\n\r\n this.setMoveRangeVisibility();\r\n\r\n if (this.setBrainPanelVisibility()) {\r\n this.setBrainDetails();\r\n\r\n }\r\n $('#organism-details').css('display', 'block');\r\n }\r\n\r\n setEditorPanel() {\r\n this.clearDetailsPanel();\r\n var org = this.env.organism;\r\n\r\n $('.cell-count').text(\"Cell count: \"+org.anatomy.cells.length);\r\n if (this.setMoveRangeVisibility()){\r\n $('#move-range-edit').val(org.move_range);\r\n }\r\n \r\n if (this.setBrainPanelVisibility()){\r\n this.setBrainEditorValues($('#observation-type-edit').val());\r\n }\r\n\r\n $('#cell-selections').css('display', 'grid');\r\n $('#edit-organism-details').css('display', 'block');\r\n }\r\n\r\n setBrainPanelVisibility() {\r\n var org = this.env.organism;\r\n if (org.anatomy.has_eyes && org.anatomy.is_mover) {\r\n $('.brain-details').css('display', 'block');\r\n return true;\r\n }\r\n $('.brain-details').css('display', 'none');\r\n return false;\r\n }\r\n\r\n setBrainDetails() {\r\n var chase_types = [];\r\n var retreat_types = [];\r\n for(var cell_name in this.env.organism.brain.decisions) {\r\n var decision = this.env.organism.brain.decisions[cell_name];\r\n if (decision == 1) {\r\n retreat_types.push(cell_name)\r\n }\r\n else if (decision == 2) {\r\n chase_types.push(cell_name);\r\n }\r\n }\r\n $('.chase-types').text(\"Move Towards: \" + chase_types);\r\n $('.retreat-types').text(\"Move Away From: \" + retreat_types);\r\n }\r\n\r\n setMoveRangeVisibility() {\r\n var org = this.env.organism;\r\n if (org.anatomy.is_mover) {\r\n $('#move-range-cont').css('display', 'block');\r\n $('#move-range').css('display', 'block');\r\n return true;\r\n }\r\n $('#move-range-cont').css('display', 'none');\r\n $('#move-range').css('display', 'none');\r\n return false;\r\n }\r\n\r\n setBrainEditorValues(name) {\r\n $('#observation-type-edit').val(name);\r\n var reaction = this.env.organism.brain.decisions[name];\r\n $('#reaction-edit').val(reaction);\r\n }\r\n}\r\n\r\nmodule.exports = EditorController;\r\n\n\n//# sourceURL=webpack:///./src/Controllers/EditorController.js?"); + +/***/ }), + +/***/ "./src/Controllers/EnvironmentController.js": +/*!**************************************************!*\ + !*** ./src/Controllers/EnvironmentController.js ***! + \**************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CanvasController = __webpack_require__(/*! ./CanvasController */ \"./src/Controllers/CanvasController.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Neighbors = __webpack_require__(/*! ../Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass EnvironmentController extends CanvasController{\r\n constructor(env, canvas) {\r\n super(env, canvas);\r\n this.mode = Modes.Drag;\r\n this.org_to_clone = null;\r\n this.species_to_clone = null;\r\n this.make_new_species = false;\r\n this.defineZoomControls();\r\n this.scale = 1;\r\n }\r\n\r\n defineZoomControls() {\r\n var scale = 1;\r\n var zoom_speed = 0.5;\r\n const el = document.querySelector('#env-canvas');\r\n el.onwheel = function zoom(event) {\r\n event.preventDefault();\r\n\r\n var sign = -Math.sign(event.deltaY);\r\n\r\n // Restrict scale\r\n scale = Math.max(0.5, this.scale+(sign*zoom_speed));\r\n\r\n if (scale != 0.5) {\r\n var cur_top = parseInt($('#env-canvas').css('top'));\r\n var cur_left = parseInt($('#env-canvas').css('left'));\r\n if (sign == 1) {\r\n // If we're zooming in, zoom towards wherever the mouse is\r\n var diff_x = ((this.canvas.width/2-cur_left/this.scale) - this.mouse_x)*this.scale/1.5;\r\n var diff_y = ((this.canvas.height/2-cur_top/this.scale) - this.mouse_y)*this.scale/1.5;\r\n }\r\n else {\r\n // If we're zooming out, zoom out towards the center\r\n var diff_x = -cur_left/scale;\r\n var diff_y = -cur_top/scale;\r\n }\r\n $('#env-canvas').css('top', (cur_top+diff_y)+'px');\r\n $('#env-canvas').css('left', (cur_left+diff_x)+'px');\r\n }\r\n \r\n // Apply scale transform\r\n el.style.transform = `scale(${scale})`;\r\n this.scale = scale;\r\n\r\n }.bind(this);\r\n }\r\n\r\n resetView() {\r\n $('#env-canvas').css('transform', 'scale(1)');\r\n $('#env-canvas').css('top', '0px');\r\n $('#env-canvas').css('left', '0px');\r\n this.scale = 1;\r\n }\r\n\r\n updateMouseLocation(offsetX, offsetY){\r\n \r\n super.updateMouseLocation(offsetX, offsetY);\r\n }\r\n\r\n mouseMove() {\r\n this.performModeAction();\r\n }\r\n\r\n mouseDown() {\r\n this.start_x = this.mouse_x;\r\n this.start_y = this.mouse_y;\r\n this.performModeAction();\r\n }\r\n\r\n mouseUp() {\r\n\r\n }\r\n\r\n performModeAction() {\r\n var mode = this.mode;\r\n var right_click = this.right_click;\r\n var left_click = this.left_click;\r\n if (mode != Modes.None && (right_click || left_click)) {\r\n var cell = this.cur_cell;\r\n if (cell == null){\r\n return;\r\n }\r\n switch(mode) {\r\n case Modes.FoodDrop:\r\n if (left_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.food, false);\r\n }\r\n else if (right_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.empty, false);\r\n }\r\n break;\r\n case Modes.WallDrop:\r\n if (left_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.wall, true);\r\n\r\n }\r\n else if (right_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.empty, false);\r\n }\r\n break;\r\n case Modes.ClickKill:\r\n this.killNearOrganisms();\r\n break;\r\n\r\n case Modes.Select:\r\n if (this.cur_org == null) {\r\n this.cur_org = this.findNearOrganism();\r\n }\r\n if (this.cur_org != null){\r\n this.control_panel.setEditorOrganism(this.cur_org);\r\n }\r\n break;\r\n\r\n case Modes.Clone:\r\n if (this.org_to_clone != null){\r\n var new_org = new Organism(this.mouse_c, this.mouse_r, this.env, this.org_to_clone);\r\n if (this.make_new_species){\r\n this.species_to_clone = FossilRecord.addSpecies(new_org, null)\r\n this.make_new_species = false;\r\n }\r\n else {\r\n new_org.species = this.species_to_clone;\r\n this.species_to_clone.addPop();\r\n }\r\n if (new_org.isClear(this.mouse_c, this.mouse_r)){\r\n this.env.addOrganism(new_org)\r\n }\r\n }\r\n break;\r\n case Modes.Drag:\r\n var cur_top = parseInt($('#env-canvas').css('top'), 10);\r\n var cur_left = parseInt($('#env-canvas').css('left'), 10);\r\n var new_top = cur_top + ((this.mouse_y - this.start_y)*this.scale);\r\n var new_left = cur_left + ((this.mouse_x - this.start_x)*this.scale);\r\n $('#env-canvas').css('top', new_top+'px');\r\n $('#env-canvas').css('left', new_left+'px');\r\n break;\r\n }\r\n }\r\n }\r\n\r\n dropCellType(col, row, state, killBlocking=false) {\r\n for (var loc of Neighbors.allSelf){\r\n var c=col + loc[0];\r\n var r=row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell == null)\r\n continue;\r\n if (killBlocking && cell.owner != null){\r\n cell.owner.die();\r\n }\r\n else if (cell.owner != null) {\r\n continue;\r\n }\r\n this.env.changeCell(c, r, state, null);\r\n }\r\n }\r\n\r\n findNearOrganism() {\r\n for (var loc of Neighbors.all){\r\n var c = this.cur_cell.col + loc[0];\r\n var r = this.cur_cell.row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell != null && cell.owner != null)\r\n return cell.owner;\r\n }\r\n return null;\r\n }\r\n\r\n killNearOrganisms() {\r\n for (var loc of Neighbors.allSelf){\r\n var c = this.cur_cell.col + loc[0];\r\n var r = this.cur_cell.row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell != null && cell.owner != null)\r\n cell.owner.die();\r\n }\r\n }\r\n\r\n\r\n}\r\n\r\nmodule.exports = EnvironmentController;\r\n\n\n//# sourceURL=webpack:///./src/Controllers/EnvironmentController.js?"); + +/***/ }), + +/***/ "./src/Engine.js": +/*!***********************!*\ + !*** ./src/Engine.js ***! + \***********************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const WorldEnvironment = __webpack_require__(/*! ./Environments/WorldEnvironment */ \"./src/Environments/WorldEnvironment.js\");\r\nconst ControlPanel = __webpack_require__(/*! ./Controllers/ControlPanel */ \"./src/Controllers/ControlPanel.js\");\r\nconst OrganismEditor = __webpack_require__(/*! ./Environments/OrganismEditor */ \"./src/Environments/OrganismEditor.js\");\r\nconst ColorScheme = __webpack_require__(/*! ./Rendering/ColorScheme */ \"./src/Rendering/ColorScheme.js\");\r\n\r\nconst render_speed = 60;\r\n\r\nclass Engine{\r\n constructor(){\r\n this.fps = 60;\r\n this.env = new WorldEnvironment(5);\r\n this.organism_editor = new OrganismEditor();\r\n this.controlpanel = new ControlPanel(this);\r\n this.colorscheme = new ColorScheme(this.env, this.organism_editor);\r\n this.colorscheme.loadColorScheme();\r\n this.env.OriginOfLife();\r\n this.last_update = Date.now();\r\n this.delta_time = 0;\r\n this.actual_fps = 0;\r\n this.running = false;\r\n }\r\n\r\n start(fps=60) {\r\n if (fps <= 0)\r\n fps = 1;\r\n if (fps > 300)\r\n fps = 300;\r\n this.fps = fps;\r\n this.game_loop = setInterval(function(){this.environmentUpdate();}.bind(this), 1000/fps);\r\n this.running = true;\r\n if (this.fps >= render_speed) {\r\n if (this.render_loop != null) {\r\n clearInterval(this.render_loop);\r\n this.render_loop = null;\r\n }\r\n }\r\n else\r\n this.setRenderLoop();\r\n }\r\n \r\n stop() {\r\n clearInterval(this.game_loop);\r\n this.running = false;\r\n this.setRenderLoop();\r\n }\r\n\r\n setRenderLoop() {\r\n if (this.render_loop == null) {\r\n this.render_loop = setInterval(function(){this.necessaryUpdate();}.bind(this), 1000/render_speed);\r\n }\r\n }\r\n\r\n\r\n environmentUpdate() {\r\n this.delta_time = Date.now() - this.last_update;\r\n this.last_update = Date.now();\r\n this.env.update(this.delta_time);\r\n this.actual_fps = 1/this.delta_time*1000;\r\n if(this.render_loop == null){\r\n this.necessaryUpdate();\r\n }\r\n \r\n }\r\n\r\n necessaryUpdate() {\r\n this.env.render();\r\n this.controlpanel.update();\r\n this.organism_editor.update();\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Engine;\r\n\n\n//# sourceURL=webpack:///./src/Engine.js?"); + +/***/ }), + +/***/ "./src/Environments/Environment.js": +/*!*****************************************!*\ + !*** ./src/Environments/Environment.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("\r\n//An evironment has a grid_map, controller, and renderer\r\nclass Environment{\r\n constructor() {\r\n }\r\n\r\n update(){\r\n alert(\"Environment.update() must be overriden\");\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n this.grid_map.setCellType(c, r, state);\r\n this.grid_map.setCellOwner(c, r, owner);\r\n }\r\n}\r\n\r\n\r\nmodule.exports = Environment;\n\n//# sourceURL=webpack:///./src/Environments/Environment.js?"); + +/***/ }), + +/***/ "./src/Environments/OrganismEditor.js": +/*!********************************************!*\ + !*** ./src/Environments/OrganismEditor.js ***! + \********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environments/Environment.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst GridMap = __webpack_require__(/*! ../Grid/GridMap */ \"./src/Grid/GridMap.js\");\r\nconst Renderer = __webpack_require__(/*! ../Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst EditorController = __webpack_require__(/*! ../Controllers/EditorController */ \"./src/Controllers/EditorController.js\");\r\n\r\nclass OrganismEditor extends Environment{\r\n constructor() {\r\n super();\r\n this.is_active = true;\r\n var cell_size = 13;\r\n this.renderer = new Renderer('editor-canvas', 'editor-env', cell_size);\r\n this.controller = new EditorController(this, this.renderer.canvas);\r\n this.grid_map = new GridMap(15, 15, cell_size);\r\n this.clear();\r\n }\r\n\r\n update() {\r\n if (this.is_active){\r\n this.renderer.renderHighlights();\r\n }\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n super.changeCell(c, r, state, owner);\r\n this.renderFull();\r\n }\r\n\r\n renderFull() {\r\n this.renderer.renderFullGrid(this.grid_map.grid);\r\n }\r\n\r\n // absolute c r, not local\r\n addCellToOrg(c, r, state) {\r\n var center = this.grid_map.getCenter();\r\n var loc_c = c - center[0];\r\n var loc_r = r - center[1];\r\n var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)\r\n if (prev_cell != null) {\r\n var new_cell = this.organism.anatomy.replaceCell(state, prev_cell.loc_col, prev_cell.loc_row, false);\r\n this.changeCell(c, r, state, new_cell);\r\n }\r\n else if (this.organism.anatomy.canAddCellAt(loc_c, loc_r)){\r\n this.changeCell(c, r, state, this.organism.anatomy.addDefaultCell(state, loc_c, loc_r));\r\n }\r\n }\r\n\r\n removeCellFromOrg(c, r) {\r\n var center = this.grid_map.getCenter();\r\n var loc_c = c - center[0];\r\n var loc_r = r - center[1];\r\n if (loc_c == 0 && loc_r == 0){\r\n alert(\"Cannot remove center cell\");\r\n return;\r\n }\r\n var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)\r\n if (prev_cell != null) {\r\n if (this.organism.anatomy.removeCell(loc_c, loc_r)) {\r\n this.changeCell(c, r, CellStates.empty, null);\r\n }\r\n }\r\n }\r\n\r\n setOrganismToCopyOf(orig_org){\r\n this.grid_map.fillGrid(CellStates.empty);\r\n var center = this.grid_map.getCenter();\r\n this.organism = new Organism(center[0], center[1], this, orig_org);\r\n this.organism.updateGrid();\r\n this.controller.updateDetails();\r\n }\r\n \r\n getCopyOfOrg() {\r\n var new_org = new Organism(0, 0, null, this.organism);\r\n return new_org;\r\n }\r\n\r\n clear() {\r\n this.grid_map.fillGrid(CellStates.empty);\r\n var center = this.grid_map.getCenter();\r\n this.organism = new Organism(center[0], center[1], this, null);\r\n this.organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0);\r\n this.organism.updateGrid();\r\n }\r\n}\r\n\r\nmodule.exports = OrganismEditor;\n\n//# sourceURL=webpack:///./src/Environments/OrganismEditor.js?"); + +/***/ }), + +/***/ "./src/Environments/WorldEnvironment.js": +/*!**********************************************!*\ + !*** ./src/Environments/WorldEnvironment.js ***! + \**********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environments/Environment.js\");\r\nconst Renderer = __webpack_require__(/*! ../Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst GridMap = __webpack_require__(/*! ../Grid/GridMap */ \"./src/Grid/GridMap.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst EnvironmentController = __webpack_require__(/*! ../Controllers/EnvironmentController */ \"./src/Controllers/EnvironmentController.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters.js */ \"./src/Hyperparameters.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass WorldEnvironment extends Environment{\r\n constructor(cell_size) {\r\n super();\r\n this.renderer = new Renderer('env-canvas', 'env', cell_size);\r\n this.controller = new EnvironmentController(this, this.renderer.canvas);\r\n var grid_rows = Math.floor(this.renderer.height / cell_size);\r\n var grid_cols = Math.floor(this.renderer.width / cell_size);\r\n this.grid_map = new GridMap(grid_cols, grid_rows, cell_size);\r\n this.organisms = [];\r\n this.walls = [];\r\n this.total_mutability = 0;\r\n this.auto_reset = true;\r\n this.largest_cell_count = 0;\r\n this.reset_count = 0;\r\n this.total_ticks = 0;\r\n FossilRecord.setEnv(this);\r\n }\r\n\r\n update(delta_time) {\r\n this.total_ticks ++;\r\n var to_remove = [];\r\n for (var i in this.organisms) {\r\n var org = this.organisms[i];\r\n if (!org.living || !org.update()) {\r\n to_remove.push(i);\r\n }\r\n }\r\n if (Hyperparams.foodDropProb > 0) {\r\n this.generateFood();\r\n }\r\n this.removeOrganisms(to_remove);\r\n }\r\n\r\n render() {\r\n this.renderer.renderCells();\r\n this.renderer.renderHighlights();\r\n }\r\n\r\n removeOrganisms(org_indeces) {\r\n for (var i of org_indeces.reverse()){\r\n this.total_mutability -= this.organisms[i].mutability;\r\n this.organisms.splice(i, 1);\r\n }\r\n if (this.organisms.length == 0 && this.auto_reset){\r\n this.reset_count++;\r\n this.reset();\r\n }\r\n }\r\n\r\n OriginOfLife() {\r\n var center = this.grid_map.getCenter();\r\n var org = new Organism(center[0], center[1], this);\r\n org.anatomy.addDefaultCell(CellStates.mouth, 0, 0);\r\n org.anatomy.addDefaultCell(CellStates.producer, 1, 1);\r\n org.anatomy.addDefaultCell(CellStates.producer, -1, -1);\r\n this.addOrganism(org);\r\n FossilRecord.addSpecies(org, null);\r\n }\r\n\r\n addOrganism(organism) {\r\n organism.updateGrid();\r\n this.total_mutability += organism.mutability;\r\n this.organisms.push(organism);\r\n if (organism.anatomy.cells.length > this.largest_cell_count) \r\n this.largest_cell_count = organism.anatomy.cells.length;\r\n }\r\n\r\n averageMutability() {\r\n if (this.organisms.length < 1)\r\n return 0;\r\n return this.total_mutability / this.organisms.length;\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n super.changeCell(c, r, state, owner);\r\n this.renderer.addToRender(this.grid_map.cellAt(c, r));\r\n if(state == CellStates.wall)\r\n this.walls.push(this.grid_map.cellAt(c, r));\r\n }\r\n\r\n clearWalls() {\r\n for(var wall of this.walls){\r\n if (this.grid_map.cellAt(wall.col, wall.row).state == CellStates.wall)\r\n this.changeCell(wall.col, wall.row, CellStates.empty, null);\r\n }\r\n }\r\n\r\n clearOrganisms() {\r\n for (var org of this.organisms)\r\n org.die();\r\n this.organisms = [];\r\n }\r\n\r\n generateFood() {\r\n var num_food = Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*Hyperparams.foodDropProb/50000), 1)\r\n var prob = Hyperparams.foodDropProb;\r\n for (var i=0; i=0 && row>=0;\r\n }\r\n\r\n getCenter(){\r\n return [Math.floor(this.cols/2), Math.floor(this.rows/2)]\r\n }\r\n\r\n xyToColRow(x, y) {\r\n var c = Math.floor(x/this.cell_size);\r\n var r = Math.floor(y/this.cell_size);\r\n if (c >= this.cols)\r\n c = this.cols-1;\r\n else if (c < 0)\r\n c = 0;\r\n if (r >= this.rows)\r\n r = this.rows-1;\r\n else if (r < 0)\r\n r = 0;\r\n return [c, r];\r\n }\r\n}\r\n\r\nmodule.exports = GridMap;\r\n\n\n//# sourceURL=webpack:///./src/Grid/GridMap.js?"); + +/***/ }), + +/***/ "./src/Grid/Neighbors.js": +/*!*******************************!*\ + !*** ./src/Grid/Neighbors.js ***! + \*******************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("// contains local cell values for the following:\r\n\r\n//all ...\r\n// .x.\r\n// ...\r\n\r\n//adjacent .\r\n// .x.\r\n// .\r\n\r\n//corners . .\r\n// x\r\n// . .\r\n\r\n//allSelf ...\r\n// ...\r\n// ...\r\n\r\nconst Neighbors = {\r\n all: [[0, 1],[0, -1],[1, 0],[-1, 0],[-1, -1],[1, 1],[-1, 1],[1, -1]],\r\n adjacent: [[0, 1],[0, -1],[1, 0],[-1, 0]],\r\n corners: [[-1, -1],[1, 1],[-1, 1],[1, -1]],\r\n allSelf: [[0, 0],[0, 1],[0, -1],[1, 0],[-1, 0],[-1, -1],[1, 1],[-1, 1],[1, -1]]\r\n}\r\n\r\nmodule.exports = Neighbors;\n\n//# sourceURL=webpack:///./src/Grid/Neighbors.js?"); + +/***/ }), + +/***/ "./src/Hyperparameters.js": +/*!********************************!*\ + !*** ./src/Hyperparameters.js ***! + \********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Neighbors = __webpack_require__(/*! ./Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\n\r\nconst Hyperparams = {\r\n setDefaults: function() {\r\n this.lifespanMultiplier = 100;\r\n this.foodProdProb = 4;\r\n this.foodProdProbScalar = 4;\r\n this.killableNeighbors = Neighbors.adjacent;\r\n this.edibleNeighbors = Neighbors.adjacent;\r\n this.growableNeighbors = Neighbors.adjacent;\r\n\r\n this.useGlobalMutability = false;\r\n this.globalMutability = 5;\r\n this.addProb = 33;\r\n this.changeProb = 33;\r\n this.removeProb = 33;\r\n \r\n this.moversCanRotate = true;\r\n this.offspringRotate = true;\r\n\r\n this.foodBlocksReproduction = true;\r\n this.moversCanProduce = false;\r\n\r\n this.instaKill = false;\r\n\r\n this.lookRange = 20;\r\n\r\n this.foodDropProb = 0;\r\n },\r\n\r\n balanceMutationProbs : function(choice) {\r\n if (choice == 1) {\r\n var remaining = 100 - this.addProb;\r\n this.changeProb = remaining/2;\r\n this.removeProb = remaining/2;\r\n }\r\n else if (choice == 2) {\r\n var remaining = 100 - this.changeProb;\r\n this.addProb = remaining/2;\r\n this.removeProb = remaining/2;\r\n }\r\n else {\r\n var remaining = 100 - this.removeProb;\r\n this.changeProb = remaining/2;\r\n this.addProb = remaining/2;\r\n }\r\n }\r\n}\r\n\r\nHyperparams.setDefaults();\r\n\r\nmodule.exports = Hyperparams;\n\n//# sourceURL=webpack:///./src/Hyperparameters.js?"); + +/***/ }), + +/***/ "./src/Organism/Anatomy.js": +/*!*********************************!*\ + !*** ./src/Organism/Anatomy.js ***! + \*********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CellStates = __webpack_require__(/*! ./Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst BodyCellFactory = __webpack_require__(/*! ./Cell/BodyCells/BodyCellFactory */ \"./src/Organism/Cell/BodyCells/BodyCellFactory.js\");\r\n\r\nclass Anatomy {\r\n constructor(owner) {\r\n this.owner = owner;\r\n this.cells = [];\r\n this.is_producer = false;\r\n this.is_mover = false;\r\n this.has_eyes = false;\r\n this.birth_distance = 4;\r\n }\r\n\r\n canAddCellAt(c, r) {\r\n for (var cell of this.cells) {\r\n if (cell.loc_col == c && cell.loc_row == r){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n addDefaultCell(state, c, r) {\r\n var new_cell = BodyCellFactory.createDefault(this.owner, state, c, r);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n addRandomizedCell(state, c, r) {\r\n if (state==CellStates.eye && !this.has_eyes) {\r\n this.owner.brain.randomizeDecisions();\r\n }\r\n var new_cell = BodyCellFactory.createRandom(this.owner, state, c, r);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n addInheritCell(parent_cell) {\r\n var new_cell = BodyCellFactory.createInherited(this.owner, parent_cell);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n replaceCell(state, c, r, randomize=true) {\r\n this.removeCell(c, r, true);\r\n if (randomize) {\r\n return this.addRandomizedCell(state, c, r);\r\n }\r\n else {\r\n return this.addDefaultCell(state, c, r);\r\n }\r\n }\r\n\r\n removeCell(c, r, allow_center_removal=false) {\r\n if (c == 0 && r == 0 && !allow_center_removal)\r\n return false;\r\n for (var i=0; i 3)\r\n dir -= 4;\r\n return dir;\r\n }\r\n\r\n performFunction() {\r\n var obs = this.look();\r\n this.org.brain.observe(obs);\r\n }\r\n\r\n look() {\r\n var env = this.org.env;\r\n var direction = this.getAbsoluteDirection();\r\n var addCol = 0;\r\n var addRow = 0;\r\n switch(direction) {\r\n case Directions.up:\r\n addRow = -1;\r\n break;\r\n case Directions.down:\r\n addRow = 1;\r\n break;\r\n case Directions.right:\r\n addCol = 1;\r\n break;\r\n case Directions.left:\r\n addCol = -1;\r\n break;\r\n }\r\n var start_col = this.getRealCol();\r\n var start_row = this.getRealRow();\r\n var col = start_col;\r\n var row = start_row;\r\n var cell = null;\r\n for (var i=0; i 3){\r\n dir = 0;\r\n }\r\n return dir;\r\n }\r\n}\r\n\r\nmodule.exports = Directions;\n\n//# sourceURL=webpack:///./src/Organism/Directions.js?"); + +/***/ }), + +/***/ "./src/Organism/Organism.js": +/*!**********************************!*\ + !*** ./src/Organism/Organism.js ***! + \**********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CellStates = __webpack_require__(/*! ./Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Neighbors = __webpack_require__(/*! ../Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Directions = __webpack_require__(/*! ./Directions */ \"./src/Organism/Directions.js\");\r\nconst Anatomy = __webpack_require__(/*! ./Anatomy */ \"./src/Organism/Anatomy.js\");\r\nconst Brain = __webpack_require__(/*! ./Perception/Brain */ \"./src/Organism/Perception/Brain.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass Organism {\r\n constructor(col, row, env, parent=null) {\r\n this.c = col;\r\n this.r = row;\r\n this.env = env;\r\n this.lifetime = 0;\r\n this.food_collected = 0;\r\n this.living = true;\r\n this.anatomy = new Anatomy(this)\r\n this.direction = Directions.down; // direction of movement\r\n this.rotation = Directions.up; // direction of rotation\r\n this.can_rotate = Hyperparams.moversCanRotate;\r\n this.move_count = 0;\r\n this.move_range = 4;\r\n this.ignore_brain_for = 0;\r\n this.mutability = 5;\r\n this.damage = 0;\r\n this.brain = new Brain(this);\r\n if (parent != null) {\r\n this.inherit(parent);\r\n }\r\n }\r\n\r\n inherit(parent) {\r\n this.move_range = parent.move_range;\r\n this.mutability = parent.mutability;\r\n this.species = parent.species;\r\n // this.birth_distance = parent.birth_distance;\r\n for (var c of parent.anatomy.cells){\r\n //deep copy parent cells\r\n this.anatomy.addInheritCell(c);\r\n }\r\n if(parent.anatomy.is_mover) {\r\n for (var i in parent.brain.decisions) {\r\n this.brain.decisions[i] = parent.brain.decisions[i];\r\n }\r\n }\r\n }\r\n\r\n // amount of food required before it can reproduce\r\n foodNeeded() {\r\n return this.anatomy.cells.length;\r\n }\r\n\r\n lifespan() {\r\n // console.log(Hyperparams.lifespanMultiplier)\r\n return this.anatomy.cells.length * Hyperparams.lifespanMultiplier;\r\n }\r\n\r\n maxHealth() {\r\n return this.anatomy.cells.length;\r\n }\r\n\r\n reproduce() {\r\n //produce mutated child\r\n //check nearby locations (is there room and a direct path)\r\n var org = new Organism(0, 0, this.env, this);\r\n if(Hyperparams.offspringRotate){\r\n org.rotation = Directions.getRandomDirection();\r\n }\r\n var prob = this.mutability;\r\n if (Hyperparams.useGlobalMutability){\r\n prob = Hyperparams.globalMutability;\r\n }\r\n else {\r\n //mutate the mutability\r\n if (Math.random() <= 0.5)\r\n org.mutability++;\r\n else{ \r\n org.mutability--;\r\n if (org.mutability < 1)\r\n org.mutability = 1;\r\n }\r\n } \r\n var mutated = false;\r\n if (Math.random() * 100 <= prob) {\r\n if (org.anatomy.is_mover && Math.random() * 100 <= 10) { \r\n if (org.anatomy.has_eyes) {\r\n org.brain.mutate();\r\n }\r\n org.move_range += Math.floor(Math.random() * 4) - 2;\r\n if (org.move_range <= 0){\r\n org.move_range = 1;\r\n };\r\n \r\n }\r\n else {\r\n mutated = org.mutate();\r\n }\r\n }\r\n\r\n var direction = Directions.getRandomScalar();\r\n var direction_c = direction[0];\r\n var direction_r = direction[1];\r\n var offset = (Math.floor(Math.random() * 3));\r\n var basemovement = this.anatomy.birth_distance;\r\n var new_c = this.c + (direction_c*basemovement) + (direction_c*offset);\r\n var new_r = this.r + (direction_r*basemovement) + (direction_r*offset);\r\n\r\n // console.log(org.isClear(new_c, new_r, org.rotation, true))\r\n if (org.isClear(new_c, new_r, org.rotation, true) && org.isStraightPath(new_c, new_r, this.c, this.r, this)){\r\n org.c = new_c;\r\n org.r = new_r;\r\n this.env.addOrganism(org);\r\n org.updateGrid();\r\n if (mutated) {\r\n FossilRecord.addSpecies(org, this.species);\r\n }\r\n else {\r\n org.species.addPop();\r\n }\r\n }\r\n this.food_collected -= this.foodNeeded();\r\n\r\n }\r\n\r\n mutate() {\r\n var choice = Math.floor(Math.random() * 100);\r\n var mutated = false;\r\n if (choice <= Hyperparams.addProb) {\r\n // add cell\r\n // console.log(\"add cell\")\r\n\r\n var branch = this.anatomy.getRandomCell();\r\n var state = CellStates.getRandomLivingType();//branch.state;\r\n var growth_direction = Neighbors.all[Math.floor(Math.random() * Neighbors.all.length)]\r\n var c = branch.loc_col+growth_direction[0];\r\n var r = branch.loc_row+growth_direction[1];\r\n if (this.anatomy.canAddCellAt(c, r)){\r\n mutated = true;\r\n this.anatomy.addRandomizedCell(state, c, r);\r\n }\r\n }\r\n else if (choice <= Hyperparams.addProb + Hyperparams.changeProb){\r\n // change cell\r\n var cell = this.anatomy.getRandomCell();\r\n var state = CellStates.getRandomLivingType();\r\n // console.log(\"change cell\", state)\r\n this.anatomy.replaceCell(state, cell.loc_col, cell.loc_row);\r\n mutated = true;\r\n }\r\n else if (choice <= Hyperparams.addProb + Hyperparams.changeProb + Hyperparams.removeProb){\r\n // remove cell\r\n // console.log(\"remove cell\")\r\n\r\n if(this.anatomy.cells.length > 1) {\r\n var cell = this.anatomy.getRandomCell();\r\n mutated = this.anatomy.removeCell(cell.loc_col, cell.loc_row);\r\n }\r\n }\r\n return mutated;\r\n }\r\n\r\n attemptMove() {\r\n var direction = Directions.scalars[this.direction];\r\n var direction_c = direction[0];\r\n var direction_r = direction[1];\r\n var new_c = this.c + direction_c;\r\n var new_r = this.r + direction_r;\r\n if (this.isClear(new_c, new_r)) {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.empty, null);\r\n }\r\n this.c = new_c;\r\n this.r = new_r;\r\n this.updateGrid();\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n attemptRotate() {\r\n if(!this.can_rotate){\r\n this.direction = Directions.getRandomDirection();\r\n this.move_count = 0;\r\n return true;\r\n }\r\n var new_rotation = Directions.getRandomDirection();\r\n if(this.isClear(this.c, this.r, new_rotation)){\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.empty, null);\r\n }\r\n this.rotation = new_rotation;\r\n this.direction = Directions.getRandomDirection();\r\n this.updateGrid();\r\n this.move_count = 0;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n changeDirection(dir) {\r\n this.direction = dir;\r\n this.move_count = 0;\r\n }\r\n\r\n // assumes either c1==c2 or r1==r2, returns true if there is a clear path from point 1 to 2\r\n isStraightPath(c1, r1, c2, r2, parent){\r\n if (c1 == c2) {\r\n if (r1 > r2){\r\n var temp = r2;\r\n r2 = r1;\r\n r1 = temp;\r\n }\r\n for (var i=r1; i!=r2; i++) {\r\n var cell = this.env.grid_map.cellAt(c1, i)\r\n if (!this.isPassableCell(cell, parent)){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n else {\r\n if (c1 > c2){\r\n var temp = c2;\r\n c2 = c1;\r\n c1 = temp;\r\n }\r\n for (var i=c1; i!=c2; i++) {\r\n var cell = this.env.grid_map.cellAt(i, r1);\r\n if (!this.isPassableCell(cell, parent)){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n }\r\n\r\n isPassableCell(cell, parent){\r\n return cell != null && (cell.state == CellStates.empty || cell.owner == this || cell.owner == parent || cell.state == CellStates.food);\r\n }\r\n\r\n isClear(col, row, rotation=this.rotation, ignore_armor=false) {\r\n for(var loccell of this.anatomy.cells) {\r\n var cell = this.getRealCell(loccell, col, row, rotation);\r\n if (cell==null) {\r\n return false;\r\n }\r\n // console.log(cell.owner == this)\r\n if (cell.owner==this || cell.state==CellStates.empty || (!Hyperparams.foodBlocksReproduction && cell.state==CellStates.food) || (ignore_armor && loccell.state==CellStates.armor && cell.state==CellStates.food)){\r\n continue;\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n harm() {\r\n this.damage++;\r\n if (this.damage >= this.maxHealth() || Hyperparams.instaKill) {\r\n this.die();\r\n }\r\n }\r\n\r\n die() {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.food, null);\r\n }\r\n this.species.decreasePop();\r\n this.living = false;\r\n }\r\n\r\n updateGrid() {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, cell.state, cell);\r\n }\r\n }\r\n\r\n update() {\r\n this.lifetime++;\r\n if (this.lifetime > this.lifespan()) {\r\n this.die();\r\n return this.living;\r\n }\r\n if (this.food_collected >= this.foodNeeded()) {\r\n this.reproduce();\r\n }\r\n for (var cell of this.anatomy.cells) {\r\n cell.performFunction();\r\n if (!this.living)\r\n return this.living\r\n }\r\n \r\n if (this.anatomy.is_mover) {\r\n this.move_count++;\r\n var changed_dir = false;\r\n if (this.ignore_brain_for == 0){\r\n changed_dir = this.brain.decide();\r\n } \r\n else{\r\n this.ignore_brain_for --;\r\n }\r\n var moved = this.attemptMove();\r\n if ((this.move_count > this.move_range && !changed_dir) || !moved){\r\n var rotated = this.attemptRotate();\r\n if (!rotated) {\r\n this.changeDirection(Directions.getRandomDirection());\r\n if (changed_dir)\r\n this.ignore_brain_for = this.move_range + 1;\r\n }\r\n }\r\n }\r\n\r\n return this.living;\r\n }\r\n\r\n getRealCell(local_cell, c=this.c, r=this.r, rotation=this.rotation){\r\n var real_c = c + local_cell.rotatedCol(rotation);\r\n var real_r = r + local_cell.rotatedRow(rotation);\r\n return this.env.grid_map.cellAt(real_c, real_r);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Organism;\r\n\n\n//# sourceURL=webpack:///./src/Organism/Organism.js?"); + +/***/ }), + +/***/ "./src/Organism/Perception/Brain.js": +/*!******************************************!*\ + !*** ./src/Organism/Perception/Brain.js ***! + \******************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Hyperparams = __webpack_require__(/*! ../../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Directions = __webpack_require__(/*! ../Directions */ \"./src/Organism/Directions.js\");\r\nconst CellStates = __webpack_require__(/*! ../Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\n\r\nconst Decision = {\r\n neutral: 0,\r\n retreat: 1,\r\n chase: 2,\r\n getRandom: function(){\r\n return Math.floor(Math.random() * 3);\r\n },\r\n getRandomNonNeutral: function() {\r\n return Math.floor(Math.random() * 2)+1;\r\n }\r\n}\r\n\r\nclass Brain {\r\n constructor(owner){\r\n this.owner = owner;\r\n this.observations = [];\r\n\r\n // corresponds to CellTypes\r\n this.decisions = [];\r\n this.decisions[CellStates.empty.name] = Decision.neutral;\r\n this.decisions[CellStates.food.name] = Decision.chase;\r\n this.decisions[CellStates.wall.name] = Decision.neutral;\r\n this.decisions[CellStates.mouth.name] = Decision.neutral;\r\n this.decisions[CellStates.producer.name] = Decision.neutral;\r\n this.decisions[CellStates.mover.name] = Decision.neutral;\r\n this.decisions[CellStates.killer.name] = Decision.retreat;\r\n this.decisions[CellStates.armor.name] = Decision.neutral;\r\n this.decisions[CellStates.eye.name] = Decision.neutral;\r\n }\r\n\r\n randomizeDecisions() {\r\n // randomize the non obvious decisions\r\n this.decisions[CellStates.mouth.name] = Decision.getRandom();\r\n this.decisions[CellStates.producer.name] = Decision.getRandom();\r\n this.decisions[CellStates.mover.name] = Decision.getRandom();\r\n this.decisions[CellStates.armor.name] = Decision.getRandom();\r\n this.decisions[CellStates.eye.name] = Decision.getRandom();\r\n }\r\n\r\n observe(observation) {\r\n this.observations.push(observation);\r\n }\r\n\r\n decide() {\r\n var decision = Decision.neutral;\r\n var closest = Hyperparams.lookRange + 1;\r\n var move_direction = 0;\r\n for (var obs of this.observations) {\r\n if (obs.cell == null || obs.cell.owner == this.owner) {\r\n continue;\r\n }\r\n if (obs.distance < closest) {\r\n // console.log(obs.cell.state)\r\n decision = this.decisions[obs.cell.state.name];\r\n // console.log(decision)\r\n move_direction = obs.direction;\r\n closest = obs.distance;\r\n }\r\n }\r\n this.observations = [];\r\n if (decision == Decision.chase) {\r\n this.owner.changeDirection(move_direction);\r\n return true;\r\n }\r\n else if (decision == Decision.retreat) {\r\n this.owner.changeDirection(Directions.getOppositeDirection(move_direction));\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n mutate() {\r\n this.decisions[CellStates.getRandomName()] = Decision.getRandom();\r\n this.decisions[CellStates.empty.name] = Decision.neutral; // if the empty cell has a decision it gets weird\r\n }\r\n}\r\n\r\nmodule.exports = Brain;\n\n//# sourceURL=webpack:///./src/Organism/Perception/Brain.js?"); + +/***/ }), + +/***/ "./src/Organism/Perception/Observation.js": +/*!************************************************!*\ + !*** ./src/Organism/Perception/Observation.js ***! + \************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("class Observation {\r\n constructor(cell, distance, direction){\r\n this.cell = cell;\r\n this.distance = distance;\r\n this.direction = direction;\r\n }\r\n}\r\n\r\nmodule.exports = Observation;\n\n//# sourceURL=webpack:///./src/Organism/Perception/Observation.js?"); + +/***/ }), + +/***/ "./src/Rendering/ColorScheme.js": +/*!**************************************!*\ + !*** ./src/Rendering/ColorScheme.js ***! + \**************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\n\r\nvar color_scheme = {\r\n \"empty\":\"#0E1318\",\r\n \"food\":\"#2F7AB7\",\r\n \"wall\":\"gray\",\r\n \"mouth\":\"#DEB14D\",\r\n \"producer\":\"#15DE59\",\r\n \"mover\":\"#60D4FF\",\r\n \"killer\":\"#F82380\",\r\n \"armor\":\"#7230DB\",\r\n \"eye\":\"#B6C1EA\",\r\n \"eye-slit\": \"#0E1318\"\r\n}\r\n\r\n// Renderer controls access to a canvas. There is one renderer for each canvas\r\nclass ColorScheme {\r\n constructor(world_env, editor_env) {\r\n this.world_env = world_env;\r\n this.editor_env = editor_env;\r\n }\r\n\r\n loadColorScheme() {\r\n for (var state of CellStates.all) {\r\n state.color = color_scheme[state.name];\r\n }\r\n CellStates.eye.slit_color=color_scheme['eye-slit']\r\n for (var cell_type in color_scheme) {\r\n $('#'+cell_type+'.cell-type ').css('background-color', color_scheme[cell_type]);\r\n $('#'+cell_type+'.cell-legend-type').css('background-color', color_scheme[cell_type]);\r\n \r\n }\r\n this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid);\r\n this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid);\r\n }\r\n}\r\n\r\nmodule.exports = ColorScheme;\n\n//# sourceURL=webpack:///./src/Rendering/ColorScheme.js?"); + +/***/ }), + +/***/ "./src/Rendering/Renderer.js": +/*!***********************************!*\ + !*** ./src/Rendering/Renderer.js ***! + \***********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// const CellTypes = require(\"../Organism/Cell/CellTypes\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Directions = __webpack_require__(/*! ../Organism/Directions */ \"./src/Organism/Directions.js\");\r\n\r\n// Renderer controls access to a canvas. There is one renderer for each canvas\r\nclass Renderer {\r\n constructor(canvas_id, container_id, cell_size) {\r\n this.cell_size = cell_size;\r\n this.canvas = document.getElementById(canvas_id);\r\n this.ctx = this.canvas.getContext(\"2d\");\r\n this.fillWindow(container_id)\r\n\t\tthis.height = this.canvas.height;\r\n this.width = this.canvas.width;\r\n this.cells_to_render = new Set();\r\n this.cells_to_highlight = new Set();\r\n this.highlighted_cells = new Set();\r\n }\r\n\r\n fillWindow(container_id) {\r\n this.fillShape($('#'+container_id).height(), $('#'+container_id).width());\r\n }\r\n\r\n fillShape(height, width) {\r\n this.canvas.width = width;\r\n this.canvas.height = height;\r\n this.height = this.canvas.height;\r\n this.width = this.canvas.width;\r\n }\r\n\r\n clear() {\r\n this.ctx.fillStyle = 'white';\r\n this.ctx.fillRect(0, 0, this.height, this.width);\r\n }\r\n\r\n renderFullGrid(grid) {\r\n for (var col of grid) {\r\n for (var cell of col){\r\n this.renderCell(cell);\r\n }\r\n }\r\n }\r\n\r\n renderCells() {\r\n for (var cell of this.cells_to_render) {\r\n this.renderCell(cell);\r\n }\r\n this.cells_to_render.clear();\r\n }\r\n\r\n renderCell(cell) {\r\n cell.state.render(this.ctx, cell, this.cell_size);\r\n }\r\n\r\n renderOrganism(org) {\r\n for(var org_cell of org.anatomy.cells) {\r\n var cell = org.getRealCell(org_cell);\r\n this.renderCell(cell);\r\n }\r\n }\r\n\r\n addToRender(cell) {\r\n if (this.highlighted_cells.has(cell)){\r\n this.cells_to_highlight.add(cell);\r\n }\r\n this.cells_to_render.add(cell);\r\n }\r\n\r\n renderHighlights() {\r\n for (var cell of this.cells_to_highlight) {\r\n this.renderCellHighlight(cell);\r\n this.highlighted_cells.add(cell);\r\n }\r\n this.cells_to_highlight.clear();\r\n \r\n }\r\n\r\n highlightOrganism(org) {\r\n for(var org_cell of org.anatomy.cells) {\r\n var cell = org.getRealCell(org_cell);\r\n this.cells_to_highlight.add(cell);\r\n }\r\n }\r\n\r\n highlightCell(cell) {\r\n this.cells_to_highlight.add(cell);\r\n }\r\n\r\n renderCellHighlight(cell, color=\"yellow\") {\r\n this.renderCell(cell);\r\n this.ctx.fillStyle = color;\r\n this.ctx.globalAlpha = 0.5;\r\n this.ctx.fillRect(cell.x, cell.y, this.cell_size, this.cell_size);\r\n this.ctx.globalAlpha = 1;\r\n this.highlighted_cells.add(cell);\r\n }\r\n\r\n clearAllHighlights(clear_to_highlight=false) {\r\n for (var cell of this.highlighted_cells) {\r\n this.renderCell(cell);\r\n }\r\n this.highlighted_cells.clear();\r\n if (clear_to_highlight) {\r\n this.cells_to_highlight.clear();\r\n }\r\n }\r\n}\r\n\r\n// $(\"body\").mousemove(function(e) {\r\n// console.log(\"hello\");\r\n// });\r\n\r\nmodule.exports = Renderer;\r\n\n\n//# sourceURL=webpack:///./src/Rendering/Renderer.js?"); + +/***/ }), + +/***/ "./src/Stats/FossilRecord.js": +/*!***********************************!*\ + !*** ./src/Stats/FossilRecord.js ***! + \***********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Species = __webpack_require__(/*! ./Species */ \"./src/Stats/Species.js\");\r\n\r\nconst FossilRecord = {\r\n init: function(){\r\n this.extant_species = [];\r\n this.extinct_species = [];\r\n\r\n // if an organism has fewer than this cumulative pop, discard them\r\n this.discard_pop = 5;\r\n },\r\n\r\n setEnv: function(env) {\r\n this.env = env;\r\n },\r\n\r\n addSpecies: function(org, ancestor) {\r\n console.log(\"Adding Species\")\r\n var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks)\r\n this.extant_species.push(new_species);\r\n org.species = new_species;\r\n return new_species;\r\n },\r\n\r\n fossilize: function(species) {\r\n species.end_tick = this.env.total_ticks;\r\n for (i in this.extant_species) {\r\n var s = this.extant_species[i];\r\n if (s == species) {\r\n this.extant_species.splice(i, 1);\r\n if (species.cumulative_pop <= this.discard_pop) {\r\n return false;\r\n }\r\n this.extinct_species.push(s);\r\n console.log(\"Extant:\", this.extant_species.length)\r\n console.log(\"Extinct:\", this.extinct_species.length)\r\n return true;\r\n }\r\n }\r\n },\r\n\r\n clear_record: function() {\r\n this.species = [];\r\n },\r\n\r\n}\r\n\r\nFossilRecord.init();\r\n\r\nmodule.exports = FossilRecord;\n\n//# sourceURL=webpack:///./src/Stats/FossilRecord.js?"); + +/***/ }), + +/***/ "./src/Stats/Species.js": +/*!******************************!*\ + !*** ./src/Stats/Species.js ***! + \******************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("class Species {\r\n constructor(anatomy, ancestor, start_tick) {\r\n this.anatomy = anatomy;\r\n this.ancestor = ancestor;\r\n this.population = 1;\r\n this.cumulative_pop = 1;\r\n this.start_tick = start_tick;\r\n this.end_tick = -1;\r\n this.color = '#asdfasdf';\r\n this.name = \"crabuloid\";\r\n this.extinct = false;\r\n }\r\n\r\n addPop() {\r\n this.population++;\r\n this.cumulative_pop++;\r\n }\r\n\r\n decreasePop() {\r\n this.population--;\r\n if (this.population <= 0) {\r\n this.extinct = true;\r\n console.log(\"Extinction\");\r\n const FossilRecord = __webpack_require__(/*! ./FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n FossilRecord.fossilize(this);\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = Species;\n\n//# sourceURL=webpack:///./src/Stats/Species.js?"); + +/***/ }), + +/***/ "./src/index.js": +/*!**********************!*\ + !*** ./src/index.js ***! + \**********************/ +/*! no exports provided */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Engine */ \"./src/Engine.js\");\n/* harmony import */ var _Engine__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_Engine__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\r\n\r\n\r\n$('document').ready(function(){\r\n let isMobile = mobileCheck();\r\n if (isMobile) {\r\n alert(\"Though the simulation still works on mobile, most features are disabled. Try it on desktop for the full experience!\");\r\n $('.control-panel').css('display', 'none');\r\n }\r\n var engine = new _Engine__WEBPACK_IMPORTED_MODULE_0___default.a();\r\n engine.start(60);\r\n});\r\n\r\nfunction mobileCheck() {\r\n let check = false;\r\n (function(a){if(/(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);\r\n return check;\r\n};\n\n//# sourceURL=webpack:///./src/index.js?"); + +/***/ }) + +/******/ }); \ No newline at end of file diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index 5936fb7..25e1212 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -199,6 +199,7 @@ class ControlPanel { case "drop-org": self.setMode(Modes.Clone); self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg(); + self.env_controller.make_new_species = true; break; case "drag-view": self.setMode(Modes.Drag); diff --git a/src/Controllers/EditorController.js b/src/Controllers/EditorController.js index 5b55c6d..d873b55 100644 --- a/src/Controllers/EditorController.js +++ b/src/Controllers/EditorController.js @@ -26,7 +26,7 @@ class EditorController extends CanvasController{ mouseUp(){} getCurLocalCell(){ - return this.env.organism.getLocalCell(this.mouse_c-this.env.organism.c, this.mouse_r-this.env.organism.r); + return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c, this.mouse_r-this.env.organism.r); } editOrganism() { @@ -49,7 +49,7 @@ class EditorController extends CanvasController{ } updateDetails() { - $('.cell-count').text("Cell count: "+this.env.organism.cells.length); + $('.cell-count').text("Cell count: "+this.env.organism.anatomy.cells.length); } defineCellTypeSelection() { @@ -111,7 +111,7 @@ class EditorController extends CanvasController{ this.clearDetailsPanel(); var org = this.env.organism; - $('.cell-count').text("Cell count: "+org.cells.length); + $('.cell-count').text("Cell count: "+org.anatomy.cells.length); $('#move-range').text("Move Range: "+org.move_range); $('#mutation-rate').text("Mutation Rate: "+org.mutability); if (Hyperparams.useGlobalMutability) { @@ -134,7 +134,7 @@ class EditorController extends CanvasController{ this.clearDetailsPanel(); var org = this.env.organism; - $('.cell-count').text("Cell count: "+org.cells.length); + $('.cell-count').text("Cell count: "+org.anatomy.cells.length); if (this.setMoveRangeVisibility()){ $('#move-range-edit').val(org.move_range); } @@ -149,7 +149,7 @@ class EditorController extends CanvasController{ setBrainPanelVisibility() { var org = this.env.organism; - if (org.has_eyes && org.is_mover) { + if (org.anatomy.has_eyes && org.anatomy.is_mover) { $('.brain-details').css('display', 'block'); return true; } @@ -175,7 +175,7 @@ class EditorController extends CanvasController{ setMoveRangeVisibility() { var org = this.env.organism; - if (org.is_mover) { + if (org.anatomy.is_mover) { $('#move-range-cont').css('display', 'block'); $('#move-range').css('display', 'block'); return true; diff --git a/src/Controllers/EnvironmentController.js b/src/Controllers/EnvironmentController.js index ec4dbae..4962af8 100644 --- a/src/Controllers/EnvironmentController.js +++ b/src/Controllers/EnvironmentController.js @@ -3,12 +3,15 @@ const Organism = require('../Organism/Organism'); const Modes = require("./ControlModes"); const CellStates = require("../Organism/Cell/CellStates"); const Neighbors = require("../Grid/Neighbors"); +const FossilRecord = require("../Stats/FossilRecord"); class EnvironmentController extends CanvasController{ constructor(env, canvas) { super(env, canvas); this.mode = Modes.Drag; this.org_to_clone = null; + this.species_to_clone = null; + this.make_new_species = false; this.defineZoomControls(); this.scale = 1; } @@ -118,6 +121,14 @@ 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.make_new_species){ + this.species_to_clone = FossilRecord.addSpecies(new_org, null) + this.make_new_species = false; + } + else { + new_org.species = this.species_to_clone; + this.species_to_clone.addPop(); + } if (new_org.isClear(this.mouse_c, this.mouse_r)){ this.env.addOrganism(new_org) } diff --git a/src/Environments/OrganismEditor.js b/src/Environments/OrganismEditor.js index 9294549..7e7aaf9 100644 --- a/src/Environments/OrganismEditor.js +++ b/src/Environments/OrganismEditor.js @@ -4,7 +4,6 @@ const GridMap = require('../Grid/GridMap'); const Renderer = require('../Rendering/Renderer'); const CellStates = require('../Organism/Cell/CellStates'); const EditorController = require("../Controllers/EditorController"); -const Directions = require('../Organism/Directions'); class OrganismEditor extends Environment{ constructor() { @@ -37,13 +36,13 @@ class OrganismEditor extends Environment{ var center = this.grid_map.getCenter(); var loc_c = c - center[0]; var loc_r = r - center[1]; - var prev_cell = this.organism.getLocalCell(loc_c, loc_r) + var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r) if (prev_cell != null) { - var new_cell = this.organism.replaceCell(state, prev_cell.loc_col, prev_cell.loc_row, false); + var new_cell = this.organism.anatomy.replaceCell(state, prev_cell.loc_col, prev_cell.loc_row, false); this.changeCell(c, r, state, new_cell); } - else if (this.organism.canAddCellAt(loc_c, loc_r)){ - this.changeCell(c, r, state, this.organism.addDefaultCell(state, loc_c, loc_r)); + else if (this.organism.anatomy.canAddCellAt(loc_c, loc_r)){ + this.changeCell(c, r, state, this.organism.anatomy.addDefaultCell(state, loc_c, loc_r)); } } @@ -55,9 +54,9 @@ class OrganismEditor extends Environment{ alert("Cannot remove center cell"); return; } - var prev_cell = this.organism.getLocalCell(loc_c, loc_r) + var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r) if (prev_cell != null) { - if (this.organism.removeCell(loc_c, loc_r)) { + if (this.organism.anatomy.removeCell(loc_c, loc_r)) { this.changeCell(c, r, CellStates.empty, null); } } @@ -80,7 +79,7 @@ class OrganismEditor extends Environment{ this.grid_map.fillGrid(CellStates.empty); var center = this.grid_map.getCenter(); this.organism = new Organism(center[0], center[1], this, null); - this.organism.addDefaultCell(CellStates.mouth, 0, 0); + this.organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0); this.organism.updateGrid(); } } diff --git a/src/Environments/WorldEnvironment.js b/src/Environments/WorldEnvironment.js index dbca6a4..db13437 100644 --- a/src/Environments/WorldEnvironment.js +++ b/src/Environments/WorldEnvironment.js @@ -5,7 +5,7 @@ const Organism = require('../Organism/Organism'); const CellStates = require('../Organism/Cell/CellStates'); const EnvironmentController = require('../Controllers/EnvironmentController'); const Hyperparams = require('../Hyperparameters.js'); -const Cell = require('../Organism/Cell/GridCell'); +const FossilRecord = require('../Stats/FossilRecord'); class WorldEnvironment extends Environment{ constructor(cell_size) { @@ -21,9 +21,12 @@ class WorldEnvironment extends Environment{ this.auto_reset = true; this.largest_cell_count = 0; this.reset_count = 0; + this.total_ticks = 0; + FossilRecord.setEnv(this); } update(delta_time) { + this.total_ticks ++; var to_remove = []; for (var i in this.organisms) { var org = this.organisms[i]; @@ -56,21 +59,19 @@ class WorldEnvironment extends Environment{ OriginOfLife() { var center = this.grid_map.getCenter(); var org = new Organism(center[0], center[1], this); - // org.addDefaultCell(CellStates.eye, 0, 0); - // org.addDefaultCell(CellStates.mouth, 1, 1); - // org.addDefaultCell(CellStates.mover, 1, -1); - org.addDefaultCell(CellStates.mouth, 0, 0); - org.addDefaultCell(CellStates.producer, 1, 1); - org.addDefaultCell(CellStates.producer, -1, -1); + 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); } addOrganism(organism) { organism.updateGrid(); this.total_mutability += organism.mutability; this.organisms.push(organism); - if (organism.cells.length > this.largest_cell_count) - this.largest_cell_count = organism.cells.length; + if (organism.anatomy.cells.length > this.largest_cell_count) + this.largest_cell_count = organism.anatomy.cells.length; } averageMutability() { @@ -119,6 +120,7 @@ class WorldEnvironment extends Environment{ this.grid_map.fillGrid(CellStates.empty); this.renderer.renderFullGrid(this.grid_map.grid); this.total_mutability = 0; + this.total_ticks = 0; this.OriginOfLife(); } diff --git a/src/Organism/Anatomy.js b/src/Organism/Anatomy.js new file mode 100644 index 0000000..8175024 --- /dev/null +++ b/src/Organism/Anatomy.js @@ -0,0 +1,96 @@ +const CellStates = require("./Cell/CellStates"); +const BodyCellFactory = require("./Cell/BodyCells/BodyCellFactory"); + +class Anatomy { + constructor(owner) { + this.owner = owner; + this.cells = []; + this.is_producer = false; + this.is_mover = false; + this.has_eyes = false; + this.birth_distance = 4; + } + + canAddCellAt(c, r) { + for (var cell of this.cells) { + if (cell.loc_col == c && cell.loc_row == r){ + return false; + } + } + return true; + } + + addDefaultCell(state, c, r) { + var new_cell = BodyCellFactory.createDefault(this.owner, state, c, r); + this.cells.push(new_cell); + return new_cell; + } + + addRandomizedCell(state, c, r) { + if (state==CellStates.eye && !this.has_eyes) { + this.owner.brain.randomizeDecisions(); + } + var new_cell = BodyCellFactory.createRandom(this.owner, state, c, r); + this.cells.push(new_cell); + return new_cell; + } + + addInheritCell(parent_cell) { + var new_cell = BodyCellFactory.createInherited(this.owner, parent_cell); + this.cells.push(new_cell); + return new_cell; + } + + replaceCell(state, c, r, randomize=true) { + this.removeCell(c, r, true); + if (randomize) { + return this.addRandomizedCell(state, c, r); + } + else { + return this.addDefaultCell(state, c, r); + } + } + + removeCell(c, r, allow_center_removal=false) { + if (c == 0 && r == 0 && !allow_center_removal) + return false; + for (var i=0; i 1) { - var cell = this.cells[Math.floor(Math.random() * this.cells.length)]; - mutated = this.removeCell(cell.loc_col, cell.loc_row); + if(this.anatomy.cells.length > 1) { + var cell = this.anatomy.getRandomCell(); + mutated = this.anatomy.removeCell(cell.loc_col, cell.loc_row); } } return mutated; @@ -237,7 +166,7 @@ class Organism { var new_c = this.c + direction_c; var new_r = this.r + direction_r; if (this.isClear(new_c, new_r)) { - for (var cell of this.cells) { + for (var cell of this.anatomy.cells) { var real_c = this.c + cell.rotatedCol(this.rotation); var real_r = this.r + cell.rotatedRow(this.rotation); this.env.changeCell(real_c, real_r, CellStates.empty, null); @@ -258,7 +187,7 @@ class Organism { } var new_rotation = Directions.getRandomDirection(); if(this.isClear(this.c, this.r, new_rotation)){ - for (var cell of this.cells) { + for (var cell of this.anatomy.cells) { var real_c = this.c + cell.rotatedCol(this.rotation); var real_r = this.r + cell.rotatedRow(this.rotation); this.env.changeCell(real_c, real_r, CellStates.empty, null); @@ -277,7 +206,7 @@ class Organism { this.move_count = 0; } - // assumes either c1==c2 or r1==r2, returns true if there is a clear path from point a to b + // assumes either c1==c2 or r1==r2, returns true if there is a clear path from point 1 to 2 isStraightPath(c1, r1, c2, r2, parent){ if (c1 == c2) { if (r1 > r2){ @@ -314,11 +243,12 @@ class Organism { } isClear(col, row, rotation=this.rotation, ignore_armor=false) { - for(var loccell of this.cells) { + for(var loccell of this.anatomy.cells) { var cell = this.getRealCell(loccell, col, row, rotation); - if(cell==null) { + if (cell==null) { return false; } + // console.log(cell.owner == this) if (cell.owner==this || cell.state==CellStates.empty || (!Hyperparams.foodBlocksReproduction && cell.state==CellStates.food) || (ignore_armor && loccell.state==CellStates.armor && cell.state==CellStates.food)){ continue; } @@ -335,16 +265,17 @@ class Organism { } die() { - for (var cell of this.cells) { + for (var cell of this.anatomy.cells) { var real_c = this.c + cell.rotatedCol(this.rotation); var real_r = this.r + cell.rotatedRow(this.rotation); this.env.changeCell(real_c, real_r, CellStates.food, null); } + this.species.decreasePop(); this.living = false; } updateGrid() { - for (var cell of this.cells) { + for (var cell of this.anatomy.cells) { var real_c = this.c + cell.rotatedCol(this.rotation); var real_r = this.r + cell.rotatedRow(this.rotation); this.env.changeCell(real_c, real_r, cell.state, cell); @@ -360,13 +291,13 @@ class Organism { if (this.food_collected >= this.foodNeeded()) { this.reproduce(); } - for (var cell of this.cells) { + for (var cell of this.anatomy.cells) { cell.performFunction(); if (!this.living) return this.living } - if (this.is_mover) { + if (this.anatomy.is_mover) { this.move_count++; var changed_dir = false; if (this.ignore_brain_for == 0){ diff --git a/src/Rendering/Renderer.js b/src/Rendering/Renderer.js index e60e457..647a9a8 100644 --- a/src/Rendering/Renderer.js +++ b/src/Rendering/Renderer.js @@ -52,7 +52,7 @@ class Renderer { } renderOrganism(org) { - for(var org_cell of org.cells) { + for(var org_cell of org.anatomy.cells) { var cell = org.getRealCell(org_cell); this.renderCell(cell); } @@ -75,7 +75,7 @@ class Renderer { } highlightOrganism(org) { - for(var org_cell of org.cells) { + for(var org_cell of org.anatomy.cells) { var cell = org.getRealCell(org_cell); this.cells_to_highlight.add(cell); } diff --git a/src/Stats/FossilRecord.js b/src/Stats/FossilRecord.js new file mode 100644 index 0000000..7b54ab6 --- /dev/null +++ b/src/Stats/FossilRecord.js @@ -0,0 +1,49 @@ +const Species = require("./Species"); + +const FossilRecord = { + init: function(){ + this.extant_species = []; + this.extinct_species = []; + + // if an organism has fewer than this cumulative pop, discard them + this.discard_pop = 5; + }, + + setEnv: function(env) { + this.env = env; + }, + + addSpecies: function(org, ancestor) { + console.log("Adding Species") + var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks) + this.extant_species.push(new_species); + org.species = new_species; + return new_species; + }, + + fossilize: function(species) { + species.end_tick = this.env.total_ticks; + for (i in this.extant_species) { + var s = this.extant_species[i]; + if (s == species) { + this.extant_species.splice(i, 1); + if (species.cumulative_pop <= this.discard_pop) { + return false; + } + this.extinct_species.push(s); + console.log("Extant:", this.extant_species.length) + console.log("Extinct:", this.extinct_species.length) + return true; + } + } + }, + + clear_record: function() { + this.species = []; + }, + +} + +FossilRecord.init(); + +module.exports = FossilRecord; \ No newline at end of file diff --git a/src/Stats/Species.js b/src/Stats/Species.js new file mode 100644 index 0000000..452fd8d --- /dev/null +++ b/src/Stats/Species.js @@ -0,0 +1,30 @@ +class Species { + constructor(anatomy, ancestor, start_tick) { + this.anatomy = anatomy; + this.ancestor = ancestor; + this.population = 1; + this.cumulative_pop = 1; + this.start_tick = start_tick; + this.end_tick = -1; + this.color = '#asdfasdf'; + this.name = "crabuloid"; + this.extinct = false; + } + + addPop() { + this.population++; + this.cumulative_pop++; + } + + decreasePop() { + this.population--; + if (this.population <= 0) { + this.extinct = true; + console.log("Extinction"); + const FossilRecord = require("./FossilRecord"); + FossilRecord.fossilize(this); + } + } +} + +module.exports = Species; \ No newline at end of file From 7087c5b4aef9daae6111ed9408815678200176fb Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Fri, 5 Feb 2021 10:23:28 -0700 Subject: [PATCH 2/9] removed logs --- dist/js/bundle.js | 443 +------------------------------------- src/Stats/FossilRecord.js | 6 +- src/Stats/Species.js | 2 +- 3 files changed, 5 insertions(+), 446 deletions(-) diff --git a/dist/js/bundle.js b/dist/js/bundle.js index 6bf7d4c..f93c9a6 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1,442 +1 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./src/Controllers/CanvasController.js": -/*!*********************************************!*\ - !*** ./src/Controllers/CanvasController.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("\r\n\r\nclass CanvasController{\r\n constructor(env, canvas) {\r\n this.env = env;\r\n this.canvas = canvas;\r\n this.mouse_x;\r\n this.mouse_y;\r\n this.mouse_c;\r\n this.mouse_r;\r\n this.left_click = false;\r\n this.right_click = false;\r\n this.cur_cell = null;\r\n this.cur_org = null;\r\n this.highlight_org = true;\r\n this.defineEvents();\r\n }\r\n\r\n setControlPanel(panel){\r\n this.control_panel = panel;\r\n }\r\n\r\n defineEvents() {\r\n this.canvas.addEventListener('mousemove', e => {\r\n this.updateMouseLocation(e.offsetX, e.offsetY)\r\n this.mouseMove();\r\n });\r\n\r\n this.canvas.addEventListener('mouseup', function(evt) {\r\n evt.preventDefault();\r\n this.updateMouseLocation(evt.offsetX, evt.offsetY)\r\n this.mouseUp();\r\n this.left_click=false;\r\n this.right_click=false;\r\n }.bind(this));\r\n\r\n this.canvas.addEventListener('mousedown', function(evt) {\r\n evt.preventDefault();\r\n this.updateMouseLocation(evt.offsetX, evt.offsetY)\r\n if (evt.button == 0) {\r\n this.left_click = true;\r\n }\r\n if (evt.button == 2) \r\n this.right_click = true;\r\n this.mouseDown();\r\n }.bind(this));\r\n\r\n this.canvas.addEventListener('contextmenu', function(evt) {\r\n evt.preventDefault();\r\n });\r\n\r\n this.canvas.addEventListener('mouseleave', function(){\r\n this.right_click = false;\r\n this.left_click = false;\r\n this.env.renderer.clearAllHighlights(true);\r\n }.bind(this));\r\n\r\n }\r\n\r\n updateMouseLocation(offsetX, offsetY) {\r\n var prev_cell = this.cur_cell;\r\n var prev_org = this.cur_org;\r\n\r\n this.mouse_x = offsetX;\r\n this.mouse_y = offsetY;\r\n var colRow = this.env.grid_map.xyToColRow(this.mouse_x, this.mouse_y);\r\n this.mouse_c = colRow[0];\r\n this.mouse_r = colRow[1];\r\n this.cur_cell = this.env.grid_map.cellAt(this.mouse_c, this.mouse_r);\r\n this.cur_org = this.cur_cell.owner;\r\n\r\n if (this.cur_org != prev_org || this.cur_cell != prev_cell) {\r\n this.env.renderer.clearAllHighlights(true);\r\n if (this.cur_org != null && this.highlight_org) {\r\n this.env.renderer.highlightOrganism(this.cur_org);\r\n }\r\n else if (this.cur_cell != null) {\r\n this.env.renderer.highlightCell(this.cur_cell, true);\r\n }\r\n }\r\n }\r\n\r\n mouseMove() {\r\n alert(\"mouse move must be overridden\");\r\n }\r\n\r\n mouseDown() {\r\n alert(\"mouse down must be overridden\");\r\n }\r\n\r\n mouseUp(){\r\n alert(\"mouse up must be overridden\")\r\n }\r\n}\r\n\r\nmodule.exports = CanvasController;\n\n//# sourceURL=webpack:///./src/Controllers/CanvasController.js?"); - -/***/ }), - -/***/ "./src/Controllers/ControlModes.js": -/*!*****************************************!*\ - !*** ./src/Controllers/ControlModes.js ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("const Modes = {\r\n None: 0,\r\n FoodDrop: 1,\r\n WallDrop: 2,\r\n ClickKill: 3,\r\n Select: 4,\r\n Edit: 5,\r\n Clone: 6,\r\n Drag: 7\r\n}\r\n\r\nmodule.exports = Modes;\n\n//# sourceURL=webpack:///./src/Controllers/ControlModes.js?"); - -/***/ }), - -/***/ "./src/Controllers/ControlPanel.js": -/*!*****************************************!*\ - !*** ./src/Controllers/ControlPanel.js ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\n\r\nclass ControlPanel {\r\n constructor(engine) {\r\n this.engine = engine;\r\n this.defineMinMaxControls();\r\n this.defineEngineSpeedControls();\r\n this.defineGridSizeControls();\r\n this.defineTabNavigation();\r\n this.defineHyperparameterControls();\r\n this.defineModeControls();\r\n this.defineChallenges();\r\n this.fps = engine.fps;\r\n this.organism_record=0;\r\n this.env_controller = this.engine.env.controller;\r\n this.editor_controller = this.engine.organism_editor.controller;\r\n this.env_controller.setControlPanel(this);\r\n this.editor_controller.setControlPanel(this);\r\n }\r\n\r\n defineMinMaxControls(){\r\n $('#minimize').click ( function() {\r\n $('.control-panel').css('display', 'none');\r\n $('.hot-controls').css('display', 'block');\r\n });\r\n $('#maximize').click ( function() {\r\n $('.control-panel').css('display', 'grid');\r\n $('.hot-controls').css('display', 'none');\r\n });\r\n }\r\n\r\n defineEngineSpeedControls(){\r\n this.slider = document.getElementById(\"slider\");\r\n this.slider.oninput = function() {\r\n this.fps = this.slider.value\r\n if (this.engine.running) {\r\n this.changeEngineSpeed(this.fps);\r\n \r\n }\r\n $('#fps').text(\"Target FPS: \"+this.fps);\r\n }.bind(this);\r\n $('.pause-button').click(function() {\r\n $('.pause-button').find(\"i\").toggleClass(\"fa fa-pause\");\r\n $('.pause-button').find(\"i\").toggleClass(\"fa fa-play\");\r\n if (this.engine.running) {\r\n this.engine.stop();\r\n }\r\n else if (!this.engine.running){\r\n this.engine.start(this.fps);\r\n }\r\n }.bind(this));\r\n }\r\n\r\n defineGridSizeControls() {\r\n $('#fill-window').change(function() {\r\n if (this.checked)\r\n $('.col-row-input').css('display' ,'none');\r\n else\r\n $('.col-row-input').css('display' ,'block');\r\n });\r\n\r\n $('#resize').click(function() {\r\n var cell_size = $('#cell-size').val();\r\n var fill_window = $('#fill-window').is(\":checked\");\r\n if (fill_window) {\r\n this.engine.env.resizeFillWindow(cell_size);\r\n }\r\n else {\r\n var cols = $('#col-input').val();\r\n var rows = $('#row-input').val();\r\n this.engine.env.resizeGridColRow(cell_size, cols, rows);\r\n }\r\n \r\n }.bind(this));\r\n }\r\n\r\n defineTabNavigation() {\r\n var self = this;\r\n $('.tabnav-item').click(function() {\r\n $('.tab').css('display', 'none');\r\n var tab = '#'+this.id+'.tab';\r\n self.engine.organism_editor.is_active = (this.id == 'editor');\r\n $(tab).css('display', 'grid');\r\n });\r\n }\r\n\r\n defineHyperparameterControls() {\r\n $('#food-prod-prob').change(function() {\r\n var food_prob = \r\n Hyperparams.foodProdProb = $('#food-prod-prob').val();;\r\n }.bind(this));\r\n $('#lifespan-multiplier').change(function() {\r\n Hyperparams.lifespanMultiplier = $('#lifespan-multiplier').val();\r\n }.bind(this));\r\n\r\n $('#mover-rot').change(function() {\r\n Hyperparams.moversCanRotate = this.checked;\r\n });\r\n $('#offspring-rot').change(function() {\r\n Hyperparams.offspringRotate = this.checked;\r\n });\r\n $('#insta-kill').change(function() {\r\n Hyperparams.instaKill = this.checked;\r\n });\r\n $('#look-range').change(function() {\r\n Hyperparams.lookRange = $('#look-range').val();\r\n });\r\n $('#food-drop-rate').change(function() {\r\n Hyperparams.foodDropProb = $('#food-drop-rate').val();\r\n });\r\n\r\n $('#evolved-mutation').change( function() {\r\n if (this.checked) {\r\n $('.global-mutation-in').css('display', 'none');\r\n $('#avg-mut').css('display', 'block');\r\n }\r\n else {\r\n $('.global-mutation-in').css('display', 'block');\r\n $('#avg-mut').css('display', 'none');\r\n }\r\n Hyperparams.useGlobalMutability = !this.checked;\r\n });\r\n $('#global-mutation').change( function() {\r\n Hyperparams.globalMutability = $('#global-mutation').val();\r\n });\r\n $('.mut-prob').change( function() {\r\n switch(this.id){\r\n case \"add-prob\":\r\n Hyperparams.addProb = this.value;\r\n Hyperparams.balanceMutationProbs(1);\r\n break;\r\n case \"change-prob\":\r\n Hyperparams.changeProb = this.value;\r\n Hyperparams.balanceMutationProbs(2);\r\n break;\r\n case \"remove-prob\":\r\n Hyperparams.removeProb = this.value;\r\n Hyperparams.balanceMutationProbs(3);\r\n break;\r\n }\r\n $('#add-prob').val(Math.floor(Hyperparams.addProb));\r\n $('#change-prob').val(Math.floor(Hyperparams.changeProb));\r\n $('#remove-prob').val(Math.floor(Hyperparams.removeProb));\r\n });\r\n $('#movers-produce').change( function() {\r\n Hyperparams.moversCanProduce = this.checked;\r\n });\r\n $('#food-blocks').change( function() {\r\n Hyperparams.foodBlocksReproduction = this.checked; \r\n });\r\n $('#reset-rules').click( function() {\r\n Hyperparams.setDefaults();\r\n $('#food-prod-prob').val(Hyperparams.foodProdProb);\r\n $('#lifespan-multiplier').val(Hyperparams.lifespanMultiplier);\r\n $('#mover-rot').prop('checked', Hyperparams.moversCanRotate);\r\n $('#offspring-rot').prop('checked', Hyperparams.offspringRotate);\r\n $('#insta-kill').prop('checked', Hyperparams.instaKill);\r\n $('#evolved-mutation').prop('checked', !Hyperparams.useGlobalMutability);\r\n $('#add-prob').val(Hyperparams.addProb);\r\n $('#change-prob').val(Hyperparams.changeProb);\r\n $('#remove-prob').val(Hyperparams.removeProb);\r\n $('#movers-produce').prop('checked', Hyperparams.moversCanProduce);\r\n $('#food-blocks').prop('checked', Hyperparams.foodBlocksReproduction);\r\n if (!Hyperparams.useGlobalMutability) {\r\n $('.global-mutation-in').css('display', 'none');\r\n $('#avg-mut').css('display', 'block');\r\n }\r\n else {\r\n $('.global-mutation-in').css('display', 'block');\r\n $('#avg-mut').css('display', 'none');\r\n }\r\n });\r\n }\r\n\r\n defineModeControls() {\r\n var self = this;\r\n $('.edit-mode-btn').click( function() {\r\n $('#cell-selections').css('display', 'none');\r\n $('#organism-options').css('display', 'none');\r\n self.editor_controller.setDetailsPanel();\r\n switch(this.id){\r\n case \"food-drop\":\r\n self.setMode(Modes.FoodDrop);\r\n break;\r\n case \"wall-drop\":\r\n self.setMode(Modes.WallDrop);\r\n break;\r\n case \"click-kill\":\r\n self.setMode(Modes.ClickKill);\r\n break;\r\n case \"select\":\r\n self.setMode(Modes.Select);\r\n break;\r\n case \"edit\":\r\n self.setMode(Modes.Edit);\r\n self.editor_controller.setEditorPanel();\r\n break;\r\n case \"drop-org\":\r\n self.setMode(Modes.Clone);\r\n self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg();\r\n self.env_controller.make_new_species = true;\r\n break;\r\n case \"drag-view\":\r\n self.setMode(Modes.Drag);\r\n }\r\n $('.edit-mode-btn').css('background-color', '#9099c2');\r\n $('#'+this.id).css('background-color', '#81d2c7');\r\n });\r\n\r\n $('.reset-view').click( function(){\r\n this.env_controller.resetView();\r\n }.bind(this));\r\n\r\n var env = this.engine.env;\r\n $('#reset-env').click( function() {\r\n this.engine.env.reset();\r\n }.bind(this));\r\n $('#auto-reset').change(function() {\r\n env.auto_reset = this.checked;\r\n });\r\n $('#clear-walls').click( function() {\r\n if (confirm(\"Are you sure you want to clear all the walls?\")) {\r\n this.engine.env.clearWalls();\r\n }\r\n }.bind(this));\r\n $('#clear-editor').click( function() {\r\n this.engine.organism_editor.clear();\r\n this.editor_controller.setEditorPanel();\r\n }.bind(this));\r\n }\r\n\r\n defineChallenges() {\r\n $('.challenge-btn').click(function() {\r\n $('#challenge-title').text($(this).text());\r\n $('#challenge-description').text($(this).val());\r\n });\r\n }\r\n\r\n setMode(mode) {\r\n this.env_controller.mode = mode;\r\n this.editor_controller.mode = mode;\r\n }\r\n\r\n setEditorOrganism(org) {\r\n this.engine.organism_editor.setOrganismToCopyOf(org);\r\n this.editor_controller.clearDetailsPanel();\r\n this.editor_controller.setDetailsPanel();\r\n }\r\n\r\n changeEngineSpeed(change_val) {\r\n this.engine.stop();\r\n this.engine.start(change_val)\r\n this.fps = this.engine.fps;\r\n }\r\n\r\n update() {\r\n $('#fps-actual').text(\"Actual FPS: \" + Math.floor(this.engine.actual_fps));\r\n var org_count = this.engine.env.organisms.length;\r\n $('#org-count').text(\"Organism count: \" + org_count);\r\n if (org_count > this.organism_record) \r\n this.organism_record = org_count;\r\n $('#org-record').text(\"Highest count: \" + this.organism_record);\r\n $('#avg-mut').text(\"Average Mutation Rate: \" + Math.round(this.engine.env.averageMutability() * 100) / 100);\r\n $('#largest-org').text(\"Largest Organism: \" + this.engine.env.largest_cell_count + \" cells\");\r\n $('#reset-count').text(\"Auto reset count: \" + this.engine.env.reset_count);\r\n }\r\n\r\n}\r\n\r\n\r\nmodule.exports = ControlPanel;\n\n//# sourceURL=webpack:///./src/Controllers/ControlPanel.js?"); - -/***/ }), - -/***/ "./src/Controllers/EditorController.js": -/*!*********************************************!*\ - !*** ./src/Controllers/EditorController.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CanvasController = __webpack_require__(/*! ./CanvasController */ \"./src/Controllers/CanvasController.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Directions = __webpack_require__(/*! ../Organism/Directions */ \"./src/Organism/Directions.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\n\r\nclass EditorController extends CanvasController{\r\n constructor(env, canvas) {\r\n super(env, canvas);\r\n this.mode = Modes.None;\r\n this.edit_cell_type = null;\r\n this.highlight_org = false;\r\n this.defineCellTypeSelection();\r\n this.defineEditorDetails();\r\n }\r\n\r\n mouseMove() {\r\n if (this.right_click || this.left_click)\r\n this.editOrganism();\r\n }\r\n\r\n mouseDown() {\r\n this.editOrganism();\r\n }\r\n\r\n mouseUp(){}\r\n\r\n getCurLocalCell(){\r\n return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c, this.mouse_r-this.env.organism.r);\r\n }\r\n\r\n editOrganism() {\r\n if (this.edit_cell_type == null || this.mode != Modes.Edit)\r\n return;\r\n if (this.left_click){\r\n if(this.edit_cell_type == CellStates.eye && this.cur_cell.state == CellStates.eye) {\r\n var loc_cell = this.getCurLocalCell();\r\n loc_cell.direction = Directions.rotateRight(loc_cell.direction);\r\n this.env.renderFull();\r\n }\r\n else\r\n this.env.addCellToOrg(this.mouse_c, this.mouse_r, this.edit_cell_type);\r\n }\r\n if (this.right_click)\r\n this.env.removeCellFromOrg(this.mouse_c, this.mouse_r);\r\n this.setBrainPanelVisibility();\r\n this.setMoveRangeVisibility();\r\n this.updateDetails();\r\n }\r\n\r\n updateDetails() {\r\n $('.cell-count').text(\"Cell count: \"+this.env.organism.anatomy.cells.length);\r\n }\r\n\r\n defineCellTypeSelection() {\r\n var self = this;\r\n $('.cell-type').click( function() {\r\n switch(this.id){\r\n case \"mouth\":\r\n self.edit_cell_type = CellStates.mouth;\r\n break;\r\n case \"producer\":\r\n self.edit_cell_type = CellStates.producer;\r\n break;\r\n case \"mover\":\r\n self.edit_cell_type = CellStates.mover;\r\n break;\r\n case \"killer\":\r\n self.edit_cell_type = CellStates.killer;\r\n break;\r\n case \"armor\":\r\n self.edit_cell_type = CellStates.armor;\r\n break;\r\n case \"eye\":\r\n self.edit_cell_type = CellStates.eye;\r\n break;\r\n }\r\n $(\".cell-type\" ).css( \"border-color\", \"black\" );\r\n var selected = '#'+this.id+'.cell-type';\r\n $(selected).css(\"border-color\", \"yellow\");\r\n });\r\n }\r\n\r\n defineEditorDetails() {\r\n this.details_html = $('#organism-details');\r\n this.edit_details_html = $('#edit-organism-details');\r\n\r\n this.decision_names = [\"ignore\", \"move away\", \"move towards\"];\r\n\r\n $('#move-range-edit').change ( function() {\r\n this.env.organism.move_range = parseInt($('#move-range-edit').val());\r\n }.bind(this));\r\n $('#observation-type-edit').change ( function() {\r\n this.setBrainEditorValues($('#observation-type-edit').val());\r\n this.setBrainDetails();\r\n }.bind(this));\r\n $('#reaction-edit').change ( function() {\r\n var obs = $('#observation-type-edit').val();\r\n var decision = parseInt($('#reaction-edit').val());\r\n this.env.organism.brain.decisions[obs] = decision;\r\n this.setBrainDetails();\r\n }.bind(this));\r\n }\r\n\r\n clearDetailsPanel() {\r\n $('#organism-details').css('display', 'none');\r\n $('#edit-organism-details').css('display', 'none');\r\n }\r\n\r\n setDetailsPanel() {\r\n this.clearDetailsPanel();\r\n var org = this.env.organism;\r\n \r\n $('.cell-count').text(\"Cell count: \"+org.anatomy.cells.length);\r\n $('#move-range').text(\"Move Range: \"+org.move_range);\r\n $('#mutation-rate').text(\"Mutation Rate: \"+org.mutability);\r\n if (Hyperparams.useGlobalMutability) {\r\n $('#mutation-rate').css('display', 'none');\r\n }\r\n else {\r\n $('#mutation-rate').css('display', 'block');\r\n }\r\n\r\n this.setMoveRangeVisibility();\r\n\r\n if (this.setBrainPanelVisibility()) {\r\n this.setBrainDetails();\r\n\r\n }\r\n $('#organism-details').css('display', 'block');\r\n }\r\n\r\n setEditorPanel() {\r\n this.clearDetailsPanel();\r\n var org = this.env.organism;\r\n\r\n $('.cell-count').text(\"Cell count: \"+org.anatomy.cells.length);\r\n if (this.setMoveRangeVisibility()){\r\n $('#move-range-edit').val(org.move_range);\r\n }\r\n \r\n if (this.setBrainPanelVisibility()){\r\n this.setBrainEditorValues($('#observation-type-edit').val());\r\n }\r\n\r\n $('#cell-selections').css('display', 'grid');\r\n $('#edit-organism-details').css('display', 'block');\r\n }\r\n\r\n setBrainPanelVisibility() {\r\n var org = this.env.organism;\r\n if (org.anatomy.has_eyes && org.anatomy.is_mover) {\r\n $('.brain-details').css('display', 'block');\r\n return true;\r\n }\r\n $('.brain-details').css('display', 'none');\r\n return false;\r\n }\r\n\r\n setBrainDetails() {\r\n var chase_types = [];\r\n var retreat_types = [];\r\n for(var cell_name in this.env.organism.brain.decisions) {\r\n var decision = this.env.organism.brain.decisions[cell_name];\r\n if (decision == 1) {\r\n retreat_types.push(cell_name)\r\n }\r\n else if (decision == 2) {\r\n chase_types.push(cell_name);\r\n }\r\n }\r\n $('.chase-types').text(\"Move Towards: \" + chase_types);\r\n $('.retreat-types').text(\"Move Away From: \" + retreat_types);\r\n }\r\n\r\n setMoveRangeVisibility() {\r\n var org = this.env.organism;\r\n if (org.anatomy.is_mover) {\r\n $('#move-range-cont').css('display', 'block');\r\n $('#move-range').css('display', 'block');\r\n return true;\r\n }\r\n $('#move-range-cont').css('display', 'none');\r\n $('#move-range').css('display', 'none');\r\n return false;\r\n }\r\n\r\n setBrainEditorValues(name) {\r\n $('#observation-type-edit').val(name);\r\n var reaction = this.env.organism.brain.decisions[name];\r\n $('#reaction-edit').val(reaction);\r\n }\r\n}\r\n\r\nmodule.exports = EditorController;\r\n\n\n//# sourceURL=webpack:///./src/Controllers/EditorController.js?"); - -/***/ }), - -/***/ "./src/Controllers/EnvironmentController.js": -/*!**************************************************!*\ - !*** ./src/Controllers/EnvironmentController.js ***! - \**************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CanvasController = __webpack_require__(/*! ./CanvasController */ \"./src/Controllers/CanvasController.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Neighbors = __webpack_require__(/*! ../Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass EnvironmentController extends CanvasController{\r\n constructor(env, canvas) {\r\n super(env, canvas);\r\n this.mode = Modes.Drag;\r\n this.org_to_clone = null;\r\n this.species_to_clone = null;\r\n this.make_new_species = false;\r\n this.defineZoomControls();\r\n this.scale = 1;\r\n }\r\n\r\n defineZoomControls() {\r\n var scale = 1;\r\n var zoom_speed = 0.5;\r\n const el = document.querySelector('#env-canvas');\r\n el.onwheel = function zoom(event) {\r\n event.preventDefault();\r\n\r\n var sign = -Math.sign(event.deltaY);\r\n\r\n // Restrict scale\r\n scale = Math.max(0.5, this.scale+(sign*zoom_speed));\r\n\r\n if (scale != 0.5) {\r\n var cur_top = parseInt($('#env-canvas').css('top'));\r\n var cur_left = parseInt($('#env-canvas').css('left'));\r\n if (sign == 1) {\r\n // If we're zooming in, zoom towards wherever the mouse is\r\n var diff_x = ((this.canvas.width/2-cur_left/this.scale) - this.mouse_x)*this.scale/1.5;\r\n var diff_y = ((this.canvas.height/2-cur_top/this.scale) - this.mouse_y)*this.scale/1.5;\r\n }\r\n else {\r\n // If we're zooming out, zoom out towards the center\r\n var diff_x = -cur_left/scale;\r\n var diff_y = -cur_top/scale;\r\n }\r\n $('#env-canvas').css('top', (cur_top+diff_y)+'px');\r\n $('#env-canvas').css('left', (cur_left+diff_x)+'px');\r\n }\r\n \r\n // Apply scale transform\r\n el.style.transform = `scale(${scale})`;\r\n this.scale = scale;\r\n\r\n }.bind(this);\r\n }\r\n\r\n resetView() {\r\n $('#env-canvas').css('transform', 'scale(1)');\r\n $('#env-canvas').css('top', '0px');\r\n $('#env-canvas').css('left', '0px');\r\n this.scale = 1;\r\n }\r\n\r\n updateMouseLocation(offsetX, offsetY){\r\n \r\n super.updateMouseLocation(offsetX, offsetY);\r\n }\r\n\r\n mouseMove() {\r\n this.performModeAction();\r\n }\r\n\r\n mouseDown() {\r\n this.start_x = this.mouse_x;\r\n this.start_y = this.mouse_y;\r\n this.performModeAction();\r\n }\r\n\r\n mouseUp() {\r\n\r\n }\r\n\r\n performModeAction() {\r\n var mode = this.mode;\r\n var right_click = this.right_click;\r\n var left_click = this.left_click;\r\n if (mode != Modes.None && (right_click || left_click)) {\r\n var cell = this.cur_cell;\r\n if (cell == null){\r\n return;\r\n }\r\n switch(mode) {\r\n case Modes.FoodDrop:\r\n if (left_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.food, false);\r\n }\r\n else if (right_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.empty, false);\r\n }\r\n break;\r\n case Modes.WallDrop:\r\n if (left_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.wall, true);\r\n\r\n }\r\n else if (right_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.empty, false);\r\n }\r\n break;\r\n case Modes.ClickKill:\r\n this.killNearOrganisms();\r\n break;\r\n\r\n case Modes.Select:\r\n if (this.cur_org == null) {\r\n this.cur_org = this.findNearOrganism();\r\n }\r\n if (this.cur_org != null){\r\n this.control_panel.setEditorOrganism(this.cur_org);\r\n }\r\n break;\r\n\r\n case Modes.Clone:\r\n if (this.org_to_clone != null){\r\n var new_org = new Organism(this.mouse_c, this.mouse_r, this.env, this.org_to_clone);\r\n if (this.make_new_species){\r\n this.species_to_clone = FossilRecord.addSpecies(new_org, null)\r\n this.make_new_species = false;\r\n }\r\n else {\r\n new_org.species = this.species_to_clone;\r\n this.species_to_clone.addPop();\r\n }\r\n if (new_org.isClear(this.mouse_c, this.mouse_r)){\r\n this.env.addOrganism(new_org)\r\n }\r\n }\r\n break;\r\n case Modes.Drag:\r\n var cur_top = parseInt($('#env-canvas').css('top'), 10);\r\n var cur_left = parseInt($('#env-canvas').css('left'), 10);\r\n var new_top = cur_top + ((this.mouse_y - this.start_y)*this.scale);\r\n var new_left = cur_left + ((this.mouse_x - this.start_x)*this.scale);\r\n $('#env-canvas').css('top', new_top+'px');\r\n $('#env-canvas').css('left', new_left+'px');\r\n break;\r\n }\r\n }\r\n }\r\n\r\n dropCellType(col, row, state, killBlocking=false) {\r\n for (var loc of Neighbors.allSelf){\r\n var c=col + loc[0];\r\n var r=row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell == null)\r\n continue;\r\n if (killBlocking && cell.owner != null){\r\n cell.owner.die();\r\n }\r\n else if (cell.owner != null) {\r\n continue;\r\n }\r\n this.env.changeCell(c, r, state, null);\r\n }\r\n }\r\n\r\n findNearOrganism() {\r\n for (var loc of Neighbors.all){\r\n var c = this.cur_cell.col + loc[0];\r\n var r = this.cur_cell.row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell != null && cell.owner != null)\r\n return cell.owner;\r\n }\r\n return null;\r\n }\r\n\r\n killNearOrganisms() {\r\n for (var loc of Neighbors.allSelf){\r\n var c = this.cur_cell.col + loc[0];\r\n var r = this.cur_cell.row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell != null && cell.owner != null)\r\n cell.owner.die();\r\n }\r\n }\r\n\r\n\r\n}\r\n\r\nmodule.exports = EnvironmentController;\r\n\n\n//# sourceURL=webpack:///./src/Controllers/EnvironmentController.js?"); - -/***/ }), - -/***/ "./src/Engine.js": -/*!***********************!*\ - !*** ./src/Engine.js ***! - \***********************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const WorldEnvironment = __webpack_require__(/*! ./Environments/WorldEnvironment */ \"./src/Environments/WorldEnvironment.js\");\r\nconst ControlPanel = __webpack_require__(/*! ./Controllers/ControlPanel */ \"./src/Controllers/ControlPanel.js\");\r\nconst OrganismEditor = __webpack_require__(/*! ./Environments/OrganismEditor */ \"./src/Environments/OrganismEditor.js\");\r\nconst ColorScheme = __webpack_require__(/*! ./Rendering/ColorScheme */ \"./src/Rendering/ColorScheme.js\");\r\n\r\nconst render_speed = 60;\r\n\r\nclass Engine{\r\n constructor(){\r\n this.fps = 60;\r\n this.env = new WorldEnvironment(5);\r\n this.organism_editor = new OrganismEditor();\r\n this.controlpanel = new ControlPanel(this);\r\n this.colorscheme = new ColorScheme(this.env, this.organism_editor);\r\n this.colorscheme.loadColorScheme();\r\n this.env.OriginOfLife();\r\n this.last_update = Date.now();\r\n this.delta_time = 0;\r\n this.actual_fps = 0;\r\n this.running = false;\r\n }\r\n\r\n start(fps=60) {\r\n if (fps <= 0)\r\n fps = 1;\r\n if (fps > 300)\r\n fps = 300;\r\n this.fps = fps;\r\n this.game_loop = setInterval(function(){this.environmentUpdate();}.bind(this), 1000/fps);\r\n this.running = true;\r\n if (this.fps >= render_speed) {\r\n if (this.render_loop != null) {\r\n clearInterval(this.render_loop);\r\n this.render_loop = null;\r\n }\r\n }\r\n else\r\n this.setRenderLoop();\r\n }\r\n \r\n stop() {\r\n clearInterval(this.game_loop);\r\n this.running = false;\r\n this.setRenderLoop();\r\n }\r\n\r\n setRenderLoop() {\r\n if (this.render_loop == null) {\r\n this.render_loop = setInterval(function(){this.necessaryUpdate();}.bind(this), 1000/render_speed);\r\n }\r\n }\r\n\r\n\r\n environmentUpdate() {\r\n this.delta_time = Date.now() - this.last_update;\r\n this.last_update = Date.now();\r\n this.env.update(this.delta_time);\r\n this.actual_fps = 1/this.delta_time*1000;\r\n if(this.render_loop == null){\r\n this.necessaryUpdate();\r\n }\r\n \r\n }\r\n\r\n necessaryUpdate() {\r\n this.env.render();\r\n this.controlpanel.update();\r\n this.organism_editor.update();\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Engine;\r\n\n\n//# sourceURL=webpack:///./src/Engine.js?"); - -/***/ }), - -/***/ "./src/Environments/Environment.js": -/*!*****************************************!*\ - !*** ./src/Environments/Environment.js ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("\r\n//An evironment has a grid_map, controller, and renderer\r\nclass Environment{\r\n constructor() {\r\n }\r\n\r\n update(){\r\n alert(\"Environment.update() must be overriden\");\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n this.grid_map.setCellType(c, r, state);\r\n this.grid_map.setCellOwner(c, r, owner);\r\n }\r\n}\r\n\r\n\r\nmodule.exports = Environment;\n\n//# sourceURL=webpack:///./src/Environments/Environment.js?"); - -/***/ }), - -/***/ "./src/Environments/OrganismEditor.js": -/*!********************************************!*\ - !*** ./src/Environments/OrganismEditor.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environments/Environment.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst GridMap = __webpack_require__(/*! ../Grid/GridMap */ \"./src/Grid/GridMap.js\");\r\nconst Renderer = __webpack_require__(/*! ../Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst EditorController = __webpack_require__(/*! ../Controllers/EditorController */ \"./src/Controllers/EditorController.js\");\r\n\r\nclass OrganismEditor extends Environment{\r\n constructor() {\r\n super();\r\n this.is_active = true;\r\n var cell_size = 13;\r\n this.renderer = new Renderer('editor-canvas', 'editor-env', cell_size);\r\n this.controller = new EditorController(this, this.renderer.canvas);\r\n this.grid_map = new GridMap(15, 15, cell_size);\r\n this.clear();\r\n }\r\n\r\n update() {\r\n if (this.is_active){\r\n this.renderer.renderHighlights();\r\n }\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n super.changeCell(c, r, state, owner);\r\n this.renderFull();\r\n }\r\n\r\n renderFull() {\r\n this.renderer.renderFullGrid(this.grid_map.grid);\r\n }\r\n\r\n // absolute c r, not local\r\n addCellToOrg(c, r, state) {\r\n var center = this.grid_map.getCenter();\r\n var loc_c = c - center[0];\r\n var loc_r = r - center[1];\r\n var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)\r\n if (prev_cell != null) {\r\n var new_cell = this.organism.anatomy.replaceCell(state, prev_cell.loc_col, prev_cell.loc_row, false);\r\n this.changeCell(c, r, state, new_cell);\r\n }\r\n else if (this.organism.anatomy.canAddCellAt(loc_c, loc_r)){\r\n this.changeCell(c, r, state, this.organism.anatomy.addDefaultCell(state, loc_c, loc_r));\r\n }\r\n }\r\n\r\n removeCellFromOrg(c, r) {\r\n var center = this.grid_map.getCenter();\r\n var loc_c = c - center[0];\r\n var loc_r = r - center[1];\r\n if (loc_c == 0 && loc_r == 0){\r\n alert(\"Cannot remove center cell\");\r\n return;\r\n }\r\n var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)\r\n if (prev_cell != null) {\r\n if (this.organism.anatomy.removeCell(loc_c, loc_r)) {\r\n this.changeCell(c, r, CellStates.empty, null);\r\n }\r\n }\r\n }\r\n\r\n setOrganismToCopyOf(orig_org){\r\n this.grid_map.fillGrid(CellStates.empty);\r\n var center = this.grid_map.getCenter();\r\n this.organism = new Organism(center[0], center[1], this, orig_org);\r\n this.organism.updateGrid();\r\n this.controller.updateDetails();\r\n }\r\n \r\n getCopyOfOrg() {\r\n var new_org = new Organism(0, 0, null, this.organism);\r\n return new_org;\r\n }\r\n\r\n clear() {\r\n this.grid_map.fillGrid(CellStates.empty);\r\n var center = this.grid_map.getCenter();\r\n this.organism = new Organism(center[0], center[1], this, null);\r\n this.organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0);\r\n this.organism.updateGrid();\r\n }\r\n}\r\n\r\nmodule.exports = OrganismEditor;\n\n//# sourceURL=webpack:///./src/Environments/OrganismEditor.js?"); - -/***/ }), - -/***/ "./src/Environments/WorldEnvironment.js": -/*!**********************************************!*\ - !*** ./src/Environments/WorldEnvironment.js ***! - \**********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environments/Environment.js\");\r\nconst Renderer = __webpack_require__(/*! ../Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst GridMap = __webpack_require__(/*! ../Grid/GridMap */ \"./src/Grid/GridMap.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst EnvironmentController = __webpack_require__(/*! ../Controllers/EnvironmentController */ \"./src/Controllers/EnvironmentController.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters.js */ \"./src/Hyperparameters.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass WorldEnvironment extends Environment{\r\n constructor(cell_size) {\r\n super();\r\n this.renderer = new Renderer('env-canvas', 'env', cell_size);\r\n this.controller = new EnvironmentController(this, this.renderer.canvas);\r\n var grid_rows = Math.floor(this.renderer.height / cell_size);\r\n var grid_cols = Math.floor(this.renderer.width / cell_size);\r\n this.grid_map = new GridMap(grid_cols, grid_rows, cell_size);\r\n this.organisms = [];\r\n this.walls = [];\r\n this.total_mutability = 0;\r\n this.auto_reset = true;\r\n this.largest_cell_count = 0;\r\n this.reset_count = 0;\r\n this.total_ticks = 0;\r\n FossilRecord.setEnv(this);\r\n }\r\n\r\n update(delta_time) {\r\n this.total_ticks ++;\r\n var to_remove = [];\r\n for (var i in this.organisms) {\r\n var org = this.organisms[i];\r\n if (!org.living || !org.update()) {\r\n to_remove.push(i);\r\n }\r\n }\r\n if (Hyperparams.foodDropProb > 0) {\r\n this.generateFood();\r\n }\r\n this.removeOrganisms(to_remove);\r\n }\r\n\r\n render() {\r\n this.renderer.renderCells();\r\n this.renderer.renderHighlights();\r\n }\r\n\r\n removeOrganisms(org_indeces) {\r\n for (var i of org_indeces.reverse()){\r\n this.total_mutability -= this.organisms[i].mutability;\r\n this.organisms.splice(i, 1);\r\n }\r\n if (this.organisms.length == 0 && this.auto_reset){\r\n this.reset_count++;\r\n this.reset();\r\n }\r\n }\r\n\r\n OriginOfLife() {\r\n var center = this.grid_map.getCenter();\r\n var org = new Organism(center[0], center[1], this);\r\n org.anatomy.addDefaultCell(CellStates.mouth, 0, 0);\r\n org.anatomy.addDefaultCell(CellStates.producer, 1, 1);\r\n org.anatomy.addDefaultCell(CellStates.producer, -1, -1);\r\n this.addOrganism(org);\r\n FossilRecord.addSpecies(org, null);\r\n }\r\n\r\n addOrganism(organism) {\r\n organism.updateGrid();\r\n this.total_mutability += organism.mutability;\r\n this.organisms.push(organism);\r\n if (organism.anatomy.cells.length > this.largest_cell_count) \r\n this.largest_cell_count = organism.anatomy.cells.length;\r\n }\r\n\r\n averageMutability() {\r\n if (this.organisms.length < 1)\r\n return 0;\r\n return this.total_mutability / this.organisms.length;\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n super.changeCell(c, r, state, owner);\r\n this.renderer.addToRender(this.grid_map.cellAt(c, r));\r\n if(state == CellStates.wall)\r\n this.walls.push(this.grid_map.cellAt(c, r));\r\n }\r\n\r\n clearWalls() {\r\n for(var wall of this.walls){\r\n if (this.grid_map.cellAt(wall.col, wall.row).state == CellStates.wall)\r\n this.changeCell(wall.col, wall.row, CellStates.empty, null);\r\n }\r\n }\r\n\r\n clearOrganisms() {\r\n for (var org of this.organisms)\r\n org.die();\r\n this.organisms = [];\r\n }\r\n\r\n generateFood() {\r\n var num_food = Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*Hyperparams.foodDropProb/50000), 1)\r\n var prob = Hyperparams.foodDropProb;\r\n for (var i=0; i=0 && row>=0;\r\n }\r\n\r\n getCenter(){\r\n return [Math.floor(this.cols/2), Math.floor(this.rows/2)]\r\n }\r\n\r\n xyToColRow(x, y) {\r\n var c = Math.floor(x/this.cell_size);\r\n var r = Math.floor(y/this.cell_size);\r\n if (c >= this.cols)\r\n c = this.cols-1;\r\n else if (c < 0)\r\n c = 0;\r\n if (r >= this.rows)\r\n r = this.rows-1;\r\n else if (r < 0)\r\n r = 0;\r\n return [c, r];\r\n }\r\n}\r\n\r\nmodule.exports = GridMap;\r\n\n\n//# sourceURL=webpack:///./src/Grid/GridMap.js?"); - -/***/ }), - -/***/ "./src/Grid/Neighbors.js": -/*!*******************************!*\ - !*** ./src/Grid/Neighbors.js ***! - \*******************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("// contains local cell values for the following:\r\n\r\n//all ...\r\n// .x.\r\n// ...\r\n\r\n//adjacent .\r\n// .x.\r\n// .\r\n\r\n//corners . .\r\n// x\r\n// . .\r\n\r\n//allSelf ...\r\n// ...\r\n// ...\r\n\r\nconst Neighbors = {\r\n all: [[0, 1],[0, -1],[1, 0],[-1, 0],[-1, -1],[1, 1],[-1, 1],[1, -1]],\r\n adjacent: [[0, 1],[0, -1],[1, 0],[-1, 0]],\r\n corners: [[-1, -1],[1, 1],[-1, 1],[1, -1]],\r\n allSelf: [[0, 0],[0, 1],[0, -1],[1, 0],[-1, 0],[-1, -1],[1, 1],[-1, 1],[1, -1]]\r\n}\r\n\r\nmodule.exports = Neighbors;\n\n//# sourceURL=webpack:///./src/Grid/Neighbors.js?"); - -/***/ }), - -/***/ "./src/Hyperparameters.js": -/*!********************************!*\ - !*** ./src/Hyperparameters.js ***! - \********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Neighbors = __webpack_require__(/*! ./Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\n\r\nconst Hyperparams = {\r\n setDefaults: function() {\r\n this.lifespanMultiplier = 100;\r\n this.foodProdProb = 4;\r\n this.foodProdProbScalar = 4;\r\n this.killableNeighbors = Neighbors.adjacent;\r\n this.edibleNeighbors = Neighbors.adjacent;\r\n this.growableNeighbors = Neighbors.adjacent;\r\n\r\n this.useGlobalMutability = false;\r\n this.globalMutability = 5;\r\n this.addProb = 33;\r\n this.changeProb = 33;\r\n this.removeProb = 33;\r\n \r\n this.moversCanRotate = true;\r\n this.offspringRotate = true;\r\n\r\n this.foodBlocksReproduction = true;\r\n this.moversCanProduce = false;\r\n\r\n this.instaKill = false;\r\n\r\n this.lookRange = 20;\r\n\r\n this.foodDropProb = 0;\r\n },\r\n\r\n balanceMutationProbs : function(choice) {\r\n if (choice == 1) {\r\n var remaining = 100 - this.addProb;\r\n this.changeProb = remaining/2;\r\n this.removeProb = remaining/2;\r\n }\r\n else if (choice == 2) {\r\n var remaining = 100 - this.changeProb;\r\n this.addProb = remaining/2;\r\n this.removeProb = remaining/2;\r\n }\r\n else {\r\n var remaining = 100 - this.removeProb;\r\n this.changeProb = remaining/2;\r\n this.addProb = remaining/2;\r\n }\r\n }\r\n}\r\n\r\nHyperparams.setDefaults();\r\n\r\nmodule.exports = Hyperparams;\n\n//# sourceURL=webpack:///./src/Hyperparameters.js?"); - -/***/ }), - -/***/ "./src/Organism/Anatomy.js": -/*!*********************************!*\ - !*** ./src/Organism/Anatomy.js ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CellStates = __webpack_require__(/*! ./Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst BodyCellFactory = __webpack_require__(/*! ./Cell/BodyCells/BodyCellFactory */ \"./src/Organism/Cell/BodyCells/BodyCellFactory.js\");\r\n\r\nclass Anatomy {\r\n constructor(owner) {\r\n this.owner = owner;\r\n this.cells = [];\r\n this.is_producer = false;\r\n this.is_mover = false;\r\n this.has_eyes = false;\r\n this.birth_distance = 4;\r\n }\r\n\r\n canAddCellAt(c, r) {\r\n for (var cell of this.cells) {\r\n if (cell.loc_col == c && cell.loc_row == r){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n addDefaultCell(state, c, r) {\r\n var new_cell = BodyCellFactory.createDefault(this.owner, state, c, r);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n addRandomizedCell(state, c, r) {\r\n if (state==CellStates.eye && !this.has_eyes) {\r\n this.owner.brain.randomizeDecisions();\r\n }\r\n var new_cell = BodyCellFactory.createRandom(this.owner, state, c, r);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n addInheritCell(parent_cell) {\r\n var new_cell = BodyCellFactory.createInherited(this.owner, parent_cell);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n replaceCell(state, c, r, randomize=true) {\r\n this.removeCell(c, r, true);\r\n if (randomize) {\r\n return this.addRandomizedCell(state, c, r);\r\n }\r\n else {\r\n return this.addDefaultCell(state, c, r);\r\n }\r\n }\r\n\r\n removeCell(c, r, allow_center_removal=false) {\r\n if (c == 0 && r == 0 && !allow_center_removal)\r\n return false;\r\n for (var i=0; i 3)\r\n dir -= 4;\r\n return dir;\r\n }\r\n\r\n performFunction() {\r\n var obs = this.look();\r\n this.org.brain.observe(obs);\r\n }\r\n\r\n look() {\r\n var env = this.org.env;\r\n var direction = this.getAbsoluteDirection();\r\n var addCol = 0;\r\n var addRow = 0;\r\n switch(direction) {\r\n case Directions.up:\r\n addRow = -1;\r\n break;\r\n case Directions.down:\r\n addRow = 1;\r\n break;\r\n case Directions.right:\r\n addCol = 1;\r\n break;\r\n case Directions.left:\r\n addCol = -1;\r\n break;\r\n }\r\n var start_col = this.getRealCol();\r\n var start_row = this.getRealRow();\r\n var col = start_col;\r\n var row = start_row;\r\n var cell = null;\r\n for (var i=0; i 3){\r\n dir = 0;\r\n }\r\n return dir;\r\n }\r\n}\r\n\r\nmodule.exports = Directions;\n\n//# sourceURL=webpack:///./src/Organism/Directions.js?"); - -/***/ }), - -/***/ "./src/Organism/Organism.js": -/*!**********************************!*\ - !*** ./src/Organism/Organism.js ***! - \**********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CellStates = __webpack_require__(/*! ./Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Neighbors = __webpack_require__(/*! ../Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Directions = __webpack_require__(/*! ./Directions */ \"./src/Organism/Directions.js\");\r\nconst Anatomy = __webpack_require__(/*! ./Anatomy */ \"./src/Organism/Anatomy.js\");\r\nconst Brain = __webpack_require__(/*! ./Perception/Brain */ \"./src/Organism/Perception/Brain.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass Organism {\r\n constructor(col, row, env, parent=null) {\r\n this.c = col;\r\n this.r = row;\r\n this.env = env;\r\n this.lifetime = 0;\r\n this.food_collected = 0;\r\n this.living = true;\r\n this.anatomy = new Anatomy(this)\r\n this.direction = Directions.down; // direction of movement\r\n this.rotation = Directions.up; // direction of rotation\r\n this.can_rotate = Hyperparams.moversCanRotate;\r\n this.move_count = 0;\r\n this.move_range = 4;\r\n this.ignore_brain_for = 0;\r\n this.mutability = 5;\r\n this.damage = 0;\r\n this.brain = new Brain(this);\r\n if (parent != null) {\r\n this.inherit(parent);\r\n }\r\n }\r\n\r\n inherit(parent) {\r\n this.move_range = parent.move_range;\r\n this.mutability = parent.mutability;\r\n this.species = parent.species;\r\n // this.birth_distance = parent.birth_distance;\r\n for (var c of parent.anatomy.cells){\r\n //deep copy parent cells\r\n this.anatomy.addInheritCell(c);\r\n }\r\n if(parent.anatomy.is_mover) {\r\n for (var i in parent.brain.decisions) {\r\n this.brain.decisions[i] = parent.brain.decisions[i];\r\n }\r\n }\r\n }\r\n\r\n // amount of food required before it can reproduce\r\n foodNeeded() {\r\n return this.anatomy.cells.length;\r\n }\r\n\r\n lifespan() {\r\n // console.log(Hyperparams.lifespanMultiplier)\r\n return this.anatomy.cells.length * Hyperparams.lifespanMultiplier;\r\n }\r\n\r\n maxHealth() {\r\n return this.anatomy.cells.length;\r\n }\r\n\r\n reproduce() {\r\n //produce mutated child\r\n //check nearby locations (is there room and a direct path)\r\n var org = new Organism(0, 0, this.env, this);\r\n if(Hyperparams.offspringRotate){\r\n org.rotation = Directions.getRandomDirection();\r\n }\r\n var prob = this.mutability;\r\n if (Hyperparams.useGlobalMutability){\r\n prob = Hyperparams.globalMutability;\r\n }\r\n else {\r\n //mutate the mutability\r\n if (Math.random() <= 0.5)\r\n org.mutability++;\r\n else{ \r\n org.mutability--;\r\n if (org.mutability < 1)\r\n org.mutability = 1;\r\n }\r\n } \r\n var mutated = false;\r\n if (Math.random() * 100 <= prob) {\r\n if (org.anatomy.is_mover && Math.random() * 100 <= 10) { \r\n if (org.anatomy.has_eyes) {\r\n org.brain.mutate();\r\n }\r\n org.move_range += Math.floor(Math.random() * 4) - 2;\r\n if (org.move_range <= 0){\r\n org.move_range = 1;\r\n };\r\n \r\n }\r\n else {\r\n mutated = org.mutate();\r\n }\r\n }\r\n\r\n var direction = Directions.getRandomScalar();\r\n var direction_c = direction[0];\r\n var direction_r = direction[1];\r\n var offset = (Math.floor(Math.random() * 3));\r\n var basemovement = this.anatomy.birth_distance;\r\n var new_c = this.c + (direction_c*basemovement) + (direction_c*offset);\r\n var new_r = this.r + (direction_r*basemovement) + (direction_r*offset);\r\n\r\n // console.log(org.isClear(new_c, new_r, org.rotation, true))\r\n if (org.isClear(new_c, new_r, org.rotation, true) && org.isStraightPath(new_c, new_r, this.c, this.r, this)){\r\n org.c = new_c;\r\n org.r = new_r;\r\n this.env.addOrganism(org);\r\n org.updateGrid();\r\n if (mutated) {\r\n FossilRecord.addSpecies(org, this.species);\r\n }\r\n else {\r\n org.species.addPop();\r\n }\r\n }\r\n this.food_collected -= this.foodNeeded();\r\n\r\n }\r\n\r\n mutate() {\r\n var choice = Math.floor(Math.random() * 100);\r\n var mutated = false;\r\n if (choice <= Hyperparams.addProb) {\r\n // add cell\r\n // console.log(\"add cell\")\r\n\r\n var branch = this.anatomy.getRandomCell();\r\n var state = CellStates.getRandomLivingType();//branch.state;\r\n var growth_direction = Neighbors.all[Math.floor(Math.random() * Neighbors.all.length)]\r\n var c = branch.loc_col+growth_direction[0];\r\n var r = branch.loc_row+growth_direction[1];\r\n if (this.anatomy.canAddCellAt(c, r)){\r\n mutated = true;\r\n this.anatomy.addRandomizedCell(state, c, r);\r\n }\r\n }\r\n else if (choice <= Hyperparams.addProb + Hyperparams.changeProb){\r\n // change cell\r\n var cell = this.anatomy.getRandomCell();\r\n var state = CellStates.getRandomLivingType();\r\n // console.log(\"change cell\", state)\r\n this.anatomy.replaceCell(state, cell.loc_col, cell.loc_row);\r\n mutated = true;\r\n }\r\n else if (choice <= Hyperparams.addProb + Hyperparams.changeProb + Hyperparams.removeProb){\r\n // remove cell\r\n // console.log(\"remove cell\")\r\n\r\n if(this.anatomy.cells.length > 1) {\r\n var cell = this.anatomy.getRandomCell();\r\n mutated = this.anatomy.removeCell(cell.loc_col, cell.loc_row);\r\n }\r\n }\r\n return mutated;\r\n }\r\n\r\n attemptMove() {\r\n var direction = Directions.scalars[this.direction];\r\n var direction_c = direction[0];\r\n var direction_r = direction[1];\r\n var new_c = this.c + direction_c;\r\n var new_r = this.r + direction_r;\r\n if (this.isClear(new_c, new_r)) {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.empty, null);\r\n }\r\n this.c = new_c;\r\n this.r = new_r;\r\n this.updateGrid();\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n attemptRotate() {\r\n if(!this.can_rotate){\r\n this.direction = Directions.getRandomDirection();\r\n this.move_count = 0;\r\n return true;\r\n }\r\n var new_rotation = Directions.getRandomDirection();\r\n if(this.isClear(this.c, this.r, new_rotation)){\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.empty, null);\r\n }\r\n this.rotation = new_rotation;\r\n this.direction = Directions.getRandomDirection();\r\n this.updateGrid();\r\n this.move_count = 0;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n changeDirection(dir) {\r\n this.direction = dir;\r\n this.move_count = 0;\r\n }\r\n\r\n // assumes either c1==c2 or r1==r2, returns true if there is a clear path from point 1 to 2\r\n isStraightPath(c1, r1, c2, r2, parent){\r\n if (c1 == c2) {\r\n if (r1 > r2){\r\n var temp = r2;\r\n r2 = r1;\r\n r1 = temp;\r\n }\r\n for (var i=r1; i!=r2; i++) {\r\n var cell = this.env.grid_map.cellAt(c1, i)\r\n if (!this.isPassableCell(cell, parent)){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n else {\r\n if (c1 > c2){\r\n var temp = c2;\r\n c2 = c1;\r\n c1 = temp;\r\n }\r\n for (var i=c1; i!=c2; i++) {\r\n var cell = this.env.grid_map.cellAt(i, r1);\r\n if (!this.isPassableCell(cell, parent)){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n }\r\n\r\n isPassableCell(cell, parent){\r\n return cell != null && (cell.state == CellStates.empty || cell.owner == this || cell.owner == parent || cell.state == CellStates.food);\r\n }\r\n\r\n isClear(col, row, rotation=this.rotation, ignore_armor=false) {\r\n for(var loccell of this.anatomy.cells) {\r\n var cell = this.getRealCell(loccell, col, row, rotation);\r\n if (cell==null) {\r\n return false;\r\n }\r\n // console.log(cell.owner == this)\r\n if (cell.owner==this || cell.state==CellStates.empty || (!Hyperparams.foodBlocksReproduction && cell.state==CellStates.food) || (ignore_armor && loccell.state==CellStates.armor && cell.state==CellStates.food)){\r\n continue;\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n harm() {\r\n this.damage++;\r\n if (this.damage >= this.maxHealth() || Hyperparams.instaKill) {\r\n this.die();\r\n }\r\n }\r\n\r\n die() {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.food, null);\r\n }\r\n this.species.decreasePop();\r\n this.living = false;\r\n }\r\n\r\n updateGrid() {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, cell.state, cell);\r\n }\r\n }\r\n\r\n update() {\r\n this.lifetime++;\r\n if (this.lifetime > this.lifespan()) {\r\n this.die();\r\n return this.living;\r\n }\r\n if (this.food_collected >= this.foodNeeded()) {\r\n this.reproduce();\r\n }\r\n for (var cell of this.anatomy.cells) {\r\n cell.performFunction();\r\n if (!this.living)\r\n return this.living\r\n }\r\n \r\n if (this.anatomy.is_mover) {\r\n this.move_count++;\r\n var changed_dir = false;\r\n if (this.ignore_brain_for == 0){\r\n changed_dir = this.brain.decide();\r\n } \r\n else{\r\n this.ignore_brain_for --;\r\n }\r\n var moved = this.attemptMove();\r\n if ((this.move_count > this.move_range && !changed_dir) || !moved){\r\n var rotated = this.attemptRotate();\r\n if (!rotated) {\r\n this.changeDirection(Directions.getRandomDirection());\r\n if (changed_dir)\r\n this.ignore_brain_for = this.move_range + 1;\r\n }\r\n }\r\n }\r\n\r\n return this.living;\r\n }\r\n\r\n getRealCell(local_cell, c=this.c, r=this.r, rotation=this.rotation){\r\n var real_c = c + local_cell.rotatedCol(rotation);\r\n var real_r = r + local_cell.rotatedRow(rotation);\r\n return this.env.grid_map.cellAt(real_c, real_r);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Organism;\r\n\n\n//# sourceURL=webpack:///./src/Organism/Organism.js?"); - -/***/ }), - -/***/ "./src/Organism/Perception/Brain.js": -/*!******************************************!*\ - !*** ./src/Organism/Perception/Brain.js ***! - \******************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Hyperparams = __webpack_require__(/*! ../../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Directions = __webpack_require__(/*! ../Directions */ \"./src/Organism/Directions.js\");\r\nconst CellStates = __webpack_require__(/*! ../Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\n\r\nconst Decision = {\r\n neutral: 0,\r\n retreat: 1,\r\n chase: 2,\r\n getRandom: function(){\r\n return Math.floor(Math.random() * 3);\r\n },\r\n getRandomNonNeutral: function() {\r\n return Math.floor(Math.random() * 2)+1;\r\n }\r\n}\r\n\r\nclass Brain {\r\n constructor(owner){\r\n this.owner = owner;\r\n this.observations = [];\r\n\r\n // corresponds to CellTypes\r\n this.decisions = [];\r\n this.decisions[CellStates.empty.name] = Decision.neutral;\r\n this.decisions[CellStates.food.name] = Decision.chase;\r\n this.decisions[CellStates.wall.name] = Decision.neutral;\r\n this.decisions[CellStates.mouth.name] = Decision.neutral;\r\n this.decisions[CellStates.producer.name] = Decision.neutral;\r\n this.decisions[CellStates.mover.name] = Decision.neutral;\r\n this.decisions[CellStates.killer.name] = Decision.retreat;\r\n this.decisions[CellStates.armor.name] = Decision.neutral;\r\n this.decisions[CellStates.eye.name] = Decision.neutral;\r\n }\r\n\r\n randomizeDecisions() {\r\n // randomize the non obvious decisions\r\n this.decisions[CellStates.mouth.name] = Decision.getRandom();\r\n this.decisions[CellStates.producer.name] = Decision.getRandom();\r\n this.decisions[CellStates.mover.name] = Decision.getRandom();\r\n this.decisions[CellStates.armor.name] = Decision.getRandom();\r\n this.decisions[CellStates.eye.name] = Decision.getRandom();\r\n }\r\n\r\n observe(observation) {\r\n this.observations.push(observation);\r\n }\r\n\r\n decide() {\r\n var decision = Decision.neutral;\r\n var closest = Hyperparams.lookRange + 1;\r\n var move_direction = 0;\r\n for (var obs of this.observations) {\r\n if (obs.cell == null || obs.cell.owner == this.owner) {\r\n continue;\r\n }\r\n if (obs.distance < closest) {\r\n // console.log(obs.cell.state)\r\n decision = this.decisions[obs.cell.state.name];\r\n // console.log(decision)\r\n move_direction = obs.direction;\r\n closest = obs.distance;\r\n }\r\n }\r\n this.observations = [];\r\n if (decision == Decision.chase) {\r\n this.owner.changeDirection(move_direction);\r\n return true;\r\n }\r\n else if (decision == Decision.retreat) {\r\n this.owner.changeDirection(Directions.getOppositeDirection(move_direction));\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n mutate() {\r\n this.decisions[CellStates.getRandomName()] = Decision.getRandom();\r\n this.decisions[CellStates.empty.name] = Decision.neutral; // if the empty cell has a decision it gets weird\r\n }\r\n}\r\n\r\nmodule.exports = Brain;\n\n//# sourceURL=webpack:///./src/Organism/Perception/Brain.js?"); - -/***/ }), - -/***/ "./src/Organism/Perception/Observation.js": -/*!************************************************!*\ - !*** ./src/Organism/Perception/Observation.js ***! - \************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("class Observation {\r\n constructor(cell, distance, direction){\r\n this.cell = cell;\r\n this.distance = distance;\r\n this.direction = direction;\r\n }\r\n}\r\n\r\nmodule.exports = Observation;\n\n//# sourceURL=webpack:///./src/Organism/Perception/Observation.js?"); - -/***/ }), - -/***/ "./src/Rendering/ColorScheme.js": -/*!**************************************!*\ - !*** ./src/Rendering/ColorScheme.js ***! - \**************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\n\r\nvar color_scheme = {\r\n \"empty\":\"#0E1318\",\r\n \"food\":\"#2F7AB7\",\r\n \"wall\":\"gray\",\r\n \"mouth\":\"#DEB14D\",\r\n \"producer\":\"#15DE59\",\r\n \"mover\":\"#60D4FF\",\r\n \"killer\":\"#F82380\",\r\n \"armor\":\"#7230DB\",\r\n \"eye\":\"#B6C1EA\",\r\n \"eye-slit\": \"#0E1318\"\r\n}\r\n\r\n// Renderer controls access to a canvas. There is one renderer for each canvas\r\nclass ColorScheme {\r\n constructor(world_env, editor_env) {\r\n this.world_env = world_env;\r\n this.editor_env = editor_env;\r\n }\r\n\r\n loadColorScheme() {\r\n for (var state of CellStates.all) {\r\n state.color = color_scheme[state.name];\r\n }\r\n CellStates.eye.slit_color=color_scheme['eye-slit']\r\n for (var cell_type in color_scheme) {\r\n $('#'+cell_type+'.cell-type ').css('background-color', color_scheme[cell_type]);\r\n $('#'+cell_type+'.cell-legend-type').css('background-color', color_scheme[cell_type]);\r\n \r\n }\r\n this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid);\r\n this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid);\r\n }\r\n}\r\n\r\nmodule.exports = ColorScheme;\n\n//# sourceURL=webpack:///./src/Rendering/ColorScheme.js?"); - -/***/ }), - -/***/ "./src/Rendering/Renderer.js": -/*!***********************************!*\ - !*** ./src/Rendering/Renderer.js ***! - \***********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("// const CellTypes = require(\"../Organism/Cell/CellTypes\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Directions = __webpack_require__(/*! ../Organism/Directions */ \"./src/Organism/Directions.js\");\r\n\r\n// Renderer controls access to a canvas. There is one renderer for each canvas\r\nclass Renderer {\r\n constructor(canvas_id, container_id, cell_size) {\r\n this.cell_size = cell_size;\r\n this.canvas = document.getElementById(canvas_id);\r\n this.ctx = this.canvas.getContext(\"2d\");\r\n this.fillWindow(container_id)\r\n\t\tthis.height = this.canvas.height;\r\n this.width = this.canvas.width;\r\n this.cells_to_render = new Set();\r\n this.cells_to_highlight = new Set();\r\n this.highlighted_cells = new Set();\r\n }\r\n\r\n fillWindow(container_id) {\r\n this.fillShape($('#'+container_id).height(), $('#'+container_id).width());\r\n }\r\n\r\n fillShape(height, width) {\r\n this.canvas.width = width;\r\n this.canvas.height = height;\r\n this.height = this.canvas.height;\r\n this.width = this.canvas.width;\r\n }\r\n\r\n clear() {\r\n this.ctx.fillStyle = 'white';\r\n this.ctx.fillRect(0, 0, this.height, this.width);\r\n }\r\n\r\n renderFullGrid(grid) {\r\n for (var col of grid) {\r\n for (var cell of col){\r\n this.renderCell(cell);\r\n }\r\n }\r\n }\r\n\r\n renderCells() {\r\n for (var cell of this.cells_to_render) {\r\n this.renderCell(cell);\r\n }\r\n this.cells_to_render.clear();\r\n }\r\n\r\n renderCell(cell) {\r\n cell.state.render(this.ctx, cell, this.cell_size);\r\n }\r\n\r\n renderOrganism(org) {\r\n for(var org_cell of org.anatomy.cells) {\r\n var cell = org.getRealCell(org_cell);\r\n this.renderCell(cell);\r\n }\r\n }\r\n\r\n addToRender(cell) {\r\n if (this.highlighted_cells.has(cell)){\r\n this.cells_to_highlight.add(cell);\r\n }\r\n this.cells_to_render.add(cell);\r\n }\r\n\r\n renderHighlights() {\r\n for (var cell of this.cells_to_highlight) {\r\n this.renderCellHighlight(cell);\r\n this.highlighted_cells.add(cell);\r\n }\r\n this.cells_to_highlight.clear();\r\n \r\n }\r\n\r\n highlightOrganism(org) {\r\n for(var org_cell of org.anatomy.cells) {\r\n var cell = org.getRealCell(org_cell);\r\n this.cells_to_highlight.add(cell);\r\n }\r\n }\r\n\r\n highlightCell(cell) {\r\n this.cells_to_highlight.add(cell);\r\n }\r\n\r\n renderCellHighlight(cell, color=\"yellow\") {\r\n this.renderCell(cell);\r\n this.ctx.fillStyle = color;\r\n this.ctx.globalAlpha = 0.5;\r\n this.ctx.fillRect(cell.x, cell.y, this.cell_size, this.cell_size);\r\n this.ctx.globalAlpha = 1;\r\n this.highlighted_cells.add(cell);\r\n }\r\n\r\n clearAllHighlights(clear_to_highlight=false) {\r\n for (var cell of this.highlighted_cells) {\r\n this.renderCell(cell);\r\n }\r\n this.highlighted_cells.clear();\r\n if (clear_to_highlight) {\r\n this.cells_to_highlight.clear();\r\n }\r\n }\r\n}\r\n\r\n// $(\"body\").mousemove(function(e) {\r\n// console.log(\"hello\");\r\n// });\r\n\r\nmodule.exports = Renderer;\r\n\n\n//# sourceURL=webpack:///./src/Rendering/Renderer.js?"); - -/***/ }), - -/***/ "./src/Stats/FossilRecord.js": -/*!***********************************!*\ - !*** ./src/Stats/FossilRecord.js ***! - \***********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Species = __webpack_require__(/*! ./Species */ \"./src/Stats/Species.js\");\r\n\r\nconst FossilRecord = {\r\n init: function(){\r\n this.extant_species = [];\r\n this.extinct_species = [];\r\n\r\n // if an organism has fewer than this cumulative pop, discard them\r\n this.discard_pop = 5;\r\n },\r\n\r\n setEnv: function(env) {\r\n this.env = env;\r\n },\r\n\r\n addSpecies: function(org, ancestor) {\r\n console.log(\"Adding Species\")\r\n var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks)\r\n this.extant_species.push(new_species);\r\n org.species = new_species;\r\n return new_species;\r\n },\r\n\r\n fossilize: function(species) {\r\n species.end_tick = this.env.total_ticks;\r\n for (i in this.extant_species) {\r\n var s = this.extant_species[i];\r\n if (s == species) {\r\n this.extant_species.splice(i, 1);\r\n if (species.cumulative_pop <= this.discard_pop) {\r\n return false;\r\n }\r\n this.extinct_species.push(s);\r\n console.log(\"Extant:\", this.extant_species.length)\r\n console.log(\"Extinct:\", this.extinct_species.length)\r\n return true;\r\n }\r\n }\r\n },\r\n\r\n clear_record: function() {\r\n this.species = [];\r\n },\r\n\r\n}\r\n\r\nFossilRecord.init();\r\n\r\nmodule.exports = FossilRecord;\n\n//# sourceURL=webpack:///./src/Stats/FossilRecord.js?"); - -/***/ }), - -/***/ "./src/Stats/Species.js": -/*!******************************!*\ - !*** ./src/Stats/Species.js ***! - \******************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("class Species {\r\n constructor(anatomy, ancestor, start_tick) {\r\n this.anatomy = anatomy;\r\n this.ancestor = ancestor;\r\n this.population = 1;\r\n this.cumulative_pop = 1;\r\n this.start_tick = start_tick;\r\n this.end_tick = -1;\r\n this.color = '#asdfasdf';\r\n this.name = \"crabuloid\";\r\n this.extinct = false;\r\n }\r\n\r\n addPop() {\r\n this.population++;\r\n this.cumulative_pop++;\r\n }\r\n\r\n decreasePop() {\r\n this.population--;\r\n if (this.population <= 0) {\r\n this.extinct = true;\r\n console.log(\"Extinction\");\r\n const FossilRecord = __webpack_require__(/*! ./FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n FossilRecord.fossilize(this);\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = Species;\n\n//# sourceURL=webpack:///./src/Stats/Species.js?"); - -/***/ }), - -/***/ "./src/index.js": -/*!**********************!*\ - !*** ./src/index.js ***! - \**********************/ -/*! no exports provided */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Engine */ \"./src/Engine.js\");\n/* harmony import */ var _Engine__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_Engine__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\r\n\r\n\r\n$('document').ready(function(){\r\n let isMobile = mobileCheck();\r\n if (isMobile) {\r\n alert(\"Though the simulation still works on mobile, most features are disabled. Try it on desktop for the full experience!\");\r\n $('.control-panel').css('display', 'none');\r\n }\r\n var engine = new _Engine__WEBPACK_IMPORTED_MODULE_0___default.a();\r\n engine.start(60);\r\n});\r\n\r\nfunction mobileCheck() {\r\n let check = false;\r\n (function(a){if(/(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);\r\n return check;\r\n};\n\n//# sourceURL=webpack:///./src/index.js?"); - -/***/ }) - -/******/ }); \ No newline at end of file +!function(e){var t={};function i(s){if(t[s])return t[s].exports;var o=t[s]={i:s,l:!1,exports:{}};return e[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=e,i.c=t,i.d=function(e,t,s){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:s})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)i.d(s,o,function(t){return e[t]}.bind(null,o));return s},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=13)}([function(e,t){class i{constructor(e){this.name=e,this.color="black"}render(e,t,i){e.fillStyle=this.color,e.fillRect(t.x,t.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(e,t,i){if(e.fillStyle=this.color,e.fillRect(t.x,t.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,n=i/2+i/4,a=i/4;e.translate(t.x+s,t.y+s),e.rotate(90*t.cell_owner.getAbsoluteDirection()*Math.PI/180),e.fillStyle=this.slit_color,e.fillRect(o,r,a,n),e.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),e.exports=s},function(e,t,i){const s=i(5),o={setDefaults:function(){this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(e){if(1==e){var t=100-this.addProb;this.changeProb=t/2,this.removeProb=t/2}else if(2==e){t=100-this.changeProb;this.addProb=t/2,this.removeProb=t/2}else{t=100-this.removeProb;this.changeProb=t/2,this.addProb=t/2}}};o.setDefaults(),e.exports=o},function(e,t){const i={up:0,right:1,down:2,left:3,scalars:[[0,-1],[1,0],[0,1],[-1,0]],getRandomDirection:function(){return Math.floor(4*Math.random())},getRandomScalar:function(){return this.scalars[Math.floor(Math.random()*this.scalars.length)]},getOppositeDirection:function(e){switch(e){case this.up:return this.down;case this.down:return this.up;case this.left:return this.right;case this.right:return this.left}},rotateRight:function(e){return++e>3&&(e=0),e}};e.exports=i},function(e,t,i){i(0);const s=i(2);e.exports=class{constructor(e,t,i,s){this.state=e,this.org=t,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance1){c=this.anatomy.getRandomCell();t=this.anatomy.removeCell(c.loc_col,c.loc_row)}return t}attemptMove(){var e=n.scalars[this.direction],t=e[0],i=e[1],o=this.c+t,r=this.r+i;if(this.isClear(o,r)){for(var a of this.anatomy.cells){var l=this.c+a.rotatedCol(this.rotation),h=this.r+a.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=n.getRandomDirection(),this.move_count=0,!0;var e=n.getRandomDirection();if(this.isClear(this.c,this.r,e)){for(var t of this.anatomy.cells){var i=this.c+t.rotatedCol(this.rotation),o=this.r+t.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=e,this.direction=n.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(e){this.direction=e,this.move_count=0}isStraightPath(e,t,i,s,o){if(e==i){if(t>s){var r=s;s=t,t=r}for(var n=t;n!=s;n++){var a=this.env.grid_map.cellAt(e,n);if(!this.isPassableCell(a,o))return!1}return!0}if(e>i){r=i;i=e,e=r}for(n=e;n!=i;n++){a=this.env.grid_map.cellAt(n,t);if(!this.isPassableCell(a,o))return!1}return!0}isPassableCell(e,t){return null!=e&&(e.state==s.empty||e.owner==this||e.owner==t||e.state==s.food)}isClear(e,t,i=this.rotation,o=!1){for(var n of this.anatomy.cells){var a=this.getRealCell(n,e,t,i);if(null==a)return!1;if(!(a.owner==this||a.state==s.empty||!r.foodBlocksReproduction&&a.state==s.food||o&&n.state==s.armor&&a.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var e of this.anatomy.cells){var t=this.c+e.rotatedCol(this.rotation),i=this.r+e.rotatedRow(this.rotation);this.env.changeCell(t,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var e of this.anatomy.cells){var t=this.c+e.rotatedCol(this.rotation),i=this.r+e.rotatedRow(this.rotation);this.env.changeCell(t,i,e.state,e)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var e of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(e.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var t=!1;0==this.ignore_brain_for?t=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!t||!i)this.attemptRotate()||(this.changeDirection(n.getRandomDirection()),t&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(e,t=this.c,i=this.r,s=this.rotation){var o=t+e.rotatedCol(s),r=i+e.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}e.exports=c},function(e,t){e.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(e,t){e.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(e,t,i,s){this.grid_map.setCellType(e,t,i),this.grid_map.setCellOwner(e,t,s)}}},function(e,t,i){i(0),i(2);e.exports=class{constructor(e,t,i){this.cell_size=i,this.canvas=document.getElementById(e),this.ctx=this.canvas.getContext("2d"),this.fillWindow(t),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(e){this.fillShape($("#"+e).height(),$("#"+e).width())}fillShape(e,t){this.canvas.width=t,this.canvas.height=e,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(e){for(var t of e)for(var i of t)this.renderCell(i)}renderCells(){for(var e of this.cells_to_render)this.renderCell(e);this.cells_to_render.clear()}renderCell(e){e.state.render(this.ctx,e,this.cell_size)}renderOrganism(e){for(var t of e.anatomy.cells){var i=e.getRealCell(t);this.renderCell(i)}}addToRender(e){this.highlighted_cells.has(e)&&this.cells_to_highlight.add(e),this.cells_to_render.add(e)}renderHighlights(){for(var e of this.cells_to_highlight)this.renderCellHighlight(e),this.highlighted_cells.add(e);this.cells_to_highlight.clear()}highlightOrganism(e){for(var t of e.anatomy.cells){var i=e.getRealCell(t);this.cells_to_highlight.add(i)}}highlightCell(e){this.cells_to_highlight.add(e)}renderCellHighlight(e,t="yellow"){this.renderCell(e),this.ctx.fillStyle=t,this.ctx.globalAlpha=.5,this.ctx.fillRect(e.x,e.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(e)}clearAllHighlights(e=!1){for(var t of this.highlighted_cells)this.renderCell(t);this.highlighted_cells.clear(),e&&this.cells_to_highlight.clear()}}},function(e,t,i){const s=i(15),o=i(0);e.exports=class{constructor(e,t,i){this.resize(e,t,i)}resize(e,t,i){this.grid=[],this.cols=e,this.rows=t,this.cell_size=i;for(var r=0;r=0&&t>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(e,t){var i=Math.floor(e/this.cell_size),s=Math.floor(t/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(e,t){e.exports=class{constructor(e,t){this.env=e,this.canvas=t,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(e){this.control_panel=e}defineEvents(){this.canvas.addEventListener("mousemove",e=>{this.updateMouseLocation(e.offsetX,e.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(e){e.preventDefault(),this.updateMouseLocation(e.offsetX,e.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(e){e.preventDefault(),this.updateMouseLocation(e.offsetX,e.offsetY),0==e.button&&(this.left_click=!0),2==e.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(e){e.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(e,t){var i=this.cur_cell,s=this.cur_org;this.mouse_x=e,this.mouse_y=t;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(e,t,i){const s=i(14),o=i(28),r=i(29),n=i(31);e.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new n(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(e=60){e<=0&&(e=1),e>300&&(e=300),this.fps=e,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/e),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(e,t,i){"use strict";i.r(t);var s=i(12),o=i.n(s);$("document").ready((function(){(function(){let e=!1;return function(t){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substr(0,4)))&&(e=!0)}(navigator.userAgent||navigator.vendor||window.opera),e})()&&(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")),(new o.a).start(60)}))},function(e,t,i){const s=i(8),o=i(9),r=i(10),n=i(6),a=i(0),l=i(27),h=i(1),c=i(4);e.exports=class extends s{constructor(e){super(),this.renderer=new o("env-canvas","env",e),this.controller=new l(this,this.renderer.canvas);var t=Math.floor(this.renderer.height/e),i=Math.floor(this.renderer.width/e);this.grid_map=new r(i,t,e),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,c.setEnv(this)}update(e){this.total_ticks++;var t=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||t.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(t)}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(e){for(var t of e.reverse())this.total_mutability-=this.organisms[t].mutability,this.organisms.splice(t,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var e=this.grid_map.getCenter(),t=new n(e[0],e[1],this);t.anatomy.addDefaultCell(a.mouth,0,0),t.anatomy.addDefaultCell(a.producer,1,1),t.anatomy.addDefaultCell(a.producer,-1,-1),this.addOrganism(t),c.addSpecies(t,null)}addOrganism(e){e.updateGrid(),this.total_mutability+=e.mutability,this.organisms.push(e),e.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=e.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:this.total_mutability/this.organisms.length}changeCell(e,t,i,s){super.changeCell(e,t,i,s),this.renderer.addToRender(this.grid_map.cellAt(e,t)),i==a.wall&&this.walls.push(this.grid_map.cellAt(e,t))}clearWalls(){for(var e of this.walls)this.grid_map.cellAt(e.col,e.row).state==a.wall&&this.changeCell(e.col,e.row,a.empty,null)}clearOrganisms(){for(var e of this.organisms)e.die();this.organisms=[]}generateFood(){for(var e=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),t=h.foodDropProb,i=0;i3&&(e-=4),e}performFunction(){var e=this.look();this.org.brain.observe(e)}look(){var e=this.org.env,t=this.getAbsoluteDirection(),i=0,o=0;switch(t){case n.up:o=-1;break;case n.down:o=1;break;case n.right:i=1;break;case n.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,m=0;mthis.organism_record&&(this.organism_record=e),$("#org-record").text("Highest count: "+this.organism_record),$("#avg-mut").text("Average Mutation Rate: "+Math.round(100*this.engine.env.averageMutability())/100),$("#largest-org").text("Largest Organism: "+this.engine.env.largest_cell_count+" cells"),$("#reset-count").text("Auto reset count: "+this.engine.env.reset_count)}}},function(e,t,i){const s=i(8),o=i(6),r=i(10),n=i(9),a=i(0),l=i(30);e.exports=class extends s{constructor(){super(),this.is_active=!0;this.renderer=new n("editor-canvas","editor-env",13),this.controller=new l(this,this.renderer.canvas),this.grid_map=new r(15,15,13),this.clear()}update(){this.is_active&&this.renderer.renderHighlights()}changeCell(e,t,i,s){super.changeCell(e,t,i,s),this.renderFull()}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}addCellToOrg(e,t,i){var s=this.grid_map.getCenter(),o=e-s[0],r=t-s[1],n=this.organism.anatomy.getLocalCell(o,r);if(null!=n){var a=this.organism.anatomy.replaceCell(i,n.loc_col,n.loc_row,!1);this.changeCell(e,t,i,a)}else this.organism.anatomy.canAddCellAt(o,r)&&this.changeCell(e,t,i,this.organism.anatomy.addDefaultCell(i,o,r))}removeCellFromOrg(e,t){var i=this.grid_map.getCenter(),s=e-i[0],o=t-i[1];0!=s||0!=o?null!=this.organism.anatomy.getLocalCell(s,o)&&this.organism.anatomy.removeCell(s,o)&&this.changeCell(e,t,a.empty,null):alert("Cannot remove center cell")}setOrganismToCopyOf(e){this.grid_map.fillGrid(a.empty);var t=this.grid_map.getCenter();this.organism=new o(t[0],t[1],this,e),this.organism.updateGrid(),this.controller.updateDetails()}getCopyOfOrg(){return new o(0,0,null,this.organism)}clear(){this.grid_map.fillGrid(a.empty);var e=this.grid_map.getCenter();this.organism=new o(e[0],e[1],this,null),this.organism.anatomy.addDefaultCell(a.mouth,0,0),this.organism.updateGrid()}}},function(e,t,i){const s=i(11),o=i(7),r=i(0),n=i(2),a=i(1);e.exports=class extends s{constructor(e,t){super(e,t),this.mode=o.None,this.edit_cell_type=null,this.highlight_org=!1,this.defineCellTypeSelection(),this.defineEditorDetails()}mouseMove(){(this.right_click||this.left_click)&&this.editOrganism()}mouseDown(){this.editOrganism()}mouseUp(){}getCurLocalCell(){return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c,this.mouse_r-this.env.organism.r)}editOrganism(){if(null!=this.edit_cell_type&&this.mode==o.Edit){if(this.left_click)if(this.edit_cell_type==r.eye&&this.cur_cell.state==r.eye){var e=this.getCurLocalCell();e.direction=n.rotateRight(e.direction),this.env.renderFull()}else this.env.addCellToOrg(this.mouse_c,this.mouse_r,this.edit_cell_type);this.right_click&&this.env.removeCellFromOrg(this.mouse_c,this.mouse_r),this.setBrainPanelVisibility(),this.setMoveRangeVisibility(),this.updateDetails()}}updateDetails(){$(".cell-count").text("Cell count: "+this.env.organism.anatomy.cells.length)}defineCellTypeSelection(){var e=this;$(".cell-type").click((function(){switch(this.id){case"mouth":e.edit_cell_type=r.mouth;break;case"producer":e.edit_cell_type=r.producer;break;case"mover":e.edit_cell_type=r.mover;break;case"killer":e.edit_cell_type=r.killer;break;case"armor":e.edit_cell_type=r.armor;break;case"eye":e.edit_cell_type=r.eye}$(".cell-type").css("border-color","black");var t="#"+this.id+".cell-type";$(t).css("border-color","yellow")}))}defineEditorDetails(){this.details_html=$("#organism-details"),this.edit_details_html=$("#edit-organism-details"),this.decision_names=["ignore","move away","move towards"],$("#move-range-edit").change(function(){this.env.organism.move_range=parseInt($("#move-range-edit").val())}.bind(this)),$("#observation-type-edit").change(function(){this.setBrainEditorValues($("#observation-type-edit").val()),this.setBrainDetails()}.bind(this)),$("#reaction-edit").change(function(){var e=$("#observation-type-edit").val(),t=parseInt($("#reaction-edit").val());this.env.organism.brain.decisions[e]=t,this.setBrainDetails()}.bind(this))}clearDetailsPanel(){$("#organism-details").css("display","none"),$("#edit-organism-details").css("display","none")}setDetailsPanel(){this.clearDetailsPanel();var e=this.env.organism;$(".cell-count").text("Cell count: "+e.anatomy.cells.length),$("#move-range").text("Move Range: "+e.move_range),$("#mutation-rate").text("Mutation Rate: "+e.mutability),a.useGlobalMutability?$("#mutation-rate").css("display","none"):$("#mutation-rate").css("display","block"),this.setMoveRangeVisibility(),this.setBrainPanelVisibility()&&this.setBrainDetails(),$("#organism-details").css("display","block")}setEditorPanel(){this.clearDetailsPanel();var e=this.env.organism;$(".cell-count").text("Cell count: "+e.anatomy.cells.length),this.setMoveRangeVisibility()&&$("#move-range-edit").val(e.move_range),this.setBrainPanelVisibility()&&this.setBrainEditorValues($("#observation-type-edit").val()),$("#cell-selections").css("display","grid"),$("#edit-organism-details").css("display","block")}setBrainPanelVisibility(){var e=this.env.organism;return e.anatomy.has_eyes&&e.anatomy.is_mover?($(".brain-details").css("display","block"),!0):($(".brain-details").css("display","none"),!1)}setBrainDetails(){var e=[],t=[];for(var i in this.env.organism.brain.decisions){var s=this.env.organism.brain.decisions[i];1==s?t.push(i):2==s&&e.push(i)}$(".chase-types").text("Move Towards: "+e),$(".retreat-types").text("Move Away From: "+t)}setMoveRangeVisibility(){return this.env.organism.anatomy.is_mover?($("#move-range-cont").css("display","block"),$("#move-range").css("display","block"),!0):($("#move-range-cont").css("display","none"),$("#move-range").css("display","none"),!1)}setBrainEditorValues(e){$("#observation-type-edit").val(e);var t=this.env.organism.brain.decisions[e];$("#reaction-edit").val(t)}}},function(e,t,i){const s=i(0);var o={empty:"#0E1318",food:"#2F7AB7",wall:"gray",mouth:"#DEB14D",producer:"#15DE59",mover:"#60D4FF",killer:"#F82380",armor:"#7230DB",eye:"#B6C1EA","eye-slit":"#0E1318"};e.exports=class{constructor(e,t){this.world_env=e,this.editor_env=t}loadColorScheme(){for(var e of s.all)e.color=o[e.name];for(var t in s.eye.slit_color=o["eye-slit"],o)$("#"+t+".cell-type ").css("background-color",o[t]),$("#"+t+".cell-legend-type").css("background-color",o[t]);this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid),this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid)}}}]); \ No newline at end of file diff --git a/src/Stats/FossilRecord.js b/src/Stats/FossilRecord.js index 7b54ab6..6eefd2a 100644 --- a/src/Stats/FossilRecord.js +++ b/src/Stats/FossilRecord.js @@ -14,7 +14,7 @@ const FossilRecord = { }, addSpecies: function(org, ancestor) { - console.log("Adding Species") + // console.log("Adding Species") var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks) this.extant_species.push(new_species); org.species = new_species; @@ -31,8 +31,8 @@ const FossilRecord = { return false; } this.extinct_species.push(s); - console.log("Extant:", this.extant_species.length) - console.log("Extinct:", this.extinct_species.length) + // console.log("Extant:", this.extant_species.length) + // console.log("Extinct:", this.extinct_species.length) return true; } } diff --git a/src/Stats/Species.js b/src/Stats/Species.js index 452fd8d..8bb6c24 100644 --- a/src/Stats/Species.js +++ b/src/Stats/Species.js @@ -20,7 +20,7 @@ class Species { this.population--; if (this.population <= 0) { this.extinct = true; - console.log("Extinction"); + // console.log("Extinction"); const FossilRecord = require("./FossilRecord"); FossilRecord.fossilize(this); } From 382794bf3fa24b3e3471856e76b8a2d506bf6202 Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Mon, 8 Feb 2021 17:19:10 -0700 Subject: [PATCH 3/9] Added population chart to statistics panel --- dist/index.html | 8 +- dist/js/bundle.js | 454 ++++++++++++++++++++++- src/Controllers/ControlPanel.js | 24 +- src/Controllers/EditorController.js | 5 +- src/Controllers/EnvironmentController.js | 20 +- src/Controllers/StatsPanel.js | 77 ++++ src/Environments/OrganismEditor.js | 7 +- src/Environments/WorldEnvironment.js | 1 + src/Stats/FossilRecord.js | 37 +- src/Stats/Species.js | 7 +- 10 files changed, 614 insertions(+), 26 deletions(-) create mode 100644 src/Controllers/StatsPanel.js diff --git a/dist/index.html b/dist/index.html index e581c6f..1870f77 100644 --- a/dist/index.html +++ b/dist/index.html @@ -7,6 +7,7 @@ + @@ -225,8 +226,13 @@

Highest count:

Average Mutation Rate:

Largest Organism:

+ + + +
+
+
-
diff --git a/dist/js/bundle.js b/dist/js/bundle.js index f93c9a6..cdc27a3 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1 +1,453 @@ -!function(e){var t={};function i(s){if(t[s])return t[s].exports;var o=t[s]={i:s,l:!1,exports:{}};return e[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=e,i.c=t,i.d=function(e,t,s){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:s})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)i.d(s,o,function(t){return e[t]}.bind(null,o));return s},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=13)}([function(e,t){class i{constructor(e){this.name=e,this.color="black"}render(e,t,i){e.fillStyle=this.color,e.fillRect(t.x,t.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(e,t,i){if(e.fillStyle=this.color,e.fillRect(t.x,t.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,n=i/2+i/4,a=i/4;e.translate(t.x+s,t.y+s),e.rotate(90*t.cell_owner.getAbsoluteDirection()*Math.PI/180),e.fillStyle=this.slit_color,e.fillRect(o,r,a,n),e.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),e.exports=s},function(e,t,i){const s=i(5),o={setDefaults:function(){this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(e){if(1==e){var t=100-this.addProb;this.changeProb=t/2,this.removeProb=t/2}else if(2==e){t=100-this.changeProb;this.addProb=t/2,this.removeProb=t/2}else{t=100-this.removeProb;this.changeProb=t/2,this.addProb=t/2}}};o.setDefaults(),e.exports=o},function(e,t){const i={up:0,right:1,down:2,left:3,scalars:[[0,-1],[1,0],[0,1],[-1,0]],getRandomDirection:function(){return Math.floor(4*Math.random())},getRandomScalar:function(){return this.scalars[Math.floor(Math.random()*this.scalars.length)]},getOppositeDirection:function(e){switch(e){case this.up:return this.down;case this.down:return this.up;case this.left:return this.right;case this.right:return this.left}},rotateRight:function(e){return++e>3&&(e=0),e}};e.exports=i},function(e,t,i){i(0);const s=i(2);e.exports=class{constructor(e,t,i,s){this.state=e,this.org=t,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance1){c=this.anatomy.getRandomCell();t=this.anatomy.removeCell(c.loc_col,c.loc_row)}return t}attemptMove(){var e=n.scalars[this.direction],t=e[0],i=e[1],o=this.c+t,r=this.r+i;if(this.isClear(o,r)){for(var a of this.anatomy.cells){var l=this.c+a.rotatedCol(this.rotation),h=this.r+a.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=n.getRandomDirection(),this.move_count=0,!0;var e=n.getRandomDirection();if(this.isClear(this.c,this.r,e)){for(var t of this.anatomy.cells){var i=this.c+t.rotatedCol(this.rotation),o=this.r+t.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=e,this.direction=n.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(e){this.direction=e,this.move_count=0}isStraightPath(e,t,i,s,o){if(e==i){if(t>s){var r=s;s=t,t=r}for(var n=t;n!=s;n++){var a=this.env.grid_map.cellAt(e,n);if(!this.isPassableCell(a,o))return!1}return!0}if(e>i){r=i;i=e,e=r}for(n=e;n!=i;n++){a=this.env.grid_map.cellAt(n,t);if(!this.isPassableCell(a,o))return!1}return!0}isPassableCell(e,t){return null!=e&&(e.state==s.empty||e.owner==this||e.owner==t||e.state==s.food)}isClear(e,t,i=this.rotation,o=!1){for(var n of this.anatomy.cells){var a=this.getRealCell(n,e,t,i);if(null==a)return!1;if(!(a.owner==this||a.state==s.empty||!r.foodBlocksReproduction&&a.state==s.food||o&&n.state==s.armor&&a.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var e of this.anatomy.cells){var t=this.c+e.rotatedCol(this.rotation),i=this.r+e.rotatedRow(this.rotation);this.env.changeCell(t,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var e of this.anatomy.cells){var t=this.c+e.rotatedCol(this.rotation),i=this.r+e.rotatedRow(this.rotation);this.env.changeCell(t,i,e.state,e)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var e of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(e.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var t=!1;0==this.ignore_brain_for?t=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!t||!i)this.attemptRotate()||(this.changeDirection(n.getRandomDirection()),t&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(e,t=this.c,i=this.r,s=this.rotation){var o=t+e.rotatedCol(s),r=i+e.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}e.exports=c},function(e,t){e.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(e,t){e.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(e,t,i,s){this.grid_map.setCellType(e,t,i),this.grid_map.setCellOwner(e,t,s)}}},function(e,t,i){i(0),i(2);e.exports=class{constructor(e,t,i){this.cell_size=i,this.canvas=document.getElementById(e),this.ctx=this.canvas.getContext("2d"),this.fillWindow(t),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(e){this.fillShape($("#"+e).height(),$("#"+e).width())}fillShape(e,t){this.canvas.width=t,this.canvas.height=e,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(e){for(var t of e)for(var i of t)this.renderCell(i)}renderCells(){for(var e of this.cells_to_render)this.renderCell(e);this.cells_to_render.clear()}renderCell(e){e.state.render(this.ctx,e,this.cell_size)}renderOrganism(e){for(var t of e.anatomy.cells){var i=e.getRealCell(t);this.renderCell(i)}}addToRender(e){this.highlighted_cells.has(e)&&this.cells_to_highlight.add(e),this.cells_to_render.add(e)}renderHighlights(){for(var e of this.cells_to_highlight)this.renderCellHighlight(e),this.highlighted_cells.add(e);this.cells_to_highlight.clear()}highlightOrganism(e){for(var t of e.anatomy.cells){var i=e.getRealCell(t);this.cells_to_highlight.add(i)}}highlightCell(e){this.cells_to_highlight.add(e)}renderCellHighlight(e,t="yellow"){this.renderCell(e),this.ctx.fillStyle=t,this.ctx.globalAlpha=.5,this.ctx.fillRect(e.x,e.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(e)}clearAllHighlights(e=!1){for(var t of this.highlighted_cells)this.renderCell(t);this.highlighted_cells.clear(),e&&this.cells_to_highlight.clear()}}},function(e,t,i){const s=i(15),o=i(0);e.exports=class{constructor(e,t,i){this.resize(e,t,i)}resize(e,t,i){this.grid=[],this.cols=e,this.rows=t,this.cell_size=i;for(var r=0;r=0&&t>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(e,t){var i=Math.floor(e/this.cell_size),s=Math.floor(t/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(e,t){e.exports=class{constructor(e,t){this.env=e,this.canvas=t,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(e){this.control_panel=e}defineEvents(){this.canvas.addEventListener("mousemove",e=>{this.updateMouseLocation(e.offsetX,e.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(e){e.preventDefault(),this.updateMouseLocation(e.offsetX,e.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(e){e.preventDefault(),this.updateMouseLocation(e.offsetX,e.offsetY),0==e.button&&(this.left_click=!0),2==e.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(e){e.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(e,t){var i=this.cur_cell,s=this.cur_org;this.mouse_x=e,this.mouse_y=t;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(e,t,i){const s=i(14),o=i(28),r=i(29),n=i(31);e.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new n(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(e=60){e<=0&&(e=1),e>300&&(e=300),this.fps=e,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/e),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(e,t,i){"use strict";i.r(t);var s=i(12),o=i.n(s);$("document").ready((function(){(function(){let e=!1;return function(t){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(t.substr(0,4)))&&(e=!0)}(navigator.userAgent||navigator.vendor||window.opera),e})()&&(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")),(new o.a).start(60)}))},function(e,t,i){const s=i(8),o=i(9),r=i(10),n=i(6),a=i(0),l=i(27),h=i(1),c=i(4);e.exports=class extends s{constructor(e){super(),this.renderer=new o("env-canvas","env",e),this.controller=new l(this,this.renderer.canvas);var t=Math.floor(this.renderer.height/e),i=Math.floor(this.renderer.width/e);this.grid_map=new r(i,t,e),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,c.setEnv(this)}update(e){this.total_ticks++;var t=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||t.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(t)}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(e){for(var t of e.reverse())this.total_mutability-=this.organisms[t].mutability,this.organisms.splice(t,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var e=this.grid_map.getCenter(),t=new n(e[0],e[1],this);t.anatomy.addDefaultCell(a.mouth,0,0),t.anatomy.addDefaultCell(a.producer,1,1),t.anatomy.addDefaultCell(a.producer,-1,-1),this.addOrganism(t),c.addSpecies(t,null)}addOrganism(e){e.updateGrid(),this.total_mutability+=e.mutability,this.organisms.push(e),e.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=e.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:this.total_mutability/this.organisms.length}changeCell(e,t,i,s){super.changeCell(e,t,i,s),this.renderer.addToRender(this.grid_map.cellAt(e,t)),i==a.wall&&this.walls.push(this.grid_map.cellAt(e,t))}clearWalls(){for(var e of this.walls)this.grid_map.cellAt(e.col,e.row).state==a.wall&&this.changeCell(e.col,e.row,a.empty,null)}clearOrganisms(){for(var e of this.organisms)e.die();this.organisms=[]}generateFood(){for(var e=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),t=h.foodDropProb,i=0;i3&&(e-=4),e}performFunction(){var e=this.look();this.org.brain.observe(e)}look(){var e=this.org.env,t=this.getAbsoluteDirection(),i=0,o=0;switch(t){case n.up:o=-1;break;case n.down:o=1;break;case n.right:i=1;break;case n.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,m=0;mthis.organism_record&&(this.organism_record=e),$("#org-record").text("Highest count: "+this.organism_record),$("#avg-mut").text("Average Mutation Rate: "+Math.round(100*this.engine.env.averageMutability())/100),$("#largest-org").text("Largest Organism: "+this.engine.env.largest_cell_count+" cells"),$("#reset-count").text("Auto reset count: "+this.engine.env.reset_count)}}},function(e,t,i){const s=i(8),o=i(6),r=i(10),n=i(9),a=i(0),l=i(30);e.exports=class extends s{constructor(){super(),this.is_active=!0;this.renderer=new n("editor-canvas","editor-env",13),this.controller=new l(this,this.renderer.canvas),this.grid_map=new r(15,15,13),this.clear()}update(){this.is_active&&this.renderer.renderHighlights()}changeCell(e,t,i,s){super.changeCell(e,t,i,s),this.renderFull()}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}addCellToOrg(e,t,i){var s=this.grid_map.getCenter(),o=e-s[0],r=t-s[1],n=this.organism.anatomy.getLocalCell(o,r);if(null!=n){var a=this.organism.anatomy.replaceCell(i,n.loc_col,n.loc_row,!1);this.changeCell(e,t,i,a)}else this.organism.anatomy.canAddCellAt(o,r)&&this.changeCell(e,t,i,this.organism.anatomy.addDefaultCell(i,o,r))}removeCellFromOrg(e,t){var i=this.grid_map.getCenter(),s=e-i[0],o=t-i[1];0!=s||0!=o?null!=this.organism.anatomy.getLocalCell(s,o)&&this.organism.anatomy.removeCell(s,o)&&this.changeCell(e,t,a.empty,null):alert("Cannot remove center cell")}setOrganismToCopyOf(e){this.grid_map.fillGrid(a.empty);var t=this.grid_map.getCenter();this.organism=new o(t[0],t[1],this,e),this.organism.updateGrid(),this.controller.updateDetails()}getCopyOfOrg(){return new o(0,0,null,this.organism)}clear(){this.grid_map.fillGrid(a.empty);var e=this.grid_map.getCenter();this.organism=new o(e[0],e[1],this,null),this.organism.anatomy.addDefaultCell(a.mouth,0,0),this.organism.updateGrid()}}},function(e,t,i){const s=i(11),o=i(7),r=i(0),n=i(2),a=i(1);e.exports=class extends s{constructor(e,t){super(e,t),this.mode=o.None,this.edit_cell_type=null,this.highlight_org=!1,this.defineCellTypeSelection(),this.defineEditorDetails()}mouseMove(){(this.right_click||this.left_click)&&this.editOrganism()}mouseDown(){this.editOrganism()}mouseUp(){}getCurLocalCell(){return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c,this.mouse_r-this.env.organism.r)}editOrganism(){if(null!=this.edit_cell_type&&this.mode==o.Edit){if(this.left_click)if(this.edit_cell_type==r.eye&&this.cur_cell.state==r.eye){var e=this.getCurLocalCell();e.direction=n.rotateRight(e.direction),this.env.renderFull()}else this.env.addCellToOrg(this.mouse_c,this.mouse_r,this.edit_cell_type);this.right_click&&this.env.removeCellFromOrg(this.mouse_c,this.mouse_r),this.setBrainPanelVisibility(),this.setMoveRangeVisibility(),this.updateDetails()}}updateDetails(){$(".cell-count").text("Cell count: "+this.env.organism.anatomy.cells.length)}defineCellTypeSelection(){var e=this;$(".cell-type").click((function(){switch(this.id){case"mouth":e.edit_cell_type=r.mouth;break;case"producer":e.edit_cell_type=r.producer;break;case"mover":e.edit_cell_type=r.mover;break;case"killer":e.edit_cell_type=r.killer;break;case"armor":e.edit_cell_type=r.armor;break;case"eye":e.edit_cell_type=r.eye}$(".cell-type").css("border-color","black");var t="#"+this.id+".cell-type";$(t).css("border-color","yellow")}))}defineEditorDetails(){this.details_html=$("#organism-details"),this.edit_details_html=$("#edit-organism-details"),this.decision_names=["ignore","move away","move towards"],$("#move-range-edit").change(function(){this.env.organism.move_range=parseInt($("#move-range-edit").val())}.bind(this)),$("#observation-type-edit").change(function(){this.setBrainEditorValues($("#observation-type-edit").val()),this.setBrainDetails()}.bind(this)),$("#reaction-edit").change(function(){var e=$("#observation-type-edit").val(),t=parseInt($("#reaction-edit").val());this.env.organism.brain.decisions[e]=t,this.setBrainDetails()}.bind(this))}clearDetailsPanel(){$("#organism-details").css("display","none"),$("#edit-organism-details").css("display","none")}setDetailsPanel(){this.clearDetailsPanel();var e=this.env.organism;$(".cell-count").text("Cell count: "+e.anatomy.cells.length),$("#move-range").text("Move Range: "+e.move_range),$("#mutation-rate").text("Mutation Rate: "+e.mutability),a.useGlobalMutability?$("#mutation-rate").css("display","none"):$("#mutation-rate").css("display","block"),this.setMoveRangeVisibility(),this.setBrainPanelVisibility()&&this.setBrainDetails(),$("#organism-details").css("display","block")}setEditorPanel(){this.clearDetailsPanel();var e=this.env.organism;$(".cell-count").text("Cell count: "+e.anatomy.cells.length),this.setMoveRangeVisibility()&&$("#move-range-edit").val(e.move_range),this.setBrainPanelVisibility()&&this.setBrainEditorValues($("#observation-type-edit").val()),$("#cell-selections").css("display","grid"),$("#edit-organism-details").css("display","block")}setBrainPanelVisibility(){var e=this.env.organism;return e.anatomy.has_eyes&&e.anatomy.is_mover?($(".brain-details").css("display","block"),!0):($(".brain-details").css("display","none"),!1)}setBrainDetails(){var e=[],t=[];for(var i in this.env.organism.brain.decisions){var s=this.env.organism.brain.decisions[i];1==s?t.push(i):2==s&&e.push(i)}$(".chase-types").text("Move Towards: "+e),$(".retreat-types").text("Move Away From: "+t)}setMoveRangeVisibility(){return this.env.organism.anatomy.is_mover?($("#move-range-cont").css("display","block"),$("#move-range").css("display","block"),!0):($("#move-range-cont").css("display","none"),$("#move-range").css("display","none"),!1)}setBrainEditorValues(e){$("#observation-type-edit").val(e);var t=this.env.organism.brain.decisions[e];$("#reaction-edit").val(t)}}},function(e,t,i){const s=i(0);var o={empty:"#0E1318",food:"#2F7AB7",wall:"gray",mouth:"#DEB14D",producer:"#15DE59",mover:"#60D4FF",killer:"#F82380",armor:"#7230DB",eye:"#B6C1EA","eye-slit":"#0E1318"};e.exports=class{constructor(e,t){this.world_env=e,this.editor_env=t}loadColorScheme(){for(var e of s.all)e.color=o[e.name];for(var t in s.eye.slit_color=o["eye-slit"],o)$("#"+t+".cell-type ").css("background-color",o[t]),$("#"+t+".cell-legend-type").css("background-color",o[t]);this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid),this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid)}}}]); \ No newline at end of file +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); +/******/ }) +/************************************************************************/ +/******/ ({ + +/***/ "./src/Controllers/CanvasController.js": +/*!*********************************************!*\ + !*** ./src/Controllers/CanvasController.js ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("\r\n\r\nclass CanvasController{\r\n constructor(env, canvas) {\r\n this.env = env;\r\n this.canvas = canvas;\r\n this.mouse_x;\r\n this.mouse_y;\r\n this.mouse_c;\r\n this.mouse_r;\r\n this.left_click = false;\r\n this.right_click = false;\r\n this.cur_cell = null;\r\n this.cur_org = null;\r\n this.highlight_org = true;\r\n this.defineEvents();\r\n }\r\n\r\n setControlPanel(panel){\r\n this.control_panel = panel;\r\n }\r\n\r\n defineEvents() {\r\n this.canvas.addEventListener('mousemove', e => {\r\n this.updateMouseLocation(e.offsetX, e.offsetY)\r\n this.mouseMove();\r\n });\r\n\r\n this.canvas.addEventListener('mouseup', function(evt) {\r\n evt.preventDefault();\r\n this.updateMouseLocation(evt.offsetX, evt.offsetY)\r\n this.mouseUp();\r\n this.left_click=false;\r\n this.right_click=false;\r\n }.bind(this));\r\n\r\n this.canvas.addEventListener('mousedown', function(evt) {\r\n evt.preventDefault();\r\n this.updateMouseLocation(evt.offsetX, evt.offsetY)\r\n if (evt.button == 0) {\r\n this.left_click = true;\r\n }\r\n if (evt.button == 2) \r\n this.right_click = true;\r\n this.mouseDown();\r\n }.bind(this));\r\n\r\n this.canvas.addEventListener('contextmenu', function(evt) {\r\n evt.preventDefault();\r\n });\r\n\r\n this.canvas.addEventListener('mouseleave', function(){\r\n this.right_click = false;\r\n this.left_click = false;\r\n this.env.renderer.clearAllHighlights(true);\r\n }.bind(this));\r\n\r\n }\r\n\r\n updateMouseLocation(offsetX, offsetY) {\r\n var prev_cell = this.cur_cell;\r\n var prev_org = this.cur_org;\r\n\r\n this.mouse_x = offsetX;\r\n this.mouse_y = offsetY;\r\n var colRow = this.env.grid_map.xyToColRow(this.mouse_x, this.mouse_y);\r\n this.mouse_c = colRow[0];\r\n this.mouse_r = colRow[1];\r\n this.cur_cell = this.env.grid_map.cellAt(this.mouse_c, this.mouse_r);\r\n this.cur_org = this.cur_cell.owner;\r\n\r\n if (this.cur_org != prev_org || this.cur_cell != prev_cell) {\r\n this.env.renderer.clearAllHighlights(true);\r\n if (this.cur_org != null && this.highlight_org) {\r\n this.env.renderer.highlightOrganism(this.cur_org);\r\n }\r\n else if (this.cur_cell != null) {\r\n this.env.renderer.highlightCell(this.cur_cell, true);\r\n }\r\n }\r\n }\r\n\r\n mouseMove() {\r\n alert(\"mouse move must be overridden\");\r\n }\r\n\r\n mouseDown() {\r\n alert(\"mouse down must be overridden\");\r\n }\r\n\r\n mouseUp(){\r\n alert(\"mouse up must be overridden\")\r\n }\r\n}\r\n\r\nmodule.exports = CanvasController;\n\n//# sourceURL=webpack:///./src/Controllers/CanvasController.js?"); + +/***/ }), + +/***/ "./src/Controllers/ControlModes.js": +/*!*****************************************!*\ + !*** ./src/Controllers/ControlModes.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("const Modes = {\r\n None: 0,\r\n FoodDrop: 1,\r\n WallDrop: 2,\r\n ClickKill: 3,\r\n Select: 4,\r\n Edit: 5,\r\n Clone: 6,\r\n Drag: 7\r\n}\r\n\r\nmodule.exports = Modes;\n\n//# sourceURL=webpack:///./src/Controllers/ControlModes.js?"); + +/***/ }), + +/***/ "./src/Controllers/ControlPanel.js": +/*!*****************************************!*\ + !*** ./src/Controllers/ControlPanel.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst StatsPanel = __webpack_require__(/*! ./StatsPanel */ \"./src/Controllers/StatsPanel.js\");\r\n\r\nclass ControlPanel {\r\n constructor(engine) {\r\n this.engine = engine;\r\n this.defineMinMaxControls();\r\n this.defineEngineSpeedControls();\r\n this.defineGridSizeControls();\r\n this.defineTabNavigation();\r\n this.defineHyperparameterControls();\r\n this.defineModeControls();\r\n this.defineChallenges();\r\n this.fps = engine.fps;\r\n this.organism_record=0;\r\n this.env_controller = this.engine.env.controller;\r\n this.editor_controller = this.engine.organism_editor.controller;\r\n this.env_controller.setControlPanel(this);\r\n this.editor_controller.setControlPanel(this);\r\n this.stats_panel = new StatsPanel();\r\n this.stats_panel.render();\r\n }\r\n\r\n defineMinMaxControls(){\r\n $('#minimize').click ( function() {\r\n $('.control-panel').css('display', 'none');\r\n $('.hot-controls').css('display', 'block');\r\n this.stats_panel.stopAutoRender();\r\n }.bind(this));\r\n $('#maximize').click ( function() {\r\n $('.control-panel').css('display', 'grid');\r\n $('.hot-controls').css('display', 'none');\r\n if (this.id == 'stats') {\r\n self.stats_panel.startAutoRender();\r\n }\r\n });\r\n }\r\n\r\n defineEngineSpeedControls(){\r\n this.slider = document.getElementById(\"slider\");\r\n this.slider.oninput = function() {\r\n this.fps = this.slider.value\r\n if (this.engine.running) {\r\n this.changeEngineSpeed(this.fps);\r\n \r\n }\r\n $('#fps').text(\"Target FPS: \"+this.fps);\r\n }.bind(this);\r\n $('.pause-button').click(function() {\r\n $('.pause-button').find(\"i\").toggleClass(\"fa fa-pause\");\r\n $('.pause-button').find(\"i\").toggleClass(\"fa fa-play\");\r\n if (this.engine.running) {\r\n this.engine.stop();\r\n }\r\n else if (!this.engine.running){\r\n this.engine.start(this.fps);\r\n }\r\n }.bind(this));\r\n }\r\n\r\n defineGridSizeControls() {\r\n $('#fill-window').change(function() {\r\n if (this.checked)\r\n $('.col-row-input').css('display' ,'none');\r\n else\r\n $('.col-row-input').css('display' ,'block');\r\n });\r\n\r\n $('#resize').click(function() {\r\n var cell_size = $('#cell-size').val();\r\n var fill_window = $('#fill-window').is(\":checked\");\r\n if (fill_window) {\r\n this.engine.env.resizeFillWindow(cell_size);\r\n }\r\n else {\r\n var cols = $('#col-input').val();\r\n var rows = $('#row-input').val();\r\n this.engine.env.resizeGridColRow(cell_size, cols, rows);\r\n }\r\n \r\n }.bind(this));\r\n }\r\n\r\n defineTabNavigation() {\r\n this.tab_id = 'about';\r\n var self = this;\r\n $('.tabnav-item').click(function() {\r\n $('.tab').css('display', 'none');\r\n var tab = '#'+this.id+'.tab';\r\n self.engine.organism_editor.is_active = (this.id == 'editor');\r\n if (this.id == 'stats') {\r\n self.stats_panel.startAutoRender();\r\n }\r\n self.id = this.id;\r\n \r\n $(tab).css('display', 'grid');\r\n });\r\n }\r\n\r\n defineHyperparameterControls() {\r\n $('#food-prod-prob').change(function() {\r\n Hyperparams.foodProdProb = $('#food-prod-prob').val();\r\n }.bind(this));\r\n $('#lifespan-multiplier').change(function() {\r\n Hyperparams.lifespanMultiplier = $('#lifespan-multiplier').val();\r\n }.bind(this));\r\n\r\n $('#mover-rot').change(function() {\r\n Hyperparams.moversCanRotate = this.checked;\r\n });\r\n $('#offspring-rot').change(function() {\r\n Hyperparams.offspringRotate = this.checked;\r\n });\r\n $('#insta-kill').change(function() {\r\n Hyperparams.instaKill = this.checked;\r\n });\r\n $('#look-range').change(function() {\r\n Hyperparams.lookRange = $('#look-range').val();\r\n });\r\n $('#food-drop-rate').change(function() {\r\n Hyperparams.foodDropProb = $('#food-drop-rate').val();\r\n });\r\n\r\n $('#evolved-mutation').change( function() {\r\n if (this.checked) {\r\n $('.global-mutation-in').css('display', 'none');\r\n $('#avg-mut').css('display', 'block');\r\n }\r\n else {\r\n $('.global-mutation-in').css('display', 'block');\r\n $('#avg-mut').css('display', 'none');\r\n }\r\n Hyperparams.useGlobalMutability = !this.checked;\r\n });\r\n $('#global-mutation').change( function() {\r\n Hyperparams.globalMutability = $('#global-mutation').val();\r\n });\r\n $('.mut-prob').change( function() {\r\n switch(this.id){\r\n case \"add-prob\":\r\n Hyperparams.addProb = this.value;\r\n Hyperparams.balanceMutationProbs(1);\r\n break;\r\n case \"change-prob\":\r\n Hyperparams.changeProb = this.value;\r\n Hyperparams.balanceMutationProbs(2);\r\n break;\r\n case \"remove-prob\":\r\n Hyperparams.removeProb = this.value;\r\n Hyperparams.balanceMutationProbs(3);\r\n break;\r\n }\r\n $('#add-prob').val(Math.floor(Hyperparams.addProb));\r\n $('#change-prob').val(Math.floor(Hyperparams.changeProb));\r\n $('#remove-prob').val(Math.floor(Hyperparams.removeProb));\r\n });\r\n $('#movers-produce').change( function() {\r\n Hyperparams.moversCanProduce = this.checked;\r\n });\r\n $('#food-blocks').change( function() {\r\n Hyperparams.foodBlocksReproduction = this.checked; \r\n });\r\n $('#reset-rules').click( function() {\r\n Hyperparams.setDefaults();\r\n $('#food-prod-prob').val(Hyperparams.foodProdProb);\r\n $('#lifespan-multiplier').val(Hyperparams.lifespanMultiplier);\r\n $('#mover-rot').prop('checked', Hyperparams.moversCanRotate);\r\n $('#offspring-rot').prop('checked', Hyperparams.offspringRotate);\r\n $('#insta-kill').prop('checked', Hyperparams.instaKill);\r\n $('#evolved-mutation').prop('checked', !Hyperparams.useGlobalMutability);\r\n $('#add-prob').val(Hyperparams.addProb);\r\n $('#change-prob').val(Hyperparams.changeProb);\r\n $('#remove-prob').val(Hyperparams.removeProb);\r\n $('#movers-produce').prop('checked', Hyperparams.moversCanProduce);\r\n $('#food-blocks').prop('checked', Hyperparams.foodBlocksReproduction);\r\n if (!Hyperparams.useGlobalMutability) {\r\n $('.global-mutation-in').css('display', 'none');\r\n $('#avg-mut').css('display', 'block');\r\n }\r\n else {\r\n $('.global-mutation-in').css('display', 'block');\r\n $('#avg-mut').css('display', 'none');\r\n }\r\n });\r\n }\r\n\r\n defineModeControls() {\r\n var self = this;\r\n $('.edit-mode-btn').click( function() {\r\n $('#cell-selections').css('display', 'none');\r\n $('#organism-options').css('display', 'none');\r\n self.editor_controller.setDetailsPanel();\r\n switch(this.id){\r\n case \"food-drop\":\r\n self.setMode(Modes.FoodDrop);\r\n break;\r\n case \"wall-drop\":\r\n self.setMode(Modes.WallDrop);\r\n break;\r\n case \"click-kill\":\r\n self.setMode(Modes.ClickKill);\r\n break;\r\n case \"select\":\r\n self.setMode(Modes.Select);\r\n break;\r\n case \"edit\":\r\n self.setMode(Modes.Edit);\r\n self.editor_controller.setEditorPanel();\r\n break;\r\n case \"drop-org\":\r\n self.setMode(Modes.Clone);\r\n self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg();\r\n self.env_controller.add_new_species = self.editor_controller.new_species;\r\n self.editor_controller.new_species = false;\r\n // console.log(self.env_controller.add_new_species)\r\n break;\r\n case \"drag-view\":\r\n self.setMode(Modes.Drag);\r\n }\r\n $('.edit-mode-btn').css('background-color', '#9099c2');\r\n $('#'+this.id).css('background-color', '#81d2c7');\r\n });\r\n\r\n $('.reset-view').click( function(){\r\n this.env_controller.resetView();\r\n }.bind(this));\r\n\r\n var env = this.engine.env;\r\n $('#reset-env').click( function() {\r\n this.engine.env.reset();\r\n this.stats_panel.clearData();\r\n }.bind(this));\r\n $('#auto-reset').change(function() {\r\n env.auto_reset = this.checked;\r\n });\r\n $('#clear-walls').click( function() {\r\n if (confirm(\"Are you sure you want to clear all the walls?\")) {\r\n this.engine.env.clearWalls();\r\n }\r\n }.bind(this));\r\n $('#clear-editor').click( function() {\r\n this.engine.organism_editor.clear();\r\n this.editor_controller.setEditorPanel();\r\n }.bind(this));\r\n }\r\n\r\n defineChallenges() {\r\n $('.challenge-btn').click(function() {\r\n $('#challenge-title').text($(this).text());\r\n $('#challenge-description').text($(this).val());\r\n });\r\n }\r\n\r\n setMode(mode) {\r\n this.env_controller.mode = mode;\r\n this.editor_controller.mode = mode;\r\n }\r\n\r\n setEditorOrganism(org) {\r\n this.engine.organism_editor.setOrganismToCopyOf(org);\r\n this.editor_controller.clearDetailsPanel();\r\n this.editor_controller.setDetailsPanel();\r\n }\r\n\r\n changeEngineSpeed(change_val) {\r\n this.engine.stop();\r\n this.engine.start(change_val)\r\n this.fps = this.engine.fps;\r\n }\r\n\r\n update() {\r\n $('#fps-actual').text(\"Actual FPS: \" + Math.floor(this.engine.actual_fps));\r\n var org_count = this.engine.env.organisms.length;\r\n $('#org-count').text(\"Organism count: \" + org_count);\r\n if (org_count > this.organism_record) \r\n this.organism_record = org_count;\r\n $('#org-record').text(\"Highest count: \" + this.organism_record);\r\n $('#avg-mut').text(\"Average Mutation Rate: \" + Math.round(this.engine.env.averageMutability() * 100) / 100);\r\n $('#largest-org').text(\"Largest Organism: \" + this.engine.env.largest_cell_count + \" cells\");\r\n $('#reset-count').text(\"Auto reset count: \" + this.engine.env.reset_count);\r\n this.stats_panel.updateData(this.engine.env.total_ticks, this.engine.env.organisms.length)\r\n }\r\n\r\n}\r\n\r\n\r\nmodule.exports = ControlPanel;\n\n//# sourceURL=webpack:///./src/Controllers/ControlPanel.js?"); + +/***/ }), + +/***/ "./src/Controllers/EditorController.js": +/*!*********************************************!*\ + !*** ./src/Controllers/EditorController.js ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CanvasController = __webpack_require__(/*! ./CanvasController */ \"./src/Controllers/CanvasController.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Directions = __webpack_require__(/*! ../Organism/Directions */ \"./src/Organism/Directions.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\n\r\nclass EditorController extends CanvasController{\r\n constructor(env, canvas) {\r\n super(env, canvas);\r\n this.mode = Modes.None;\r\n this.edit_cell_type = null;\r\n this.highlight_org = false;\r\n this.new_species = false;\r\n this.defineCellTypeSelection();\r\n this.defineEditorDetails();\r\n }\r\n\r\n mouseMove() {\r\n if (this.right_click || this.left_click)\r\n this.editOrganism();\r\n }\r\n\r\n mouseDown() {\r\n this.editOrganism();\r\n }\r\n\r\n mouseUp(){}\r\n\r\n getCurLocalCell(){\r\n return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c, this.mouse_r-this.env.organism.r);\r\n }\r\n\r\n editOrganism() {\r\n if (this.edit_cell_type == null || this.mode != Modes.Edit)\r\n return;\r\n if (this.left_click){\r\n if(this.edit_cell_type == CellStates.eye && this.cur_cell.state == CellStates.eye) {\r\n var loc_cell = this.getCurLocalCell();\r\n loc_cell.direction = Directions.rotateRight(loc_cell.direction);\r\n this.env.renderFull();\r\n }\r\n else\r\n this.env.addCellToOrg(this.mouse_c, this.mouse_r, this.edit_cell_type);\r\n }\r\n else if (this.right_click)\r\n this.env.removeCellFromOrg(this.mouse_c, this.mouse_r);\r\n\r\n this.new_species = true;\r\n this.setBrainPanelVisibility();\r\n this.setMoveRangeVisibility();\r\n this.updateDetails();\r\n }\r\n\r\n updateDetails() {\r\n $('.cell-count').text(\"Cell count: \"+this.env.organism.anatomy.cells.length);\r\n }\r\n\r\n defineCellTypeSelection() {\r\n var self = this;\r\n $('.cell-type').click( function() {\r\n switch(this.id){\r\n case \"mouth\":\r\n self.edit_cell_type = CellStates.mouth;\r\n break;\r\n case \"producer\":\r\n self.edit_cell_type = CellStates.producer;\r\n break;\r\n case \"mover\":\r\n self.edit_cell_type = CellStates.mover;\r\n break;\r\n case \"killer\":\r\n self.edit_cell_type = CellStates.killer;\r\n break;\r\n case \"armor\":\r\n self.edit_cell_type = CellStates.armor;\r\n break;\r\n case \"eye\":\r\n self.edit_cell_type = CellStates.eye;\r\n break;\r\n }\r\n $(\".cell-type\" ).css( \"border-color\", \"black\" );\r\n var selected = '#'+this.id+'.cell-type';\r\n $(selected).css(\"border-color\", \"yellow\");\r\n });\r\n }\r\n\r\n defineEditorDetails() {\r\n this.details_html = $('#organism-details');\r\n this.edit_details_html = $('#edit-organism-details');\r\n\r\n this.decision_names = [\"ignore\", \"move away\", \"move towards\"];\r\n\r\n $('#move-range-edit').change ( function() {\r\n this.env.organism.move_range = parseInt($('#move-range-edit').val());\r\n }.bind(this));\r\n $('#observation-type-edit').change ( function() {\r\n this.setBrainEditorValues($('#observation-type-edit').val());\r\n this.setBrainDetails();\r\n }.bind(this));\r\n $('#reaction-edit').change ( function() {\r\n var obs = $('#observation-type-edit').val();\r\n var decision = parseInt($('#reaction-edit').val());\r\n this.env.organism.brain.decisions[obs] = decision;\r\n this.setBrainDetails();\r\n }.bind(this));\r\n }\r\n\r\n clearDetailsPanel() {\r\n $('#organism-details').css('display', 'none');\r\n $('#edit-organism-details').css('display', 'none');\r\n }\r\n\r\n setDetailsPanel() {\r\n this.clearDetailsPanel();\r\n var org = this.env.organism;\r\n \r\n $('.cell-count').text(\"Cell count: \"+org.anatomy.cells.length);\r\n $('#move-range').text(\"Move Range: \"+org.move_range);\r\n $('#mutation-rate').text(\"Mutation Rate: \"+org.mutability);\r\n if (Hyperparams.useGlobalMutability) {\r\n $('#mutation-rate').css('display', 'none');\r\n }\r\n else {\r\n $('#mutation-rate').css('display', 'block');\r\n }\r\n\r\n this.setMoveRangeVisibility();\r\n\r\n if (this.setBrainPanelVisibility()) {\r\n this.setBrainDetails();\r\n\r\n }\r\n $('#organism-details').css('display', 'block');\r\n }\r\n\r\n setEditorPanel() {\r\n this.clearDetailsPanel();\r\n var org = this.env.organism;\r\n\r\n $('.cell-count').text(\"Cell count: \"+org.anatomy.cells.length);\r\n if (this.setMoveRangeVisibility()){\r\n $('#move-range-edit').val(org.move_range);\r\n }\r\n \r\n if (this.setBrainPanelVisibility()){\r\n this.setBrainEditorValues($('#observation-type-edit').val());\r\n }\r\n\r\n $('#cell-selections').css('display', 'grid');\r\n $('#edit-organism-details').css('display', 'block');\r\n }\r\n\r\n setBrainPanelVisibility() {\r\n var org = this.env.organism;\r\n if (org.anatomy.has_eyes && org.anatomy.is_mover) {\r\n $('.brain-details').css('display', 'block');\r\n return true;\r\n }\r\n $('.brain-details').css('display', 'none');\r\n return false;\r\n }\r\n\r\n setBrainDetails() {\r\n var chase_types = [];\r\n var retreat_types = [];\r\n for(var cell_name in this.env.organism.brain.decisions) {\r\n var decision = this.env.organism.brain.decisions[cell_name];\r\n if (decision == 1) {\r\n retreat_types.push(cell_name)\r\n }\r\n else if (decision == 2) {\r\n chase_types.push(cell_name);\r\n }\r\n }\r\n $('.chase-types').text(\"Move Towards: \" + chase_types);\r\n $('.retreat-types').text(\"Move Away From: \" + retreat_types);\r\n }\r\n\r\n setMoveRangeVisibility() {\r\n var org = this.env.organism;\r\n if (org.anatomy.is_mover) {\r\n $('#move-range-cont').css('display', 'block');\r\n $('#move-range').css('display', 'block');\r\n return true;\r\n }\r\n $('#move-range-cont').css('display', 'none');\r\n $('#move-range').css('display', 'none');\r\n return false;\r\n }\r\n\r\n setBrainEditorValues(name) {\r\n $('#observation-type-edit').val(name);\r\n var reaction = this.env.organism.brain.decisions[name];\r\n $('#reaction-edit').val(reaction);\r\n }\r\n}\r\n\r\nmodule.exports = EditorController;\r\n\n\n//# sourceURL=webpack:///./src/Controllers/EditorController.js?"); + +/***/ }), + +/***/ "./src/Controllers/EnvironmentController.js": +/*!**************************************************!*\ + !*** ./src/Controllers/EnvironmentController.js ***! + \**************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CanvasController = __webpack_require__(/*! ./CanvasController */ \"./src/Controllers/CanvasController.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Neighbors = __webpack_require__(/*! ../Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass EnvironmentController extends CanvasController{\r\n constructor(env, canvas) {\r\n super(env, canvas);\r\n this.mode = Modes.Drag;\r\n this.org_to_clone = null;\r\n this.add_new_species = false;\r\n this.defineZoomControls();\r\n this.scale = 1;\r\n }\r\n\r\n defineZoomControls() {\r\n var scale = 1;\r\n var zoom_speed = 0.5;\r\n const el = document.querySelector('#env-canvas');\r\n el.onwheel = function zoom(event) {\r\n event.preventDefault();\r\n\r\n var sign = -Math.sign(event.deltaY);\r\n\r\n // Restrict scale\r\n scale = Math.max(0.5, this.scale+(sign*zoom_speed));\r\n\r\n if (scale != 0.5) {\r\n var cur_top = parseInt($('#env-canvas').css('top'));\r\n var cur_left = parseInt($('#env-canvas').css('left'));\r\n if (sign == 1) {\r\n // If we're zooming in, zoom towards wherever the mouse is\r\n var diff_x = ((this.canvas.width/2-cur_left/this.scale) - this.mouse_x)*this.scale/1.5;\r\n var diff_y = ((this.canvas.height/2-cur_top/this.scale) - this.mouse_y)*this.scale/1.5;\r\n }\r\n else {\r\n // If we're zooming out, zoom out towards the center\r\n var diff_x = -cur_left/scale;\r\n var diff_y = -cur_top/scale;\r\n }\r\n $('#env-canvas').css('top', (cur_top+diff_y)+'px');\r\n $('#env-canvas').css('left', (cur_left+diff_x)+'px');\r\n }\r\n \r\n // Apply scale transform\r\n el.style.transform = `scale(${scale})`;\r\n this.scale = scale;\r\n\r\n }.bind(this);\r\n }\r\n\r\n resetView() {\r\n $('#env-canvas').css('transform', 'scale(1)');\r\n $('#env-canvas').css('top', '0px');\r\n $('#env-canvas').css('left', '0px');\r\n this.scale = 1;\r\n }\r\n\r\n updateMouseLocation(offsetX, offsetY){\r\n \r\n super.updateMouseLocation(offsetX, offsetY);\r\n }\r\n\r\n mouseMove() {\r\n this.performModeAction();\r\n }\r\n\r\n mouseDown() {\r\n this.start_x = this.mouse_x;\r\n this.start_y = this.mouse_y;\r\n this.performModeAction();\r\n }\r\n\r\n mouseUp() {\r\n\r\n }\r\n\r\n performModeAction() {\r\n var mode = this.mode;\r\n var right_click = this.right_click;\r\n var left_click = this.left_click;\r\n if (mode != Modes.None && (right_click || left_click)) {\r\n var cell = this.cur_cell;\r\n if (cell == null){\r\n return;\r\n }\r\n switch(mode) {\r\n case Modes.FoodDrop:\r\n if (left_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.food, false);\r\n }\r\n else if (right_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.empty, false);\r\n }\r\n break;\r\n case Modes.WallDrop:\r\n if (left_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.wall, true);\r\n\r\n }\r\n else if (right_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.empty, false);\r\n }\r\n break;\r\n case Modes.ClickKill:\r\n this.killNearOrganisms();\r\n break;\r\n\r\n case Modes.Select:\r\n if (this.cur_org == null) {\r\n this.cur_org = this.findNearOrganism();\r\n }\r\n if (this.cur_org != null){\r\n this.control_panel.setEditorOrganism(this.cur_org);\r\n }\r\n break;\r\n\r\n case Modes.Clone:\r\n if (this.org_to_clone != null){\r\n var new_org = new Organism(this.mouse_c, this.mouse_r, this.env, this.org_to_clone);\r\n if (this.add_new_species){\r\n FossilRecord.addSpeciesObj(new_org.species);\r\n new_org.species.start_tick = this.env.total_ticks;\r\n this.add_new_species = false;\r\n new_org.species.population = 0;\r\n }\r\n else if (this.org_to_clone.species.extinct){\r\n FossilRecord.resurrect(this.org_to_clone.species);\r\n }\r\n\r\n if (new_org.isClear(this.mouse_c, this.mouse_r)){\r\n this.env.addOrganism(new_org);\r\n new_org.species.addPop();\r\n }\r\n }\r\n break;\r\n case Modes.Drag:\r\n var cur_top = parseInt($('#env-canvas').css('top'), 10);\r\n var cur_left = parseInt($('#env-canvas').css('left'), 10);\r\n var new_top = cur_top + ((this.mouse_y - this.start_y)*this.scale);\r\n var new_left = cur_left + ((this.mouse_x - this.start_x)*this.scale);\r\n $('#env-canvas').css('top', new_top+'px');\r\n $('#env-canvas').css('left', new_left+'px');\r\n break;\r\n }\r\n }\r\n }\r\n\r\n dropCellType(col, row, state, killBlocking=false) {\r\n for (var loc of Neighbors.allSelf){\r\n var c=col + loc[0];\r\n var r=row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell == null)\r\n continue;\r\n if (killBlocking && cell.owner != null){\r\n cell.owner.die();\r\n }\r\n else if (cell.owner != null) {\r\n continue;\r\n }\r\n this.env.changeCell(c, r, state, null);\r\n }\r\n }\r\n\r\n findNearOrganism() {\r\n for (var loc of Neighbors.all){\r\n var c = this.cur_cell.col + loc[0];\r\n var r = this.cur_cell.row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell != null && cell.owner != null)\r\n return cell.owner;\r\n }\r\n return null;\r\n }\r\n\r\n killNearOrganisms() {\r\n for (var loc of Neighbors.allSelf){\r\n var c = this.cur_cell.col + loc[0];\r\n var r = this.cur_cell.row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell != null && cell.owner != null)\r\n cell.owner.die();\r\n }\r\n }\r\n\r\n\r\n}\r\n\r\nmodule.exports = EnvironmentController;\r\n\n\n//# sourceURL=webpack:///./src/Controllers/EnvironmentController.js?"); + +/***/ }), + +/***/ "./src/Controllers/StatsPanel.js": +/*!***************************************!*\ + !*** ./src/Controllers/StatsPanel.js ***! + \***************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass StatsPanel {\r\n constructor() {\r\n this.defineControls();\r\n this.clearData();\r\n this.last_update_tick = 0;\r\n this.update_every = 100;\r\n\r\n // maps species to their index in chart's data storage\r\n this.species_index_map = [];\r\n this.index_counter = 0;\r\n this.min_display = 10;\r\n }\r\n\r\n startAutoRender(){\r\n this.render_loop = setInterval(function(){this.render();}.bind(this), 1000);\r\n }\r\n\r\n stopAutoRender() {\r\n clearInterval(this.render_loop);\r\n }\r\n\r\n defineControls() {\r\n $('#update-chart').click( function() {\r\n this.render();\r\n }.bind(this));\r\n }\r\n\r\n updateData(tick, population_size) {\r\n if (tick - this.last_update_tick >= this.update_every){\r\n // this.data[0].dataPoints.push({x: tick, y:population_size});\r\n this.last_update_tick = tick;\r\n\r\n for (var species of FossilRecord.extant_species) {\r\n if (species.cumulative_pop < this.min_display){\r\n continue;\r\n }\r\n \r\n if (this.species_index_map[species.name] == null) {\r\n console.log(\"new species\")\r\n this.species_index_map[species.name] = this.index_counter;\r\n this.index_counter++;\r\n this.data.push({\r\n type: \"line\",\r\n markerType: \"none\",\r\n dataPoints: []\r\n });\r\n }\r\n var data_index = this.species_index_map[species.name];\r\n this.data[data_index].dataPoints.push({x:tick, y:species.population});\r\n }\r\n }\r\n }\r\n \r\n render() {\r\n this.chart.render();\r\n }\r\n\r\n clearData() {\r\n this.data = [{\r\n type: \"line\",\r\n markerType: \"none\",\r\n dataPoints: []\r\n }];\r\n this.chart = new CanvasJS.Chart(\"chartContainer\", {\r\n title:{\r\n text: \"Population\" \r\n },\r\n data: this.data\r\n });\r\n this.render();\r\n }\r\n \r\n}\r\n\r\nmodule.exports = StatsPanel;\n\n//# sourceURL=webpack:///./src/Controllers/StatsPanel.js?"); + +/***/ }), + +/***/ "./src/Engine.js": +/*!***********************!*\ + !*** ./src/Engine.js ***! + \***********************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const WorldEnvironment = __webpack_require__(/*! ./Environments/WorldEnvironment */ \"./src/Environments/WorldEnvironment.js\");\r\nconst ControlPanel = __webpack_require__(/*! ./Controllers/ControlPanel */ \"./src/Controllers/ControlPanel.js\");\r\nconst OrganismEditor = __webpack_require__(/*! ./Environments/OrganismEditor */ \"./src/Environments/OrganismEditor.js\");\r\nconst ColorScheme = __webpack_require__(/*! ./Rendering/ColorScheme */ \"./src/Rendering/ColorScheme.js\");\r\n\r\nconst render_speed = 60;\r\n\r\nclass Engine{\r\n constructor(){\r\n this.fps = 60;\r\n this.env = new WorldEnvironment(5);\r\n this.organism_editor = new OrganismEditor();\r\n this.controlpanel = new ControlPanel(this);\r\n this.colorscheme = new ColorScheme(this.env, this.organism_editor);\r\n this.colorscheme.loadColorScheme();\r\n this.env.OriginOfLife();\r\n this.last_update = Date.now();\r\n this.delta_time = 0;\r\n this.actual_fps = 0;\r\n this.running = false;\r\n }\r\n\r\n start(fps=60) {\r\n if (fps <= 0)\r\n fps = 1;\r\n if (fps > 300)\r\n fps = 300;\r\n this.fps = fps;\r\n this.game_loop = setInterval(function(){this.environmentUpdate();}.bind(this), 1000/fps);\r\n this.running = true;\r\n if (this.fps >= render_speed) {\r\n if (this.render_loop != null) {\r\n clearInterval(this.render_loop);\r\n this.render_loop = null;\r\n }\r\n }\r\n else\r\n this.setRenderLoop();\r\n }\r\n \r\n stop() {\r\n clearInterval(this.game_loop);\r\n this.running = false;\r\n this.setRenderLoop();\r\n }\r\n\r\n setRenderLoop() {\r\n if (this.render_loop == null) {\r\n this.render_loop = setInterval(function(){this.necessaryUpdate();}.bind(this), 1000/render_speed);\r\n }\r\n }\r\n\r\n\r\n environmentUpdate() {\r\n this.delta_time = Date.now() - this.last_update;\r\n this.last_update = Date.now();\r\n this.env.update(this.delta_time);\r\n this.actual_fps = 1/this.delta_time*1000;\r\n if(this.render_loop == null){\r\n this.necessaryUpdate();\r\n }\r\n \r\n }\r\n\r\n necessaryUpdate() {\r\n this.env.render();\r\n this.controlpanel.update();\r\n this.organism_editor.update();\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Engine;\r\n\n\n//# sourceURL=webpack:///./src/Engine.js?"); + +/***/ }), + +/***/ "./src/Environments/Environment.js": +/*!*****************************************!*\ + !*** ./src/Environments/Environment.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("\r\n//An evironment has a grid_map, controller, and renderer\r\nclass Environment{\r\n constructor() {\r\n }\r\n\r\n update(){\r\n alert(\"Environment.update() must be overriden\");\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n this.grid_map.setCellType(c, r, state);\r\n this.grid_map.setCellOwner(c, r, owner);\r\n }\r\n}\r\n\r\n\r\nmodule.exports = Environment;\n\n//# sourceURL=webpack:///./src/Environments/Environment.js?"); + +/***/ }), + +/***/ "./src/Environments/OrganismEditor.js": +/*!********************************************!*\ + !*** ./src/Environments/OrganismEditor.js ***! + \********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environments/Environment.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst GridMap = __webpack_require__(/*! ../Grid/GridMap */ \"./src/Grid/GridMap.js\");\r\nconst Renderer = __webpack_require__(/*! ../Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst EditorController = __webpack_require__(/*! ../Controllers/EditorController */ \"./src/Controllers/EditorController.js\");\r\nconst Species = __webpack_require__(/*! ../Stats/Species */ \"./src/Stats/Species.js\");\r\n\r\nclass OrganismEditor extends Environment{\r\n constructor() {\r\n super();\r\n this.is_active = true;\r\n var cell_size = 13;\r\n this.renderer = new Renderer('editor-canvas', 'editor-env', cell_size);\r\n this.controller = new EditorController(this, this.renderer.canvas);\r\n this.grid_map = new GridMap(15, 15, cell_size);\r\n this.clear();\r\n }\r\n\r\n update() {\r\n if (this.is_active){\r\n this.renderer.renderHighlights();\r\n }\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n super.changeCell(c, r, state, owner);\r\n this.renderFull();\r\n }\r\n\r\n renderFull() {\r\n this.renderer.renderFullGrid(this.grid_map.grid);\r\n }\r\n\r\n // absolute c r, not local\r\n addCellToOrg(c, r, state) {\r\n var center = this.grid_map.getCenter();\r\n var loc_c = c - center[0];\r\n var loc_r = r - center[1];\r\n var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)\r\n if (prev_cell != null) {\r\n var new_cell = this.organism.anatomy.replaceCell(state, prev_cell.loc_col, prev_cell.loc_row, false);\r\n this.changeCell(c, r, state, new_cell);\r\n }\r\n else if (this.organism.anatomy.canAddCellAt(loc_c, loc_r)){\r\n this.changeCell(c, r, state, this.organism.anatomy.addDefaultCell(state, loc_c, loc_r));\r\n }\r\n this.organism.species = new Species(this.organism.anatomy, null, 0);\r\n }\r\n\r\n removeCellFromOrg(c, r) {\r\n var center = this.grid_map.getCenter();\r\n var loc_c = c - center[0];\r\n var loc_r = r - center[1];\r\n if (loc_c == 0 && loc_r == 0){\r\n alert(\"Cannot remove center cell\");\r\n return;\r\n }\r\n var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)\r\n if (prev_cell != null) {\r\n if (this.organism.anatomy.removeCell(loc_c, loc_r)) {\r\n this.changeCell(c, r, CellStates.empty, null);\r\n this.organism.species = new Species(this.organism.anatomy, null, 0);\r\n }\r\n }\r\n }\r\n\r\n setOrganismToCopyOf(orig_org) {\r\n this.grid_map.fillGrid(CellStates.empty);\r\n var center = this.grid_map.getCenter();\r\n this.organism = new Organism(center[0], center[1], this, orig_org);\r\n this.organism.updateGrid();\r\n this.controller.updateDetails();\r\n this.controller.new_species = false;\r\n }\r\n \r\n getCopyOfOrg() {\r\n var new_org = new Organism(0, 0, null, this.organism);\r\n return new_org;\r\n }\r\n\r\n clear() {\r\n this.grid_map.fillGrid(CellStates.empty);\r\n var center = this.grid_map.getCenter();\r\n this.organism = new Organism(center[0], center[1], this, null);\r\n this.organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0);\r\n this.organism.updateGrid();\r\n this.organism.species = new Species(this.organism.anatomy, null, 0);\r\n }\r\n}\r\n\r\nmodule.exports = OrganismEditor;\n\n//# sourceURL=webpack:///./src/Environments/OrganismEditor.js?"); + +/***/ }), + +/***/ "./src/Environments/WorldEnvironment.js": +/*!**********************************************!*\ + !*** ./src/Environments/WorldEnvironment.js ***! + \**********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environments/Environment.js\");\r\nconst Renderer = __webpack_require__(/*! ../Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst GridMap = __webpack_require__(/*! ../Grid/GridMap */ \"./src/Grid/GridMap.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst EnvironmentController = __webpack_require__(/*! ../Controllers/EnvironmentController */ \"./src/Controllers/EnvironmentController.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters.js */ \"./src/Hyperparameters.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass WorldEnvironment extends Environment{\r\n constructor(cell_size) {\r\n super();\r\n this.renderer = new Renderer('env-canvas', 'env', cell_size);\r\n this.controller = new EnvironmentController(this, this.renderer.canvas);\r\n var grid_rows = Math.floor(this.renderer.height / cell_size);\r\n var grid_cols = Math.floor(this.renderer.width / cell_size);\r\n this.grid_map = new GridMap(grid_cols, grid_rows, cell_size);\r\n this.organisms = [];\r\n this.walls = [];\r\n this.total_mutability = 0;\r\n this.auto_reset = true;\r\n this.largest_cell_count = 0;\r\n this.reset_count = 0;\r\n this.total_ticks = 0;\r\n FossilRecord.setEnv(this);\r\n }\r\n\r\n update(delta_time) {\r\n this.total_ticks ++;\r\n var to_remove = [];\r\n for (var i in this.organisms) {\r\n var org = this.organisms[i];\r\n if (!org.living || !org.update()) {\r\n to_remove.push(i);\r\n }\r\n }\r\n if (Hyperparams.foodDropProb > 0) {\r\n this.generateFood();\r\n }\r\n this.removeOrganisms(to_remove);\r\n }\r\n\r\n render() {\r\n this.renderer.renderCells();\r\n this.renderer.renderHighlights();\r\n }\r\n\r\n removeOrganisms(org_indeces) {\r\n for (var i of org_indeces.reverse()){\r\n this.total_mutability -= this.organisms[i].mutability;\r\n this.organisms.splice(i, 1);\r\n }\r\n if (this.organisms.length == 0 && this.auto_reset){\r\n this.reset_count++;\r\n this.reset();\r\n }\r\n }\r\n\r\n OriginOfLife() {\r\n var center = this.grid_map.getCenter();\r\n var org = new Organism(center[0], center[1], this);\r\n org.anatomy.addDefaultCell(CellStates.mouth, 0, 0);\r\n org.anatomy.addDefaultCell(CellStates.producer, 1, 1);\r\n org.anatomy.addDefaultCell(CellStates.producer, -1, -1);\r\n this.addOrganism(org);\r\n FossilRecord.addSpecies(org, null);\r\n }\r\n\r\n addOrganism(organism) {\r\n organism.updateGrid();\r\n this.total_mutability += organism.mutability;\r\n this.organisms.push(organism);\r\n if (organism.anatomy.cells.length > this.largest_cell_count) \r\n this.largest_cell_count = organism.anatomy.cells.length;\r\n }\r\n\r\n averageMutability() {\r\n if (this.organisms.length < 1)\r\n return 0;\r\n return this.total_mutability / this.organisms.length;\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n super.changeCell(c, r, state, owner);\r\n this.renderer.addToRender(this.grid_map.cellAt(c, r));\r\n if(state == CellStates.wall)\r\n this.walls.push(this.grid_map.cellAt(c, r));\r\n }\r\n\r\n clearWalls() {\r\n for(var wall of this.walls){\r\n if (this.grid_map.cellAt(wall.col, wall.row).state == CellStates.wall)\r\n this.changeCell(wall.col, wall.row, CellStates.empty, null);\r\n }\r\n }\r\n\r\n clearOrganisms() {\r\n for (var org of this.organisms)\r\n org.die();\r\n this.organisms = [];\r\n }\r\n\r\n generateFood() {\r\n var num_food = Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*Hyperparams.foodDropProb/50000), 1)\r\n var prob = Hyperparams.foodDropProb;\r\n for (var i=0; i=0 && row>=0;\r\n }\r\n\r\n getCenter(){\r\n return [Math.floor(this.cols/2), Math.floor(this.rows/2)]\r\n }\r\n\r\n xyToColRow(x, y) {\r\n var c = Math.floor(x/this.cell_size);\r\n var r = Math.floor(y/this.cell_size);\r\n if (c >= this.cols)\r\n c = this.cols-1;\r\n else if (c < 0)\r\n c = 0;\r\n if (r >= this.rows)\r\n r = this.rows-1;\r\n else if (r < 0)\r\n r = 0;\r\n return [c, r];\r\n }\r\n}\r\n\r\nmodule.exports = GridMap;\r\n\n\n//# sourceURL=webpack:///./src/Grid/GridMap.js?"); + +/***/ }), + +/***/ "./src/Grid/Neighbors.js": +/*!*******************************!*\ + !*** ./src/Grid/Neighbors.js ***! + \*******************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("// contains local cell values for the following:\r\n\r\n//all ...\r\n// .x.\r\n// ...\r\n\r\n//adjacent .\r\n// .x.\r\n// .\r\n\r\n//corners . .\r\n// x\r\n// . .\r\n\r\n//allSelf ...\r\n// ...\r\n// ...\r\n\r\nconst Neighbors = {\r\n all: [[0, 1],[0, -1],[1, 0],[-1, 0],[-1, -1],[1, 1],[-1, 1],[1, -1]],\r\n adjacent: [[0, 1],[0, -1],[1, 0],[-1, 0]],\r\n corners: [[-1, -1],[1, 1],[-1, 1],[1, -1]],\r\n allSelf: [[0, 0],[0, 1],[0, -1],[1, 0],[-1, 0],[-1, -1],[1, 1],[-1, 1],[1, -1]]\r\n}\r\n\r\nmodule.exports = Neighbors;\n\n//# sourceURL=webpack:///./src/Grid/Neighbors.js?"); + +/***/ }), + +/***/ "./src/Hyperparameters.js": +/*!********************************!*\ + !*** ./src/Hyperparameters.js ***! + \********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Neighbors = __webpack_require__(/*! ./Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\n\r\nconst Hyperparams = {\r\n setDefaults: function() {\r\n this.lifespanMultiplier = 100;\r\n this.foodProdProb = 4;\r\n this.foodProdProbScalar = 4;\r\n this.killableNeighbors = Neighbors.adjacent;\r\n this.edibleNeighbors = Neighbors.adjacent;\r\n this.growableNeighbors = Neighbors.adjacent;\r\n\r\n this.useGlobalMutability = false;\r\n this.globalMutability = 5;\r\n this.addProb = 33;\r\n this.changeProb = 33;\r\n this.removeProb = 33;\r\n \r\n this.moversCanRotate = true;\r\n this.offspringRotate = true;\r\n\r\n this.foodBlocksReproduction = true;\r\n this.moversCanProduce = false;\r\n\r\n this.instaKill = false;\r\n\r\n this.lookRange = 20;\r\n\r\n this.foodDropProb = 0;\r\n },\r\n\r\n balanceMutationProbs : function(choice) {\r\n if (choice == 1) {\r\n var remaining = 100 - this.addProb;\r\n this.changeProb = remaining/2;\r\n this.removeProb = remaining/2;\r\n }\r\n else if (choice == 2) {\r\n var remaining = 100 - this.changeProb;\r\n this.addProb = remaining/2;\r\n this.removeProb = remaining/2;\r\n }\r\n else {\r\n var remaining = 100 - this.removeProb;\r\n this.changeProb = remaining/2;\r\n this.addProb = remaining/2;\r\n }\r\n }\r\n}\r\n\r\nHyperparams.setDefaults();\r\n\r\nmodule.exports = Hyperparams;\n\n//# sourceURL=webpack:///./src/Hyperparameters.js?"); + +/***/ }), + +/***/ "./src/Organism/Anatomy.js": +/*!*********************************!*\ + !*** ./src/Organism/Anatomy.js ***! + \*********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CellStates = __webpack_require__(/*! ./Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst BodyCellFactory = __webpack_require__(/*! ./Cell/BodyCells/BodyCellFactory */ \"./src/Organism/Cell/BodyCells/BodyCellFactory.js\");\r\n\r\nclass Anatomy {\r\n constructor(owner) {\r\n this.owner = owner;\r\n this.cells = [];\r\n this.is_producer = false;\r\n this.is_mover = false;\r\n this.has_eyes = false;\r\n this.birth_distance = 4;\r\n }\r\n\r\n canAddCellAt(c, r) {\r\n for (var cell of this.cells) {\r\n if (cell.loc_col == c && cell.loc_row == r){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n addDefaultCell(state, c, r) {\r\n var new_cell = BodyCellFactory.createDefault(this.owner, state, c, r);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n addRandomizedCell(state, c, r) {\r\n if (state==CellStates.eye && !this.has_eyes) {\r\n this.owner.brain.randomizeDecisions();\r\n }\r\n var new_cell = BodyCellFactory.createRandom(this.owner, state, c, r);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n addInheritCell(parent_cell) {\r\n var new_cell = BodyCellFactory.createInherited(this.owner, parent_cell);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n replaceCell(state, c, r, randomize=true) {\r\n this.removeCell(c, r, true);\r\n if (randomize) {\r\n return this.addRandomizedCell(state, c, r);\r\n }\r\n else {\r\n return this.addDefaultCell(state, c, r);\r\n }\r\n }\r\n\r\n removeCell(c, r, allow_center_removal=false) {\r\n if (c == 0 && r == 0 && !allow_center_removal)\r\n return false;\r\n for (var i=0; i 3)\r\n dir -= 4;\r\n return dir;\r\n }\r\n\r\n performFunction() {\r\n var obs = this.look();\r\n this.org.brain.observe(obs);\r\n }\r\n\r\n look() {\r\n var env = this.org.env;\r\n var direction = this.getAbsoluteDirection();\r\n var addCol = 0;\r\n var addRow = 0;\r\n switch(direction) {\r\n case Directions.up:\r\n addRow = -1;\r\n break;\r\n case Directions.down:\r\n addRow = 1;\r\n break;\r\n case Directions.right:\r\n addCol = 1;\r\n break;\r\n case Directions.left:\r\n addCol = -1;\r\n break;\r\n }\r\n var start_col = this.getRealCol();\r\n var start_row = this.getRealRow();\r\n var col = start_col;\r\n var row = start_row;\r\n var cell = null;\r\n for (var i=0; i 3){\r\n dir = 0;\r\n }\r\n return dir;\r\n }\r\n}\r\n\r\nmodule.exports = Directions;\n\n//# sourceURL=webpack:///./src/Organism/Directions.js?"); + +/***/ }), + +/***/ "./src/Organism/Organism.js": +/*!**********************************!*\ + !*** ./src/Organism/Organism.js ***! + \**********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CellStates = __webpack_require__(/*! ./Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Neighbors = __webpack_require__(/*! ../Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Directions = __webpack_require__(/*! ./Directions */ \"./src/Organism/Directions.js\");\r\nconst Anatomy = __webpack_require__(/*! ./Anatomy */ \"./src/Organism/Anatomy.js\");\r\nconst Brain = __webpack_require__(/*! ./Perception/Brain */ \"./src/Organism/Perception/Brain.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass Organism {\r\n constructor(col, row, env, parent=null) {\r\n this.c = col;\r\n this.r = row;\r\n this.env = env;\r\n this.lifetime = 0;\r\n this.food_collected = 0;\r\n this.living = true;\r\n this.anatomy = new Anatomy(this)\r\n this.direction = Directions.down; // direction of movement\r\n this.rotation = Directions.up; // direction of rotation\r\n this.can_rotate = Hyperparams.moversCanRotate;\r\n this.move_count = 0;\r\n this.move_range = 4;\r\n this.ignore_brain_for = 0;\r\n this.mutability = 5;\r\n this.damage = 0;\r\n this.brain = new Brain(this);\r\n if (parent != null) {\r\n this.inherit(parent);\r\n }\r\n }\r\n\r\n inherit(parent) {\r\n this.move_range = parent.move_range;\r\n this.mutability = parent.mutability;\r\n this.species = parent.species;\r\n // this.birth_distance = parent.birth_distance;\r\n for (var c of parent.anatomy.cells){\r\n //deep copy parent cells\r\n this.anatomy.addInheritCell(c);\r\n }\r\n if(parent.anatomy.is_mover) {\r\n for (var i in parent.brain.decisions) {\r\n this.brain.decisions[i] = parent.brain.decisions[i];\r\n }\r\n }\r\n }\r\n\r\n // amount of food required before it can reproduce\r\n foodNeeded() {\r\n return this.anatomy.cells.length;\r\n }\r\n\r\n lifespan() {\r\n // console.log(Hyperparams.lifespanMultiplier)\r\n return this.anatomy.cells.length * Hyperparams.lifespanMultiplier;\r\n }\r\n\r\n maxHealth() {\r\n return this.anatomy.cells.length;\r\n }\r\n\r\n reproduce() {\r\n //produce mutated child\r\n //check nearby locations (is there room and a direct path)\r\n var org = new Organism(0, 0, this.env, this);\r\n if(Hyperparams.offspringRotate){\r\n org.rotation = Directions.getRandomDirection();\r\n }\r\n var prob = this.mutability;\r\n if (Hyperparams.useGlobalMutability){\r\n prob = Hyperparams.globalMutability;\r\n }\r\n else {\r\n //mutate the mutability\r\n if (Math.random() <= 0.5)\r\n org.mutability++;\r\n else{ \r\n org.mutability--;\r\n if (org.mutability < 1)\r\n org.mutability = 1;\r\n }\r\n } \r\n var mutated = false;\r\n if (Math.random() * 100 <= prob) {\r\n if (org.anatomy.is_mover && Math.random() * 100 <= 10) { \r\n if (org.anatomy.has_eyes) {\r\n org.brain.mutate();\r\n }\r\n org.move_range += Math.floor(Math.random() * 4) - 2;\r\n if (org.move_range <= 0){\r\n org.move_range = 1;\r\n };\r\n \r\n }\r\n else {\r\n mutated = org.mutate();\r\n }\r\n }\r\n\r\n var direction = Directions.getRandomScalar();\r\n var direction_c = direction[0];\r\n var direction_r = direction[1];\r\n var offset = (Math.floor(Math.random() * 3));\r\n var basemovement = this.anatomy.birth_distance;\r\n var new_c = this.c + (direction_c*basemovement) + (direction_c*offset);\r\n var new_r = this.r + (direction_r*basemovement) + (direction_r*offset);\r\n\r\n // console.log(org.isClear(new_c, new_r, org.rotation, true))\r\n if (org.isClear(new_c, new_r, org.rotation, true) && org.isStraightPath(new_c, new_r, this.c, this.r, this)){\r\n org.c = new_c;\r\n org.r = new_r;\r\n this.env.addOrganism(org);\r\n org.updateGrid();\r\n if (mutated) {\r\n FossilRecord.addSpecies(org, this.species);\r\n }\r\n else {\r\n org.species.addPop();\r\n }\r\n }\r\n this.food_collected -= this.foodNeeded();\r\n\r\n }\r\n\r\n mutate() {\r\n var choice = Math.floor(Math.random() * 100);\r\n var mutated = false;\r\n if (choice <= Hyperparams.addProb) {\r\n // add cell\r\n // console.log(\"add cell\")\r\n\r\n var branch = this.anatomy.getRandomCell();\r\n var state = CellStates.getRandomLivingType();//branch.state;\r\n var growth_direction = Neighbors.all[Math.floor(Math.random() * Neighbors.all.length)]\r\n var c = branch.loc_col+growth_direction[0];\r\n var r = branch.loc_row+growth_direction[1];\r\n if (this.anatomy.canAddCellAt(c, r)){\r\n mutated = true;\r\n this.anatomy.addRandomizedCell(state, c, r);\r\n }\r\n }\r\n else if (choice <= Hyperparams.addProb + Hyperparams.changeProb){\r\n // change cell\r\n var cell = this.anatomy.getRandomCell();\r\n var state = CellStates.getRandomLivingType();\r\n // console.log(\"change cell\", state)\r\n this.anatomy.replaceCell(state, cell.loc_col, cell.loc_row);\r\n mutated = true;\r\n }\r\n else if (choice <= Hyperparams.addProb + Hyperparams.changeProb + Hyperparams.removeProb){\r\n // remove cell\r\n // console.log(\"remove cell\")\r\n\r\n if(this.anatomy.cells.length > 1) {\r\n var cell = this.anatomy.getRandomCell();\r\n mutated = this.anatomy.removeCell(cell.loc_col, cell.loc_row);\r\n }\r\n }\r\n return mutated;\r\n }\r\n\r\n attemptMove() {\r\n var direction = Directions.scalars[this.direction];\r\n var direction_c = direction[0];\r\n var direction_r = direction[1];\r\n var new_c = this.c + direction_c;\r\n var new_r = this.r + direction_r;\r\n if (this.isClear(new_c, new_r)) {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.empty, null);\r\n }\r\n this.c = new_c;\r\n this.r = new_r;\r\n this.updateGrid();\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n attemptRotate() {\r\n if(!this.can_rotate){\r\n this.direction = Directions.getRandomDirection();\r\n this.move_count = 0;\r\n return true;\r\n }\r\n var new_rotation = Directions.getRandomDirection();\r\n if(this.isClear(this.c, this.r, new_rotation)){\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.empty, null);\r\n }\r\n this.rotation = new_rotation;\r\n this.direction = Directions.getRandomDirection();\r\n this.updateGrid();\r\n this.move_count = 0;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n changeDirection(dir) {\r\n this.direction = dir;\r\n this.move_count = 0;\r\n }\r\n\r\n // assumes either c1==c2 or r1==r2, returns true if there is a clear path from point 1 to 2\r\n isStraightPath(c1, r1, c2, r2, parent){\r\n if (c1 == c2) {\r\n if (r1 > r2){\r\n var temp = r2;\r\n r2 = r1;\r\n r1 = temp;\r\n }\r\n for (var i=r1; i!=r2; i++) {\r\n var cell = this.env.grid_map.cellAt(c1, i)\r\n if (!this.isPassableCell(cell, parent)){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n else {\r\n if (c1 > c2){\r\n var temp = c2;\r\n c2 = c1;\r\n c1 = temp;\r\n }\r\n for (var i=c1; i!=c2; i++) {\r\n var cell = this.env.grid_map.cellAt(i, r1);\r\n if (!this.isPassableCell(cell, parent)){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n }\r\n\r\n isPassableCell(cell, parent){\r\n return cell != null && (cell.state == CellStates.empty || cell.owner == this || cell.owner == parent || cell.state == CellStates.food);\r\n }\r\n\r\n isClear(col, row, rotation=this.rotation, ignore_armor=false) {\r\n for(var loccell of this.anatomy.cells) {\r\n var cell = this.getRealCell(loccell, col, row, rotation);\r\n if (cell==null) {\r\n return false;\r\n }\r\n // console.log(cell.owner == this)\r\n if (cell.owner==this || cell.state==CellStates.empty || (!Hyperparams.foodBlocksReproduction && cell.state==CellStates.food) || (ignore_armor && loccell.state==CellStates.armor && cell.state==CellStates.food)){\r\n continue;\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n harm() {\r\n this.damage++;\r\n if (this.damage >= this.maxHealth() || Hyperparams.instaKill) {\r\n this.die();\r\n }\r\n }\r\n\r\n die() {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.food, null);\r\n }\r\n this.species.decreasePop();\r\n this.living = false;\r\n }\r\n\r\n updateGrid() {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, cell.state, cell);\r\n }\r\n }\r\n\r\n update() {\r\n this.lifetime++;\r\n if (this.lifetime > this.lifespan()) {\r\n this.die();\r\n return this.living;\r\n }\r\n if (this.food_collected >= this.foodNeeded()) {\r\n this.reproduce();\r\n }\r\n for (var cell of this.anatomy.cells) {\r\n cell.performFunction();\r\n if (!this.living)\r\n return this.living\r\n }\r\n \r\n if (this.anatomy.is_mover) {\r\n this.move_count++;\r\n var changed_dir = false;\r\n if (this.ignore_brain_for == 0){\r\n changed_dir = this.brain.decide();\r\n } \r\n else{\r\n this.ignore_brain_for --;\r\n }\r\n var moved = this.attemptMove();\r\n if ((this.move_count > this.move_range && !changed_dir) || !moved){\r\n var rotated = this.attemptRotate();\r\n if (!rotated) {\r\n this.changeDirection(Directions.getRandomDirection());\r\n if (changed_dir)\r\n this.ignore_brain_for = this.move_range + 1;\r\n }\r\n }\r\n }\r\n\r\n return this.living;\r\n }\r\n\r\n getRealCell(local_cell, c=this.c, r=this.r, rotation=this.rotation){\r\n var real_c = c + local_cell.rotatedCol(rotation);\r\n var real_r = r + local_cell.rotatedRow(rotation);\r\n return this.env.grid_map.cellAt(real_c, real_r);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Organism;\r\n\n\n//# sourceURL=webpack:///./src/Organism/Organism.js?"); + +/***/ }), + +/***/ "./src/Organism/Perception/Brain.js": +/*!******************************************!*\ + !*** ./src/Organism/Perception/Brain.js ***! + \******************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Hyperparams = __webpack_require__(/*! ../../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Directions = __webpack_require__(/*! ../Directions */ \"./src/Organism/Directions.js\");\r\nconst CellStates = __webpack_require__(/*! ../Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\n\r\nconst Decision = {\r\n neutral: 0,\r\n retreat: 1,\r\n chase: 2,\r\n getRandom: function(){\r\n return Math.floor(Math.random() * 3);\r\n },\r\n getRandomNonNeutral: function() {\r\n return Math.floor(Math.random() * 2)+1;\r\n }\r\n}\r\n\r\nclass Brain {\r\n constructor(owner){\r\n this.owner = owner;\r\n this.observations = [];\r\n\r\n // corresponds to CellTypes\r\n this.decisions = [];\r\n this.decisions[CellStates.empty.name] = Decision.neutral;\r\n this.decisions[CellStates.food.name] = Decision.chase;\r\n this.decisions[CellStates.wall.name] = Decision.neutral;\r\n this.decisions[CellStates.mouth.name] = Decision.neutral;\r\n this.decisions[CellStates.producer.name] = Decision.neutral;\r\n this.decisions[CellStates.mover.name] = Decision.neutral;\r\n this.decisions[CellStates.killer.name] = Decision.retreat;\r\n this.decisions[CellStates.armor.name] = Decision.neutral;\r\n this.decisions[CellStates.eye.name] = Decision.neutral;\r\n }\r\n\r\n randomizeDecisions() {\r\n // randomize the non obvious decisions\r\n this.decisions[CellStates.mouth.name] = Decision.getRandom();\r\n this.decisions[CellStates.producer.name] = Decision.getRandom();\r\n this.decisions[CellStates.mover.name] = Decision.getRandom();\r\n this.decisions[CellStates.armor.name] = Decision.getRandom();\r\n this.decisions[CellStates.eye.name] = Decision.getRandom();\r\n }\r\n\r\n observe(observation) {\r\n this.observations.push(observation);\r\n }\r\n\r\n decide() {\r\n var decision = Decision.neutral;\r\n var closest = Hyperparams.lookRange + 1;\r\n var move_direction = 0;\r\n for (var obs of this.observations) {\r\n if (obs.cell == null || obs.cell.owner == this.owner) {\r\n continue;\r\n }\r\n if (obs.distance < closest) {\r\n // console.log(obs.cell.state)\r\n decision = this.decisions[obs.cell.state.name];\r\n // console.log(decision)\r\n move_direction = obs.direction;\r\n closest = obs.distance;\r\n }\r\n }\r\n this.observations = [];\r\n if (decision == Decision.chase) {\r\n this.owner.changeDirection(move_direction);\r\n return true;\r\n }\r\n else if (decision == Decision.retreat) {\r\n this.owner.changeDirection(Directions.getOppositeDirection(move_direction));\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n mutate() {\r\n this.decisions[CellStates.getRandomName()] = Decision.getRandom();\r\n this.decisions[CellStates.empty.name] = Decision.neutral; // if the empty cell has a decision it gets weird\r\n }\r\n}\r\n\r\nmodule.exports = Brain;\n\n//# sourceURL=webpack:///./src/Organism/Perception/Brain.js?"); + +/***/ }), + +/***/ "./src/Organism/Perception/Observation.js": +/*!************************************************!*\ + !*** ./src/Organism/Perception/Observation.js ***! + \************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +eval("class Observation {\r\n constructor(cell, distance, direction){\r\n this.cell = cell;\r\n this.distance = distance;\r\n this.direction = direction;\r\n }\r\n}\r\n\r\nmodule.exports = Observation;\n\n//# sourceURL=webpack:///./src/Organism/Perception/Observation.js?"); + +/***/ }), + +/***/ "./src/Rendering/ColorScheme.js": +/*!**************************************!*\ + !*** ./src/Rendering/ColorScheme.js ***! + \**************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\n\r\nvar color_scheme = {\r\n \"empty\":\"#0E1318\",\r\n \"food\":\"#2F7AB7\",\r\n \"wall\":\"gray\",\r\n \"mouth\":\"#DEB14D\",\r\n \"producer\":\"#15DE59\",\r\n \"mover\":\"#60D4FF\",\r\n \"killer\":\"#F82380\",\r\n \"armor\":\"#7230DB\",\r\n \"eye\":\"#B6C1EA\",\r\n \"eye-slit\": \"#0E1318\"\r\n}\r\n\r\n// Renderer controls access to a canvas. There is one renderer for each canvas\r\nclass ColorScheme {\r\n constructor(world_env, editor_env) {\r\n this.world_env = world_env;\r\n this.editor_env = editor_env;\r\n }\r\n\r\n loadColorScheme() {\r\n for (var state of CellStates.all) {\r\n state.color = color_scheme[state.name];\r\n }\r\n CellStates.eye.slit_color=color_scheme['eye-slit']\r\n for (var cell_type in color_scheme) {\r\n $('#'+cell_type+'.cell-type ').css('background-color', color_scheme[cell_type]);\r\n $('#'+cell_type+'.cell-legend-type').css('background-color', color_scheme[cell_type]);\r\n \r\n }\r\n this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid);\r\n this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid);\r\n }\r\n}\r\n\r\nmodule.exports = ColorScheme;\n\n//# sourceURL=webpack:///./src/Rendering/ColorScheme.js?"); + +/***/ }), + +/***/ "./src/Rendering/Renderer.js": +/*!***********************************!*\ + !*** ./src/Rendering/Renderer.js ***! + \***********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("// const CellTypes = require(\"../Organism/Cell/CellTypes\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Directions = __webpack_require__(/*! ../Organism/Directions */ \"./src/Organism/Directions.js\");\r\n\r\n// Renderer controls access to a canvas. There is one renderer for each canvas\r\nclass Renderer {\r\n constructor(canvas_id, container_id, cell_size) {\r\n this.cell_size = cell_size;\r\n this.canvas = document.getElementById(canvas_id);\r\n this.ctx = this.canvas.getContext(\"2d\");\r\n this.fillWindow(container_id)\r\n\t\tthis.height = this.canvas.height;\r\n this.width = this.canvas.width;\r\n this.cells_to_render = new Set();\r\n this.cells_to_highlight = new Set();\r\n this.highlighted_cells = new Set();\r\n }\r\n\r\n fillWindow(container_id) {\r\n this.fillShape($('#'+container_id).height(), $('#'+container_id).width());\r\n }\r\n\r\n fillShape(height, width) {\r\n this.canvas.width = width;\r\n this.canvas.height = height;\r\n this.height = this.canvas.height;\r\n this.width = this.canvas.width;\r\n }\r\n\r\n clear() {\r\n this.ctx.fillStyle = 'white';\r\n this.ctx.fillRect(0, 0, this.height, this.width);\r\n }\r\n\r\n renderFullGrid(grid) {\r\n for (var col of grid) {\r\n for (var cell of col){\r\n this.renderCell(cell);\r\n }\r\n }\r\n }\r\n\r\n renderCells() {\r\n for (var cell of this.cells_to_render) {\r\n this.renderCell(cell);\r\n }\r\n this.cells_to_render.clear();\r\n }\r\n\r\n renderCell(cell) {\r\n cell.state.render(this.ctx, cell, this.cell_size);\r\n }\r\n\r\n renderOrganism(org) {\r\n for(var org_cell of org.anatomy.cells) {\r\n var cell = org.getRealCell(org_cell);\r\n this.renderCell(cell);\r\n }\r\n }\r\n\r\n addToRender(cell) {\r\n if (this.highlighted_cells.has(cell)){\r\n this.cells_to_highlight.add(cell);\r\n }\r\n this.cells_to_render.add(cell);\r\n }\r\n\r\n renderHighlights() {\r\n for (var cell of this.cells_to_highlight) {\r\n this.renderCellHighlight(cell);\r\n this.highlighted_cells.add(cell);\r\n }\r\n this.cells_to_highlight.clear();\r\n \r\n }\r\n\r\n highlightOrganism(org) {\r\n for(var org_cell of org.anatomy.cells) {\r\n var cell = org.getRealCell(org_cell);\r\n this.cells_to_highlight.add(cell);\r\n }\r\n }\r\n\r\n highlightCell(cell) {\r\n this.cells_to_highlight.add(cell);\r\n }\r\n\r\n renderCellHighlight(cell, color=\"yellow\") {\r\n this.renderCell(cell);\r\n this.ctx.fillStyle = color;\r\n this.ctx.globalAlpha = 0.5;\r\n this.ctx.fillRect(cell.x, cell.y, this.cell_size, this.cell_size);\r\n this.ctx.globalAlpha = 1;\r\n this.highlighted_cells.add(cell);\r\n }\r\n\r\n clearAllHighlights(clear_to_highlight=false) {\r\n for (var cell of this.highlighted_cells) {\r\n this.renderCell(cell);\r\n }\r\n this.highlighted_cells.clear();\r\n if (clear_to_highlight) {\r\n this.cells_to_highlight.clear();\r\n }\r\n }\r\n}\r\n\r\n// $(\"body\").mousemove(function(e) {\r\n// console.log(\"hello\");\r\n// });\r\n\r\nmodule.exports = Renderer;\r\n\n\n//# sourceURL=webpack:///./src/Rendering/Renderer.js?"); + +/***/ }), + +/***/ "./src/Stats/FossilRecord.js": +/*!***********************************!*\ + !*** ./src/Stats/FossilRecord.js ***! + \***********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("const Species = __webpack_require__(/*! ./Species */ \"./src/Stats/Species.js\");\r\n\r\nconst FossilRecord = {\r\n init: function(){\r\n this.extant_species = [];\r\n this.extinct_species = [];\r\n\r\n // if an organism has fewer than this cumulative pop, discard them on extinction\r\n this.min_discard = 5;\r\n },\r\n\r\n setEnv: function(env) {\r\n this.env = env;\r\n },\r\n\r\n addSpecies: function(org, ancestor) {\r\n // console.log(\"Adding Species\")\r\n var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks);\r\n this.extant_species.push(new_species);\r\n org.species = new_species;\r\n return new_species;\r\n },\r\n\r\n addSpeciesObj: function(species) {\r\n // console.log(\"Adding Species\")\r\n this.extant_species.push(species);\r\n return species;\r\n },\r\n\r\n fossilize: function(species) {\r\n // console.log(\"Extinction\")\r\n species.end_tick = this.env.total_ticks;\r\n for (i in this.extant_species) {\r\n var s = this.extant_species[i];\r\n if (s == species) {\r\n this.extant_species.splice(i, 1);\r\n if (species.cumulative_pop < this.min_pop) {\r\n return false;\r\n }\r\n this.extinct_species.push(s);\r\n // console.log(\"Extant species:\", this.extant_species.length)\r\n // console.log(\"Extinct species:\", this.extinct_species.length)\r\n return true;\r\n }\r\n }\r\n },\r\n\r\n resurrect: function(species) {\r\n // console.log(\"Resurrecting species\")\r\n if (species.extinct) {\r\n for (i in this.extinct_species) {\r\n var s = this.extinct_species[i];\r\n if (s == species) {\r\n this.extinct_species.splice(i, 1);\r\n this.extant_species.push(species);\r\n species.extinct = false;\r\n }\r\n }\r\n }\r\n },\r\n\r\n clear_record: function() {\r\n this.extant_species = [];\r\n this.extinct_species = [];\r\n // console.log(\"Cleared\", this.extant_species, this.extinct_species)\r\n },\r\n\r\n}\r\n\r\nFossilRecord.init();\r\n\r\nmodule.exports = FossilRecord;\n\n//# sourceURL=webpack:///./src/Stats/FossilRecord.js?"); + +/***/ }), + +/***/ "./src/Stats/Species.js": +/*!******************************!*\ + !*** ./src/Stats/Species.js ***! + \******************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +eval("class Species {\r\n constructor(anatomy, ancestor, start_tick) {\r\n this.anatomy = anatomy;\r\n this.ancestor = ancestor;\r\n this.population = 1;\r\n this.cumulative_pop = 1;\r\n this.start_tick = start_tick;\r\n this.end_tick = -1;\r\n this.color = '#asdfasdf';\r\n this.name = '_' + Math.random().toString(36).substr(2, 9);;\r\n this.extinct = false;\r\n }\r\n\r\n addPop() {\r\n this.population++;\r\n this.cumulative_pop++;\r\n }\r\n\r\n decreasePop() {\r\n this.population--;\r\n if (this.population <= 0) {\r\n this.extinct = true;\r\n const FossilRecord = __webpack_require__(/*! ./FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n FossilRecord.fossilize(this);\r\n }\r\n }\r\n\r\n lifespan() {\r\n return this.end_tick - this.start_tick;\r\n }\r\n}\r\n\r\nmodule.exports = Species;\n\n//# sourceURL=webpack:///./src/Stats/Species.js?"); + +/***/ }), + +/***/ "./src/index.js": +/*!**********************!*\ + !*** ./src/index.js ***! + \**********************/ +/*! no exports provided */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Engine */ \"./src/Engine.js\");\n/* harmony import */ var _Engine__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_Engine__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\r\n\r\n\r\n$('document').ready(function(){\r\n let isMobile = mobileCheck();\r\n if (isMobile) {\r\n alert(\"Though the simulation still works on mobile, most features are disabled. Try it on desktop for the full experience!\");\r\n $('.control-panel').css('display', 'none');\r\n }\r\n var engine = new _Engine__WEBPACK_IMPORTED_MODULE_0___default.a();\r\n engine.start(60);\r\n});\r\n\r\nfunction mobileCheck() {\r\n let check = false;\r\n (function(a){if(/(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);\r\n return check;\r\n};\n\n//# sourceURL=webpack:///./src/index.js?"); + +/***/ }) + +/******/ }); \ No newline at end of file diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index 25e1212..96430ba 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -1,5 +1,6 @@ const Hyperparams = require("../Hyperparameters"); const Modes = require("./ControlModes"); +const StatsPanel = require("./StatsPanel"); class ControlPanel { constructor(engine) { @@ -17,16 +18,22 @@ class ControlPanel { this.editor_controller = this.engine.organism_editor.controller; this.env_controller.setControlPanel(this); this.editor_controller.setControlPanel(this); + this.stats_panel = new StatsPanel(); + this.stats_panel.render(); } defineMinMaxControls(){ $('#minimize').click ( function() { $('.control-panel').css('display', 'none'); $('.hot-controls').css('display', 'block'); - }); + this.stats_panel.stopAutoRender(); + }.bind(this)); $('#maximize').click ( function() { $('.control-panel').css('display', 'grid'); $('.hot-controls').css('display', 'none'); + if (this.id == 'stats') { + self.stats_panel.startAutoRender(); + } }); } @@ -76,19 +83,24 @@ class ControlPanel { } defineTabNavigation() { + this.tab_id = 'about'; var self = this; $('.tabnav-item').click(function() { $('.tab').css('display', 'none'); var tab = '#'+this.id+'.tab'; self.engine.organism_editor.is_active = (this.id == 'editor'); + if (this.id == 'stats') { + self.stats_panel.startAutoRender(); + } + self.id = this.id; + $(tab).css('display', 'grid'); }); } defineHyperparameterControls() { $('#food-prod-prob').change(function() { - var food_prob = - Hyperparams.foodProdProb = $('#food-prod-prob').val();; + Hyperparams.foodProdProb = $('#food-prod-prob').val(); }.bind(this)); $('#lifespan-multiplier').change(function() { Hyperparams.lifespanMultiplier = $('#lifespan-multiplier').val(); @@ -199,7 +211,9 @@ class ControlPanel { case "drop-org": self.setMode(Modes.Clone); self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg(); - self.env_controller.make_new_species = true; + self.env_controller.add_new_species = self.editor_controller.new_species; + self.editor_controller.new_species = false; + // console.log(self.env_controller.add_new_species) break; case "drag-view": self.setMode(Modes.Drag); @@ -215,6 +229,7 @@ class ControlPanel { var env = this.engine.env; $('#reset-env').click( function() { this.engine.env.reset(); + this.stats_panel.clearData(); }.bind(this)); $('#auto-reset').change(function() { env.auto_reset = this.checked; @@ -264,6 +279,7 @@ class ControlPanel { $('#avg-mut').text("Average Mutation Rate: " + Math.round(this.engine.env.averageMutability() * 100) / 100); $('#largest-org').text("Largest Organism: " + this.engine.env.largest_cell_count + " cells"); $('#reset-count').text("Auto reset count: " + this.engine.env.reset_count); + this.stats_panel.updateData(this.engine.env.total_ticks, this.engine.env.organisms.length) } } diff --git a/src/Controllers/EditorController.js b/src/Controllers/EditorController.js index d873b55..e7c2152 100644 --- a/src/Controllers/EditorController.js +++ b/src/Controllers/EditorController.js @@ -10,6 +10,7 @@ class EditorController extends CanvasController{ this.mode = Modes.None; this.edit_cell_type = null; this.highlight_org = false; + this.new_species = false; this.defineCellTypeSelection(); this.defineEditorDetails(); } @@ -41,8 +42,10 @@ class EditorController extends CanvasController{ else this.env.addCellToOrg(this.mouse_c, this.mouse_r, this.edit_cell_type); } - if (this.right_click) + else if (this.right_click) this.env.removeCellFromOrg(this.mouse_c, this.mouse_r); + + this.new_species = true; this.setBrainPanelVisibility(); this.setMoveRangeVisibility(); this.updateDetails(); diff --git a/src/Controllers/EnvironmentController.js b/src/Controllers/EnvironmentController.js index 4962af8..f297292 100644 --- a/src/Controllers/EnvironmentController.js +++ b/src/Controllers/EnvironmentController.js @@ -10,8 +10,7 @@ class EnvironmentController extends CanvasController{ super(env, canvas); this.mode = Modes.Drag; this.org_to_clone = null; - this.species_to_clone = null; - this.make_new_species = false; + this.add_new_species = false; this.defineZoomControls(); this.scale = 1; } @@ -121,16 +120,19 @@ 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.make_new_species){ - this.species_to_clone = FossilRecord.addSpecies(new_org, null) - this.make_new_species = false; + 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 { - new_org.species = this.species_to_clone; - this.species_to_clone.addPop(); + 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) + this.env.addOrganism(new_org); + new_org.species.addPop(); } } break; diff --git a/src/Controllers/StatsPanel.js b/src/Controllers/StatsPanel.js new file mode 100644 index 0000000..830fafb --- /dev/null +++ b/src/Controllers/StatsPanel.js @@ -0,0 +1,77 @@ +const FossilRecord = require("../Stats/FossilRecord"); + +class StatsPanel { + constructor() { + this.defineControls(); + this.clearData(); + this.last_update_tick = 0; + this.update_every = 100; + + // maps species to their index in chart's data storage + this.species_index_map = []; + this.index_counter = 0; + this.min_display = 10; + } + + startAutoRender(){ + this.render_loop = setInterval(function(){this.render();}.bind(this), 1000); + } + + stopAutoRender() { + clearInterval(this.render_loop); + } + + defineControls() { + $('#update-chart').click( function() { + this.render(); + }.bind(this)); + } + + updateData(tick, population_size) { + if (tick - this.last_update_tick >= this.update_every){ + // this.data[0].dataPoints.push({x: tick, y:population_size}); + this.last_update_tick = tick; + + for (var species of FossilRecord.extant_species) { + if (species.cumulative_pop < this.min_display){ + continue; + } + + if (this.species_index_map[species.name] == null) { + console.log("new species") + this.species_index_map[species.name] = this.index_counter; + this.index_counter++; + this.data.push({ + type: "line", + markerType: "none", + dataPoints: [] + }); + } + var data_index = this.species_index_map[species.name]; + this.data[data_index].dataPoints.push({x:tick, y:species.population}); + } + } + } + + render() { + this.chart.render(); + } + + clearData() { + this.data = [{ + type: "line", + markerType: "none", + dataPoints: [] + }]; + this.chart = new CanvasJS.Chart("chartContainer", { + title:{ + text: "Population" + }, + data: this.data + }); + this.render(); + } + +} + +module.exports = StatsPanel; \ No newline at end of file diff --git a/src/Environments/OrganismEditor.js b/src/Environments/OrganismEditor.js index 7e7aaf9..b969774 100644 --- a/src/Environments/OrganismEditor.js +++ b/src/Environments/OrganismEditor.js @@ -4,6 +4,7 @@ const GridMap = require('../Grid/GridMap'); const Renderer = require('../Rendering/Renderer'); const CellStates = require('../Organism/Cell/CellStates'); const EditorController = require("../Controllers/EditorController"); +const Species = require('../Stats/Species'); class OrganismEditor extends Environment{ constructor() { @@ -44,6 +45,7 @@ class OrganismEditor extends Environment{ else if (this.organism.anatomy.canAddCellAt(loc_c, loc_r)){ this.changeCell(c, r, state, this.organism.anatomy.addDefaultCell(state, loc_c, loc_r)); } + this.organism.species = new Species(this.organism.anatomy, null, 0); } removeCellFromOrg(c, r) { @@ -58,16 +60,18 @@ class OrganismEditor extends Environment{ if (prev_cell != null) { if (this.organism.anatomy.removeCell(loc_c, loc_r)) { this.changeCell(c, r, CellStates.empty, null); + this.organism.species = new Species(this.organism.anatomy, null, 0); } } } - setOrganismToCopyOf(orig_org){ + setOrganismToCopyOf(orig_org) { this.grid_map.fillGrid(CellStates.empty); var center = this.grid_map.getCenter(); this.organism = new Organism(center[0], center[1], this, orig_org); this.organism.updateGrid(); this.controller.updateDetails(); + this.controller.new_species = false; } getCopyOfOrg() { @@ -81,6 +85,7 @@ class OrganismEditor extends Environment{ this.organism = new Organism(center[0], center[1], this, null); this.organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0); this.organism.updateGrid(); + this.organism.species = new Species(this.organism.anatomy, null, 0); } } diff --git a/src/Environments/WorldEnvironment.js b/src/Environments/WorldEnvironment.js index db13437..e2d051e 100644 --- a/src/Environments/WorldEnvironment.js +++ b/src/Environments/WorldEnvironment.js @@ -121,6 +121,7 @@ class WorldEnvironment extends Environment{ this.renderer.renderFullGrid(this.grid_map.grid); this.total_mutability = 0; this.total_ticks = 0; + FossilRecord.clear_record(); this.OriginOfLife(); } diff --git a/src/Stats/FossilRecord.js b/src/Stats/FossilRecord.js index 6eefd2a..a41dd7d 100644 --- a/src/Stats/FossilRecord.js +++ b/src/Stats/FossilRecord.js @@ -5,8 +5,8 @@ const FossilRecord = { this.extant_species = []; this.extinct_species = []; - // if an organism has fewer than this cumulative pop, discard them - this.discard_pop = 5; + // if an organism has fewer than this cumulative pop, discard them on extinction + this.min_discard = 5; }, setEnv: function(env) { @@ -15,31 +15,54 @@ const FossilRecord = { addSpecies: function(org, ancestor) { // console.log("Adding Species") - var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks) + var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks); this.extant_species.push(new_species); org.species = new_species; return new_species; }, + addSpeciesObj: function(species) { + // console.log("Adding Species") + this.extant_species.push(species); + return species; + }, + fossilize: function(species) { + // console.log("Extinction") species.end_tick = this.env.total_ticks; for (i in this.extant_species) { var s = this.extant_species[i]; if (s == species) { this.extant_species.splice(i, 1); - if (species.cumulative_pop <= this.discard_pop) { + if (species.cumulative_pop < this.min_pop) { return false; } this.extinct_species.push(s); - // console.log("Extant:", this.extant_species.length) - // console.log("Extinct:", this.extinct_species.length) + // console.log("Extant species:", this.extant_species.length) + // console.log("Extinct species:", this.extinct_species.length) return true; } } }, + resurrect: function(species) { + // console.log("Resurrecting species") + if (species.extinct) { + for (i in this.extinct_species) { + var s = this.extinct_species[i]; + if (s == species) { + this.extinct_species.splice(i, 1); + this.extant_species.push(species); + species.extinct = false; + } + } + } + }, + clear_record: function() { - this.species = []; + this.extant_species = []; + this.extinct_species = []; + // console.log("Cleared", this.extant_species, this.extinct_species) }, } diff --git a/src/Stats/Species.js b/src/Stats/Species.js index 8bb6c24..f2a94ac 100644 --- a/src/Stats/Species.js +++ b/src/Stats/Species.js @@ -7,7 +7,7 @@ class Species { this.start_tick = start_tick; this.end_tick = -1; this.color = '#asdfasdf'; - this.name = "crabuloid"; + this.name = '_' + Math.random().toString(36).substr(2, 9);; this.extinct = false; } @@ -20,11 +20,14 @@ class Species { this.population--; if (this.population <= 0) { this.extinct = true; - // console.log("Extinction"); const FossilRecord = require("./FossilRecord"); FossilRecord.fossilize(this); } } + + lifespan() { + return this.end_tick - this.start_tick; + } } module.exports = Species; \ No newline at end of file From 7b19798be96149d239c49b4e78b20b737ffb3053 Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Wed, 10 Feb 2021 18:09:18 -0700 Subject: [PATCH 4/9] Fixed up chart --- dist/css/style.css | 6 + dist/index.html | 18 +- dist/js/bundle.js | 454 +-------------------------- src/Controllers/ControlPanel.js | 31 +- src/Controllers/StatsPanel.js | 77 ----- src/Engine.js | 2 +- src/Environments/WorldEnvironment.js | 11 +- src/Stats/Charts/ChartController.js | 55 ++++ src/Stats/Charts/MutationChart.js | 41 +++ src/Stats/Charts/PopulationChart.js | 41 +++ src/Stats/Charts/SpeciesChart.js | 40 +++ src/Stats/FossilRecord.js | 31 +- src/Stats/Species.js | 9 +- src/Stats/StatsPanel.js | 65 ++++ 14 files changed, 318 insertions(+), 563 deletions(-) delete mode 100644 src/Controllers/StatsPanel.js create mode 100644 src/Stats/Charts/ChartController.js create mode 100644 src/Stats/Charts/MutationChart.js create mode 100644 src/Stats/Charts/PopulationChart.js create mode 100644 src/Stats/Charts/SpeciesChart.js create mode 100644 src/Stats/StatsPanel.js diff --git a/dist/css/style.css b/dist/css/style.css index f78c279..8bfb661 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -226,6 +226,12 @@ button:hover{ margin: 5px; } +#chartContainer { + height: 200px; + width: 100%; +} + + .hot-controls { position: fixed; bottom: 10px; diff --git a/dist/index.html b/dist/index.html index 1870f77..02f41dc 100644 --- a/dist/index.html +++ b/dist/index.html @@ -51,10 +51,6 @@

-
@@ -92,6 +88,10 @@ readme.

+
@@ -226,12 +226,16 @@

Highest count:

Average Mutation Rate:

Largest Organism:

- + +
-
-
+
diff --git a/dist/js/bundle.js b/dist/js/bundle.js index cdc27a3..4b18cc8 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1,453 +1 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./src/index.js"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./src/Controllers/CanvasController.js": -/*!*********************************************!*\ - !*** ./src/Controllers/CanvasController.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("\r\n\r\nclass CanvasController{\r\n constructor(env, canvas) {\r\n this.env = env;\r\n this.canvas = canvas;\r\n this.mouse_x;\r\n this.mouse_y;\r\n this.mouse_c;\r\n this.mouse_r;\r\n this.left_click = false;\r\n this.right_click = false;\r\n this.cur_cell = null;\r\n this.cur_org = null;\r\n this.highlight_org = true;\r\n this.defineEvents();\r\n }\r\n\r\n setControlPanel(panel){\r\n this.control_panel = panel;\r\n }\r\n\r\n defineEvents() {\r\n this.canvas.addEventListener('mousemove', e => {\r\n this.updateMouseLocation(e.offsetX, e.offsetY)\r\n this.mouseMove();\r\n });\r\n\r\n this.canvas.addEventListener('mouseup', function(evt) {\r\n evt.preventDefault();\r\n this.updateMouseLocation(evt.offsetX, evt.offsetY)\r\n this.mouseUp();\r\n this.left_click=false;\r\n this.right_click=false;\r\n }.bind(this));\r\n\r\n this.canvas.addEventListener('mousedown', function(evt) {\r\n evt.preventDefault();\r\n this.updateMouseLocation(evt.offsetX, evt.offsetY)\r\n if (evt.button == 0) {\r\n this.left_click = true;\r\n }\r\n if (evt.button == 2) \r\n this.right_click = true;\r\n this.mouseDown();\r\n }.bind(this));\r\n\r\n this.canvas.addEventListener('contextmenu', function(evt) {\r\n evt.preventDefault();\r\n });\r\n\r\n this.canvas.addEventListener('mouseleave', function(){\r\n this.right_click = false;\r\n this.left_click = false;\r\n this.env.renderer.clearAllHighlights(true);\r\n }.bind(this));\r\n\r\n }\r\n\r\n updateMouseLocation(offsetX, offsetY) {\r\n var prev_cell = this.cur_cell;\r\n var prev_org = this.cur_org;\r\n\r\n this.mouse_x = offsetX;\r\n this.mouse_y = offsetY;\r\n var colRow = this.env.grid_map.xyToColRow(this.mouse_x, this.mouse_y);\r\n this.mouse_c = colRow[0];\r\n this.mouse_r = colRow[1];\r\n this.cur_cell = this.env.grid_map.cellAt(this.mouse_c, this.mouse_r);\r\n this.cur_org = this.cur_cell.owner;\r\n\r\n if (this.cur_org != prev_org || this.cur_cell != prev_cell) {\r\n this.env.renderer.clearAllHighlights(true);\r\n if (this.cur_org != null && this.highlight_org) {\r\n this.env.renderer.highlightOrganism(this.cur_org);\r\n }\r\n else if (this.cur_cell != null) {\r\n this.env.renderer.highlightCell(this.cur_cell, true);\r\n }\r\n }\r\n }\r\n\r\n mouseMove() {\r\n alert(\"mouse move must be overridden\");\r\n }\r\n\r\n mouseDown() {\r\n alert(\"mouse down must be overridden\");\r\n }\r\n\r\n mouseUp(){\r\n alert(\"mouse up must be overridden\")\r\n }\r\n}\r\n\r\nmodule.exports = CanvasController;\n\n//# sourceURL=webpack:///./src/Controllers/CanvasController.js?"); - -/***/ }), - -/***/ "./src/Controllers/ControlModes.js": -/*!*****************************************!*\ - !*** ./src/Controllers/ControlModes.js ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("const Modes = {\r\n None: 0,\r\n FoodDrop: 1,\r\n WallDrop: 2,\r\n ClickKill: 3,\r\n Select: 4,\r\n Edit: 5,\r\n Clone: 6,\r\n Drag: 7\r\n}\r\n\r\nmodule.exports = Modes;\n\n//# sourceURL=webpack:///./src/Controllers/ControlModes.js?"); - -/***/ }), - -/***/ "./src/Controllers/ControlPanel.js": -/*!*****************************************!*\ - !*** ./src/Controllers/ControlPanel.js ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst StatsPanel = __webpack_require__(/*! ./StatsPanel */ \"./src/Controllers/StatsPanel.js\");\r\n\r\nclass ControlPanel {\r\n constructor(engine) {\r\n this.engine = engine;\r\n this.defineMinMaxControls();\r\n this.defineEngineSpeedControls();\r\n this.defineGridSizeControls();\r\n this.defineTabNavigation();\r\n this.defineHyperparameterControls();\r\n this.defineModeControls();\r\n this.defineChallenges();\r\n this.fps = engine.fps;\r\n this.organism_record=0;\r\n this.env_controller = this.engine.env.controller;\r\n this.editor_controller = this.engine.organism_editor.controller;\r\n this.env_controller.setControlPanel(this);\r\n this.editor_controller.setControlPanel(this);\r\n this.stats_panel = new StatsPanel();\r\n this.stats_panel.render();\r\n }\r\n\r\n defineMinMaxControls(){\r\n $('#minimize').click ( function() {\r\n $('.control-panel').css('display', 'none');\r\n $('.hot-controls').css('display', 'block');\r\n this.stats_panel.stopAutoRender();\r\n }.bind(this));\r\n $('#maximize').click ( function() {\r\n $('.control-panel').css('display', 'grid');\r\n $('.hot-controls').css('display', 'none');\r\n if (this.id == 'stats') {\r\n self.stats_panel.startAutoRender();\r\n }\r\n });\r\n }\r\n\r\n defineEngineSpeedControls(){\r\n this.slider = document.getElementById(\"slider\");\r\n this.slider.oninput = function() {\r\n this.fps = this.slider.value\r\n if (this.engine.running) {\r\n this.changeEngineSpeed(this.fps);\r\n \r\n }\r\n $('#fps').text(\"Target FPS: \"+this.fps);\r\n }.bind(this);\r\n $('.pause-button').click(function() {\r\n $('.pause-button').find(\"i\").toggleClass(\"fa fa-pause\");\r\n $('.pause-button').find(\"i\").toggleClass(\"fa fa-play\");\r\n if (this.engine.running) {\r\n this.engine.stop();\r\n }\r\n else if (!this.engine.running){\r\n this.engine.start(this.fps);\r\n }\r\n }.bind(this));\r\n }\r\n\r\n defineGridSizeControls() {\r\n $('#fill-window').change(function() {\r\n if (this.checked)\r\n $('.col-row-input').css('display' ,'none');\r\n else\r\n $('.col-row-input').css('display' ,'block');\r\n });\r\n\r\n $('#resize').click(function() {\r\n var cell_size = $('#cell-size').val();\r\n var fill_window = $('#fill-window').is(\":checked\");\r\n if (fill_window) {\r\n this.engine.env.resizeFillWindow(cell_size);\r\n }\r\n else {\r\n var cols = $('#col-input').val();\r\n var rows = $('#row-input').val();\r\n this.engine.env.resizeGridColRow(cell_size, cols, rows);\r\n }\r\n \r\n }.bind(this));\r\n }\r\n\r\n defineTabNavigation() {\r\n this.tab_id = 'about';\r\n var self = this;\r\n $('.tabnav-item').click(function() {\r\n $('.tab').css('display', 'none');\r\n var tab = '#'+this.id+'.tab';\r\n self.engine.organism_editor.is_active = (this.id == 'editor');\r\n if (this.id == 'stats') {\r\n self.stats_panel.startAutoRender();\r\n }\r\n self.id = this.id;\r\n \r\n $(tab).css('display', 'grid');\r\n });\r\n }\r\n\r\n defineHyperparameterControls() {\r\n $('#food-prod-prob').change(function() {\r\n Hyperparams.foodProdProb = $('#food-prod-prob').val();\r\n }.bind(this));\r\n $('#lifespan-multiplier').change(function() {\r\n Hyperparams.lifespanMultiplier = $('#lifespan-multiplier').val();\r\n }.bind(this));\r\n\r\n $('#mover-rot').change(function() {\r\n Hyperparams.moversCanRotate = this.checked;\r\n });\r\n $('#offspring-rot').change(function() {\r\n Hyperparams.offspringRotate = this.checked;\r\n });\r\n $('#insta-kill').change(function() {\r\n Hyperparams.instaKill = this.checked;\r\n });\r\n $('#look-range').change(function() {\r\n Hyperparams.lookRange = $('#look-range').val();\r\n });\r\n $('#food-drop-rate').change(function() {\r\n Hyperparams.foodDropProb = $('#food-drop-rate').val();\r\n });\r\n\r\n $('#evolved-mutation').change( function() {\r\n if (this.checked) {\r\n $('.global-mutation-in').css('display', 'none');\r\n $('#avg-mut').css('display', 'block');\r\n }\r\n else {\r\n $('.global-mutation-in').css('display', 'block');\r\n $('#avg-mut').css('display', 'none');\r\n }\r\n Hyperparams.useGlobalMutability = !this.checked;\r\n });\r\n $('#global-mutation').change( function() {\r\n Hyperparams.globalMutability = $('#global-mutation').val();\r\n });\r\n $('.mut-prob').change( function() {\r\n switch(this.id){\r\n case \"add-prob\":\r\n Hyperparams.addProb = this.value;\r\n Hyperparams.balanceMutationProbs(1);\r\n break;\r\n case \"change-prob\":\r\n Hyperparams.changeProb = this.value;\r\n Hyperparams.balanceMutationProbs(2);\r\n break;\r\n case \"remove-prob\":\r\n Hyperparams.removeProb = this.value;\r\n Hyperparams.balanceMutationProbs(3);\r\n break;\r\n }\r\n $('#add-prob').val(Math.floor(Hyperparams.addProb));\r\n $('#change-prob').val(Math.floor(Hyperparams.changeProb));\r\n $('#remove-prob').val(Math.floor(Hyperparams.removeProb));\r\n });\r\n $('#movers-produce').change( function() {\r\n Hyperparams.moversCanProduce = this.checked;\r\n });\r\n $('#food-blocks').change( function() {\r\n Hyperparams.foodBlocksReproduction = this.checked; \r\n });\r\n $('#reset-rules').click( function() {\r\n Hyperparams.setDefaults();\r\n $('#food-prod-prob').val(Hyperparams.foodProdProb);\r\n $('#lifespan-multiplier').val(Hyperparams.lifespanMultiplier);\r\n $('#mover-rot').prop('checked', Hyperparams.moversCanRotate);\r\n $('#offspring-rot').prop('checked', Hyperparams.offspringRotate);\r\n $('#insta-kill').prop('checked', Hyperparams.instaKill);\r\n $('#evolved-mutation').prop('checked', !Hyperparams.useGlobalMutability);\r\n $('#add-prob').val(Hyperparams.addProb);\r\n $('#change-prob').val(Hyperparams.changeProb);\r\n $('#remove-prob').val(Hyperparams.removeProb);\r\n $('#movers-produce').prop('checked', Hyperparams.moversCanProduce);\r\n $('#food-blocks').prop('checked', Hyperparams.foodBlocksReproduction);\r\n if (!Hyperparams.useGlobalMutability) {\r\n $('.global-mutation-in').css('display', 'none');\r\n $('#avg-mut').css('display', 'block');\r\n }\r\n else {\r\n $('.global-mutation-in').css('display', 'block');\r\n $('#avg-mut').css('display', 'none');\r\n }\r\n });\r\n }\r\n\r\n defineModeControls() {\r\n var self = this;\r\n $('.edit-mode-btn').click( function() {\r\n $('#cell-selections').css('display', 'none');\r\n $('#organism-options').css('display', 'none');\r\n self.editor_controller.setDetailsPanel();\r\n switch(this.id){\r\n case \"food-drop\":\r\n self.setMode(Modes.FoodDrop);\r\n break;\r\n case \"wall-drop\":\r\n self.setMode(Modes.WallDrop);\r\n break;\r\n case \"click-kill\":\r\n self.setMode(Modes.ClickKill);\r\n break;\r\n case \"select\":\r\n self.setMode(Modes.Select);\r\n break;\r\n case \"edit\":\r\n self.setMode(Modes.Edit);\r\n self.editor_controller.setEditorPanel();\r\n break;\r\n case \"drop-org\":\r\n self.setMode(Modes.Clone);\r\n self.env_controller.org_to_clone = self.engine.organism_editor.getCopyOfOrg();\r\n self.env_controller.add_new_species = self.editor_controller.new_species;\r\n self.editor_controller.new_species = false;\r\n // console.log(self.env_controller.add_new_species)\r\n break;\r\n case \"drag-view\":\r\n self.setMode(Modes.Drag);\r\n }\r\n $('.edit-mode-btn').css('background-color', '#9099c2');\r\n $('#'+this.id).css('background-color', '#81d2c7');\r\n });\r\n\r\n $('.reset-view').click( function(){\r\n this.env_controller.resetView();\r\n }.bind(this));\r\n\r\n var env = this.engine.env;\r\n $('#reset-env').click( function() {\r\n this.engine.env.reset();\r\n this.stats_panel.clearData();\r\n }.bind(this));\r\n $('#auto-reset').change(function() {\r\n env.auto_reset = this.checked;\r\n });\r\n $('#clear-walls').click( function() {\r\n if (confirm(\"Are you sure you want to clear all the walls?\")) {\r\n this.engine.env.clearWalls();\r\n }\r\n }.bind(this));\r\n $('#clear-editor').click( function() {\r\n this.engine.organism_editor.clear();\r\n this.editor_controller.setEditorPanel();\r\n }.bind(this));\r\n }\r\n\r\n defineChallenges() {\r\n $('.challenge-btn').click(function() {\r\n $('#challenge-title').text($(this).text());\r\n $('#challenge-description').text($(this).val());\r\n });\r\n }\r\n\r\n setMode(mode) {\r\n this.env_controller.mode = mode;\r\n this.editor_controller.mode = mode;\r\n }\r\n\r\n setEditorOrganism(org) {\r\n this.engine.organism_editor.setOrganismToCopyOf(org);\r\n this.editor_controller.clearDetailsPanel();\r\n this.editor_controller.setDetailsPanel();\r\n }\r\n\r\n changeEngineSpeed(change_val) {\r\n this.engine.stop();\r\n this.engine.start(change_val)\r\n this.fps = this.engine.fps;\r\n }\r\n\r\n update() {\r\n $('#fps-actual').text(\"Actual FPS: \" + Math.floor(this.engine.actual_fps));\r\n var org_count = this.engine.env.organisms.length;\r\n $('#org-count').text(\"Organism count: \" + org_count);\r\n if (org_count > this.organism_record) \r\n this.organism_record = org_count;\r\n $('#org-record').text(\"Highest count: \" + this.organism_record);\r\n $('#avg-mut').text(\"Average Mutation Rate: \" + Math.round(this.engine.env.averageMutability() * 100) / 100);\r\n $('#largest-org').text(\"Largest Organism: \" + this.engine.env.largest_cell_count + \" cells\");\r\n $('#reset-count').text(\"Auto reset count: \" + this.engine.env.reset_count);\r\n this.stats_panel.updateData(this.engine.env.total_ticks, this.engine.env.organisms.length)\r\n }\r\n\r\n}\r\n\r\n\r\nmodule.exports = ControlPanel;\n\n//# sourceURL=webpack:///./src/Controllers/ControlPanel.js?"); - -/***/ }), - -/***/ "./src/Controllers/EditorController.js": -/*!*********************************************!*\ - !*** ./src/Controllers/EditorController.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CanvasController = __webpack_require__(/*! ./CanvasController */ \"./src/Controllers/CanvasController.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Directions = __webpack_require__(/*! ../Organism/Directions */ \"./src/Organism/Directions.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\n\r\nclass EditorController extends CanvasController{\r\n constructor(env, canvas) {\r\n super(env, canvas);\r\n this.mode = Modes.None;\r\n this.edit_cell_type = null;\r\n this.highlight_org = false;\r\n this.new_species = false;\r\n this.defineCellTypeSelection();\r\n this.defineEditorDetails();\r\n }\r\n\r\n mouseMove() {\r\n if (this.right_click || this.left_click)\r\n this.editOrganism();\r\n }\r\n\r\n mouseDown() {\r\n this.editOrganism();\r\n }\r\n\r\n mouseUp(){}\r\n\r\n getCurLocalCell(){\r\n return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c, this.mouse_r-this.env.organism.r);\r\n }\r\n\r\n editOrganism() {\r\n if (this.edit_cell_type == null || this.mode != Modes.Edit)\r\n return;\r\n if (this.left_click){\r\n if(this.edit_cell_type == CellStates.eye && this.cur_cell.state == CellStates.eye) {\r\n var loc_cell = this.getCurLocalCell();\r\n loc_cell.direction = Directions.rotateRight(loc_cell.direction);\r\n this.env.renderFull();\r\n }\r\n else\r\n this.env.addCellToOrg(this.mouse_c, this.mouse_r, this.edit_cell_type);\r\n }\r\n else if (this.right_click)\r\n this.env.removeCellFromOrg(this.mouse_c, this.mouse_r);\r\n\r\n this.new_species = true;\r\n this.setBrainPanelVisibility();\r\n this.setMoveRangeVisibility();\r\n this.updateDetails();\r\n }\r\n\r\n updateDetails() {\r\n $('.cell-count').text(\"Cell count: \"+this.env.organism.anatomy.cells.length);\r\n }\r\n\r\n defineCellTypeSelection() {\r\n var self = this;\r\n $('.cell-type').click( function() {\r\n switch(this.id){\r\n case \"mouth\":\r\n self.edit_cell_type = CellStates.mouth;\r\n break;\r\n case \"producer\":\r\n self.edit_cell_type = CellStates.producer;\r\n break;\r\n case \"mover\":\r\n self.edit_cell_type = CellStates.mover;\r\n break;\r\n case \"killer\":\r\n self.edit_cell_type = CellStates.killer;\r\n break;\r\n case \"armor\":\r\n self.edit_cell_type = CellStates.armor;\r\n break;\r\n case \"eye\":\r\n self.edit_cell_type = CellStates.eye;\r\n break;\r\n }\r\n $(\".cell-type\" ).css( \"border-color\", \"black\" );\r\n var selected = '#'+this.id+'.cell-type';\r\n $(selected).css(\"border-color\", \"yellow\");\r\n });\r\n }\r\n\r\n defineEditorDetails() {\r\n this.details_html = $('#organism-details');\r\n this.edit_details_html = $('#edit-organism-details');\r\n\r\n this.decision_names = [\"ignore\", \"move away\", \"move towards\"];\r\n\r\n $('#move-range-edit').change ( function() {\r\n this.env.organism.move_range = parseInt($('#move-range-edit').val());\r\n }.bind(this));\r\n $('#observation-type-edit').change ( function() {\r\n this.setBrainEditorValues($('#observation-type-edit').val());\r\n this.setBrainDetails();\r\n }.bind(this));\r\n $('#reaction-edit').change ( function() {\r\n var obs = $('#observation-type-edit').val();\r\n var decision = parseInt($('#reaction-edit').val());\r\n this.env.organism.brain.decisions[obs] = decision;\r\n this.setBrainDetails();\r\n }.bind(this));\r\n }\r\n\r\n clearDetailsPanel() {\r\n $('#organism-details').css('display', 'none');\r\n $('#edit-organism-details').css('display', 'none');\r\n }\r\n\r\n setDetailsPanel() {\r\n this.clearDetailsPanel();\r\n var org = this.env.organism;\r\n \r\n $('.cell-count').text(\"Cell count: \"+org.anatomy.cells.length);\r\n $('#move-range').text(\"Move Range: \"+org.move_range);\r\n $('#mutation-rate').text(\"Mutation Rate: \"+org.mutability);\r\n if (Hyperparams.useGlobalMutability) {\r\n $('#mutation-rate').css('display', 'none');\r\n }\r\n else {\r\n $('#mutation-rate').css('display', 'block');\r\n }\r\n\r\n this.setMoveRangeVisibility();\r\n\r\n if (this.setBrainPanelVisibility()) {\r\n this.setBrainDetails();\r\n\r\n }\r\n $('#organism-details').css('display', 'block');\r\n }\r\n\r\n setEditorPanel() {\r\n this.clearDetailsPanel();\r\n var org = this.env.organism;\r\n\r\n $('.cell-count').text(\"Cell count: \"+org.anatomy.cells.length);\r\n if (this.setMoveRangeVisibility()){\r\n $('#move-range-edit').val(org.move_range);\r\n }\r\n \r\n if (this.setBrainPanelVisibility()){\r\n this.setBrainEditorValues($('#observation-type-edit').val());\r\n }\r\n\r\n $('#cell-selections').css('display', 'grid');\r\n $('#edit-organism-details').css('display', 'block');\r\n }\r\n\r\n setBrainPanelVisibility() {\r\n var org = this.env.organism;\r\n if (org.anatomy.has_eyes && org.anatomy.is_mover) {\r\n $('.brain-details').css('display', 'block');\r\n return true;\r\n }\r\n $('.brain-details').css('display', 'none');\r\n return false;\r\n }\r\n\r\n setBrainDetails() {\r\n var chase_types = [];\r\n var retreat_types = [];\r\n for(var cell_name in this.env.organism.brain.decisions) {\r\n var decision = this.env.organism.brain.decisions[cell_name];\r\n if (decision == 1) {\r\n retreat_types.push(cell_name)\r\n }\r\n else if (decision == 2) {\r\n chase_types.push(cell_name);\r\n }\r\n }\r\n $('.chase-types').text(\"Move Towards: \" + chase_types);\r\n $('.retreat-types').text(\"Move Away From: \" + retreat_types);\r\n }\r\n\r\n setMoveRangeVisibility() {\r\n var org = this.env.organism;\r\n if (org.anatomy.is_mover) {\r\n $('#move-range-cont').css('display', 'block');\r\n $('#move-range').css('display', 'block');\r\n return true;\r\n }\r\n $('#move-range-cont').css('display', 'none');\r\n $('#move-range').css('display', 'none');\r\n return false;\r\n }\r\n\r\n setBrainEditorValues(name) {\r\n $('#observation-type-edit').val(name);\r\n var reaction = this.env.organism.brain.decisions[name];\r\n $('#reaction-edit').val(reaction);\r\n }\r\n}\r\n\r\nmodule.exports = EditorController;\r\n\n\n//# sourceURL=webpack:///./src/Controllers/EditorController.js?"); - -/***/ }), - -/***/ "./src/Controllers/EnvironmentController.js": -/*!**************************************************!*\ - !*** ./src/Controllers/EnvironmentController.js ***! - \**************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CanvasController = __webpack_require__(/*! ./CanvasController */ \"./src/Controllers/CanvasController.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst Modes = __webpack_require__(/*! ./ControlModes */ \"./src/Controllers/ControlModes.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Neighbors = __webpack_require__(/*! ../Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass EnvironmentController extends CanvasController{\r\n constructor(env, canvas) {\r\n super(env, canvas);\r\n this.mode = Modes.Drag;\r\n this.org_to_clone = null;\r\n this.add_new_species = false;\r\n this.defineZoomControls();\r\n this.scale = 1;\r\n }\r\n\r\n defineZoomControls() {\r\n var scale = 1;\r\n var zoom_speed = 0.5;\r\n const el = document.querySelector('#env-canvas');\r\n el.onwheel = function zoom(event) {\r\n event.preventDefault();\r\n\r\n var sign = -Math.sign(event.deltaY);\r\n\r\n // Restrict scale\r\n scale = Math.max(0.5, this.scale+(sign*zoom_speed));\r\n\r\n if (scale != 0.5) {\r\n var cur_top = parseInt($('#env-canvas').css('top'));\r\n var cur_left = parseInt($('#env-canvas').css('left'));\r\n if (sign == 1) {\r\n // If we're zooming in, zoom towards wherever the mouse is\r\n var diff_x = ((this.canvas.width/2-cur_left/this.scale) - this.mouse_x)*this.scale/1.5;\r\n var diff_y = ((this.canvas.height/2-cur_top/this.scale) - this.mouse_y)*this.scale/1.5;\r\n }\r\n else {\r\n // If we're zooming out, zoom out towards the center\r\n var diff_x = -cur_left/scale;\r\n var diff_y = -cur_top/scale;\r\n }\r\n $('#env-canvas').css('top', (cur_top+diff_y)+'px');\r\n $('#env-canvas').css('left', (cur_left+diff_x)+'px');\r\n }\r\n \r\n // Apply scale transform\r\n el.style.transform = `scale(${scale})`;\r\n this.scale = scale;\r\n\r\n }.bind(this);\r\n }\r\n\r\n resetView() {\r\n $('#env-canvas').css('transform', 'scale(1)');\r\n $('#env-canvas').css('top', '0px');\r\n $('#env-canvas').css('left', '0px');\r\n this.scale = 1;\r\n }\r\n\r\n updateMouseLocation(offsetX, offsetY){\r\n \r\n super.updateMouseLocation(offsetX, offsetY);\r\n }\r\n\r\n mouseMove() {\r\n this.performModeAction();\r\n }\r\n\r\n mouseDown() {\r\n this.start_x = this.mouse_x;\r\n this.start_y = this.mouse_y;\r\n this.performModeAction();\r\n }\r\n\r\n mouseUp() {\r\n\r\n }\r\n\r\n performModeAction() {\r\n var mode = this.mode;\r\n var right_click = this.right_click;\r\n var left_click = this.left_click;\r\n if (mode != Modes.None && (right_click || left_click)) {\r\n var cell = this.cur_cell;\r\n if (cell == null){\r\n return;\r\n }\r\n switch(mode) {\r\n case Modes.FoodDrop:\r\n if (left_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.food, false);\r\n }\r\n else if (right_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.empty, false);\r\n }\r\n break;\r\n case Modes.WallDrop:\r\n if (left_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.wall, true);\r\n\r\n }\r\n else if (right_click){\r\n this.dropCellType(cell.col, cell.row, CellStates.empty, false);\r\n }\r\n break;\r\n case Modes.ClickKill:\r\n this.killNearOrganisms();\r\n break;\r\n\r\n case Modes.Select:\r\n if (this.cur_org == null) {\r\n this.cur_org = this.findNearOrganism();\r\n }\r\n if (this.cur_org != null){\r\n this.control_panel.setEditorOrganism(this.cur_org);\r\n }\r\n break;\r\n\r\n case Modes.Clone:\r\n if (this.org_to_clone != null){\r\n var new_org = new Organism(this.mouse_c, this.mouse_r, this.env, this.org_to_clone);\r\n if (this.add_new_species){\r\n FossilRecord.addSpeciesObj(new_org.species);\r\n new_org.species.start_tick = this.env.total_ticks;\r\n this.add_new_species = false;\r\n new_org.species.population = 0;\r\n }\r\n else if (this.org_to_clone.species.extinct){\r\n FossilRecord.resurrect(this.org_to_clone.species);\r\n }\r\n\r\n if (new_org.isClear(this.mouse_c, this.mouse_r)){\r\n this.env.addOrganism(new_org);\r\n new_org.species.addPop();\r\n }\r\n }\r\n break;\r\n case Modes.Drag:\r\n var cur_top = parseInt($('#env-canvas').css('top'), 10);\r\n var cur_left = parseInt($('#env-canvas').css('left'), 10);\r\n var new_top = cur_top + ((this.mouse_y - this.start_y)*this.scale);\r\n var new_left = cur_left + ((this.mouse_x - this.start_x)*this.scale);\r\n $('#env-canvas').css('top', new_top+'px');\r\n $('#env-canvas').css('left', new_left+'px');\r\n break;\r\n }\r\n }\r\n }\r\n\r\n dropCellType(col, row, state, killBlocking=false) {\r\n for (var loc of Neighbors.allSelf){\r\n var c=col + loc[0];\r\n var r=row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell == null)\r\n continue;\r\n if (killBlocking && cell.owner != null){\r\n cell.owner.die();\r\n }\r\n else if (cell.owner != null) {\r\n continue;\r\n }\r\n this.env.changeCell(c, r, state, null);\r\n }\r\n }\r\n\r\n findNearOrganism() {\r\n for (var loc of Neighbors.all){\r\n var c = this.cur_cell.col + loc[0];\r\n var r = this.cur_cell.row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell != null && cell.owner != null)\r\n return cell.owner;\r\n }\r\n return null;\r\n }\r\n\r\n killNearOrganisms() {\r\n for (var loc of Neighbors.allSelf){\r\n var c = this.cur_cell.col + loc[0];\r\n var r = this.cur_cell.row + loc[1];\r\n var cell = this.env.grid_map.cellAt(c, r);\r\n if (cell != null && cell.owner != null)\r\n cell.owner.die();\r\n }\r\n }\r\n\r\n\r\n}\r\n\r\nmodule.exports = EnvironmentController;\r\n\n\n//# sourceURL=webpack:///./src/Controllers/EnvironmentController.js?"); - -/***/ }), - -/***/ "./src/Controllers/StatsPanel.js": -/*!***************************************!*\ - !*** ./src/Controllers/StatsPanel.js ***! - \***************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass StatsPanel {\r\n constructor() {\r\n this.defineControls();\r\n this.clearData();\r\n this.last_update_tick = 0;\r\n this.update_every = 100;\r\n\r\n // maps species to their index in chart's data storage\r\n this.species_index_map = [];\r\n this.index_counter = 0;\r\n this.min_display = 10;\r\n }\r\n\r\n startAutoRender(){\r\n this.render_loop = setInterval(function(){this.render();}.bind(this), 1000);\r\n }\r\n\r\n stopAutoRender() {\r\n clearInterval(this.render_loop);\r\n }\r\n\r\n defineControls() {\r\n $('#update-chart').click( function() {\r\n this.render();\r\n }.bind(this));\r\n }\r\n\r\n updateData(tick, population_size) {\r\n if (tick - this.last_update_tick >= this.update_every){\r\n // this.data[0].dataPoints.push({x: tick, y:population_size});\r\n this.last_update_tick = tick;\r\n\r\n for (var species of FossilRecord.extant_species) {\r\n if (species.cumulative_pop < this.min_display){\r\n continue;\r\n }\r\n \r\n if (this.species_index_map[species.name] == null) {\r\n console.log(\"new species\")\r\n this.species_index_map[species.name] = this.index_counter;\r\n this.index_counter++;\r\n this.data.push({\r\n type: \"line\",\r\n markerType: \"none\",\r\n dataPoints: []\r\n });\r\n }\r\n var data_index = this.species_index_map[species.name];\r\n this.data[data_index].dataPoints.push({x:tick, y:species.population});\r\n }\r\n }\r\n }\r\n \r\n render() {\r\n this.chart.render();\r\n }\r\n\r\n clearData() {\r\n this.data = [{\r\n type: \"line\",\r\n markerType: \"none\",\r\n dataPoints: []\r\n }];\r\n this.chart = new CanvasJS.Chart(\"chartContainer\", {\r\n title:{\r\n text: \"Population\" \r\n },\r\n data: this.data\r\n });\r\n this.render();\r\n }\r\n \r\n}\r\n\r\nmodule.exports = StatsPanel;\n\n//# sourceURL=webpack:///./src/Controllers/StatsPanel.js?"); - -/***/ }), - -/***/ "./src/Engine.js": -/*!***********************!*\ - !*** ./src/Engine.js ***! - \***********************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const WorldEnvironment = __webpack_require__(/*! ./Environments/WorldEnvironment */ \"./src/Environments/WorldEnvironment.js\");\r\nconst ControlPanel = __webpack_require__(/*! ./Controllers/ControlPanel */ \"./src/Controllers/ControlPanel.js\");\r\nconst OrganismEditor = __webpack_require__(/*! ./Environments/OrganismEditor */ \"./src/Environments/OrganismEditor.js\");\r\nconst ColorScheme = __webpack_require__(/*! ./Rendering/ColorScheme */ \"./src/Rendering/ColorScheme.js\");\r\n\r\nconst render_speed = 60;\r\n\r\nclass Engine{\r\n constructor(){\r\n this.fps = 60;\r\n this.env = new WorldEnvironment(5);\r\n this.organism_editor = new OrganismEditor();\r\n this.controlpanel = new ControlPanel(this);\r\n this.colorscheme = new ColorScheme(this.env, this.organism_editor);\r\n this.colorscheme.loadColorScheme();\r\n this.env.OriginOfLife();\r\n this.last_update = Date.now();\r\n this.delta_time = 0;\r\n this.actual_fps = 0;\r\n this.running = false;\r\n }\r\n\r\n start(fps=60) {\r\n if (fps <= 0)\r\n fps = 1;\r\n if (fps > 300)\r\n fps = 300;\r\n this.fps = fps;\r\n this.game_loop = setInterval(function(){this.environmentUpdate();}.bind(this), 1000/fps);\r\n this.running = true;\r\n if (this.fps >= render_speed) {\r\n if (this.render_loop != null) {\r\n clearInterval(this.render_loop);\r\n this.render_loop = null;\r\n }\r\n }\r\n else\r\n this.setRenderLoop();\r\n }\r\n \r\n stop() {\r\n clearInterval(this.game_loop);\r\n this.running = false;\r\n this.setRenderLoop();\r\n }\r\n\r\n setRenderLoop() {\r\n if (this.render_loop == null) {\r\n this.render_loop = setInterval(function(){this.necessaryUpdate();}.bind(this), 1000/render_speed);\r\n }\r\n }\r\n\r\n\r\n environmentUpdate() {\r\n this.delta_time = Date.now() - this.last_update;\r\n this.last_update = Date.now();\r\n this.env.update(this.delta_time);\r\n this.actual_fps = 1/this.delta_time*1000;\r\n if(this.render_loop == null){\r\n this.necessaryUpdate();\r\n }\r\n \r\n }\r\n\r\n necessaryUpdate() {\r\n this.env.render();\r\n this.controlpanel.update();\r\n this.organism_editor.update();\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Engine;\r\n\n\n//# sourceURL=webpack:///./src/Engine.js?"); - -/***/ }), - -/***/ "./src/Environments/Environment.js": -/*!*****************************************!*\ - !*** ./src/Environments/Environment.js ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("\r\n//An evironment has a grid_map, controller, and renderer\r\nclass Environment{\r\n constructor() {\r\n }\r\n\r\n update(){\r\n alert(\"Environment.update() must be overriden\");\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n this.grid_map.setCellType(c, r, state);\r\n this.grid_map.setCellOwner(c, r, owner);\r\n }\r\n}\r\n\r\n\r\nmodule.exports = Environment;\n\n//# sourceURL=webpack:///./src/Environments/Environment.js?"); - -/***/ }), - -/***/ "./src/Environments/OrganismEditor.js": -/*!********************************************!*\ - !*** ./src/Environments/OrganismEditor.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environments/Environment.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst GridMap = __webpack_require__(/*! ../Grid/GridMap */ \"./src/Grid/GridMap.js\");\r\nconst Renderer = __webpack_require__(/*! ../Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst EditorController = __webpack_require__(/*! ../Controllers/EditorController */ \"./src/Controllers/EditorController.js\");\r\nconst Species = __webpack_require__(/*! ../Stats/Species */ \"./src/Stats/Species.js\");\r\n\r\nclass OrganismEditor extends Environment{\r\n constructor() {\r\n super();\r\n this.is_active = true;\r\n var cell_size = 13;\r\n this.renderer = new Renderer('editor-canvas', 'editor-env', cell_size);\r\n this.controller = new EditorController(this, this.renderer.canvas);\r\n this.grid_map = new GridMap(15, 15, cell_size);\r\n this.clear();\r\n }\r\n\r\n update() {\r\n if (this.is_active){\r\n this.renderer.renderHighlights();\r\n }\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n super.changeCell(c, r, state, owner);\r\n this.renderFull();\r\n }\r\n\r\n renderFull() {\r\n this.renderer.renderFullGrid(this.grid_map.grid);\r\n }\r\n\r\n // absolute c r, not local\r\n addCellToOrg(c, r, state) {\r\n var center = this.grid_map.getCenter();\r\n var loc_c = c - center[0];\r\n var loc_r = r - center[1];\r\n var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)\r\n if (prev_cell != null) {\r\n var new_cell = this.organism.anatomy.replaceCell(state, prev_cell.loc_col, prev_cell.loc_row, false);\r\n this.changeCell(c, r, state, new_cell);\r\n }\r\n else if (this.organism.anatomy.canAddCellAt(loc_c, loc_r)){\r\n this.changeCell(c, r, state, this.organism.anatomy.addDefaultCell(state, loc_c, loc_r));\r\n }\r\n this.organism.species = new Species(this.organism.anatomy, null, 0);\r\n }\r\n\r\n removeCellFromOrg(c, r) {\r\n var center = this.grid_map.getCenter();\r\n var loc_c = c - center[0];\r\n var loc_r = r - center[1];\r\n if (loc_c == 0 && loc_r == 0){\r\n alert(\"Cannot remove center cell\");\r\n return;\r\n }\r\n var prev_cell = this.organism.anatomy.getLocalCell(loc_c, loc_r)\r\n if (prev_cell != null) {\r\n if (this.organism.anatomy.removeCell(loc_c, loc_r)) {\r\n this.changeCell(c, r, CellStates.empty, null);\r\n this.organism.species = new Species(this.organism.anatomy, null, 0);\r\n }\r\n }\r\n }\r\n\r\n setOrganismToCopyOf(orig_org) {\r\n this.grid_map.fillGrid(CellStates.empty);\r\n var center = this.grid_map.getCenter();\r\n this.organism = new Organism(center[0], center[1], this, orig_org);\r\n this.organism.updateGrid();\r\n this.controller.updateDetails();\r\n this.controller.new_species = false;\r\n }\r\n \r\n getCopyOfOrg() {\r\n var new_org = new Organism(0, 0, null, this.organism);\r\n return new_org;\r\n }\r\n\r\n clear() {\r\n this.grid_map.fillGrid(CellStates.empty);\r\n var center = this.grid_map.getCenter();\r\n this.organism = new Organism(center[0], center[1], this, null);\r\n this.organism.anatomy.addDefaultCell(CellStates.mouth, 0, 0);\r\n this.organism.updateGrid();\r\n this.organism.species = new Species(this.organism.anatomy, null, 0);\r\n }\r\n}\r\n\r\nmodule.exports = OrganismEditor;\n\n//# sourceURL=webpack:///./src/Environments/OrganismEditor.js?"); - -/***/ }), - -/***/ "./src/Environments/WorldEnvironment.js": -/*!**********************************************!*\ - !*** ./src/Environments/WorldEnvironment.js ***! - \**********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environments/Environment.js\");\r\nconst Renderer = __webpack_require__(/*! ../Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst GridMap = __webpack_require__(/*! ../Grid/GridMap */ \"./src/Grid/GridMap.js\");\r\nconst Organism = __webpack_require__(/*! ../Organism/Organism */ \"./src/Organism/Organism.js\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst EnvironmentController = __webpack_require__(/*! ../Controllers/EnvironmentController */ \"./src/Controllers/EnvironmentController.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters.js */ \"./src/Hyperparameters.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass WorldEnvironment extends Environment{\r\n constructor(cell_size) {\r\n super();\r\n this.renderer = new Renderer('env-canvas', 'env', cell_size);\r\n this.controller = new EnvironmentController(this, this.renderer.canvas);\r\n var grid_rows = Math.floor(this.renderer.height / cell_size);\r\n var grid_cols = Math.floor(this.renderer.width / cell_size);\r\n this.grid_map = new GridMap(grid_cols, grid_rows, cell_size);\r\n this.organisms = [];\r\n this.walls = [];\r\n this.total_mutability = 0;\r\n this.auto_reset = true;\r\n this.largest_cell_count = 0;\r\n this.reset_count = 0;\r\n this.total_ticks = 0;\r\n FossilRecord.setEnv(this);\r\n }\r\n\r\n update(delta_time) {\r\n this.total_ticks ++;\r\n var to_remove = [];\r\n for (var i in this.organisms) {\r\n var org = this.organisms[i];\r\n if (!org.living || !org.update()) {\r\n to_remove.push(i);\r\n }\r\n }\r\n if (Hyperparams.foodDropProb > 0) {\r\n this.generateFood();\r\n }\r\n this.removeOrganisms(to_remove);\r\n }\r\n\r\n render() {\r\n this.renderer.renderCells();\r\n this.renderer.renderHighlights();\r\n }\r\n\r\n removeOrganisms(org_indeces) {\r\n for (var i of org_indeces.reverse()){\r\n this.total_mutability -= this.organisms[i].mutability;\r\n this.organisms.splice(i, 1);\r\n }\r\n if (this.organisms.length == 0 && this.auto_reset){\r\n this.reset_count++;\r\n this.reset();\r\n }\r\n }\r\n\r\n OriginOfLife() {\r\n var center = this.grid_map.getCenter();\r\n var org = new Organism(center[0], center[1], this);\r\n org.anatomy.addDefaultCell(CellStates.mouth, 0, 0);\r\n org.anatomy.addDefaultCell(CellStates.producer, 1, 1);\r\n org.anatomy.addDefaultCell(CellStates.producer, -1, -1);\r\n this.addOrganism(org);\r\n FossilRecord.addSpecies(org, null);\r\n }\r\n\r\n addOrganism(organism) {\r\n organism.updateGrid();\r\n this.total_mutability += organism.mutability;\r\n this.organisms.push(organism);\r\n if (organism.anatomy.cells.length > this.largest_cell_count) \r\n this.largest_cell_count = organism.anatomy.cells.length;\r\n }\r\n\r\n averageMutability() {\r\n if (this.organisms.length < 1)\r\n return 0;\r\n return this.total_mutability / this.organisms.length;\r\n }\r\n\r\n changeCell(c, r, state, owner) {\r\n super.changeCell(c, r, state, owner);\r\n this.renderer.addToRender(this.grid_map.cellAt(c, r));\r\n if(state == CellStates.wall)\r\n this.walls.push(this.grid_map.cellAt(c, r));\r\n }\r\n\r\n clearWalls() {\r\n for(var wall of this.walls){\r\n if (this.grid_map.cellAt(wall.col, wall.row).state == CellStates.wall)\r\n this.changeCell(wall.col, wall.row, CellStates.empty, null);\r\n }\r\n }\r\n\r\n clearOrganisms() {\r\n for (var org of this.organisms)\r\n org.die();\r\n this.organisms = [];\r\n }\r\n\r\n generateFood() {\r\n var num_food = Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*Hyperparams.foodDropProb/50000), 1)\r\n var prob = Hyperparams.foodDropProb;\r\n for (var i=0; i=0 && row>=0;\r\n }\r\n\r\n getCenter(){\r\n return [Math.floor(this.cols/2), Math.floor(this.rows/2)]\r\n }\r\n\r\n xyToColRow(x, y) {\r\n var c = Math.floor(x/this.cell_size);\r\n var r = Math.floor(y/this.cell_size);\r\n if (c >= this.cols)\r\n c = this.cols-1;\r\n else if (c < 0)\r\n c = 0;\r\n if (r >= this.rows)\r\n r = this.rows-1;\r\n else if (r < 0)\r\n r = 0;\r\n return [c, r];\r\n }\r\n}\r\n\r\nmodule.exports = GridMap;\r\n\n\n//# sourceURL=webpack:///./src/Grid/GridMap.js?"); - -/***/ }), - -/***/ "./src/Grid/Neighbors.js": -/*!*******************************!*\ - !*** ./src/Grid/Neighbors.js ***! - \*******************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("// contains local cell values for the following:\r\n\r\n//all ...\r\n// .x.\r\n// ...\r\n\r\n//adjacent .\r\n// .x.\r\n// .\r\n\r\n//corners . .\r\n// x\r\n// . .\r\n\r\n//allSelf ...\r\n// ...\r\n// ...\r\n\r\nconst Neighbors = {\r\n all: [[0, 1],[0, -1],[1, 0],[-1, 0],[-1, -1],[1, 1],[-1, 1],[1, -1]],\r\n adjacent: [[0, 1],[0, -1],[1, 0],[-1, 0]],\r\n corners: [[-1, -1],[1, 1],[-1, 1],[1, -1]],\r\n allSelf: [[0, 0],[0, 1],[0, -1],[1, 0],[-1, 0],[-1, -1],[1, 1],[-1, 1],[1, -1]]\r\n}\r\n\r\nmodule.exports = Neighbors;\n\n//# sourceURL=webpack:///./src/Grid/Neighbors.js?"); - -/***/ }), - -/***/ "./src/Hyperparameters.js": -/*!********************************!*\ - !*** ./src/Hyperparameters.js ***! - \********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Neighbors = __webpack_require__(/*! ./Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\n\r\nconst Hyperparams = {\r\n setDefaults: function() {\r\n this.lifespanMultiplier = 100;\r\n this.foodProdProb = 4;\r\n this.foodProdProbScalar = 4;\r\n this.killableNeighbors = Neighbors.adjacent;\r\n this.edibleNeighbors = Neighbors.adjacent;\r\n this.growableNeighbors = Neighbors.adjacent;\r\n\r\n this.useGlobalMutability = false;\r\n this.globalMutability = 5;\r\n this.addProb = 33;\r\n this.changeProb = 33;\r\n this.removeProb = 33;\r\n \r\n this.moversCanRotate = true;\r\n this.offspringRotate = true;\r\n\r\n this.foodBlocksReproduction = true;\r\n this.moversCanProduce = false;\r\n\r\n this.instaKill = false;\r\n\r\n this.lookRange = 20;\r\n\r\n this.foodDropProb = 0;\r\n },\r\n\r\n balanceMutationProbs : function(choice) {\r\n if (choice == 1) {\r\n var remaining = 100 - this.addProb;\r\n this.changeProb = remaining/2;\r\n this.removeProb = remaining/2;\r\n }\r\n else if (choice == 2) {\r\n var remaining = 100 - this.changeProb;\r\n this.addProb = remaining/2;\r\n this.removeProb = remaining/2;\r\n }\r\n else {\r\n var remaining = 100 - this.removeProb;\r\n this.changeProb = remaining/2;\r\n this.addProb = remaining/2;\r\n }\r\n }\r\n}\r\n\r\nHyperparams.setDefaults();\r\n\r\nmodule.exports = Hyperparams;\n\n//# sourceURL=webpack:///./src/Hyperparameters.js?"); - -/***/ }), - -/***/ "./src/Organism/Anatomy.js": -/*!*********************************!*\ - !*** ./src/Organism/Anatomy.js ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CellStates = __webpack_require__(/*! ./Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst BodyCellFactory = __webpack_require__(/*! ./Cell/BodyCells/BodyCellFactory */ \"./src/Organism/Cell/BodyCells/BodyCellFactory.js\");\r\n\r\nclass Anatomy {\r\n constructor(owner) {\r\n this.owner = owner;\r\n this.cells = [];\r\n this.is_producer = false;\r\n this.is_mover = false;\r\n this.has_eyes = false;\r\n this.birth_distance = 4;\r\n }\r\n\r\n canAddCellAt(c, r) {\r\n for (var cell of this.cells) {\r\n if (cell.loc_col == c && cell.loc_row == r){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n addDefaultCell(state, c, r) {\r\n var new_cell = BodyCellFactory.createDefault(this.owner, state, c, r);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n addRandomizedCell(state, c, r) {\r\n if (state==CellStates.eye && !this.has_eyes) {\r\n this.owner.brain.randomizeDecisions();\r\n }\r\n var new_cell = BodyCellFactory.createRandom(this.owner, state, c, r);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n addInheritCell(parent_cell) {\r\n var new_cell = BodyCellFactory.createInherited(this.owner, parent_cell);\r\n this.cells.push(new_cell);\r\n return new_cell;\r\n }\r\n\r\n replaceCell(state, c, r, randomize=true) {\r\n this.removeCell(c, r, true);\r\n if (randomize) {\r\n return this.addRandomizedCell(state, c, r);\r\n }\r\n else {\r\n return this.addDefaultCell(state, c, r);\r\n }\r\n }\r\n\r\n removeCell(c, r, allow_center_removal=false) {\r\n if (c == 0 && r == 0 && !allow_center_removal)\r\n return false;\r\n for (var i=0; i 3)\r\n dir -= 4;\r\n return dir;\r\n }\r\n\r\n performFunction() {\r\n var obs = this.look();\r\n this.org.brain.observe(obs);\r\n }\r\n\r\n look() {\r\n var env = this.org.env;\r\n var direction = this.getAbsoluteDirection();\r\n var addCol = 0;\r\n var addRow = 0;\r\n switch(direction) {\r\n case Directions.up:\r\n addRow = -1;\r\n break;\r\n case Directions.down:\r\n addRow = 1;\r\n break;\r\n case Directions.right:\r\n addCol = 1;\r\n break;\r\n case Directions.left:\r\n addCol = -1;\r\n break;\r\n }\r\n var start_col = this.getRealCol();\r\n var start_row = this.getRealRow();\r\n var col = start_col;\r\n var row = start_row;\r\n var cell = null;\r\n for (var i=0; i 3){\r\n dir = 0;\r\n }\r\n return dir;\r\n }\r\n}\r\n\r\nmodule.exports = Directions;\n\n//# sourceURL=webpack:///./src/Organism/Directions.js?"); - -/***/ }), - -/***/ "./src/Organism/Organism.js": -/*!**********************************!*\ - !*** ./src/Organism/Organism.js ***! - \**********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CellStates = __webpack_require__(/*! ./Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Neighbors = __webpack_require__(/*! ../Grid/Neighbors */ \"./src/Grid/Neighbors.js\");\r\nconst Hyperparams = __webpack_require__(/*! ../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Directions = __webpack_require__(/*! ./Directions */ \"./src/Organism/Directions.js\");\r\nconst Anatomy = __webpack_require__(/*! ./Anatomy */ \"./src/Organism/Anatomy.js\");\r\nconst Brain = __webpack_require__(/*! ./Perception/Brain */ \"./src/Organism/Perception/Brain.js\");\r\nconst FossilRecord = __webpack_require__(/*! ../Stats/FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n\r\nclass Organism {\r\n constructor(col, row, env, parent=null) {\r\n this.c = col;\r\n this.r = row;\r\n this.env = env;\r\n this.lifetime = 0;\r\n this.food_collected = 0;\r\n this.living = true;\r\n this.anatomy = new Anatomy(this)\r\n this.direction = Directions.down; // direction of movement\r\n this.rotation = Directions.up; // direction of rotation\r\n this.can_rotate = Hyperparams.moversCanRotate;\r\n this.move_count = 0;\r\n this.move_range = 4;\r\n this.ignore_brain_for = 0;\r\n this.mutability = 5;\r\n this.damage = 0;\r\n this.brain = new Brain(this);\r\n if (parent != null) {\r\n this.inherit(parent);\r\n }\r\n }\r\n\r\n inherit(parent) {\r\n this.move_range = parent.move_range;\r\n this.mutability = parent.mutability;\r\n this.species = parent.species;\r\n // this.birth_distance = parent.birth_distance;\r\n for (var c of parent.anatomy.cells){\r\n //deep copy parent cells\r\n this.anatomy.addInheritCell(c);\r\n }\r\n if(parent.anatomy.is_mover) {\r\n for (var i in parent.brain.decisions) {\r\n this.brain.decisions[i] = parent.brain.decisions[i];\r\n }\r\n }\r\n }\r\n\r\n // amount of food required before it can reproduce\r\n foodNeeded() {\r\n return this.anatomy.cells.length;\r\n }\r\n\r\n lifespan() {\r\n // console.log(Hyperparams.lifespanMultiplier)\r\n return this.anatomy.cells.length * Hyperparams.lifespanMultiplier;\r\n }\r\n\r\n maxHealth() {\r\n return this.anatomy.cells.length;\r\n }\r\n\r\n reproduce() {\r\n //produce mutated child\r\n //check nearby locations (is there room and a direct path)\r\n var org = new Organism(0, 0, this.env, this);\r\n if(Hyperparams.offspringRotate){\r\n org.rotation = Directions.getRandomDirection();\r\n }\r\n var prob = this.mutability;\r\n if (Hyperparams.useGlobalMutability){\r\n prob = Hyperparams.globalMutability;\r\n }\r\n else {\r\n //mutate the mutability\r\n if (Math.random() <= 0.5)\r\n org.mutability++;\r\n else{ \r\n org.mutability--;\r\n if (org.mutability < 1)\r\n org.mutability = 1;\r\n }\r\n } \r\n var mutated = false;\r\n if (Math.random() * 100 <= prob) {\r\n if (org.anatomy.is_mover && Math.random() * 100 <= 10) { \r\n if (org.anatomy.has_eyes) {\r\n org.brain.mutate();\r\n }\r\n org.move_range += Math.floor(Math.random() * 4) - 2;\r\n if (org.move_range <= 0){\r\n org.move_range = 1;\r\n };\r\n \r\n }\r\n else {\r\n mutated = org.mutate();\r\n }\r\n }\r\n\r\n var direction = Directions.getRandomScalar();\r\n var direction_c = direction[0];\r\n var direction_r = direction[1];\r\n var offset = (Math.floor(Math.random() * 3));\r\n var basemovement = this.anatomy.birth_distance;\r\n var new_c = this.c + (direction_c*basemovement) + (direction_c*offset);\r\n var new_r = this.r + (direction_r*basemovement) + (direction_r*offset);\r\n\r\n // console.log(org.isClear(new_c, new_r, org.rotation, true))\r\n if (org.isClear(new_c, new_r, org.rotation, true) && org.isStraightPath(new_c, new_r, this.c, this.r, this)){\r\n org.c = new_c;\r\n org.r = new_r;\r\n this.env.addOrganism(org);\r\n org.updateGrid();\r\n if (mutated) {\r\n FossilRecord.addSpecies(org, this.species);\r\n }\r\n else {\r\n org.species.addPop();\r\n }\r\n }\r\n this.food_collected -= this.foodNeeded();\r\n\r\n }\r\n\r\n mutate() {\r\n var choice = Math.floor(Math.random() * 100);\r\n var mutated = false;\r\n if (choice <= Hyperparams.addProb) {\r\n // add cell\r\n // console.log(\"add cell\")\r\n\r\n var branch = this.anatomy.getRandomCell();\r\n var state = CellStates.getRandomLivingType();//branch.state;\r\n var growth_direction = Neighbors.all[Math.floor(Math.random() * Neighbors.all.length)]\r\n var c = branch.loc_col+growth_direction[0];\r\n var r = branch.loc_row+growth_direction[1];\r\n if (this.anatomy.canAddCellAt(c, r)){\r\n mutated = true;\r\n this.anatomy.addRandomizedCell(state, c, r);\r\n }\r\n }\r\n else if (choice <= Hyperparams.addProb + Hyperparams.changeProb){\r\n // change cell\r\n var cell = this.anatomy.getRandomCell();\r\n var state = CellStates.getRandomLivingType();\r\n // console.log(\"change cell\", state)\r\n this.anatomy.replaceCell(state, cell.loc_col, cell.loc_row);\r\n mutated = true;\r\n }\r\n else if (choice <= Hyperparams.addProb + Hyperparams.changeProb + Hyperparams.removeProb){\r\n // remove cell\r\n // console.log(\"remove cell\")\r\n\r\n if(this.anatomy.cells.length > 1) {\r\n var cell = this.anatomy.getRandomCell();\r\n mutated = this.anatomy.removeCell(cell.loc_col, cell.loc_row);\r\n }\r\n }\r\n return mutated;\r\n }\r\n\r\n attemptMove() {\r\n var direction = Directions.scalars[this.direction];\r\n var direction_c = direction[0];\r\n var direction_r = direction[1];\r\n var new_c = this.c + direction_c;\r\n var new_r = this.r + direction_r;\r\n if (this.isClear(new_c, new_r)) {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.empty, null);\r\n }\r\n this.c = new_c;\r\n this.r = new_r;\r\n this.updateGrid();\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n attemptRotate() {\r\n if(!this.can_rotate){\r\n this.direction = Directions.getRandomDirection();\r\n this.move_count = 0;\r\n return true;\r\n }\r\n var new_rotation = Directions.getRandomDirection();\r\n if(this.isClear(this.c, this.r, new_rotation)){\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.empty, null);\r\n }\r\n this.rotation = new_rotation;\r\n this.direction = Directions.getRandomDirection();\r\n this.updateGrid();\r\n this.move_count = 0;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n changeDirection(dir) {\r\n this.direction = dir;\r\n this.move_count = 0;\r\n }\r\n\r\n // assumes either c1==c2 or r1==r2, returns true if there is a clear path from point 1 to 2\r\n isStraightPath(c1, r1, c2, r2, parent){\r\n if (c1 == c2) {\r\n if (r1 > r2){\r\n var temp = r2;\r\n r2 = r1;\r\n r1 = temp;\r\n }\r\n for (var i=r1; i!=r2; i++) {\r\n var cell = this.env.grid_map.cellAt(c1, i)\r\n if (!this.isPassableCell(cell, parent)){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n else {\r\n if (c1 > c2){\r\n var temp = c2;\r\n c2 = c1;\r\n c1 = temp;\r\n }\r\n for (var i=c1; i!=c2; i++) {\r\n var cell = this.env.grid_map.cellAt(i, r1);\r\n if (!this.isPassableCell(cell, parent)){\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n }\r\n\r\n isPassableCell(cell, parent){\r\n return cell != null && (cell.state == CellStates.empty || cell.owner == this || cell.owner == parent || cell.state == CellStates.food);\r\n }\r\n\r\n isClear(col, row, rotation=this.rotation, ignore_armor=false) {\r\n for(var loccell of this.anatomy.cells) {\r\n var cell = this.getRealCell(loccell, col, row, rotation);\r\n if (cell==null) {\r\n return false;\r\n }\r\n // console.log(cell.owner == this)\r\n if (cell.owner==this || cell.state==CellStates.empty || (!Hyperparams.foodBlocksReproduction && cell.state==CellStates.food) || (ignore_armor && loccell.state==CellStates.armor && cell.state==CellStates.food)){\r\n continue;\r\n }\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n harm() {\r\n this.damage++;\r\n if (this.damage >= this.maxHealth() || Hyperparams.instaKill) {\r\n this.die();\r\n }\r\n }\r\n\r\n die() {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, CellStates.food, null);\r\n }\r\n this.species.decreasePop();\r\n this.living = false;\r\n }\r\n\r\n updateGrid() {\r\n for (var cell of this.anatomy.cells) {\r\n var real_c = this.c + cell.rotatedCol(this.rotation);\r\n var real_r = this.r + cell.rotatedRow(this.rotation);\r\n this.env.changeCell(real_c, real_r, cell.state, cell);\r\n }\r\n }\r\n\r\n update() {\r\n this.lifetime++;\r\n if (this.lifetime > this.lifespan()) {\r\n this.die();\r\n return this.living;\r\n }\r\n if (this.food_collected >= this.foodNeeded()) {\r\n this.reproduce();\r\n }\r\n for (var cell of this.anatomy.cells) {\r\n cell.performFunction();\r\n if (!this.living)\r\n return this.living\r\n }\r\n \r\n if (this.anatomy.is_mover) {\r\n this.move_count++;\r\n var changed_dir = false;\r\n if (this.ignore_brain_for == 0){\r\n changed_dir = this.brain.decide();\r\n } \r\n else{\r\n this.ignore_brain_for --;\r\n }\r\n var moved = this.attemptMove();\r\n if ((this.move_count > this.move_range && !changed_dir) || !moved){\r\n var rotated = this.attemptRotate();\r\n if (!rotated) {\r\n this.changeDirection(Directions.getRandomDirection());\r\n if (changed_dir)\r\n this.ignore_brain_for = this.move_range + 1;\r\n }\r\n }\r\n }\r\n\r\n return this.living;\r\n }\r\n\r\n getRealCell(local_cell, c=this.c, r=this.r, rotation=this.rotation){\r\n var real_c = c + local_cell.rotatedCol(rotation);\r\n var real_r = r + local_cell.rotatedRow(rotation);\r\n return this.env.grid_map.cellAt(real_c, real_r);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Organism;\r\n\n\n//# sourceURL=webpack:///./src/Organism/Organism.js?"); - -/***/ }), - -/***/ "./src/Organism/Perception/Brain.js": -/*!******************************************!*\ - !*** ./src/Organism/Perception/Brain.js ***! - \******************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Hyperparams = __webpack_require__(/*! ../../Hyperparameters */ \"./src/Hyperparameters.js\");\r\nconst Directions = __webpack_require__(/*! ../Directions */ \"./src/Organism/Directions.js\");\r\nconst CellStates = __webpack_require__(/*! ../Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\n\r\nconst Decision = {\r\n neutral: 0,\r\n retreat: 1,\r\n chase: 2,\r\n getRandom: function(){\r\n return Math.floor(Math.random() * 3);\r\n },\r\n getRandomNonNeutral: function() {\r\n return Math.floor(Math.random() * 2)+1;\r\n }\r\n}\r\n\r\nclass Brain {\r\n constructor(owner){\r\n this.owner = owner;\r\n this.observations = [];\r\n\r\n // corresponds to CellTypes\r\n this.decisions = [];\r\n this.decisions[CellStates.empty.name] = Decision.neutral;\r\n this.decisions[CellStates.food.name] = Decision.chase;\r\n this.decisions[CellStates.wall.name] = Decision.neutral;\r\n this.decisions[CellStates.mouth.name] = Decision.neutral;\r\n this.decisions[CellStates.producer.name] = Decision.neutral;\r\n this.decisions[CellStates.mover.name] = Decision.neutral;\r\n this.decisions[CellStates.killer.name] = Decision.retreat;\r\n this.decisions[CellStates.armor.name] = Decision.neutral;\r\n this.decisions[CellStates.eye.name] = Decision.neutral;\r\n }\r\n\r\n randomizeDecisions() {\r\n // randomize the non obvious decisions\r\n this.decisions[CellStates.mouth.name] = Decision.getRandom();\r\n this.decisions[CellStates.producer.name] = Decision.getRandom();\r\n this.decisions[CellStates.mover.name] = Decision.getRandom();\r\n this.decisions[CellStates.armor.name] = Decision.getRandom();\r\n this.decisions[CellStates.eye.name] = Decision.getRandom();\r\n }\r\n\r\n observe(observation) {\r\n this.observations.push(observation);\r\n }\r\n\r\n decide() {\r\n var decision = Decision.neutral;\r\n var closest = Hyperparams.lookRange + 1;\r\n var move_direction = 0;\r\n for (var obs of this.observations) {\r\n if (obs.cell == null || obs.cell.owner == this.owner) {\r\n continue;\r\n }\r\n if (obs.distance < closest) {\r\n // console.log(obs.cell.state)\r\n decision = this.decisions[obs.cell.state.name];\r\n // console.log(decision)\r\n move_direction = obs.direction;\r\n closest = obs.distance;\r\n }\r\n }\r\n this.observations = [];\r\n if (decision == Decision.chase) {\r\n this.owner.changeDirection(move_direction);\r\n return true;\r\n }\r\n else if (decision == Decision.retreat) {\r\n this.owner.changeDirection(Directions.getOppositeDirection(move_direction));\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n mutate() {\r\n this.decisions[CellStates.getRandomName()] = Decision.getRandom();\r\n this.decisions[CellStates.empty.name] = Decision.neutral; // if the empty cell has a decision it gets weird\r\n }\r\n}\r\n\r\nmodule.exports = Brain;\n\n//# sourceURL=webpack:///./src/Organism/Perception/Brain.js?"); - -/***/ }), - -/***/ "./src/Organism/Perception/Observation.js": -/*!************************************************!*\ - !*** ./src/Organism/Perception/Observation.js ***! - \************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("class Observation {\r\n constructor(cell, distance, direction){\r\n this.cell = cell;\r\n this.distance = distance;\r\n this.direction = direction;\r\n }\r\n}\r\n\r\nmodule.exports = Observation;\n\n//# sourceURL=webpack:///./src/Organism/Perception/Observation.js?"); - -/***/ }), - -/***/ "./src/Rendering/ColorScheme.js": -/*!**************************************!*\ - !*** ./src/Rendering/ColorScheme.js ***! - \**************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\n\r\nvar color_scheme = {\r\n \"empty\":\"#0E1318\",\r\n \"food\":\"#2F7AB7\",\r\n \"wall\":\"gray\",\r\n \"mouth\":\"#DEB14D\",\r\n \"producer\":\"#15DE59\",\r\n \"mover\":\"#60D4FF\",\r\n \"killer\":\"#F82380\",\r\n \"armor\":\"#7230DB\",\r\n \"eye\":\"#B6C1EA\",\r\n \"eye-slit\": \"#0E1318\"\r\n}\r\n\r\n// Renderer controls access to a canvas. There is one renderer for each canvas\r\nclass ColorScheme {\r\n constructor(world_env, editor_env) {\r\n this.world_env = world_env;\r\n this.editor_env = editor_env;\r\n }\r\n\r\n loadColorScheme() {\r\n for (var state of CellStates.all) {\r\n state.color = color_scheme[state.name];\r\n }\r\n CellStates.eye.slit_color=color_scheme['eye-slit']\r\n for (var cell_type in color_scheme) {\r\n $('#'+cell_type+'.cell-type ').css('background-color', color_scheme[cell_type]);\r\n $('#'+cell_type+'.cell-legend-type').css('background-color', color_scheme[cell_type]);\r\n \r\n }\r\n this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid);\r\n this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid);\r\n }\r\n}\r\n\r\nmodule.exports = ColorScheme;\n\n//# sourceURL=webpack:///./src/Rendering/ColorScheme.js?"); - -/***/ }), - -/***/ "./src/Rendering/Renderer.js": -/*!***********************************!*\ - !*** ./src/Rendering/Renderer.js ***! - \***********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("// const CellTypes = require(\"../Organism/Cell/CellTypes\");\r\nconst CellStates = __webpack_require__(/*! ../Organism/Cell/CellStates */ \"./src/Organism/Cell/CellStates.js\");\r\nconst Directions = __webpack_require__(/*! ../Organism/Directions */ \"./src/Organism/Directions.js\");\r\n\r\n// Renderer controls access to a canvas. There is one renderer for each canvas\r\nclass Renderer {\r\n constructor(canvas_id, container_id, cell_size) {\r\n this.cell_size = cell_size;\r\n this.canvas = document.getElementById(canvas_id);\r\n this.ctx = this.canvas.getContext(\"2d\");\r\n this.fillWindow(container_id)\r\n\t\tthis.height = this.canvas.height;\r\n this.width = this.canvas.width;\r\n this.cells_to_render = new Set();\r\n this.cells_to_highlight = new Set();\r\n this.highlighted_cells = new Set();\r\n }\r\n\r\n fillWindow(container_id) {\r\n this.fillShape($('#'+container_id).height(), $('#'+container_id).width());\r\n }\r\n\r\n fillShape(height, width) {\r\n this.canvas.width = width;\r\n this.canvas.height = height;\r\n this.height = this.canvas.height;\r\n this.width = this.canvas.width;\r\n }\r\n\r\n clear() {\r\n this.ctx.fillStyle = 'white';\r\n this.ctx.fillRect(0, 0, this.height, this.width);\r\n }\r\n\r\n renderFullGrid(grid) {\r\n for (var col of grid) {\r\n for (var cell of col){\r\n this.renderCell(cell);\r\n }\r\n }\r\n }\r\n\r\n renderCells() {\r\n for (var cell of this.cells_to_render) {\r\n this.renderCell(cell);\r\n }\r\n this.cells_to_render.clear();\r\n }\r\n\r\n renderCell(cell) {\r\n cell.state.render(this.ctx, cell, this.cell_size);\r\n }\r\n\r\n renderOrganism(org) {\r\n for(var org_cell of org.anatomy.cells) {\r\n var cell = org.getRealCell(org_cell);\r\n this.renderCell(cell);\r\n }\r\n }\r\n\r\n addToRender(cell) {\r\n if (this.highlighted_cells.has(cell)){\r\n this.cells_to_highlight.add(cell);\r\n }\r\n this.cells_to_render.add(cell);\r\n }\r\n\r\n renderHighlights() {\r\n for (var cell of this.cells_to_highlight) {\r\n this.renderCellHighlight(cell);\r\n this.highlighted_cells.add(cell);\r\n }\r\n this.cells_to_highlight.clear();\r\n \r\n }\r\n\r\n highlightOrganism(org) {\r\n for(var org_cell of org.anatomy.cells) {\r\n var cell = org.getRealCell(org_cell);\r\n this.cells_to_highlight.add(cell);\r\n }\r\n }\r\n\r\n highlightCell(cell) {\r\n this.cells_to_highlight.add(cell);\r\n }\r\n\r\n renderCellHighlight(cell, color=\"yellow\") {\r\n this.renderCell(cell);\r\n this.ctx.fillStyle = color;\r\n this.ctx.globalAlpha = 0.5;\r\n this.ctx.fillRect(cell.x, cell.y, this.cell_size, this.cell_size);\r\n this.ctx.globalAlpha = 1;\r\n this.highlighted_cells.add(cell);\r\n }\r\n\r\n clearAllHighlights(clear_to_highlight=false) {\r\n for (var cell of this.highlighted_cells) {\r\n this.renderCell(cell);\r\n }\r\n this.highlighted_cells.clear();\r\n if (clear_to_highlight) {\r\n this.cells_to_highlight.clear();\r\n }\r\n }\r\n}\r\n\r\n// $(\"body\").mousemove(function(e) {\r\n// console.log(\"hello\");\r\n// });\r\n\r\nmodule.exports = Renderer;\r\n\n\n//# sourceURL=webpack:///./src/Rendering/Renderer.js?"); - -/***/ }), - -/***/ "./src/Stats/FossilRecord.js": -/*!***********************************!*\ - !*** ./src/Stats/FossilRecord.js ***! - \***********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("const Species = __webpack_require__(/*! ./Species */ \"./src/Stats/Species.js\");\r\n\r\nconst FossilRecord = {\r\n init: function(){\r\n this.extant_species = [];\r\n this.extinct_species = [];\r\n\r\n // if an organism has fewer than this cumulative pop, discard them on extinction\r\n this.min_discard = 5;\r\n },\r\n\r\n setEnv: function(env) {\r\n this.env = env;\r\n },\r\n\r\n addSpecies: function(org, ancestor) {\r\n // console.log(\"Adding Species\")\r\n var new_species = new Species(org.anatomy, ancestor, this.env.total_ticks);\r\n this.extant_species.push(new_species);\r\n org.species = new_species;\r\n return new_species;\r\n },\r\n\r\n addSpeciesObj: function(species) {\r\n // console.log(\"Adding Species\")\r\n this.extant_species.push(species);\r\n return species;\r\n },\r\n\r\n fossilize: function(species) {\r\n // console.log(\"Extinction\")\r\n species.end_tick = this.env.total_ticks;\r\n for (i in this.extant_species) {\r\n var s = this.extant_species[i];\r\n if (s == species) {\r\n this.extant_species.splice(i, 1);\r\n if (species.cumulative_pop < this.min_pop) {\r\n return false;\r\n }\r\n this.extinct_species.push(s);\r\n // console.log(\"Extant species:\", this.extant_species.length)\r\n // console.log(\"Extinct species:\", this.extinct_species.length)\r\n return true;\r\n }\r\n }\r\n },\r\n\r\n resurrect: function(species) {\r\n // console.log(\"Resurrecting species\")\r\n if (species.extinct) {\r\n for (i in this.extinct_species) {\r\n var s = this.extinct_species[i];\r\n if (s == species) {\r\n this.extinct_species.splice(i, 1);\r\n this.extant_species.push(species);\r\n species.extinct = false;\r\n }\r\n }\r\n }\r\n },\r\n\r\n clear_record: function() {\r\n this.extant_species = [];\r\n this.extinct_species = [];\r\n // console.log(\"Cleared\", this.extant_species, this.extinct_species)\r\n },\r\n\r\n}\r\n\r\nFossilRecord.init();\r\n\r\nmodule.exports = FossilRecord;\n\n//# sourceURL=webpack:///./src/Stats/FossilRecord.js?"); - -/***/ }), - -/***/ "./src/Stats/Species.js": -/*!******************************!*\ - !*** ./src/Stats/Species.js ***! - \******************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -eval("class Species {\r\n constructor(anatomy, ancestor, start_tick) {\r\n this.anatomy = anatomy;\r\n this.ancestor = ancestor;\r\n this.population = 1;\r\n this.cumulative_pop = 1;\r\n this.start_tick = start_tick;\r\n this.end_tick = -1;\r\n this.color = '#asdfasdf';\r\n this.name = '_' + Math.random().toString(36).substr(2, 9);;\r\n this.extinct = false;\r\n }\r\n\r\n addPop() {\r\n this.population++;\r\n this.cumulative_pop++;\r\n }\r\n\r\n decreasePop() {\r\n this.population--;\r\n if (this.population <= 0) {\r\n this.extinct = true;\r\n const FossilRecord = __webpack_require__(/*! ./FossilRecord */ \"./src/Stats/FossilRecord.js\");\r\n FossilRecord.fossilize(this);\r\n }\r\n }\r\n\r\n lifespan() {\r\n return this.end_tick - this.start_tick;\r\n }\r\n}\r\n\r\nmodule.exports = Species;\n\n//# sourceURL=webpack:///./src/Stats/Species.js?"); - -/***/ }), - -/***/ "./src/index.js": -/*!**********************!*\ - !*** ./src/index.js ***! - \**********************/ -/*! no exports provided */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Engine */ \"./src/Engine.js\");\n/* harmony import */ var _Engine__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_Engine__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\r\n\r\n\r\n$('document').ready(function(){\r\n let isMobile = mobileCheck();\r\n if (isMobile) {\r\n alert(\"Though the simulation still works on mobile, most features are disabled. Try it on desktop for the full experience!\");\r\n $('.control-panel').css('display', 'none');\r\n }\r\n var engine = new _Engine__WEBPACK_IMPORTED_MODULE_0___default.a();\r\n engine.start(60);\r\n});\r\n\r\nfunction mobileCheck() {\r\n let check = false;\r\n (function(a){if(/(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);\r\n return check;\r\n};\n\n//# sourceURL=webpack:///./src/index.js?"); - -/***/ }) - -/******/ }); \ No newline at end of file +!function(t){var e={};function i(s){if(e[s])return e[s].exports;var o=e[s]={i:s,l:!1,exports:{}};return t[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(s,o,function(e){return t[e]}.bind(null,o));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=15)}([function(t,e){class i{constructor(t){this.name=t,this.color="black"}render(t,e,i){t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(t,e,i){if(t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,n=i/2+i/4,a=i/4;t.translate(e.x+s,e.y+s),t.rotate(90*e.cell_owner.getAbsoluteDirection()*Math.PI/180),t.fillStyle=this.slit_color,t.fillRect(o,r,a,n),t.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),t.exports=s},function(t,e,i){const s=i(5),o={setDefaults:function(){this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(t){if(1==t){var e=100-this.addProb;this.changeProb=e/2,this.removeProb=e/2}else if(2==t){e=100-this.changeProb;this.addProb=e/2,this.removeProb=e/2}else{e=100-this.removeProb;this.changeProb=e/2,this.addProb=e/2}}};o.setDefaults(),t.exports=o},function(t,e,s){const o=s(12),r={init:function(){this.extant_species=[],this.extinct_species=[],this.min_discard=10,this.record_size_limit=500,this.setData()},setEnv:function(t){this.env=t},addSpecies:function(t,e){var i=new o(t.anatomy,e,this.env.total_ticks);return this.extant_species.push(i),t.species=i,i},addSpeciesObj:function(t){return this.extant_species.push(t),t},fossilize:function(t){for(i in t.end_tick=this.env.total_ticks,this.extant_species){var e=this.extant_species[i];if(e==t)return this.extant_species.splice(i,1),!(t.cumulative_popthis.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.av_pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift())},clear_record:function(){this.extant_species=[],this.extinct_species=[],this.setData()}};r.init(),t.exports=r},function(t,e){const i={up:0,right:1,down:2,left:3,scalars:[[0,-1],[1,0],[0,1],[-1,0]],getRandomDirection:function(){return Math.floor(4*Math.random())},getRandomScalar:function(){return this.scalars[Math.floor(Math.random()*this.scalars.length)]},getOppositeDirection:function(t){switch(t){case this.up:return this.down;case this.down:return this.up;case this.left:return this.right;case this.right:return this.left}},rotateRight:function(t){return++t>3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=n.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var a of this.anatomy.cells){var l=this.c+a.rotatedCol(this.rotation),h=this.r+a.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=n.getRandomDirection(),this.move_count=0,!0;var t=n.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=n.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var n=e;n!=s;n++){var a=this.env.grid_map.cellAt(t,n);if(!this.isPassableCell(a,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(n=t;n!=i;n++){a=this.env.grid_map.cellAt(n,e);if(!this.isPassableCell(a,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var n of this.anatomy.cells){var a=this.getRealCell(n,t,e,i);if(null==a)return!1;if(!(a.owner==this||a.state==s.empty||!r.foodBlocksReproduction&&a.state==s.food||o&&n.state==s.armor&&a.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(n.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e,i){const s=i(2);t.exports=class{constructor(t){this.data=[],this.chart=new CanvasJS.Chart("chartContainer",{zoomEnabled:!0,title:{text:t},data:this.data}),this.chart.render(),this.data}setData(){alert("Must override updateData!")}render(){this.chart.render()}updateData(){var t=s.tick_record.length,e=-1;this.data[0].dataPoints.length>0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(34),n=i(36);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new n(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),t>300&&(t=300),this.fps=t,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),n=i(6),a=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new n(t[0],t[1],this);e.anatomy.addDefaultCell(a.mouth,0,0),e.anatomy.addDefaultCell(a.producer,1,1),e.anatomy.addDefaultCell(a.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==a.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==a.wall&&this.changeCell(t.col,t.row,a.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case n.up:o=-1;break;case n.down:o=1;break;case n.right:i=1;break;case n.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;pthis.organism_record&&(this.organism_record=t),$("#org-record").text("Highest count: "+this.env.organism_record),$("#avg-mut").text("Average Mutation Rate: "+Math.round(100*this.env.averageMutability())/100),$("#largest-org").text("Largest Organism: "+this.env.largest_cell_count+" cells")}reset(){this.setChart()}}},function(t,e,i){const s=i(2),o=i(8);t.exports=class extends o{constructor(){super("Population")}setData(){for(var t in this.clear(),this.data.push({type:"line",markerType:"none",color:"black",showInLegend:!0,name:"pop1",legendText:"Total Population",dataPoints:[]}),s.tick_record){var e=s.tick_record[t],i=s.pop_counts[t];this.data[0].dataPoints.push({x:e,y:i})}}addNewest(){var t=s.tick_record.length-1,e=s.tick_record[t],i=s.pop_counts[t];this.data[0].dataPoints.push({x:e,y:i})}removeOldest(){this.data[0].dataPoints.shift()}}},function(t,e,i){const s=i(2),o=i(8);t.exports=class extends o{constructor(){super("Species")}setData(){for(var t in this.clear(),this.data.push({type:"line",markerType:"none",color:"black",showInLegend:!0,name:"spec",legendText:"Number of Species",dataPoints:[]}),s.tick_record){var e=s.tick_record[t],i=s.species_counts[t];this.data[0].dataPoints.push({x:e,y:i})}}addNewest(){var t=s.tick_record.length-1,e=s.tick_record[t],i=s.species_counts[t];this.data[0].dataPoints.push({x:e,y:i})}removeOldest(){this.data[0].dataPoints.shift()}}},function(t,e,i){const s=i(2),o=i(8);t.exports=class extends o{constructor(){super("Mutation Rate")}setData(){for(var t in this.clear(),this.data.push({type:"line",markerType:"none",color:"black",showInLegend:!0,name:"pop1",legendText:"Average Mutation Rate",dataPoints:[]}),s.tick_record){var e=s.tick_record[t],i=s.av_mut_rates[t];this.data[0].dataPoints.push({x:e,y:i})}}addNewest(){var t=s.tick_record.length-1,e=s.tick_record[t],i=s.av_mut_rates[t];this.data[0].dataPoints.push({x:e,y:i})}removeOldest(){this.data[0].dataPoints.shift()}}},function(t,e,i){const s=i(9),o=i(6),r=i(11),n=i(10),a=i(0),l=i(35),h=i(12);t.exports=class extends s{constructor(){super(),this.is_active=!0;this.renderer=new n("editor-canvas","editor-env",13),this.controller=new l(this,this.renderer.canvas),this.grid_map=new r(15,15,13),this.clear()}update(){this.is_active&&this.renderer.renderHighlights()}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderFull()}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}addCellToOrg(t,e,i){var s=this.grid_map.getCenter(),o=t-s[0],r=e-s[1],n=this.organism.anatomy.getLocalCell(o,r);if(null!=n){var a=this.organism.anatomy.replaceCell(i,n.loc_col,n.loc_row,!1);this.changeCell(t,e,i,a)}else this.organism.anatomy.canAddCellAt(o,r)&&this.changeCell(t,e,i,this.organism.anatomy.addDefaultCell(i,o,r));this.organism.species=new h(this.organism.anatomy,null,0)}removeCellFromOrg(t,e){var i=this.grid_map.getCenter(),s=t-i[0],o=e-i[1];0!=s||0!=o?null!=this.organism.anatomy.getLocalCell(s,o)&&this.organism.anatomy.removeCell(s,o)&&(this.changeCell(t,e,a.empty,null),this.organism.species=new h(this.organism.anatomy,null,0)):alert("Cannot remove center cell")}setOrganismToCopyOf(t){this.grid_map.fillGrid(a.empty);var e=this.grid_map.getCenter();this.organism=new o(e[0],e[1],this,t),this.organism.updateGrid(),this.controller.updateDetails(),this.controller.new_species=!1}getCopyOfOrg(){return new o(0,0,null,this.organism)}clear(){this.grid_map.fillGrid(a.empty);var t=this.grid_map.getCenter();this.organism=new o(t[0],t[1],this,null),this.organism.anatomy.addDefaultCell(a.mouth,0,0),this.organism.updateGrid(),this.organism.species=new h(this.organism.anatomy,null,0)}}},function(t,e,i){const s=i(13),o=i(7),r=i(0),n=i(3),a=i(1);t.exports=class extends s{constructor(t,e){super(t,e),this.mode=o.None,this.edit_cell_type=null,this.highlight_org=!1,this.new_species=!1,this.defineCellTypeSelection(),this.defineEditorDetails()}mouseMove(){(this.right_click||this.left_click)&&this.editOrganism()}mouseDown(){this.editOrganism()}mouseUp(){}getCurLocalCell(){return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c,this.mouse_r-this.env.organism.r)}editOrganism(){if(null!=this.edit_cell_type&&this.mode==o.Edit){if(this.left_click)if(this.edit_cell_type==r.eye&&this.cur_cell.state==r.eye){var t=this.getCurLocalCell();t.direction=n.rotateRight(t.direction),this.env.renderFull()}else this.env.addCellToOrg(this.mouse_c,this.mouse_r,this.edit_cell_type);else this.right_click&&this.env.removeCellFromOrg(this.mouse_c,this.mouse_r);this.new_species=!0,this.setBrainPanelVisibility(),this.setMoveRangeVisibility(),this.updateDetails()}}updateDetails(){$(".cell-count").text("Cell count: "+this.env.organism.anatomy.cells.length)}defineCellTypeSelection(){var t=this;$(".cell-type").click((function(){switch(this.id){case"mouth":t.edit_cell_type=r.mouth;break;case"producer":t.edit_cell_type=r.producer;break;case"mover":t.edit_cell_type=r.mover;break;case"killer":t.edit_cell_type=r.killer;break;case"armor":t.edit_cell_type=r.armor;break;case"eye":t.edit_cell_type=r.eye}$(".cell-type").css("border-color","black");var e="#"+this.id+".cell-type";$(e).css("border-color","yellow")}))}defineEditorDetails(){this.details_html=$("#organism-details"),this.edit_details_html=$("#edit-organism-details"),this.decision_names=["ignore","move away","move towards"],$("#move-range-edit").change(function(){this.env.organism.move_range=parseInt($("#move-range-edit").val())}.bind(this)),$("#observation-type-edit").change(function(){this.setBrainEditorValues($("#observation-type-edit").val()),this.setBrainDetails()}.bind(this)),$("#reaction-edit").change(function(){var t=$("#observation-type-edit").val(),e=parseInt($("#reaction-edit").val());this.env.organism.brain.decisions[t]=e,this.setBrainDetails()}.bind(this))}clearDetailsPanel(){$("#organism-details").css("display","none"),$("#edit-organism-details").css("display","none")}setDetailsPanel(){this.clearDetailsPanel();var t=this.env.organism;$(".cell-count").text("Cell count: "+t.anatomy.cells.length),$("#move-range").text("Move Range: "+t.move_range),$("#mutation-rate").text("Mutation Rate: "+t.mutability),a.useGlobalMutability?$("#mutation-rate").css("display","none"):$("#mutation-rate").css("display","block"),this.setMoveRangeVisibility(),this.setBrainPanelVisibility()&&this.setBrainDetails(),$("#organism-details").css("display","block")}setEditorPanel(){this.clearDetailsPanel();var t=this.env.organism;$(".cell-count").text("Cell count: "+t.anatomy.cells.length),this.setMoveRangeVisibility()&&$("#move-range-edit").val(t.move_range),this.setBrainPanelVisibility()&&this.setBrainEditorValues($("#observation-type-edit").val()),$("#cell-selections").css("display","grid"),$("#edit-organism-details").css("display","block")}setBrainPanelVisibility(){var t=this.env.organism;return t.anatomy.has_eyes&&t.anatomy.is_mover?($(".brain-details").css("display","block"),!0):($(".brain-details").css("display","none"),!1)}setBrainDetails(){var t=[],e=[];for(var i in this.env.organism.brain.decisions){var s=this.env.organism.brain.decisions[i];1==s?e.push(i):2==s&&t.push(i)}$(".chase-types").text("Move Towards: "+t),$(".retreat-types").text("Move Away From: "+e)}setMoveRangeVisibility(){return this.env.organism.anatomy.is_mover?($("#move-range-cont").css("display","block"),$("#move-range").css("display","block"),!0):($("#move-range-cont").css("display","none"),$("#move-range").css("display","none"),!1)}setBrainEditorValues(t){$("#observation-type-edit").val(t);var e=this.env.organism.brain.decisions[t];$("#reaction-edit").val(e)}}},function(t,e,i){const s=i(0);var o={empty:"#0E1318",food:"#2F7AB7",wall:"gray",mouth:"#DEB14D",producer:"#15DE59",mover:"#60D4FF",killer:"#F82380",armor:"#7230DB",eye:"#B6C1EA","eye-slit":"#0E1318"};t.exports=class{constructor(t,e){this.world_env=t,this.editor_env=e}loadColorScheme(){for(var t of s.all)t.color=o[t.name];for(var e in s.eye.slit_color=o["eye-slit"],o)$("#"+e+".cell-type ").css("background-color",o[e]),$("#"+e+".cell-legend-type").css("background-color",o[e]);this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid),this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid)}}}]); \ No newline at end of file diff --git a/src/Controllers/ControlPanel.js b/src/Controllers/ControlPanel.js index 96430ba..c8d6089 100644 --- a/src/Controllers/ControlPanel.js +++ b/src/Controllers/ControlPanel.js @@ -1,6 +1,6 @@ const Hyperparams = require("../Hyperparameters"); const Modes = require("./ControlModes"); -const StatsPanel = require("./StatsPanel"); +const StatsPanel = require("../Stats/StatsPanel"); class ControlPanel { constructor(engine) { @@ -18,11 +18,11 @@ class ControlPanel { this.editor_controller = this.engine.organism_editor.controller; this.env_controller.setControlPanel(this); this.editor_controller.setControlPanel(this); - this.stats_panel = new StatsPanel(); - this.stats_panel.render(); + this.stats_panel = new StatsPanel(this.engine.env); } defineMinMaxControls(){ + var self = this; $('#minimize').click ( function() { $('.control-panel').css('display', 'none'); $('.hot-controls').css('display', 'block'); @@ -31,7 +31,7 @@ class ControlPanel { $('#maximize').click ( function() { $('.control-panel').css('display', 'grid'); $('.hot-controls').css('display', 'none'); - if (this.id == 'stats') { + if (self.tab_id == 'stats') { self.stats_panel.startAutoRender(); } }); @@ -78,6 +78,8 @@ class ControlPanel { var rows = $('#row-input').val(); this.engine.env.resizeGridColRow(cell_size, cols, rows); } + this.engine.env.reset(); + this.stats_panel.reset(); }.bind(this)); } @@ -88,13 +90,13 @@ class ControlPanel { $('.tabnav-item').click(function() { $('.tab').css('display', 'none'); var tab = '#'+this.id+'.tab'; + $(tab).css('display', 'grid'); self.engine.organism_editor.is_active = (this.id == 'editor'); + self.stats_panel.stopAutoRender(); if (this.id == 'stats') { self.stats_panel.startAutoRender(); } - self.id = this.id; - - $(tab).css('display', 'grid'); + self.tab_id = this.id; }); } @@ -134,7 +136,7 @@ class ControlPanel { Hyperparams.useGlobalMutability = !this.checked; }); $('#global-mutation').change( function() { - Hyperparams.globalMutability = $('#global-mutation').val(); + Hyperparams.globalMutability = parseInt($('#global-mutation').val()); }); $('.mut-prob').change( function() { switch(this.id){ @@ -191,7 +193,7 @@ class ControlPanel { $('#cell-selections').css('display', 'none'); $('#organism-options').css('display', 'none'); self.editor_controller.setDetailsPanel(); - switch(this.id){ + switch(this.id) { case "food-drop": self.setMode(Modes.FoodDrop); break; @@ -229,7 +231,7 @@ class ControlPanel { var env = this.engine.env; $('#reset-env').click( function() { this.engine.env.reset(); - this.stats_panel.clearData(); + this.stats_panel.reset(); }.bind(this)); $('#auto-reset').change(function() { env.auto_reset = this.checked; @@ -271,15 +273,8 @@ class ControlPanel { update() { $('#fps-actual').text("Actual FPS: " + Math.floor(this.engine.actual_fps)); - var org_count = this.engine.env.organisms.length; - $('#org-count').text("Organism count: " + org_count); - if (org_count > this.organism_record) - this.organism_record = org_count; - $('#org-record').text("Highest count: " + this.organism_record); - $('#avg-mut').text("Average Mutation Rate: " + Math.round(this.engine.env.averageMutability() * 100) / 100); - $('#largest-org').text("Largest Organism: " + this.engine.env.largest_cell_count + " cells"); $('#reset-count').text("Auto reset count: " + this.engine.env.reset_count); - this.stats_panel.updateData(this.engine.env.total_ticks, this.engine.env.organisms.length) + this.stats_panel.updateDetails(); } } diff --git a/src/Controllers/StatsPanel.js b/src/Controllers/StatsPanel.js deleted file mode 100644 index 830fafb..0000000 --- a/src/Controllers/StatsPanel.js +++ /dev/null @@ -1,77 +0,0 @@ -const FossilRecord = require("../Stats/FossilRecord"); - -class StatsPanel { - constructor() { - this.defineControls(); - this.clearData(); - this.last_update_tick = 0; - this.update_every = 100; - - // maps species to their index in chart's data storage - this.species_index_map = []; - this.index_counter = 0; - this.min_display = 10; - } - - startAutoRender(){ - this.render_loop = setInterval(function(){this.render();}.bind(this), 1000); - } - - stopAutoRender() { - clearInterval(this.render_loop); - } - - defineControls() { - $('#update-chart').click( function() { - this.render(); - }.bind(this)); - } - - updateData(tick, population_size) { - if (tick - this.last_update_tick >= this.update_every){ - // this.data[0].dataPoints.push({x: tick, y:population_size}); - this.last_update_tick = tick; - - for (var species of FossilRecord.extant_species) { - if (species.cumulative_pop < this.min_display){ - continue; - } - - if (this.species_index_map[species.name] == null) { - console.log("new species") - this.species_index_map[species.name] = this.index_counter; - this.index_counter++; - this.data.push({ - type: "line", - markerType: "none", - dataPoints: [] - }); - } - var data_index = this.species_index_map[species.name]; - this.data[data_index].dataPoints.push({x:tick, y:species.population}); - } - } - } - - render() { - this.chart.render(); - } - - clearData() { - this.data = [{ - type: "line", - markerType: "none", - dataPoints: [] - }]; - this.chart = new CanvasJS.Chart("chartContainer", { - title:{ - text: "Population" - }, - data: this.data - }); - this.render(); - } - -} - -module.exports = StatsPanel; \ No newline at end of file diff --git a/src/Engine.js b/src/Engine.js index 7143629..409dcce 100644 --- a/src/Engine.js +++ b/src/Engine.js @@ -5,7 +5,7 @@ const ColorScheme = require('./Rendering/ColorScheme'); const render_speed = 60; -class Engine{ +class Engine { constructor(){ this.fps = 60; this.env = new WorldEnvironment(5); diff --git a/src/Environments/WorldEnvironment.js b/src/Environments/WorldEnvironment.js index e2d051e..e6039a5 100644 --- a/src/Environments/WorldEnvironment.js +++ b/src/Environments/WorldEnvironment.js @@ -22,11 +22,11 @@ class WorldEnvironment extends Environment{ this.largest_cell_count = 0; this.reset_count = 0; this.total_ticks = 0; + this.data_update_rate = 100; FossilRecord.setEnv(this); } update(delta_time) { - this.total_ticks ++; var to_remove = []; for (var i in this.organisms) { var org = this.organisms[i]; @@ -38,6 +38,10 @@ class WorldEnvironment extends Environment{ this.generateFood(); } this.removeOrganisms(to_remove); + this.total_ticks ++; + if (this.total_ticks % this.data_update_rate == 0) { + FossilRecord.updateData(); + } } render() { @@ -77,6 +81,9 @@ class WorldEnvironment extends Environment{ averageMutability() { if (this.organisms.length < 1) return 0; + if (Hyperparams.useGlobalMutability) { + return Hyperparams.globalMutability; + } return this.total_mutability / this.organisms.length; } @@ -129,7 +136,6 @@ class WorldEnvironment extends Environment{ this.renderer.cell_size = cell_size; this.renderer.fillShape(rows*cell_size, cols*cell_size); this.grid_map.resize(cols, rows, cell_size); - this.reset(); } resizeFillWindow(cell_size) { @@ -138,7 +144,6 @@ class WorldEnvironment extends Environment{ var cols = Math.floor(this.renderer.width / cell_size); var rows = Math.floor(this.renderer.height / cell_size); this.grid_map.resize(cols, rows, cell_size); - this.reset(); } } diff --git a/src/Stats/Charts/ChartController.js b/src/Stats/Charts/ChartController.js new file mode 100644 index 0000000..a8825f5 --- /dev/null +++ b/src/Stats/Charts/ChartController.js @@ -0,0 +1,55 @@ +const FossilRecord = require("../FossilRecord"); + +class ChartController { + constructor(title) { + this.data = []; + this.chart = new CanvasJS.Chart("chartContainer", { + zoomEnabled: true, + title:{ + text: title + }, + data: this.data + }); + this.chart.render(); + this.data + } + + setData() { + alert("Must override updateData!"); + } + + render() { + this.chart.render(); + } + + updateData() { + var r_len = FossilRecord.tick_record.length; + var newest_t = -1; + var oldest_t = 0; + if (this.data[0].dataPoints.length>0) { + newest_t = this.data[0].dataPoints[this.data[0].dataPoints.length-1].x; + newest_t = this.data[0].dataPoints[0].x; + } + if (newest_t < FossilRecord.tick_record[r_len-1]) { + this.addNewest(); + } + if (oldest_t < FossilRecord.tick_record[0]) { + this.removeOldest(); + } + } + + addNewest() { + alert("Must override addNewest!"); + } + + removeOldest() { + alert("Must override addNewest!"); + } + + clear() { + this.data.length = 0; + this.chart.render(); + } +} + +module.exports = ChartController; \ No newline at end of file diff --git a/src/Stats/Charts/MutationChart.js b/src/Stats/Charts/MutationChart.js new file mode 100644 index 0000000..9cc4562 --- /dev/null +++ b/src/Stats/Charts/MutationChart.js @@ -0,0 +1,41 @@ +const FossilRecord = require("../FossilRecord"); +const ChartController = require("./ChartController"); + +class MutationChart extends ChartController { + constructor() { + super("Mutation Rate"); + } + + setData() { + this.clear(); + this.data.push({ + type: "line", + markerType: "none", + color: 'black', + showInLegend: true, + name: "pop1", + legendText: "Average Mutation Rate", + dataPoints: [] + } + ); + for (var i in FossilRecord.tick_record) { + var t = FossilRecord.tick_record[i]; + var p = FossilRecord.av_mut_rates[i]; + this.data[0].dataPoints.push({x:t, y:p}); + } + // console.log(this.data) + } + + addNewest() { + var i = FossilRecord.tick_record.length-1; + var t = FossilRecord.tick_record[i]; + var p = FossilRecord.av_mut_rates[i]; + this.data[0].dataPoints.push({x:t, y:p}); + } + + removeOldest() { + this.data[0].dataPoints.shift(); + } +} + +module.exports = MutationChart; \ No newline at end of file diff --git a/src/Stats/Charts/PopulationChart.js b/src/Stats/Charts/PopulationChart.js new file mode 100644 index 0000000..bb3eba4 --- /dev/null +++ b/src/Stats/Charts/PopulationChart.js @@ -0,0 +1,41 @@ +const FossilRecord = require("../FossilRecord"); +const ChartController = require("./ChartController"); + +class PopulationChart extends ChartController { + constructor() { + super("Population"); + } + + setData() { + this.clear(); + this.data.push({ + type: "line", + markerType: "none", + color: 'black', + showInLegend: true, + name: "pop1", + legendText: "Total Population", + dataPoints: [] + } + ); + for (var i in FossilRecord.tick_record) { + var t = FossilRecord.tick_record[i]; + var p = FossilRecord.pop_counts[i]; + this.data[0].dataPoints.push({x:t, y:p}); + } + // console.log(this.data) + } + + addNewest() { + var i = FossilRecord.tick_record.length-1; + var t = FossilRecord.tick_record[i]; + var p = FossilRecord.pop_counts[i]; + this.data[0].dataPoints.push({x:t, y:p}); + } + + removeOldest() { + this.data[0].dataPoints.shift(); + } +} + +module.exports = PopulationChart; \ No newline at end of file diff --git a/src/Stats/Charts/SpeciesChart.js b/src/Stats/Charts/SpeciesChart.js new file mode 100644 index 0000000..b330a04 --- /dev/null +++ b/src/Stats/Charts/SpeciesChart.js @@ -0,0 +1,40 @@ +const FossilRecord = require("../FossilRecord"); +const ChartController = require("./ChartController"); + +class SpeciesChart extends ChartController { + constructor() { + super("Species"); + } + + setData() { + this.clear(); + this.data.push({ + type: "line", + markerType: "none", + color: 'black', + showInLegend: true, + name: "spec", + legendText: "Number of Species", + dataPoints: [] + } + ); + for (var i in FossilRecord.tick_record) { + var t = FossilRecord.tick_record[i]; + var p = FossilRecord.species_counts[i]; + this.data[0].dataPoints.push({x:t, y:p}); + } + } + + addNewest() { + var i = FossilRecord.tick_record.length-1; + var t = FossilRecord.tick_record[i]; + var p = FossilRecord.species_counts[i]; + this.data[0].dataPoints.push({x:t, y:p}); + } + + removeOldest() { + this.data[0].dataPoints.shift(); + } +} + +module.exports = SpeciesChart; \ No newline at end of file diff --git a/src/Stats/FossilRecord.js b/src/Stats/FossilRecord.js index a41dd7d..8da97ad 100644 --- a/src/Stats/FossilRecord.js +++ b/src/Stats/FossilRecord.js @@ -6,7 +6,10 @@ const FossilRecord = { this.extinct_species = []; // if an organism has fewer than this cumulative pop, discard them on extinction - this.min_discard = 5; + this.min_discard = 10; + + this.record_size_limit = 500; // store this many data points + this.setData(); }, setEnv: function(env) { @@ -59,10 +62,34 @@ const FossilRecord = { } }, + setData() { + // all parallel arrays + this.tick_record = [0]; + this.pop_counts = [1]; + this.av_pop_counts = [1] + this.species_counts = [1]; + this.av_mut_rates = [5]; + }, + + updateData() { + var tick = this.env.total_ticks; + this.tick_record.push(tick); + this.pop_counts.push(this.env.organisms.length); + this.species_counts.push(this.extant_species.length); + this.av_mut_rates.push(this.env.averageMutability()); + if (this.tick_record.length > this.record_size_limit) { + this.tick_record.shift(); + this.pop_counts.shift(); + this.av_pop_counts.shift(); + this.species_counts.shift(); + this.av_mut_rates.shift(); + } + }, + clear_record: function() { this.extant_species = []; this.extinct_species = []; - // console.log("Cleared", this.extant_species, this.extinct_species) + this.setData(); }, } diff --git a/src/Stats/Species.js b/src/Stats/Species.js index f2a94ac..299faee 100644 --- a/src/Stats/Species.js +++ b/src/Stats/Species.js @@ -6,8 +6,13 @@ class Species { this.cumulative_pop = 1; this.start_tick = start_tick; this.end_tick = -1; - this.color = '#asdfasdf'; - this.name = '_' + Math.random().toString(36).substr(2, 9);; + this.color = Math.floor(Math.random()*16777215).toString(16); + if (ancestor != null) { + // needs to be reworked, maybe removed + var mutator = Math.floor(Math.random()*16777215)-8000000; + this.color = (mutator + parseInt(ancestor.color, 16)).toString(16); + } + this.name = '_' + Math.random().toString(36).substr(2, 9); this.extinct = false; } diff --git a/src/Stats/StatsPanel.js b/src/Stats/StatsPanel.js new file mode 100644 index 0000000..cfc3dbe --- /dev/null +++ b/src/Stats/StatsPanel.js @@ -0,0 +1,65 @@ +const PopulationChart = require("./Charts/PopulationChart"); +const SpeciesChart = require("./Charts/SpeciesChart"); +const MutationChart = require("./Charts/MutationChart"); + + +const ChartSelections = [PopulationChart, SpeciesChart, MutationChart]; + +class StatsPanel { + constructor(env) { + this.defineControls(); + this.chart_selection = 0; + this.setChart(); + this.env = env; + this.last_reset_count=env.reset_count; + } + + setChart(selection=this.chart_selection) { + this.chart_controller = new ChartSelections[selection](); + this.chart_controller.setData(); + this.chart_controller.render(); + } + + startAutoRender() { + this.setChart(); + this.render_loop = setInterval(function(){this.updateChart();}.bind(this), 1000); + } + + stopAutoRender() { + clearInterval(this.render_loop); + } + + defineControls() { + $('#chart-option').change ( function() { + this.chart_selection = $("#chart-option")[0].selectedIndex; + this.setChart(); + }.bind(this)); + } + + updateChart() { + if (this.last_reset_count < this.env.reset_count){ + this.reset() + } + this.last_reset_count = this.env.reset_count; + this.chart_controller.updateData(); + this.chart_controller.render(); + } + + updateDetails() { + var org_count = this.env.organisms.length; + $('#org-count').text("Organism count: " + org_count); + if (org_count > this.organism_record) + this.organism_record = org_count; + $('#org-record').text("Highest count: " + this.env.organism_record); + $('#avg-mut').text("Average Mutation Rate: " + Math.round(this.env.averageMutability() * 100) / 100); + $('#largest-org').text("Largest Organism: " + this.env.largest_cell_count + " cells"); + + } + + reset() { + this.setChart(); + } + +} + +module.exports = StatsPanel; \ No newline at end of file From 9626cd54d60ca347c4838737efe7b31368beaa6a Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Thu, 11 Feb 2021 13:24:42 -0700 Subject: [PATCH 5/9] cleaned chart code/added cells chart --- dist/index.html | 7 ++-- dist/js/bundle.js | 2 +- src/Controllers/ControlPanel.js | 3 ++ src/Environments/WorldEnvironment.js | 6 +++- src/Stats/Charts/CellsChart.js | 51 ++++++++++++++++++++++++++++ src/Stats/Charts/ChartController.js | 17 ++++++++-- src/Stats/Charts/MutationChart.js | 14 ++------ src/Stats/Charts/PopulationChart.js | 14 ++------ src/Stats/Charts/SpeciesChart.js | 13 ++----- src/Stats/FossilRecord.js | 34 +++++++++++++++++-- src/Stats/Species.js | 14 ++++++++ src/Stats/StatsPanel.js | 13 +++---- 12 files changed, 137 insertions(+), 51 deletions(-) create mode 100644 src/Stats/Charts/CellsChart.js diff --git a/dist/index.html b/dist/index.html index 02f41dc..df1b268 100644 --- a/dist/index.html +++ b/dist/index.html @@ -222,14 +222,15 @@

Stats

-

Organism count:

-

Highest count:

+

Total Population:

+

Number of Species:

+

Largest Organism Ever:

Average Mutation Rate:

-

Largest Organism:

diff --git a/dist/js/bundle.js b/dist/js/bundle.js index 4b18cc8..8fdf209 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1 +1 @@ -!function(t){var e={};function i(s){if(e[s])return e[s].exports;var o=e[s]={i:s,l:!1,exports:{}};return t[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(s,o,function(e){return t[e]}.bind(null,o));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=15)}([function(t,e){class i{constructor(t){this.name=t,this.color="black"}render(t,e,i){t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(t,e,i){if(t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,n=i/2+i/4,a=i/4;t.translate(e.x+s,e.y+s),t.rotate(90*e.cell_owner.getAbsoluteDirection()*Math.PI/180),t.fillStyle=this.slit_color,t.fillRect(o,r,a,n),t.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),t.exports=s},function(t,e,i){const s=i(5),o={setDefaults:function(){this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(t){if(1==t){var e=100-this.addProb;this.changeProb=e/2,this.removeProb=e/2}else if(2==t){e=100-this.changeProb;this.addProb=e/2,this.removeProb=e/2}else{e=100-this.removeProb;this.changeProb=e/2,this.addProb=e/2}}};o.setDefaults(),t.exports=o},function(t,e,s){const o=s(12),r={init:function(){this.extant_species=[],this.extinct_species=[],this.min_discard=10,this.record_size_limit=500,this.setData()},setEnv:function(t){this.env=t},addSpecies:function(t,e){var i=new o(t.anatomy,e,this.env.total_ticks);return this.extant_species.push(i),t.species=i,i},addSpeciesObj:function(t){return this.extant_species.push(t),t},fossilize:function(t){for(i in t.end_tick=this.env.total_ticks,this.extant_species){var e=this.extant_species[i];if(e==t)return this.extant_species.splice(i,1),!(t.cumulative_popthis.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.av_pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift())},clear_record:function(){this.extant_species=[],this.extinct_species=[],this.setData()}};r.init(),t.exports=r},function(t,e){const i={up:0,right:1,down:2,left:3,scalars:[[0,-1],[1,0],[0,1],[-1,0]],getRandomDirection:function(){return Math.floor(4*Math.random())},getRandomScalar:function(){return this.scalars[Math.floor(Math.random()*this.scalars.length)]},getOppositeDirection:function(t){switch(t){case this.up:return this.down;case this.down:return this.up;case this.left:return this.right;case this.right:return this.left}},rotateRight:function(t){return++t>3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=n.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var a of this.anatomy.cells){var l=this.c+a.rotatedCol(this.rotation),h=this.r+a.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=n.getRandomDirection(),this.move_count=0,!0;var t=n.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=n.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var n=e;n!=s;n++){var a=this.env.grid_map.cellAt(t,n);if(!this.isPassableCell(a,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(n=t;n!=i;n++){a=this.env.grid_map.cellAt(n,e);if(!this.isPassableCell(a,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var n of this.anatomy.cells){var a=this.getRealCell(n,t,e,i);if(null==a)return!1;if(!(a.owner==this||a.state==s.empty||!r.foodBlocksReproduction&&a.state==s.food||o&&n.state==s.armor&&a.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(n.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e,i){const s=i(2);t.exports=class{constructor(t){this.data=[],this.chart=new CanvasJS.Chart("chartContainer",{zoomEnabled:!0,title:{text:t},data:this.data}),this.chart.render(),this.data}setData(){alert("Must override updateData!")}render(){this.chart.render()}updateData(){var t=s.tick_record.length,e=-1;this.data[0].dataPoints.length>0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(34),n=i(36);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new n(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),t>300&&(t=300),this.fps=t,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),n=i(6),a=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new n(t[0],t[1],this);e.anatomy.addDefaultCell(a.mouth,0,0),e.anatomy.addDefaultCell(a.producer,1,1),e.anatomy.addDefaultCell(a.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==a.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==a.wall&&this.changeCell(t.col,t.row,a.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case n.up:o=-1;break;case n.down:o=1;break;case n.right:i=1;break;case n.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;pthis.organism_record&&(this.organism_record=t),$("#org-record").text("Highest count: "+this.env.organism_record),$("#avg-mut").text("Average Mutation Rate: "+Math.round(100*this.env.averageMutability())/100),$("#largest-org").text("Largest Organism: "+this.env.largest_cell_count+" cells")}reset(){this.setChart()}}},function(t,e,i){const s=i(2),o=i(8);t.exports=class extends o{constructor(){super("Population")}setData(){for(var t in this.clear(),this.data.push({type:"line",markerType:"none",color:"black",showInLegend:!0,name:"pop1",legendText:"Total Population",dataPoints:[]}),s.tick_record){var e=s.tick_record[t],i=s.pop_counts[t];this.data[0].dataPoints.push({x:e,y:i})}}addNewest(){var t=s.tick_record.length-1,e=s.tick_record[t],i=s.pop_counts[t];this.data[0].dataPoints.push({x:e,y:i})}removeOldest(){this.data[0].dataPoints.shift()}}},function(t,e,i){const s=i(2),o=i(8);t.exports=class extends o{constructor(){super("Species")}setData(){for(var t in this.clear(),this.data.push({type:"line",markerType:"none",color:"black",showInLegend:!0,name:"spec",legendText:"Number of Species",dataPoints:[]}),s.tick_record){var e=s.tick_record[t],i=s.species_counts[t];this.data[0].dataPoints.push({x:e,y:i})}}addNewest(){var t=s.tick_record.length-1,e=s.tick_record[t],i=s.species_counts[t];this.data[0].dataPoints.push({x:e,y:i})}removeOldest(){this.data[0].dataPoints.shift()}}},function(t,e,i){const s=i(2),o=i(8);t.exports=class extends o{constructor(){super("Mutation Rate")}setData(){for(var t in this.clear(),this.data.push({type:"line",markerType:"none",color:"black",showInLegend:!0,name:"pop1",legendText:"Average Mutation Rate",dataPoints:[]}),s.tick_record){var e=s.tick_record[t],i=s.av_mut_rates[t];this.data[0].dataPoints.push({x:e,y:i})}}addNewest(){var t=s.tick_record.length-1,e=s.tick_record[t],i=s.av_mut_rates[t];this.data[0].dataPoints.push({x:e,y:i})}removeOldest(){this.data[0].dataPoints.shift()}}},function(t,e,i){const s=i(9),o=i(6),r=i(11),n=i(10),a=i(0),l=i(35),h=i(12);t.exports=class extends s{constructor(){super(),this.is_active=!0;this.renderer=new n("editor-canvas","editor-env",13),this.controller=new l(this,this.renderer.canvas),this.grid_map=new r(15,15,13),this.clear()}update(){this.is_active&&this.renderer.renderHighlights()}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderFull()}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}addCellToOrg(t,e,i){var s=this.grid_map.getCenter(),o=t-s[0],r=e-s[1],n=this.organism.anatomy.getLocalCell(o,r);if(null!=n){var a=this.organism.anatomy.replaceCell(i,n.loc_col,n.loc_row,!1);this.changeCell(t,e,i,a)}else this.organism.anatomy.canAddCellAt(o,r)&&this.changeCell(t,e,i,this.organism.anatomy.addDefaultCell(i,o,r));this.organism.species=new h(this.organism.anatomy,null,0)}removeCellFromOrg(t,e){var i=this.grid_map.getCenter(),s=t-i[0],o=e-i[1];0!=s||0!=o?null!=this.organism.anatomy.getLocalCell(s,o)&&this.organism.anatomy.removeCell(s,o)&&(this.changeCell(t,e,a.empty,null),this.organism.species=new h(this.organism.anatomy,null,0)):alert("Cannot remove center cell")}setOrganismToCopyOf(t){this.grid_map.fillGrid(a.empty);var e=this.grid_map.getCenter();this.organism=new o(e[0],e[1],this,t),this.organism.updateGrid(),this.controller.updateDetails(),this.controller.new_species=!1}getCopyOfOrg(){return new o(0,0,null,this.organism)}clear(){this.grid_map.fillGrid(a.empty);var t=this.grid_map.getCenter();this.organism=new o(t[0],t[1],this,null),this.organism.anatomy.addDefaultCell(a.mouth,0,0),this.organism.updateGrid(),this.organism.species=new h(this.organism.anatomy,null,0)}}},function(t,e,i){const s=i(13),o=i(7),r=i(0),n=i(3),a=i(1);t.exports=class extends s{constructor(t,e){super(t,e),this.mode=o.None,this.edit_cell_type=null,this.highlight_org=!1,this.new_species=!1,this.defineCellTypeSelection(),this.defineEditorDetails()}mouseMove(){(this.right_click||this.left_click)&&this.editOrganism()}mouseDown(){this.editOrganism()}mouseUp(){}getCurLocalCell(){return this.env.organism.anatomy.getLocalCell(this.mouse_c-this.env.organism.c,this.mouse_r-this.env.organism.r)}editOrganism(){if(null!=this.edit_cell_type&&this.mode==o.Edit){if(this.left_click)if(this.edit_cell_type==r.eye&&this.cur_cell.state==r.eye){var t=this.getCurLocalCell();t.direction=n.rotateRight(t.direction),this.env.renderFull()}else this.env.addCellToOrg(this.mouse_c,this.mouse_r,this.edit_cell_type);else this.right_click&&this.env.removeCellFromOrg(this.mouse_c,this.mouse_r);this.new_species=!0,this.setBrainPanelVisibility(),this.setMoveRangeVisibility(),this.updateDetails()}}updateDetails(){$(".cell-count").text("Cell count: "+this.env.organism.anatomy.cells.length)}defineCellTypeSelection(){var t=this;$(".cell-type").click((function(){switch(this.id){case"mouth":t.edit_cell_type=r.mouth;break;case"producer":t.edit_cell_type=r.producer;break;case"mover":t.edit_cell_type=r.mover;break;case"killer":t.edit_cell_type=r.killer;break;case"armor":t.edit_cell_type=r.armor;break;case"eye":t.edit_cell_type=r.eye}$(".cell-type").css("border-color","black");var e="#"+this.id+".cell-type";$(e).css("border-color","yellow")}))}defineEditorDetails(){this.details_html=$("#organism-details"),this.edit_details_html=$("#edit-organism-details"),this.decision_names=["ignore","move away","move towards"],$("#move-range-edit").change(function(){this.env.organism.move_range=parseInt($("#move-range-edit").val())}.bind(this)),$("#observation-type-edit").change(function(){this.setBrainEditorValues($("#observation-type-edit").val()),this.setBrainDetails()}.bind(this)),$("#reaction-edit").change(function(){var t=$("#observation-type-edit").val(),e=parseInt($("#reaction-edit").val());this.env.organism.brain.decisions[t]=e,this.setBrainDetails()}.bind(this))}clearDetailsPanel(){$("#organism-details").css("display","none"),$("#edit-organism-details").css("display","none")}setDetailsPanel(){this.clearDetailsPanel();var t=this.env.organism;$(".cell-count").text("Cell count: "+t.anatomy.cells.length),$("#move-range").text("Move Range: "+t.move_range),$("#mutation-rate").text("Mutation Rate: "+t.mutability),a.useGlobalMutability?$("#mutation-rate").css("display","none"):$("#mutation-rate").css("display","block"),this.setMoveRangeVisibility(),this.setBrainPanelVisibility()&&this.setBrainDetails(),$("#organism-details").css("display","block")}setEditorPanel(){this.clearDetailsPanel();var t=this.env.organism;$(".cell-count").text("Cell count: "+t.anatomy.cells.length),this.setMoveRangeVisibility()&&$("#move-range-edit").val(t.move_range),this.setBrainPanelVisibility()&&this.setBrainEditorValues($("#observation-type-edit").val()),$("#cell-selections").css("display","grid"),$("#edit-organism-details").css("display","block")}setBrainPanelVisibility(){var t=this.env.organism;return t.anatomy.has_eyes&&t.anatomy.is_mover?($(".brain-details").css("display","block"),!0):($(".brain-details").css("display","none"),!1)}setBrainDetails(){var t=[],e=[];for(var i in this.env.organism.brain.decisions){var s=this.env.organism.brain.decisions[i];1==s?e.push(i):2==s&&t.push(i)}$(".chase-types").text("Move Towards: "+t),$(".retreat-types").text("Move Away From: "+e)}setMoveRangeVisibility(){return this.env.organism.anatomy.is_mover?($("#move-range-cont").css("display","block"),$("#move-range").css("display","block"),!0):($("#move-range-cont").css("display","none"),$("#move-range").css("display","none"),!1)}setBrainEditorValues(t){$("#observation-type-edit").val(t);var e=this.env.organism.brain.decisions[t];$("#reaction-edit").val(e)}}},function(t,e,i){const s=i(0);var o={empty:"#0E1318",food:"#2F7AB7",wall:"gray",mouth:"#DEB14D",producer:"#15DE59",mover:"#60D4FF",killer:"#F82380",armor:"#7230DB",eye:"#B6C1EA","eye-slit":"#0E1318"};t.exports=class{constructor(t,e){this.world_env=t,this.editor_env=e}loadColorScheme(){for(var t of s.all)t.color=o[t.name];for(var e in s.eye.slit_color=o["eye-slit"],o)$("#"+e+".cell-type ").css("background-color",o[e]),$("#"+e+".cell-legend-type").css("background-color",o[e]);this.world_env.renderer.renderFullGrid(this.world_env.grid_map.grid),this.editor_env.renderer.renderFullGrid(this.editor_env.grid_map.grid)}}}]); \ No newline at end of file +!function(t){var e={};function i(s){if(e[s])return e[s].exports;var o=e[s]={i:s,l:!1,exports:{}};return t[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(s,o,function(e){return t[e]}.bind(null,o));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=15)}([function(t,e){class i{constructor(t){this.name=t,this.color="black"}render(t,e,i){t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(t,e,i){if(t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,n=i/2+i/4,a=i/4;t.translate(e.x+s,e.y+s),t.rotate(90*e.cell_owner.getAbsoluteDirection()*Math.PI/180),t.fillStyle=this.slit_color,t.fillRect(o,r,a,n),t.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),t.exports=s},function(t,e,i){const s=i(6),o={setDefaults:function(){this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(t){if(1==t){var e=100-this.addProb;this.changeProb=e/2,this.removeProb=e/2}else if(2==t){e=100-this.changeProb;this.addProb=e/2,this.removeProb=e/2}else{e=100-this.removeProb;this.changeProb=e/2,this.addProb=e/2}}};o.setDefaults(),t.exports=o},function(t,e,s){const o=s(0),r=s(12),n={init:function(){this.extant_species=[],this.extinct_species=[],this.min_discard=10,this.record_size_limit=500},setEnv:function(t){this.env=t,this.setData()},addSpecies:function(t,e){var i=new r(t.anatomy,e,this.env.total_ticks);return this.extant_species.push(i),t.species=i,i},addSpeciesObj:function(t){return this.extant_species.push(t),t},fossilize:function(t){for(i in t.end_tick=this.env.total_ticks,this.extant_species){var e=this.extant_species[i];if(e==t)return this.extant_species.splice(i,1),!(t.cumulative_pop0&&(e=this.env.total_cells/this.env.organisms.length),this.av_cells.push(e),this.av_cell_counts.push(this.calcCellCountAverages()),this.tick_record.length>this.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift())},calcCellCountAverages(){var t=this.env.organisms.length,e={};for(let t of o.living)e[t.name]=0;for(let t of this.extant_species)for(let i in t.cell_counts)e[i]+=t.cell_counts[i]*t.population;if(0==t)return e;for(let i in e)e[i]/=t;return e},clear_record:function(){this.extant_species=[],this.extinct_species=[],this.setData()}};n.init(),t.exports=n},function(t,e){const i={up:0,right:1,down:2,left:3,scalars:[[0,-1],[1,0],[0,1],[-1,0]],getRandomDirection:function(){return Math.floor(4*Math.random())},getRandomScalar:function(){return this.scalars[Math.floor(Math.random()*this.scalars.length)]},getOppositeDirection:function(t){switch(t){case this.up:return this.down;case this.down:return this.up;case this.left:return this.right;case this.right:return this.left}},rotateRight:function(t){return++t>3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=n.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var a of this.anatomy.cells){var l=this.c+a.rotatedCol(this.rotation),h=this.r+a.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=n.getRandomDirection(),this.move_count=0,!0;var t=n.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=n.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var n=e;n!=s;n++){var a=this.env.grid_map.cellAt(t,n);if(!this.isPassableCell(a,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(n=t;n!=i;n++){a=this.env.grid_map.cellAt(n,e);if(!this.isPassableCell(a,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var n of this.anatomy.cells){var a=this.getRealCell(n,t,e,i);if(null==a)return!1;if(!(a.owner==this||a.state==s.empty||!r.foodBlocksReproduction&&a.state==s.food||o&&n.state==s.armor&&a.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(n.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),n=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new n(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),t>300&&(t=300),this.fps=t,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),n=i(7),a=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.total_cells=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.total_cells-=this.organisms[e].anatomy.cells.length,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new n(t[0],t[1],this);e.anatomy.addDefaultCell(a.mouth,0,0),e.anatomy.addDefaultCell(a.producer,1,1),e.anatomy.addDefaultCell(a.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length),this.total_cells+=t.anatomy.cells.length}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==a.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==a.wall&&this.changeCell(t.col,t.row,a.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case n.up:o=-1;break;case n.down:o=1;break;case n.right:i=1;break;case n.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;p this.largest_cell_count) this.largest_cell_count = organism.anatomy.cells.length; + this.total_cells += organism.anatomy.cells.length; } averageMutability() { @@ -122,12 +125,13 @@ class WorldEnvironment extends Environment{ } } - reset(clear_walls=true) { + reset() { this.organisms = []; this.grid_map.fillGrid(CellStates.empty); this.renderer.renderFullGrid(this.grid_map.grid); this.total_mutability = 0; this.total_ticks = 0; + this.total_cells = 0; FossilRecord.clear_record(); this.OriginOfLife(); } diff --git a/src/Stats/Charts/CellsChart.js b/src/Stats/Charts/CellsChart.js new file mode 100644 index 0000000..5110941 --- /dev/null +++ b/src/Stats/Charts/CellsChart.js @@ -0,0 +1,51 @@ +const CellStates = require("../../Organism/Cell/CellStates"); +const FossilRecord = require("../FossilRecord"); +const ChartController = require("./ChartController"); + +class CellsChart extends ChartController { + constructor() { + super("Organism Size / Composition"); + } + + setData() { + this.clear(); + //this.mouth, this.producer, this.mover, this.killer, this.armor, this.eye + this.data.push({ + type: "line", + markerType: "none", + color: 'black', + showInLegend: true, + name: "pop1", + legendText: "Avg. organism size", + dataPoints: [] + } + ); + for (var c of CellStates.living) { + this.data.push({ + type: "line", + markerType: "none", + color: c.color, + showInLegend: true, + name: c.name, + legendText: "Avg. " + c.name + " cells", + dataPoints: [] + } + ); + } + this.addAllDataPoints(); + } + + addDataPoint(i) { + var t = FossilRecord.tick_record[i]; + var p = FossilRecord.av_cells[i]; + this.data[0].dataPoints.push({x:t, y:p}); + var j=1; + for (var name in FossilRecord.av_cell_counts[i]) { + var count = FossilRecord.av_cell_counts[i][name]; + this.data[j].dataPoints.push({x:t,y:count}) + j++; + } + } +} + +module.exports = CellsChart; \ No newline at end of file diff --git a/src/Stats/Charts/ChartController.js b/src/Stats/Charts/ChartController.js index a8825f5..52f5757 100644 --- a/src/Stats/Charts/ChartController.js +++ b/src/Stats/Charts/ChartController.js @@ -18,6 +18,12 @@ class ChartController { alert("Must override updateData!"); } + addAllDataPoints(){ + for (var i in FossilRecord.tick_record) { + this.addDataPoint(i) + } + } + render() { this.chart.render(); } @@ -39,11 +45,18 @@ class ChartController { } addNewest() { - alert("Must override addNewest!"); + var i = FossilRecord.tick_record.length-1; + this.addDataPoint(i); + } + + addDataPoint(i) { + alert("Must override addDataPoint") } removeOldest() { - alert("Must override addNewest!"); + for (var dps of this.data) { + dps.dataPoints.shift(); + } } clear() { diff --git a/src/Stats/Charts/MutationChart.js b/src/Stats/Charts/MutationChart.js index 9cc4562..f211bdb 100644 --- a/src/Stats/Charts/MutationChart.js +++ b/src/Stats/Charts/MutationChart.js @@ -18,24 +18,14 @@ class MutationChart extends ChartController { dataPoints: [] } ); - for (var i in FossilRecord.tick_record) { - var t = FossilRecord.tick_record[i]; - var p = FossilRecord.av_mut_rates[i]; - this.data[0].dataPoints.push({x:t, y:p}); - } - // console.log(this.data) + this.addAllDataPoints(); } - addNewest() { - var i = FossilRecord.tick_record.length-1; + addDataPoint(i) { var t = FossilRecord.tick_record[i]; var p = FossilRecord.av_mut_rates[i]; this.data[0].dataPoints.push({x:t, y:p}); } - - removeOldest() { - this.data[0].dataPoints.shift(); - } } module.exports = MutationChart; \ No newline at end of file diff --git a/src/Stats/Charts/PopulationChart.js b/src/Stats/Charts/PopulationChart.js index bb3eba4..99a02af 100644 --- a/src/Stats/Charts/PopulationChart.js +++ b/src/Stats/Charts/PopulationChart.js @@ -18,24 +18,14 @@ class PopulationChart extends ChartController { dataPoints: [] } ); - for (var i in FossilRecord.tick_record) { - var t = FossilRecord.tick_record[i]; - var p = FossilRecord.pop_counts[i]; - this.data[0].dataPoints.push({x:t, y:p}); - } - // console.log(this.data) + this.addAllDataPoints(); } - addNewest() { - var i = FossilRecord.tick_record.length-1; + addDataPoint(i) { var t = FossilRecord.tick_record[i]; var p = FossilRecord.pop_counts[i]; this.data[0].dataPoints.push({x:t, y:p}); } - - removeOldest() { - this.data[0].dataPoints.shift(); - } } module.exports = PopulationChart; \ No newline at end of file diff --git a/src/Stats/Charts/SpeciesChart.js b/src/Stats/Charts/SpeciesChart.js index b330a04..50c6b84 100644 --- a/src/Stats/Charts/SpeciesChart.js +++ b/src/Stats/Charts/SpeciesChart.js @@ -18,23 +18,14 @@ class SpeciesChart extends ChartController { dataPoints: [] } ); - for (var i in FossilRecord.tick_record) { - var t = FossilRecord.tick_record[i]; - var p = FossilRecord.species_counts[i]; - this.data[0].dataPoints.push({x:t, y:p}); - } + this.addAllDataPoints(); } - addNewest() { - var i = FossilRecord.tick_record.length-1; + addDataPoint(i) { var t = FossilRecord.tick_record[i]; var p = FossilRecord.species_counts[i]; this.data[0].dataPoints.push({x:t, y:p}); } - - removeOldest() { - this.data[0].dataPoints.shift(); - } } module.exports = SpeciesChart; \ No newline at end of file diff --git a/src/Stats/FossilRecord.js b/src/Stats/FossilRecord.js index 8da97ad..8a53c48 100644 --- a/src/Stats/FossilRecord.js +++ b/src/Stats/FossilRecord.js @@ -1,3 +1,4 @@ +const CellStates = require("../Organism/Cell/CellStates"); const Species = require("./Species"); const FossilRecord = { @@ -9,11 +10,11 @@ const FossilRecord = { this.min_discard = 10; this.record_size_limit = 500; // store this many data points - this.setData(); }, setEnv: function(env) { this.env = env; + this.setData(); }, addSpecies: function(org, ancestor) { @@ -66,9 +67,10 @@ const FossilRecord = { // all parallel arrays this.tick_record = [0]; this.pop_counts = [1]; - this.av_pop_counts = [1] this.species_counts = [1]; this.av_mut_rates = [5]; + this.av_cells = [3]; + this.av_cell_counts = [this.calcCellCountAverages()]; }, updateData() { @@ -77,15 +79,41 @@ const FossilRecord = { this.pop_counts.push(this.env.organisms.length); this.species_counts.push(this.extant_species.length); this.av_mut_rates.push(this.env.averageMutability()); + let av_cell = 0; + if (this.env.organisms.length > 0) { + av_cell = this.env.total_cells / this.env.organisms.length; + } + this.av_cells.push(av_cell); + this.av_cell_counts.push(this.calcCellCountAverages()) + if (this.tick_record.length > this.record_size_limit) { this.tick_record.shift(); this.pop_counts.shift(); - this.av_pop_counts.shift(); this.species_counts.shift(); this.av_mut_rates.shift(); + this.av_cells.shift(); } }, + calcCellCountAverages() { + var total_org = this.env.organisms.length; + var cell_counts = {}; + for (let c of CellStates.living) { + cell_counts[c.name] = 0; + } + for (let s of this.extant_species) { + for (let name in s.cell_counts) { + cell_counts[name] += s.cell_counts[name] * s.population; + } + } + if (total_org == 0) + return cell_counts; + for (let c in cell_counts) { + cell_counts[c] /= total_org; + } + return cell_counts; + }, + clear_record: function() { this.extant_species = []; this.extinct_species = []; diff --git a/src/Stats/Species.js b/src/Stats/Species.js index 299faee..37daadd 100644 --- a/src/Stats/Species.js +++ b/src/Stats/Species.js @@ -1,3 +1,5 @@ +const CellStates = require("../Organism/Cell/CellStates"); + class Species { constructor(anatomy, ancestor, start_tick) { this.anatomy = anatomy; @@ -14,6 +16,18 @@ class Species { } this.name = '_' + Math.random().toString(36).substr(2, 9); this.extinct = false; + this.calcAnatomyDetails(); + } + + calcAnatomyDetails() { + var cell_counts = {}; + for (let c of CellStates.living) { + cell_counts[c.name] = 0; + } + for (let cell of this.anatomy.cells) { + cell_counts[cell.state.name]+=1; + } + this.cell_counts=cell_counts; } addPop() { diff --git a/src/Stats/StatsPanel.js b/src/Stats/StatsPanel.js index cfc3dbe..4487861 100644 --- a/src/Stats/StatsPanel.js +++ b/src/Stats/StatsPanel.js @@ -1,9 +1,11 @@ const PopulationChart = require("./Charts/PopulationChart"); const SpeciesChart = require("./Charts/SpeciesChart"); const MutationChart = require("./Charts/MutationChart"); +const CellsChart = require("./Charts/CellsChart"); +const FossilRecord = require("./FossilRecord"); -const ChartSelections = [PopulationChart, SpeciesChart, MutationChart]; +const ChartSelections = [PopulationChart, SpeciesChart, CellsChart, MutationChart]; class StatsPanel { constructor(env) { @@ -47,12 +49,11 @@ class StatsPanel { updateDetails() { var org_count = this.env.organisms.length; - $('#org-count').text("Organism count: " + org_count); - if (org_count > this.organism_record) - this.organism_record = org_count; - $('#org-record').text("Highest count: " + this.env.organism_record); + $('#org-count').text("Total Population: " + org_count); + $('#species-count').text("Number of Species: " + FossilRecord.extant_species.length); + $('#largest-org').text("Largest Organism Ever: " + this.env.largest_cell_count + " cells"); $('#avg-mut').text("Average Mutation Rate: " + Math.round(this.env.averageMutability() * 100) / 100); - $('#largest-org').text("Largest Organism: " + this.env.largest_cell_count + " cells"); + } From 2e3ad6982d6db8c01900191b086ea19d321bbb7e Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Thu, 11 Feb 2021 14:07:59 -0700 Subject: [PATCH 6/9] Made cell stats more efficient --- dist/index.html | 1 + dist/js/bundle.js | 2 +- src/Stats/Charts/CellsChart.js | 5 ++++- src/Stats/Charts/ChartController.js | 4 ++-- src/Stats/FossilRecord.js | 17 +++++++++++++---- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/dist/index.html b/dist/index.html index df1b268..e34cb09 100644 --- a/dist/index.html +++ b/dist/index.html @@ -233,6 +233,7 @@ +

diff --git a/dist/js/bundle.js b/dist/js/bundle.js index 8fdf209..a449bd2 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1 +1 @@ -!function(t){var e={};function i(s){if(e[s])return e[s].exports;var o=e[s]={i:s,l:!1,exports:{}};return t[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(s,o,function(e){return t[e]}.bind(null,o));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=15)}([function(t,e){class i{constructor(t){this.name=t,this.color="black"}render(t,e,i){t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(t,e,i){if(t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,n=i/2+i/4,a=i/4;t.translate(e.x+s,e.y+s),t.rotate(90*e.cell_owner.getAbsoluteDirection()*Math.PI/180),t.fillStyle=this.slit_color,t.fillRect(o,r,a,n),t.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),t.exports=s},function(t,e,i){const s=i(6),o={setDefaults:function(){this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(t){if(1==t){var e=100-this.addProb;this.changeProb=e/2,this.removeProb=e/2}else if(2==t){e=100-this.changeProb;this.addProb=e/2,this.removeProb=e/2}else{e=100-this.removeProb;this.changeProb=e/2,this.addProb=e/2}}};o.setDefaults(),t.exports=o},function(t,e,s){const o=s(0),r=s(12),n={init:function(){this.extant_species=[],this.extinct_species=[],this.min_discard=10,this.record_size_limit=500},setEnv:function(t){this.env=t,this.setData()},addSpecies:function(t,e){var i=new r(t.anatomy,e,this.env.total_ticks);return this.extant_species.push(i),t.species=i,i},addSpeciesObj:function(t){return this.extant_species.push(t),t},fossilize:function(t){for(i in t.end_tick=this.env.total_ticks,this.extant_species){var e=this.extant_species[i];if(e==t)return this.extant_species.splice(i,1),!(t.cumulative_pop0&&(e=this.env.total_cells/this.env.organisms.length),this.av_cells.push(e),this.av_cell_counts.push(this.calcCellCountAverages()),this.tick_record.length>this.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift())},calcCellCountAverages(){var t=this.env.organisms.length,e={};for(let t of o.living)e[t.name]=0;for(let t of this.extant_species)for(let i in t.cell_counts)e[i]+=t.cell_counts[i]*t.population;if(0==t)return e;for(let i in e)e[i]/=t;return e},clear_record:function(){this.extant_species=[],this.extinct_species=[],this.setData()}};n.init(),t.exports=n},function(t,e){const i={up:0,right:1,down:2,left:3,scalars:[[0,-1],[1,0],[0,1],[-1,0]],getRandomDirection:function(){return Math.floor(4*Math.random())},getRandomScalar:function(){return this.scalars[Math.floor(Math.random()*this.scalars.length)]},getOppositeDirection:function(t){switch(t){case this.up:return this.down;case this.down:return this.up;case this.left:return this.right;case this.right:return this.left}},rotateRight:function(t){return++t>3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=n.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var a of this.anatomy.cells){var l=this.c+a.rotatedCol(this.rotation),h=this.r+a.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=n.getRandomDirection(),this.move_count=0,!0;var t=n.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=n.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var n=e;n!=s;n++){var a=this.env.grid_map.cellAt(t,n);if(!this.isPassableCell(a,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(n=t;n!=i;n++){a=this.env.grid_map.cellAt(n,e);if(!this.isPassableCell(a,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var n of this.anatomy.cells){var a=this.getRealCell(n,t,e,i);if(null==a)return!1;if(!(a.owner==this||a.state==s.empty||!r.foodBlocksReproduction&&a.state==s.food||o&&n.state==s.armor&&a.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(n.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),n=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new n(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),t>300&&(t=300),this.fps=t,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),n=i(7),a=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.total_cells=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.total_cells-=this.organisms[e].anatomy.cells.length,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new n(t[0],t[1],this);e.anatomy.addDefaultCell(a.mouth,0,0),e.anatomy.addDefaultCell(a.producer,1,1),e.anatomy.addDefaultCell(a.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length),this.total_cells+=t.anatomy.cells.length}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==a.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==a.wall&&this.changeCell(t.col,t.row,a.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case n.up:o=-1;break;case n.down:o=1;break;case n.right:i=1;break;case n.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;p0&&(e=this.env.total_cells/this.total_relavent_organisms),this.av_cells.push(e),this.tick_record.length>this.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift(),this.av_cell_counts.shift())},calcCellCountAverages(){var t=0,e={};for(let t of o.living)e[t.name]=0;var i=!0;for(let s of this.extant_species)if(!(s.cumulative_pop3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=a.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var n of this.anatomy.cells){var l=this.c+n.rotatedCol(this.rotation),h=this.r+n.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=a.getRandomDirection(),this.move_count=0,!0;var t=a.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=a.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var a=e;a!=s;a++){var n=this.env.grid_map.cellAt(t,a);if(!this.isPassableCell(n,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(a=t;a!=i;a++){n=this.env.grid_map.cellAt(a,e);if(!this.isPassableCell(n,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var a of this.anatomy.cells){var n=this.getRealCell(a,t,e,i);if(null==n)return!1;if(!(n.owner==this||n.state==s.empty||!r.foodBlocksReproduction&&n.state==s.food||o&&a.state==s.armor&&n.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(a.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),a=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new a(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),t>300&&(t=300),this.fps=t,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),a=i(7),n=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.total_cells=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.total_cells-=this.organisms[e].anatomy.cells.length,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new a(t[0],t[1],this);e.anatomy.addDefaultCell(n.mouth,0,0),e.anatomy.addDefaultCell(n.producer,1,1),e.anatomy.addDefaultCell(n.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length),this.total_cells+=t.anatomy.cells.length}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==n.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==n.wall&&this.changeCell(t.col,t.row,n.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case a.up:o=-1;break;case a.down:o=1;break;case a.right:i=1;break;case a.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;p 0) { - av_cell = this.env.total_cells / this.env.organisms.length; + if (this.total_relavent_organisms > 0) { + av_cell = this.env.total_cells / this.total_relavent_organisms; } this.av_cells.push(av_cell); - this.av_cell_counts.push(this.calcCellCountAverages()) if (this.tick_record.length > this.record_size_limit) { this.tick_record.shift(); @@ -92,25 +93,33 @@ const FossilRecord = { this.species_counts.shift(); this.av_mut_rates.shift(); this.av_cells.shift(); + this.av_cell_counts.shift(); } }, calcCellCountAverages() { - var total_org = this.env.organisms.length; + var total_org = 0; var cell_counts = {}; for (let c of CellStates.living) { cell_counts[c.name] = 0; } + var first=true; for (let s of this.extant_species) { + if (s.cumulative_pop < this.min_discard && !first){ + continue; + } for (let name in s.cell_counts) { cell_counts[name] += s.cell_counts[name] * s.population; } + total_org += s.population; + first=false; } if (total_org == 0) return cell_counts; for (let c in cell_counts) { cell_counts[c] /= total_org; } + this.total_relavent_organisms = total_org; return cell_counts; }, From d1119b65e855b859900ea2206adbbae83cd8efc0 Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Fri, 12 Feb 2021 13:03:25 -0700 Subject: [PATCH 7/9] Added headless updates! --- dist/css/style.css | 12 +++++++- dist/index.html | 10 +++++-- dist/js/bundle.js | 2 +- src/Controllers/ControlPanel.js | 36 ++++++++++++++++++++++-- src/Controllers/EnvironmentController.js | 3 ++ src/Engine.js | 15 +++++----- src/Environments/WorldEnvironment.js | 12 +++++--- src/Hyperparameters.js | 2 ++ src/Stats/Charts/ChartController.js | 14 +++++++++ src/Stats/FossilRecord.js | 23 +++++++-------- 10 files changed, 98 insertions(+), 31 deletions(-) diff --git a/dist/css/style.css b/dist/css/style.css index 8bfb661..a9e3b6b 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -9,7 +9,7 @@ body{ * { margin: 0; padding: 0; - font-family: Arial, Helvetica, sans-serif; + font-family: Arial, Helvetica, sans-serif; } #env { @@ -239,6 +239,16 @@ button:hover{ display: none; } +#headless-notification { + display: none; + position: fixed; + color: white; + font-size: 200px; + left: 0; + top: 0; + padding-left: 10px; +} + #minimize { margin: 10px; float: right; diff --git a/dist/index.html b/dist/index.html index e34cb09..d11fe6b 100644 --- a/dist/index.html +++ b/dist/index.html @@ -27,8 +27,9 @@

Simulation Speed

- + +

Target FPS: 60

@@ -230,7 +231,7 @@

@@ -266,7 +267,10 @@ - + +
+
+
diff --git a/dist/js/bundle.js b/dist/js/bundle.js index a449bd2..e5d3e9e 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1 +1 @@ -!function(t){var e={};function i(s){if(e[s])return e[s].exports;var o=e[s]={i:s,l:!1,exports:{}};return t[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(s,o,function(e){return t[e]}.bind(null,o));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=15)}([function(t,e){class i{constructor(t){this.name=t,this.color="black"}render(t,e,i){t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(t,e,i){if(t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,a=i/2+i/4,n=i/4;t.translate(e.x+s,e.y+s),t.rotate(90*e.cell_owner.getAbsoluteDirection()*Math.PI/180),t.fillStyle=this.slit_color,t.fillRect(o,r,n,a),t.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),t.exports=s},function(t,e,i){const s=i(6),o={setDefaults:function(){this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(t){if(1==t){var e=100-this.addProb;this.changeProb=e/2,this.removeProb=e/2}else if(2==t){e=100-this.changeProb;this.addProb=e/2,this.removeProb=e/2}else{e=100-this.removeProb;this.changeProb=e/2,this.addProb=e/2}}};o.setDefaults(),t.exports=o},function(t,e,s){const o=s(0),r=s(12),a={init:function(){this.extant_species=[],this.extinct_species=[],this.min_discard=10,this.total_relavent_organisms=0,this.record_size_limit=500},setEnv:function(t){this.env=t,this.setData()},addSpecies:function(t,e){var i=new r(t.anatomy,e,this.env.total_ticks);return this.extant_species.push(i),t.species=i,i},addSpeciesObj:function(t){return this.extant_species.push(t),t},fossilize:function(t){for(i in t.end_tick=this.env.total_ticks,this.extant_species){var e=this.extant_species[i];if(e==t)return this.extant_species.splice(i,1),!(t.cumulative_pop0&&(e=this.env.total_cells/this.total_relavent_organisms),this.av_cells.push(e),this.tick_record.length>this.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift(),this.av_cell_counts.shift())},calcCellCountAverages(){var t=0,e={};for(let t of o.living)e[t.name]=0;var i=!0;for(let s of this.extant_species)if(!(s.cumulative_pop3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=a.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var n of this.anatomy.cells){var l=this.c+n.rotatedCol(this.rotation),h=this.r+n.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=a.getRandomDirection(),this.move_count=0,!0;var t=a.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=a.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var a=e;a!=s;a++){var n=this.env.grid_map.cellAt(t,a);if(!this.isPassableCell(n,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(a=t;a!=i;a++){n=this.env.grid_map.cellAt(a,e);if(!this.isPassableCell(n,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var a of this.anatomy.cells){var n=this.getRealCell(a,t,e,i);if(null==n)return!1;if(!(n.owner==this||n.state==s.empty||!r.foodBlocksReproduction&&n.state==s.food||o&&a.state==s.armor&&n.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(a.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),a=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new a(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),t>300&&(t=300),this.fps=t,this.game_loop=setInterval(function(){this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.necessaryUpdate()}.bind(this),1e3/60))}environmentUpdate(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now(),this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),a=i(7),n=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.total_cells=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){this.renderer.renderCells(),this.renderer.renderHighlights()}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.total_cells-=this.organisms[e].anatomy.cells.length,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new a(t[0],t[1],this);e.anatomy.addDefaultCell(n.mouth,0,0),e.anatomy.addDefaultCell(n.producer,1,1),e.anatomy.addDefaultCell(n.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length),this.total_cells+=t.anatomy.cells.length}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==n.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==n.wall&&this.changeCell(t.col,t.row,n.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case a.up:o=-1;break;case a.down:o=1;break;case a.right:i=1;break;case a.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;pthis.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift(),this.av_cell_counts.shift())},calcCellCountAverages(){var t=0,e={};for(let t of o.living)e[t.name]=0;var i=!0;for(let s of this.extant_species)if(!(s.cumulative_pop3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=a.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var n of this.anatomy.cells){var l=this.c+n.rotatedCol(this.rotation),h=this.r+n.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=a.getRandomDirection(),this.move_count=0,!0;var t=a.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=a.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var a=e;a!=s;a++){var n=this.env.grid_map.cellAt(t,a);if(!this.isPassableCell(n,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(a=t;a!=i;a++){n=this.env.grid_map.cellAt(a,e);if(!this.isPassableCell(n,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var a of this.anatomy.cells){var n=this.getRealCell(a,t,e,i);if(null==n)return!1;if(!(n.owner==this||n.state==s.empty||!r.foodBlocksReproduction&&n.state==s.food||o&&a.state==s.armor&&n.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(a.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),a=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new a(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),this.fps=t,this.game_loop=setInterval(function(){this.updateDeltaTime(),this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.updateDeltaTime(),this.necessaryUpdate()}.bind(this),1e3/60))}updateDeltaTime(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now()}environmentUpdate(){this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(this.delta_time),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),a=i(7),n=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){h.headless?this.renderer.cells_to_render.clear():(this.renderer.renderCells(),this.renderer.renderHighlights())}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new a(t[0],t[1],this);e.anatomy.addDefaultCell(n.mouth,0,0),e.anatomy.addDefaultCell(n.producer,1,1),e.anatomy.addDefaultCell(n.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==n.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==n.wall&&this.changeCell(t.col,t.row,n.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case a.up:o=-1;break;case a.down:o=1;break;case a.right:i=1;break;case a.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;p=1&&(e=1,this.opacity_change_rate=-this.opacity_change_rate),this.headless_opacity=e,$("#headless-notification").css("opacity",100*e+"%")}}update(t){$("#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(),s.headless&&this.updateHeadlessIcon(t)}}},function(t,e,i){const s=i(31),o=i(32),r=i(33),a=i(34),n=i(2),l=[s,o,a,r];t.exports=class{constructor(t){this.defineControls(),this.chart_selection=0,this.setChart(),this.env=t,this.last_reset_count=t.reset_count}setChart(t=this.chart_selection){this.chart_controller=new l[t],this.chart_controller.setData(),this.chart_controller.render()}startAutoRender(){this.setChart(),this.render_loop=setInterval(function(){this.updateChart()}.bind(this),1e3)}stopAutoRender(){clearInterval(this.render_loop)}defineControls(){$("#chart-option").change(function(){this.chart_selection=$("#chart-option")[0].selectedIndex,this.setChart()}.bind(this))}updateChart(){this.last_reset_count= 1){ + op=1; + this.opacity_change_rate = -this.opacity_change_rate; + } + this.headless_opacity = op; + $('#headless-notification').css('opacity',(op*100)+'%'); + } + + update(delta_time) { $('#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) + this.updateHeadlessIcon(delta_time); + } } diff --git a/src/Controllers/EnvironmentController.js b/src/Controllers/EnvironmentController.js index f297292..451d2a9 100644 --- a/src/Controllers/EnvironmentController.js +++ b/src/Controllers/EnvironmentController.js @@ -4,6 +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"); class EnvironmentController extends CanvasController{ constructor(env, canvas) { @@ -78,6 +79,8 @@ class EnvironmentController extends CanvasController{ } performModeAction() { + if (Hyperparams.headless) + return; var mode = this.mode; var right_click = this.right_click; var left_click = this.left_click; diff --git a/src/Engine.js b/src/Engine.js index 409dcce..a74f693 100644 --- a/src/Engine.js +++ b/src/Engine.js @@ -23,10 +23,8 @@ class Engine { start(fps=60) { if (fps <= 0) fps = 1; - if (fps > 300) - fps = 300; this.fps = fps; - this.game_loop = setInterval(function(){this.environmentUpdate();}.bind(this), 1000/fps); + this.game_loop = setInterval(function(){this.updateDeltaTime();this.environmentUpdate();}.bind(this), 1000/fps); this.running = true; if (this.fps >= render_speed) { if (this.render_loop != null) { @@ -46,14 +44,17 @@ class Engine { setRenderLoop() { if (this.render_loop == null) { - this.render_loop = setInterval(function(){this.necessaryUpdate();}.bind(this), 1000/render_speed); + this.render_loop = setInterval(function(){this.updateDeltaTime();this.necessaryUpdate();}.bind(this), 1000/render_speed); } } + updateDeltaTime() { + this.delta_time = Date.now() - this.last_update; + this.last_update = Date.now(); + } + environmentUpdate() { - this.delta_time = Date.now() - this.last_update; - this.last_update = Date.now(); this.env.update(this.delta_time); this.actual_fps = 1/this.delta_time*1000; if(this.render_loop == null){ @@ -64,7 +65,7 @@ class Engine { necessaryUpdate() { this.env.render(); - this.controlpanel.update(); + this.controlpanel.update(this.delta_time); this.organism_editor.update(); } diff --git a/src/Environments/WorldEnvironment.js b/src/Environments/WorldEnvironment.js index 91107f3..e09add8 100644 --- a/src/Environments/WorldEnvironment.js +++ b/src/Environments/WorldEnvironment.js @@ -22,7 +22,6 @@ class WorldEnvironment extends Environment{ this.largest_cell_count = 0; this.reset_count = 0; this.total_ticks = 0; - this.total_cells = 0; this.data_update_rate = 100; FossilRecord.setEnv(this); } @@ -46,14 +45,21 @@ class WorldEnvironment extends Environment{ } render() { + if (Hyperparams.headless) { + this.renderer.cells_to_render.clear(); + return; + } this.renderer.renderCells(); this.renderer.renderHighlights(); } + renderFull() { + this.renderer.renderFullGrid(this.grid_map.grid); + } + removeOrganisms(org_indeces) { for (var i of org_indeces.reverse()){ this.total_mutability -= this.organisms[i].mutability; - this.total_cells -= this.organisms[i].anatomy.cells.length; this.organisms.splice(i, 1); } if (this.organisms.length == 0 && this.auto_reset){ @@ -78,7 +84,6 @@ class WorldEnvironment extends Environment{ this.organisms.push(organism); if (organism.anatomy.cells.length > this.largest_cell_count) this.largest_cell_count = organism.anatomy.cells.length; - this.total_cells += organism.anatomy.cells.length; } averageMutability() { @@ -131,7 +136,6 @@ class WorldEnvironment extends Environment{ this.renderer.renderFullGrid(this.grid_map.grid); this.total_mutability = 0; this.total_ticks = 0; - this.total_cells = 0; FossilRecord.clear_record(); this.OriginOfLife(); } diff --git a/src/Hyperparameters.js b/src/Hyperparameters.js index c5c7be1..d7c34ed 100644 --- a/src/Hyperparameters.js +++ b/src/Hyperparameters.js @@ -2,6 +2,8 @@ const Neighbors = require("./Grid/Neighbors"); const Hyperparams = { setDefaults: function() { + this.headless = false; + this.lifespanMultiplier = 100; this.foodProdProb = 4; this.foodProdProbScalar = 4; diff --git a/src/Stats/Charts/ChartController.js b/src/Stats/Charts/ChartController.js index 3726b3a..25a1b19 100644 --- a/src/Stats/Charts/ChartController.js +++ b/src/Stats/Charts/ChartController.js @@ -8,6 +8,12 @@ class ChartController { title:{ text: title }, + axisX:{ + minimum: 0, + }, + axisY:{ + minimum: 0, + }, data: this.data }); this.chart.render(); @@ -18,6 +24,13 @@ class ChartController { alert("Must override updateData!"); } + setMinimum() { + var min = 0; + if (this.data[0].dataPoints != []) + min = this.data[0].dataPoints[0].x; + this.chart.options.axisX.minimum = min; + } + addAllDataPoints(){ for (var i in FossilRecord.tick_record) { this.addDataPoint(i) @@ -25,6 +38,7 @@ class ChartController { } render() { + this.setMinimum(); this.chart.render(); } diff --git a/src/Stats/FossilRecord.js b/src/Stats/FossilRecord.js index e012bbb..16e58dd 100644 --- a/src/Stats/FossilRecord.js +++ b/src/Stats/FossilRecord.js @@ -8,7 +8,6 @@ const FossilRecord = { // if an organism has fewer than this cumulative pop, discard them on extinction this.min_discard = 10; - this.total_relavent_organisms = 0; // organisms with greater than ^ cumulative pop this.record_size_limit = 500; // store this many data points }, @@ -67,10 +66,10 @@ const FossilRecord = { setData() { // all parallel arrays this.tick_record = [0]; - this.pop_counts = [1]; - this.species_counts = [1]; - this.av_mut_rates = [5]; - this.av_cells = [3]; + this.pop_counts = [0]; + this.species_counts = [0]; + this.av_mut_rates = [0]; + this.av_cells = [0]; this.av_cell_counts = [this.calcCellCountAverages()]; }, @@ -80,12 +79,7 @@ const FossilRecord = { this.pop_counts.push(this.env.organisms.length); this.species_counts.push(this.extant_species.length); this.av_mut_rates.push(this.env.averageMutability()); - this.av_cell_counts.push(this.calcCellCountAverages()); - let av_cell = 0; - if (this.total_relavent_organisms > 0) { - av_cell = this.env.total_cells / this.total_relavent_organisms; - } - this.av_cells.push(av_cell); + this.calcCellCountAverages(); if (this.tick_record.length > this.record_size_limit) { this.tick_record.shift(); @@ -116,11 +110,14 @@ const FossilRecord = { } if (total_org == 0) return cell_counts; + + var total_cells = 0; for (let c in cell_counts) { + total_cells += cell_counts[c]; cell_counts[c] /= total_org; } - this.total_relavent_organisms = total_org; - return cell_counts; + this.av_cells.push(total_cells / total_org); + this.av_cell_counts.push(cell_counts); }, clear_record: function() { From 5caa653db1a0992c467a799bdf4573c23a0717a3 Mon Sep 17 00:00:00 2001 From: Max Robinson Date: Fri, 12 Feb 2021 17:46:03 -0700 Subject: [PATCH 8/9] Cleaned up a few things --- dist/css/style.css | 6 +++--- dist/index.html | 8 ++++---- dist/js/bundle.js | 2 +- src/Controllers/ControlPanel.js | 2 ++ src/Organism/Cell/CellStates.js | 4 ++-- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/dist/css/style.css b/dist/css/style.css index a9e3b6b..f98f464 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -39,12 +39,12 @@ body{ background-color: #3a4b68; display: grid; grid-template-columns: repeat(3, 1fr); - opacity: 0.8; + /* opacity: 0.8; */ } -.control-panel:hover { +/* .control-panel:hover { opacity: 1; -} +} */ .control-set { margin: 5px; diff --git a/dist/index.html b/dist/index.html index d11fe6b..56477dd 100644 --- a/dist/index.html +++ b/dist/index.html @@ -27,9 +27,9 @@

Simulation Speed

- + - +

Target FPS: 60

@@ -222,7 +222,7 @@
-

Stats

+

Statistics

Total Population:

Number of Species:

Largest Organism Ever:

@@ -267,7 +267,7 @@ - +
diff --git a/dist/js/bundle.js b/dist/js/bundle.js index e5d3e9e..bd3287b 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1 +1 @@ -!function(t){var e={};function i(s){if(e[s])return e[s].exports;var o=e[s]={i:s,l:!1,exports:{}};return t[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(s,o,function(e){return t[e]}.bind(null,o));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=15)}([function(t,e){class i{constructor(t){this.name=t,this.color="black"}render(t,e,i){t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(t,e,i){if(t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,a=i/2+i/4,n=i/4;t.translate(e.x+s,e.y+s),t.rotate(90*e.cell_owner.getAbsoluteDirection()*Math.PI/180),t.fillStyle=this.slit_color,t.fillRect(o,r,n,a),t.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),t.exports=s},function(t,e,i){const s=i(6),o={setDefaults:function(){this.headless=!1,this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(t){if(1==t){var e=100-this.addProb;this.changeProb=e/2,this.removeProb=e/2}else if(2==t){e=100-this.changeProb;this.addProb=e/2,this.removeProb=e/2}else{e=100-this.removeProb;this.changeProb=e/2,this.addProb=e/2}}};o.setDefaults(),t.exports=o},function(t,e,s){const o=s(0),r=s(12),a={init:function(){this.extant_species=[],this.extinct_species=[],this.min_discard=10,this.record_size_limit=500},setEnv:function(t){this.env=t,this.setData()},addSpecies:function(t,e){var i=new r(t.anatomy,e,this.env.total_ticks);return this.extant_species.push(i),t.species=i,i},addSpeciesObj:function(t){return this.extant_species.push(t),t},fossilize:function(t){for(i in t.end_tick=this.env.total_ticks,this.extant_species){var e=this.extant_species[i];if(e==t)return this.extant_species.splice(i,1),!(t.cumulative_popthis.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift(),this.av_cell_counts.shift())},calcCellCountAverages(){var t=0,e={};for(let t of o.living)e[t.name]=0;var i=!0;for(let s of this.extant_species)if(!(s.cumulative_pop3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=a.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var n of this.anatomy.cells){var l=this.c+n.rotatedCol(this.rotation),h=this.r+n.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=a.getRandomDirection(),this.move_count=0,!0;var t=a.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=a.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var a=e;a!=s;a++){var n=this.env.grid_map.cellAt(t,a);if(!this.isPassableCell(n,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(a=t;a!=i;a++){n=this.env.grid_map.cellAt(a,e);if(!this.isPassableCell(n,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var a of this.anatomy.cells){var n=this.getRealCell(a,t,e,i);if(null==n)return!1;if(!(n.owner==this||n.state==s.empty||!r.foodBlocksReproduction&&n.state==s.food||o&&a.state==s.armor&&n.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(a.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),a=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new a(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),this.fps=t,this.game_loop=setInterval(function(){this.updateDeltaTime(),this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.updateDeltaTime(),this.necessaryUpdate()}.bind(this),1e3/60))}updateDeltaTime(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now()}environmentUpdate(){this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(this.delta_time),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),a=i(7),n=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){h.headless?this.renderer.cells_to_render.clear():(this.renderer.renderCells(),this.renderer.renderHighlights())}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new a(t[0],t[1],this);e.anatomy.addDefaultCell(n.mouth,0,0),e.anatomy.addDefaultCell(n.producer,1,1),e.anatomy.addDefaultCell(n.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==n.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==n.wall&&this.changeCell(t.col,t.row,n.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case a.up:o=-1;break;case a.down:o=1;break;case a.right:i=1;break;case a.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;p=1&&(e=1,this.opacity_change_rate=-this.opacity_change_rate),this.headless_opacity=e,$("#headless-notification").css("opacity",100*e+"%")}}update(t){$("#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(),s.headless&&this.updateHeadlessIcon(t)}}},function(t,e,i){const s=i(31),o=i(32),r=i(33),a=i(34),n=i(2),l=[s,o,a,r];t.exports=class{constructor(t){this.defineControls(),this.chart_selection=0,this.setChart(),this.env=t,this.last_reset_count=t.reset_count}setChart(t=this.chart_selection){this.chart_controller=new l[t],this.chart_controller.setData(),this.chart_controller.render()}startAutoRender(){this.setChart(),this.render_loop=setInterval(function(){this.updateChart()}.bind(this),1e3)}stopAutoRender(){clearInterval(this.render_loop)}defineControls(){$("#chart-option").change(function(){this.chart_selection=$("#chart-option")[0].selectedIndex,this.setChart()}.bind(this))}updateChart(){this.last_reset_countthis.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift(),this.av_cell_counts.shift())},calcCellCountAverages(){var t=0,e={};for(let t of o.living)e[t.name]=0;var i=!0;for(let s of this.extant_species)if(!(s.cumulative_pop3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=a.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var n of this.anatomy.cells){var l=this.c+n.rotatedCol(this.rotation),h=this.r+n.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=a.getRandomDirection(),this.move_count=0,!0;var t=a.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=a.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var a=e;a!=s;a++){var n=this.env.grid_map.cellAt(t,a);if(!this.isPassableCell(n,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(a=t;a!=i;a++){n=this.env.grid_map.cellAt(a,e);if(!this.isPassableCell(n,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var a of this.anatomy.cells){var n=this.getRealCell(a,t,e,i);if(null==n)return!1;if(!(n.owner==this||n.state==s.empty||!r.foodBlocksReproduction&&n.state==s.food||o&&a.state==s.armor&&n.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(a.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),a=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new a(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),this.fps=t,this.game_loop=setInterval(function(){this.updateDeltaTime(),this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.updateDeltaTime(),this.necessaryUpdate()}.bind(this),1e3/60))}updateDeltaTime(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now()}environmentUpdate(){this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(this.delta_time),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),a=i(7),n=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){h.headless?this.renderer.cells_to_render.clear():(this.renderer.renderCells(),this.renderer.renderHighlights())}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new a(t[0],t[1],this);e.anatomy.addDefaultCell(n.mouth,0,0),e.anatomy.addDefaultCell(n.producer,1,1),e.anatomy.addDefaultCell(n.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==n.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==n.wall&&this.changeCell(t.col,t.row,n.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case a.up:o=-1;break;case a.down:o=1;break;case a.right:i=1;break;case a.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;p=1&&(e=1,this.opacity_change_rate=-this.opacity_change_rate),this.headless_opacity=e,$("#headless-notification").css("opacity",100*e+"%")}}update(t){$("#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(),s.headless&&this.updateHeadlessIcon(t)}}},function(t,e,i){const s=i(31),o=i(32),r=i(33),a=i(34),n=i(2),l=[s,o,a,r];t.exports=class{constructor(t){this.defineControls(),this.chart_selection=0,this.setChart(),this.env=t,this.last_reset_count=t.reset_count}setChart(t=this.chart_selection){this.chart_controller=new l[t],this.chart_controller.setData(),this.chart_controller.render()}startAutoRender(){this.setChart(),this.render_loop=setInterval(function(){this.updateChart()}.bind(this),1e3)}stopAutoRender(){clearInterval(this.render_loop)}defineControls(){$("#chart-option").change(function(){this.chart_selection=$("#chart-option")[0].selectedIndex,this.setChart()}.bind(this))}updateChart(){this.last_reset_count Date: Mon, 15 Feb 2021 13:15:11 -0700 Subject: [PATCH 9/9] Added axis label --- dist/js/bundle.js | 2 +- src/Stats/Charts/CellsChart.js | 1 + src/Stats/Charts/ChartController.js | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/dist/js/bundle.js b/dist/js/bundle.js index bd3287b..13032a9 100644 --- a/dist/js/bundle.js +++ b/dist/js/bundle.js @@ -1 +1 @@ -!function(t){var e={};function i(s){if(e[s])return e[s].exports;var o=e[s]={i:s,l:!1,exports:{}};return t[s].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=t,i.c=e,i.d=function(t,e,s){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:s})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)i.d(s,o,function(e){return t[e]}.bind(null,o));return s},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=15)}([function(t,e){class i{constructor(t){this.name=t,this.color="black"}render(t,e,i){t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i)}}const s={empty:new class extends i{constructor(){super("empty")}},food:new class extends i{constructor(){super("food")}},wall:new class extends i{constructor(){super("wall")}},mouth:new class extends i{constructor(){super("mouth")}},producer:new class extends i{constructor(){super("producer")}},mover:new class extends i{constructor(){super("mover")}},killer:new class extends i{constructor(){super("killer")}},armor:new class extends i{constructor(){super("armor")}},eye:new class extends i{constructor(){super("eye"),this.slit_color="black"}render(t,e,i){if(t.fillStyle=this.color,t.fillRect(e.x,e.y,i,i),1!=i){var s=i/2,o=-i/8,r=-s,a=i/2+i/4,n=i/4;t.translate(e.x+s,e.y+s),t.rotate(90*e.cell_owner.getAbsoluteDirection()*Math.PI/180),t.fillStyle=this.slit_color,t.fillRect(o,r,n,a),t.setTransform(1,0,0,1,0,0)}}},defineLists(){this.all=[this.empty,this.food,this.wall,this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye],this.living=[this.mouth,this.producer,this.mover,this.killer,this.armor,this.eye]},getRandomName:function(){return this.all[Math.floor(Math.random()*this.all.length)].name},getRandomLivingType:function(){return this.living[Math.floor(Math.random()*this.living.length)]}};s.defineLists(),t.exports=s},function(t,e,i){const s=i(6),o={setDefaults:function(){this.headless=!1,this.lifespanMultiplier=100,this.foodProdProb=4,this.foodProdProbScalar=4,this.killableNeighbors=s.adjacent,this.edibleNeighbors=s.adjacent,this.growableNeighbors=s.adjacent,this.useGlobalMutability=!1,this.globalMutability=5,this.addProb=33,this.changeProb=33,this.removeProb=33,this.moversCanRotate=!0,this.offspringRotate=!0,this.foodBlocksReproduction=!0,this.moversCanProduce=!1,this.instaKill=!1,this.lookRange=20,this.foodDropProb=0},balanceMutationProbs:function(t){if(1==t){var e=100-this.addProb;this.changeProb=e/2,this.removeProb=e/2}else if(2==t){e=100-this.changeProb;this.addProb=e/2,this.removeProb=e/2}else{e=100-this.removeProb;this.changeProb=e/2,this.addProb=e/2}}};o.setDefaults(),t.exports=o},function(t,e,s){const o=s(0),r=s(12),a={init:function(){this.extant_species=[],this.extinct_species=[],this.min_discard=10,this.record_size_limit=500},setEnv:function(t){this.env=t,this.setData()},addSpecies:function(t,e){var i=new r(t.anatomy,e,this.env.total_ticks);return this.extant_species.push(i),t.species=i,i},addSpeciesObj:function(t){return this.extant_species.push(t),t},fossilize:function(t){for(i in t.end_tick=this.env.total_ticks,this.extant_species){var e=this.extant_species[i];if(e==t)return this.extant_species.splice(i,1),!(t.cumulative_popthis.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift(),this.av_cell_counts.shift())},calcCellCountAverages(){var t=0,e={};for(let t of o.living)e[t.name]=0;var i=!0;for(let s of this.extant_species)if(!(s.cumulative_pop3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=a.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var n of this.anatomy.cells){var l=this.c+n.rotatedCol(this.rotation),h=this.r+n.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=a.getRandomDirection(),this.move_count=0,!0;var t=a.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=a.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var a=e;a!=s;a++){var n=this.env.grid_map.cellAt(t,a);if(!this.isPassableCell(n,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(a=t;a!=i;a++){n=this.env.grid_map.cellAt(a,e);if(!this.isPassableCell(n,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var a of this.anatomy.cells){var n=this.getRealCell(a,t,e,i);if(null==n)return!1;if(!(n.owner==this||n.state==s.empty||!r.foodBlocksReproduction&&n.state==s.food||o&&a.state==s.armor&&n.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(a.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),a=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new a(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),this.fps=t,this.game_loop=setInterval(function(){this.updateDeltaTime(),this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.updateDeltaTime(),this.necessaryUpdate()}.bind(this),1e3/60))}updateDeltaTime(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now()}environmentUpdate(){this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(this.delta_time),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),a=i(7),n=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){h.headless?this.renderer.cells_to_render.clear():(this.renderer.renderCells(),this.renderer.renderHighlights())}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new a(t[0],t[1],this);e.anatomy.addDefaultCell(n.mouth,0,0),e.anatomy.addDefaultCell(n.producer,1,1),e.anatomy.addDefaultCell(n.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==n.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==n.wall&&this.changeCell(t.col,t.row,n.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case a.up:o=-1;break;case a.down:o=1;break;case a.right:i=1;break;case a.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;p=1&&(e=1,this.opacity_change_rate=-this.opacity_change_rate),this.headless_opacity=e,$("#headless-notification").css("opacity",100*e+"%")}}update(t){$("#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(),s.headless&&this.updateHeadlessIcon(t)}}},function(t,e,i){const s=i(31),o=i(32),r=i(33),a=i(34),n=i(2),l=[s,o,a,r];t.exports=class{constructor(t){this.defineControls(),this.chart_selection=0,this.setChart(),this.env=t,this.last_reset_count=t.reset_count}setChart(t=this.chart_selection){this.chart_controller=new l[t],this.chart_controller.setData(),this.chart_controller.render()}startAutoRender(){this.setChart(),this.render_loop=setInterval(function(){this.updateChart()}.bind(this),1e3)}stopAutoRender(){clearInterval(this.render_loop)}defineControls(){$("#chart-option").change(function(){this.chart_selection=$("#chart-option")[0].selectedIndex,this.setChart()}.bind(this))}updateChart(){this.last_reset_countthis.record_size_limit&&(this.tick_record.shift(),this.pop_counts.shift(),this.species_counts.shift(),this.av_mut_rates.shift(),this.av_cells.shift(),this.av_cell_counts.shift())},calcCellCountAverages(){var t=0,e={};for(let t of o.living)e[t.name]=0;var i=!0;for(let s of this.extant_species)if(!(s.cumulative_pop3&&(t=0),t}};t.exports=i},function(t,e,i){i(0);const s=i(3);t.exports=class{constructor(t,e,i,s){this.state=t,this.org=e,this.loc_col=i,this.loc_row=s;var o=Math.max(2*Math.abs(s)+2,2*Math.abs(i)+2);this.org.anatomy.birth_distance0&&(e=this.data[0].dataPoints[this.data[0].dataPoints.length-1].x,e=this.data[0].dataPoints[0].x),e1){c=this.anatomy.getRandomCell();e=this.anatomy.removeCell(c.loc_col,c.loc_row)}return e}attemptMove(){var t=a.scalars[this.direction],e=t[0],i=t[1],o=this.c+e,r=this.r+i;if(this.isClear(o,r)){for(var n of this.anatomy.cells){var l=this.c+n.rotatedCol(this.rotation),h=this.r+n.rotatedRow(this.rotation);this.env.changeCell(l,h,s.empty,null)}return this.c=o,this.r=r,this.updateGrid(),!0}return!1}attemptRotate(){if(!this.can_rotate)return this.direction=a.getRandomDirection(),this.move_count=0,!0;var t=a.getRandomDirection();if(this.isClear(this.c,this.r,t)){for(var e of this.anatomy.cells){var i=this.c+e.rotatedCol(this.rotation),o=this.r+e.rotatedRow(this.rotation);this.env.changeCell(i,o,s.empty,null)}return this.rotation=t,this.direction=a.getRandomDirection(),this.updateGrid(),this.move_count=0,!0}return!1}changeDirection(t){this.direction=t,this.move_count=0}isStraightPath(t,e,i,s,o){if(t==i){if(e>s){var r=s;s=e,e=r}for(var a=e;a!=s;a++){var n=this.env.grid_map.cellAt(t,a);if(!this.isPassableCell(n,o))return!1}return!0}if(t>i){r=i;i=t,t=r}for(a=t;a!=i;a++){n=this.env.grid_map.cellAt(a,e);if(!this.isPassableCell(n,o))return!1}return!0}isPassableCell(t,e){return null!=t&&(t.state==s.empty||t.owner==this||t.owner==e||t.state==s.food)}isClear(t,e,i=this.rotation,o=!1){for(var a of this.anatomy.cells){var n=this.getRealCell(a,t,e,i);if(null==n)return!1;if(!(n.owner==this||n.state==s.empty||!r.foodBlocksReproduction&&n.state==s.food||o&&a.state==s.armor&&n.state==s.food))return!1}return!0}harm(){this.damage++,(this.damage>=this.maxHealth()||r.instaKill)&&this.die()}die(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,s.food,null)}this.species.decreasePop(),this.living=!1}updateGrid(){for(var t of this.anatomy.cells){var e=this.c+t.rotatedCol(this.rotation),i=this.r+t.rotatedRow(this.rotation);this.env.changeCell(e,i,t.state,t)}}update(){if(this.lifetime++,this.lifetime>this.lifespan())return this.die(),this.living;for(var t of(this.food_collected>=this.foodNeeded()&&this.reproduce(),this.anatomy.cells))if(t.performFunction(),!this.living)return this.living;if(this.anatomy.is_mover){this.move_count++;var e=!1;0==this.ignore_brain_for?e=this.brain.decide():this.ignore_brain_for--;var i=this.attemptMove();if(this.move_count>this.move_range&&!e||!i)this.attemptRotate()||(this.changeDirection(a.getRandomDirection()),e&&(this.ignore_brain_for=this.move_range+1))}return this.living}getRealCell(t,e=this.c,i=this.r,s=this.rotation){var o=e+t.rotatedCol(s),r=i+t.rotatedRow(s);return this.env.grid_map.cellAt(o,r)}}t.exports=c},function(t,e){t.exports={None:0,FoodDrop:1,WallDrop:2,ClickKill:3,Select:4,Edit:5,Clone:6,Drag:7}},function(t,e){t.exports=class{constructor(){}update(){alert("Environment.update() must be overriden")}changeCell(t,e,i,s){this.grid_map.setCellType(t,e,i),this.grid_map.setCellOwner(t,e,s)}}},function(t,e,i){i(0),i(3);t.exports=class{constructor(t,e,i){this.cell_size=i,this.canvas=document.getElementById(t),this.ctx=this.canvas.getContext("2d"),this.fillWindow(e),this.height=this.canvas.height,this.width=this.canvas.width,this.cells_to_render=new Set,this.cells_to_highlight=new Set,this.highlighted_cells=new Set}fillWindow(t){this.fillShape($("#"+t).height(),$("#"+t).width())}fillShape(t,e){this.canvas.width=e,this.canvas.height=t,this.height=this.canvas.height,this.width=this.canvas.width}clear(){this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.height,this.width)}renderFullGrid(t){for(var e of t)for(var i of e)this.renderCell(i)}renderCells(){for(var t of this.cells_to_render)this.renderCell(t);this.cells_to_render.clear()}renderCell(t){t.state.render(this.ctx,t,this.cell_size)}renderOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.renderCell(i)}}addToRender(t){this.highlighted_cells.has(t)&&this.cells_to_highlight.add(t),this.cells_to_render.add(t)}renderHighlights(){for(var t of this.cells_to_highlight)this.renderCellHighlight(t),this.highlighted_cells.add(t);this.cells_to_highlight.clear()}highlightOrganism(t){for(var e of t.anatomy.cells){var i=t.getRealCell(e);this.cells_to_highlight.add(i)}}highlightCell(t){this.cells_to_highlight.add(t)}renderCellHighlight(t,e="yellow"){this.renderCell(t),this.ctx.fillStyle=e,this.ctx.globalAlpha=.5,this.ctx.fillRect(t.x,t.y,this.cell_size,this.cell_size),this.ctx.globalAlpha=1,this.highlighted_cells.add(t)}clearAllHighlights(t=!1){for(var e of this.highlighted_cells)this.renderCell(e);this.highlighted_cells.clear(),t&&this.cells_to_highlight.clear()}}},function(t,e,i){const s=i(17),o=i(0);t.exports=class{constructor(t,e,i){this.resize(t,e,i)}resize(t,e,i){this.grid=[],this.cols=t,this.rows=e,this.cell_size=i;for(var r=0;r=0&&e>=0}getCenter(){return[Math.floor(this.cols/2),Math.floor(this.rows/2)]}xyToColRow(t,e){var i=Math.floor(t/this.cell_size),s=Math.floor(e/this.cell_size);return i>=this.cols?i=this.cols-1:i<0&&(i=0),s>=this.rows?s=this.rows-1:s<0&&(s=0),[i,s]}}},function(t,e,i){const s=i(0);t.exports=class{constructor(t,e,i){if(this.anatomy=t,this.ancestor=e,this.population=1,this.cumulative_pop=1,this.start_tick=i,this.end_tick=-1,this.color=Math.floor(16777215*Math.random()).toString(16),null!=e){var s=Math.floor(16777215*Math.random())-8e6;this.color=(s+parseInt(e.color,16)).toString(16)}this.name="_"+Math.random().toString(36).substr(2,9),this.extinct=!1,this.calcAnatomyDetails()}calcAnatomyDetails(){var t={};for(let e of s.living)t[e.name]=0;for(let e of this.anatomy.cells)t[e.state.name]+=1;this.cell_counts=t}addPop(){this.population++,this.cumulative_pop++}decreasePop(){if(this.population--,this.population<=0){this.extinct=!0;i(2).fossilize(this)}}lifespan(){return this.end_tick-this.start_tick}}},function(t,e){t.exports=class{constructor(t,e){this.env=t,this.canvas=e,this.mouse_x,this.mouse_y,this.mouse_c,this.mouse_r,this.left_click=!1,this.right_click=!1,this.cur_cell=null,this.cur_org=null,this.highlight_org=!0,this.defineEvents()}setControlPanel(t){this.control_panel=t}defineEvents(){this.canvas.addEventListener("mousemove",t=>{this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseMove()}),this.canvas.addEventListener("mouseup",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),this.mouseUp(),this.left_click=!1,this.right_click=!1}.bind(this)),this.canvas.addEventListener("mousedown",function(t){t.preventDefault(),this.updateMouseLocation(t.offsetX,t.offsetY),0==t.button&&(this.left_click=!0),2==t.button&&(this.right_click=!0),this.mouseDown()}.bind(this)),this.canvas.addEventListener("contextmenu",(function(t){t.preventDefault()})),this.canvas.addEventListener("mouseleave",function(){this.right_click=!1,this.left_click=!1,this.env.renderer.clearAllHighlights(!0)}.bind(this))}updateMouseLocation(t,e){var i=this.cur_cell,s=this.cur_org;this.mouse_x=t,this.mouse_y=e;var o=this.env.grid_map.xyToColRow(this.mouse_x,this.mouse_y);this.mouse_c=o[0],this.mouse_r=o[1],this.cur_cell=this.env.grid_map.cellAt(this.mouse_c,this.mouse_r),this.cur_org=this.cur_cell.owner,this.cur_org==s&&this.cur_cell==i||(this.env.renderer.clearAllHighlights(!0),null!=this.cur_org&&this.highlight_org?this.env.renderer.highlightOrganism(this.cur_org):null!=this.cur_cell&&this.env.renderer.highlightCell(this.cur_cell,!0))}mouseMove(){alert("mouse move must be overridden")}mouseDown(){alert("mouse down must be overridden")}mouseUp(){alert("mouse up must be overridden")}}},function(t,e,i){const s=i(16),o=i(29),r=i(35),a=i(37);t.exports=class{constructor(){this.fps=60,this.env=new s(5),this.organism_editor=new r,this.controlpanel=new o(this),this.colorscheme=new a(this.env,this.organism_editor),this.colorscheme.loadColorScheme(),this.env.OriginOfLife(),this.last_update=Date.now(),this.delta_time=0,this.actual_fps=0,this.running=!1}start(t=60){t<=0&&(t=1),this.fps=t,this.game_loop=setInterval(function(){this.updateDeltaTime(),this.environmentUpdate()}.bind(this),1e3/t),this.running=!0,this.fps>=60?null!=this.render_loop&&(clearInterval(this.render_loop),this.render_loop=null):this.setRenderLoop()}stop(){clearInterval(this.game_loop),this.running=!1,this.setRenderLoop()}setRenderLoop(){null==this.render_loop&&(this.render_loop=setInterval(function(){this.updateDeltaTime(),this.necessaryUpdate()}.bind(this),1e3/60))}updateDeltaTime(){this.delta_time=Date.now()-this.last_update,this.last_update=Date.now()}environmentUpdate(){this.env.update(this.delta_time),this.actual_fps=1/this.delta_time*1e3,null==this.render_loop&&this.necessaryUpdate()}necessaryUpdate(){this.env.render(),this.controlpanel.update(this.delta_time),this.organism_editor.update()}}},function(t,e,i){"use strict";i.r(e);var s=i(14),o=i.n(s);$("document").ready((function(){(function(){let t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t})()&&(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")),(new o.a).start(60)}))},function(t,e,i){const s=i(9),o=i(10),r=i(11),a=i(7),n=i(0),l=i(28),h=i(1),c=i(2);t.exports=class extends s{constructor(t){super(),this.renderer=new o("env-canvas","env",t),this.controller=new l(this,this.renderer.canvas);var e=Math.floor(this.renderer.height/t),i=Math.floor(this.renderer.width/t);this.grid_map=new r(i,e,t),this.organisms=[],this.walls=[],this.total_mutability=0,this.auto_reset=!0,this.largest_cell_count=0,this.reset_count=0,this.total_ticks=0,this.data_update_rate=100,c.setEnv(this)}update(t){var e=[];for(var i in this.organisms){var s=this.organisms[i];s.living&&s.update()||e.push(i)}h.foodDropProb>0&&this.generateFood(),this.removeOrganisms(e),this.total_ticks++,this.total_ticks%this.data_update_rate==0&&c.updateData()}render(){h.headless?this.renderer.cells_to_render.clear():(this.renderer.renderCells(),this.renderer.renderHighlights())}renderFull(){this.renderer.renderFullGrid(this.grid_map.grid)}removeOrganisms(t){for(var e of t.reverse())this.total_mutability-=this.organisms[e].mutability,this.organisms.splice(e,1);0==this.organisms.length&&this.auto_reset&&(this.reset_count++,this.reset())}OriginOfLife(){var t=this.grid_map.getCenter(),e=new a(t[0],t[1],this);e.anatomy.addDefaultCell(n.mouth,0,0),e.anatomy.addDefaultCell(n.producer,1,1),e.anatomy.addDefaultCell(n.producer,-1,-1),this.addOrganism(e),c.addSpecies(e,null)}addOrganism(t){t.updateGrid(),this.total_mutability+=t.mutability,this.organisms.push(t),t.anatomy.cells.length>this.largest_cell_count&&(this.largest_cell_count=t.anatomy.cells.length)}averageMutability(){return this.organisms.length<1?0:h.useGlobalMutability?h.globalMutability:this.total_mutability/this.organisms.length}changeCell(t,e,i,s){super.changeCell(t,e,i,s),this.renderer.addToRender(this.grid_map.cellAt(t,e)),i==n.wall&&this.walls.push(this.grid_map.cellAt(t,e))}clearWalls(){for(var t of this.walls)this.grid_map.cellAt(t.col,t.row).state==n.wall&&this.changeCell(t.col,t.row,n.empty,null)}clearOrganisms(){for(var t of this.organisms)t.die();this.organisms=[]}generateFood(){for(var t=Math.max(Math.floor(this.grid_map.cols*this.grid_map.rows*h.foodDropProb/5e4),1),e=h.foodDropProb,i=0;i3&&(t-=4),t}performFunction(){var t=this.look();this.org.brain.observe(t)}look(){var t=this.org.env,e=this.getAbsoluteDirection(),i=0,o=0;switch(e){case a.up:o=-1;break;case a.down:o=1;break;case a.right:i=1;break;case a.left:i=-1}for(var l=this.getRealCol(),h=this.getRealRow(),c=l,d=h,u=null,p=0;p=1&&(e=1,this.opacity_change_rate=-this.opacity_change_rate),this.headless_opacity=e,$("#headless-notification").css("opacity",100*e+"%")}}update(t){$("#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(),s.headless&&this.updateHeadlessIcon(t)}}},function(t,e,i){const s=i(31),o=i(32),r=i(33),a=i(34),n=i(2),l=[s,o,a,r];t.exports=class{constructor(t){this.defineControls(),this.chart_selection=0,this.setChart(),this.env=t,this.last_reset_count=t.reset_count}setChart(t=this.chart_selection){this.chart_controller=new l[t],this.chart_controller.setData(),this.chart_controller.render()}startAutoRender(){this.setChart(),this.render_loop=setInterval(function(){this.updateChart()}.bind(this),1e3)}stopAutoRender(){clearInterval(this.render_loop)}defineControls(){$("#chart-option").change(function(){this.chart_selection=$("#chart-option")[0].selectedIndex,this.setChart()}.bind(this))}updateChart(){this.last_reset_count