diff --git a/dist/bundle.js b/dist/bundle.js index 0ad7f2b..3459b69 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -104,7 +104,18 @@ eval("const CellTypes = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes /*! no static exports found */ /***/ (function(module, exports) { -eval("const CellTypes = {\r\n empty: 0,\r\n food: 1,\r\n wall: 2,\r\n mouth: 3,\r\n producer: 4,\r\n mover: 5,\r\n killer: 6,\r\n armor: 7,\r\n colors: ['#121D29', 'green', 'black', 'orange', 'white', 'blue', 'red', 'purple'],\r\n getRandomLivingType: function(){\r\n return Math.floor(Math.random() * 5) + 3;\r\n }\r\n}\r\n\r\nmodule.exports = CellTypes;\r\n\n\n//# sourceURL=webpack:///./src/CellTypes.js?"); +eval("const CellTypes = {\r\n empty: 0,\r\n food: 1,\r\n wall: 2,\r\n mouth: 3,\r\n producer: 4,\r\n mover: 5,\r\n killer: 6,\r\n armor: 7,\r\n colors: ['#121D29', 'green', 'gray', 'orange', 'white', 'blue', 'red', 'purple'],\r\n getRandomLivingType: function(){\r\n return Math.floor(Math.random() * 5) + 3;\r\n }\r\n}\r\n\r\nmodule.exports = CellTypes;\r\n\n\n//# sourceURL=webpack:///./src/CellTypes.js?"); + +/***/ }), + +/***/ "./src/ControlModes.js": +/*!*****************************!*\ + !*** ./src/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}\r\n\r\nmodule.exports = Modes;\n\n//# sourceURL=webpack:///./src/ControlModes.js?"); /***/ }), @@ -115,7 +126,7 @@ eval("const CellTypes = {\r\n empty: 0,\r\n food: 1,\r\n wall: 2,\r\n /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -eval("var Hyperparams = __webpack_require__(/*! ./Hyperparameters */ \"./src/Hyperparameters.js\");\r\n\r\nclass ControlPanel {\r\n constructor(engine) {\r\n this.engine = engine;\r\n this.defineEngineSpeedControls();\r\n this.defineHyperparameterControls();\r\n this.fps = engine.fps;\r\n this.organism_record=0;\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 if ($('#pause-button').text() == \"Pause\" && this.engine.running) {\r\n $('#pause-button').text(\"Play\")\r\n this.engine.stop();\r\n }\r\n else if (!this.engine.running){\r\n $('#pause-button').text(\"Pause\")\r\n this.engine.start(this.fps);\r\n }\r\n console.log()\r\n }.bind(this));\r\n }\r\n\r\n defineHyperparameterControls() {\r\n $('#food-prod-prob').change(function() {\r\n var food_prob = $('#food-prod-prob').val();\r\n if ($('#fixed-ratio').is(\":checked\")) {\r\n Hyperparams.foodProdProb = food_prob;\r\n Hyperparams.calcProducerFoodRatio(false);\r\n $('#lifespan-multiplier').val(Hyperparams.lifespanMultiplier);\r\n }\r\n else{\r\n Hyperparams.foodProdProb = food_prob;\r\n }\r\n }.bind(this));\r\n $('#lifespan-multiplier').change(function() {\r\n var lifespan = $('#lifespan-multiplier').val();\r\n if ($('#fixed-ratio').is(\":checked\")) {\r\n Hyperparams.lifespanMultiplier = lifespan;\r\n Hyperparams.calcProducerFoodRatio(true);\r\n $('#food-prod-prob').val(Hyperparams.foodProdProb);\r\n }\r\n else {\r\n Hyperparams.lifespanMultiplier = lifespan;\r\n }\r\n }.bind(this));\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\r\n }\r\n\r\n}\r\n\r\n\r\nmodule.exports = ControlPanel;\n\n//# sourceURL=webpack:///./src/ControlPanel.js?"); +eval("var Hyperparams = __webpack_require__(/*! ./Hyperparameters */ \"./src/Hyperparameters.js\");\r\nvar Modes = __webpack_require__(/*! ./ControlModes */ \"./src/ControlModes.js\");\r\nconst CellTypes = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes.js\");\r\n\r\nclass ControlPanel {\r\n constructor(engine) {\r\n this.engine = engine;\r\n this.defineEngineSpeedControls();\r\n this.defineHyperparameterControls();\r\n this.defineModeControls();\r\n this.fps = engine.fps;\r\n this.organism_record=0;\r\n this.env_controller = this.engine.env.controller;\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 if ($('#pause-button').text() == \"Pause\" && this.engine.running) {\r\n $('#pause-button').text(\"Play\");\r\n this.engine.stop();\r\n }\r\n else if (!this.engine.running){\r\n $('#pause-button').text(\"Pause\");\r\n console.log(this.fps)\r\n this.engine.start(this.fps);\r\n }\r\n }.bind(this));\r\n }\r\n\r\n defineHyperparameterControls() {\r\n $('#food-prod-prob').change(function() {\r\n var food_prob = $('#food-prod-prob').val();\r\n if ($('#fixed-ratio').is(\":checked\")) {\r\n Hyperparams.foodProdProb = food_prob;\r\n Hyperparams.calcProducerFoodRatio(false);\r\n $('#lifespan-multiplier').val(Hyperparams.lifespanMultiplier);\r\n }\r\n else{\r\n Hyperparams.foodProdProb = food_prob;\r\n }\r\n }.bind(this));\r\n $('#lifespan-multiplier').change(function() {\r\n var lifespan = $('#lifespan-multiplier').val();\r\n if ($('#fixed-ratio').is(\":checked\")) {\r\n Hyperparams.lifespanMultiplier = lifespan;\r\n Hyperparams.calcProducerFoodRatio(true);\r\n $('#food-prod-prob').val(Hyperparams.foodProdProb);\r\n }\r\n else {\r\n Hyperparams.lifespanMultiplier = lifespan;\r\n }\r\n }.bind(this));\r\n }\r\n\r\n defineModeControls() {\r\n var self = this;\r\n $('.control-mode-button').click( function() {\r\n switch(this.id){\r\n case \"food-button\":\r\n self.env_controller.mode = Modes.FoodDrop;\r\n break;\r\n case \"wall-button\":\r\n self.env_controller.mode = Modes.WallDrop;\r\n break;\r\n case \"kill-button\":\r\n self.env_controller.mode = Modes.ClickKill;\r\n break;\r\n case \"none-button\":\r\n self.env_controller.mode = Modes.None;\r\n break;\r\n }\r\n $(\".control-mode-button\" ).css( \"background-color\", \"lightgray\" );\r\n $(\"#\"+this.id).css(\"background-color\", \"darkgray\");\r\n });\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 // this.env_controller.performModeAction();\r\n }\r\n\r\n}\r\n\r\n\r\nmodule.exports = ControlPanel;\n\n//# sourceURL=webpack:///./src/ControlPanel.js?"); /***/ }), @@ -126,7 +137,7 @@ eval("var Hyperparams = __webpack_require__(/*! ./Hyperparameters */ \"./src/Hyp /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environment.js\");\r\nconst ControlPanel = __webpack_require__(/*! ./ControlPanel */ \"./src/ControlPanel.js\");\r\n\r\nclass Engine{\r\n constructor(){\r\n this.fps = 0;\r\n this.env = new Environment(5);\r\n this.controlpanel = new ControlPanel(this);\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.update();}.bind(this), 1000/fps);\r\n this.running = true;\r\n if (this.fps >= 45) {\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.env.render();}.bind(this), 1000/45);\r\n }\r\n }\r\n\r\n\r\n update() {\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.env.render();\r\n this.actual_fps = 1/this.delta_time*1000;\r\n this.controlpanel.update();\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Engine;\r\n\n\n//# sourceURL=webpack:///./src/Engine.js?"); +eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Environment.js\");\r\nconst ControlPanel = __webpack_require__(/*! ./ControlPanel */ \"./src/ControlPanel.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 Environment(5);\r\n this.controlpanel = new ControlPanel(this);\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.update();}.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.env.render();this.controlpanel.update();}.bind(this), 1000/render_speed);\r\n }\r\n }\r\n\r\n\r\n update() {\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.env.render();\r\n this.controlpanel.update();\r\n }\r\n \r\n }\r\n\r\n}\r\n\r\nmodule.exports = Engine;\r\n\n\n//# sourceURL=webpack:///./src/Engine.js?"); /***/ }), @@ -137,7 +148,7 @@ eval("const Environment = __webpack_require__(/*! ./Environment */ \"./src/Envir /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -eval("const Grid = __webpack_require__(/*! ./GridMap */ \"./src/GridMap.js\");\r\nconst Renderer = __webpack_require__(/*! ./Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst GridMap = __webpack_require__(/*! ./GridMap */ \"./src/GridMap.js\");\r\nconst Organism = __webpack_require__(/*! ./Organism */ \"./src/Organism.js\");\r\nconst CellTypes = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes.js\");\r\nconst Cell = __webpack_require__(/*! ./Cell */ \"./src/Cell.js\");\r\nconst EnvironmentController = __webpack_require__(/*! ./EnvironmentController */ \"./src/EnvironmentController.js\");\r\n\r\nclass Environment{\r\n constructor(cell_size) {\r\n this.renderer = new Renderer('canvas', this, cell_size);\r\n this.controller = new EnvironmentController(this, this.renderer.canvas);\r\n this.grid_rows = Math.floor(this.renderer.height / cell_size);\r\n this.grid_cols = Math.floor(this.renderer.width / cell_size);\r\n this.grid_map = new GridMap(this.grid_cols, this.grid_rows, cell_size);\r\n this.renderer.renderFullGrid();\r\n this.organisms = [];\r\n }\r\n\r\n update(delta_time) {\r\n var to_remove = [];\r\n for (var i in this.organisms) {\r\n var org = this.organisms[i];\r\n if (!org.update()) {\r\n to_remove.push(i);\r\n }\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.organisms.splice(i, 1);\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.addCell(CellTypes.mouth, -1, -1);\r\n org.addCell(CellTypes.producer, 0, 0);\r\n org.addCell(CellTypes.mouth, 1, 1);\r\n this.addOrganism(org);\r\n }\r\n\r\n addOrganism(organism) {\r\n organism.updateGrid();\r\n this.organisms.push(organism);\r\n }\r\n\r\n changeCell(c, r, type, owner) {\r\n this.grid_map.setCellType(c, r, type);\r\n this.grid_map.setCellOwner(c, r, owner);\r\n this.renderer.addToRender(this.grid_map.cellAt(c, r));\r\n }\r\n}\r\n\r\nmodule.exports = Environment;\r\n\r\n\n\n//# sourceURL=webpack:///./src/Environment.js?"); +eval("const Grid = __webpack_require__(/*! ./GridMap */ \"./src/GridMap.js\");\r\nconst Renderer = __webpack_require__(/*! ./Rendering/Renderer */ \"./src/Rendering/Renderer.js\");\r\nconst GridMap = __webpack_require__(/*! ./GridMap */ \"./src/GridMap.js\");\r\nconst Organism = __webpack_require__(/*! ./Organism */ \"./src/Organism.js\");\r\nconst CellTypes = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes.js\");\r\nconst Cell = __webpack_require__(/*! ./Cell */ \"./src/Cell.js\");\r\nconst EnvironmentController = __webpack_require__(/*! ./EnvironmentController */ \"./src/EnvironmentController.js\");\r\n\r\nclass Environment{\r\n constructor(cell_size) {\r\n this.renderer = new Renderer('canvas', this, cell_size);\r\n this.controller = new EnvironmentController(this, this.renderer.canvas);\r\n this.grid_rows = Math.floor(this.renderer.height / cell_size);\r\n this.grid_cols = Math.floor(this.renderer.width / cell_size);\r\n this.grid_map = new GridMap(this.grid_cols, this.grid_rows, cell_size);\r\n this.renderer.renderFullGrid();\r\n this.organisms = [];\r\n }\r\n\r\n update(delta_time) {\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 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.organisms.splice(i, 1);\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.addCell(CellTypes.mouth, 1, 1);\r\n org.addCell(CellTypes.producer, 0, 0);\r\n // org.addCell(CellTypes.mouth, 1, -1);\r\n this.addOrganism(org);\r\n }\r\n\r\n addOrganism(organism) {\r\n organism.updateGrid();\r\n this.organisms.push(organism);\r\n }\r\n\r\n changeCell(c, r, type, owner) {\r\n this.grid_map.setCellType(c, r, type);\r\n this.grid_map.setCellOwner(c, r, owner);\r\n this.renderer.addToRender(this.grid_map.cellAt(c, r));\r\n }\r\n}\r\n\r\nmodule.exports = Environment;\r\n\r\n\n\n//# sourceURL=webpack:///./src/Environment.js?"); /***/ }), @@ -146,9 +157,9 @@ eval("const Grid = __webpack_require__(/*! ./GridMap */ \"./src/GridMap.js\");\r !*** ./src/EnvironmentController.js ***! \**************************************/ /*! no static exports found */ -/***/ (function(module, exports) { +/***/ (function(module, exports, __webpack_require__) { -eval("\r\nclass EnvironmentController{\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.mouse_down = false;\r\n this.cur_cell = null;\r\n this.cur_org = null;\r\n this.defineEvents();\r\n }\r\n\r\n defineEvents() {\r\n this.canvas.addEventListener('mousedown', e => {\r\n this.mouse_down=true;\r\n });\r\n\r\n this.canvas.addEventListener('mouseup', e => {\r\n this.mouse_down=false;\r\n });\r\n\r\n this.canvas.addEventListener('mousemove', e => {\r\n var prev_cell = this.cur_cell;\r\n var prev_org = this.cur_org;\r\n\r\n this.mouse_x = e.offsetX;\r\n this.mouse_y = e.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) {\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\r\n\r\n}\r\n\r\nmodule.exports = EnvironmentController;\r\n\n\n//# sourceURL=webpack:///./src/EnvironmentController.js?"); +eval("var Modes = __webpack_require__(/*! ./ControlModes */ \"./src/ControlModes.js\");\r\nconst CellTypes = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes.js\");\r\n\r\nclass EnvironmentController{\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.mode = Modes.None;\r\n this.defineEvents();\r\n }\r\n\r\n defineEvents() {\r\n this.canvas.addEventListener('mousemove', e => {\r\n var prev_cell = this.cur_cell;\r\n var prev_org = this.cur_org;\r\n\r\n this.mouse_x = e.offsetX;\r\n this.mouse_y = e.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) {\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 this.performModeAction();\r\n });\r\n\r\n this.canvas.addEventListener('mouseup', function(evt) {\r\n evt.preventDefault();\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 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.performModeAction();\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 }.bind(this));\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 && cell.type == CellTypes.empty){\r\n this.env.changeCell(cell.col, cell.row, CellTypes.food, null);\r\n }\r\n else if (right_click && cell.type == CellTypes.food){\r\n this.env.changeCell(cell.col, cell.row, CellTypes.empty, null);\r\n }\r\n break;\r\n case Modes.WallDrop:\r\n if (left_click && (cell.type == CellTypes.empty || cell.type == CellTypes.food)){\r\n this.env.changeCell(cell.col, cell.row, CellTypes.wall, null);\r\n }\r\n else if (right_click && cell.type == CellTypes.wall){\r\n this.env.changeCell(cell.col, cell.row, CellTypes.empty, null);\r\n }\r\n break;\r\n case Modes.ClickKill:\r\n if (this.cur_org != null)\r\n this.cur_org.die();\r\n }\r\n }\r\n }\r\n\r\n\r\n}\r\n\r\nmodule.exports = EnvironmentController;\r\n\n\n//# sourceURL=webpack:///./src/EnvironmentController.js?"); /***/ }), @@ -203,7 +214,7 @@ eval("// contains local cell values for the following:\r\n\r\n//all ...\r\ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -eval("const CellTypes = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes.js\");\r\nconst Cell = __webpack_require__(/*! ./Cell */ \"./src/Cell.js\");\r\nconst GridMap = __webpack_require__(/*! ./GridMap */ \"./src/GridMap.js\");\r\nconst LocalCell = __webpack_require__(/*! ./LocalCell */ \"./src/LocalCell.js\");\r\nconst { producer } = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes.js\");\r\nconst Neighbors = __webpack_require__(/*! ./Neighbors */ \"./src/Neighbors.js\");\r\nvar Hyperparams = __webpack_require__(/*! ./Hyperparameters */ \"./src/Hyperparameters.js\");\r\n\r\nconst directions = [[0,1],[0,-1],[1,0],[-1,0]]\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.cells = [];\r\n this.is_producer = false;\r\n this.is_mover = false;\r\n this.direction = this.getRandomDirection();\r\n this.move_count = 0;\r\n this.move_range = 5;\r\n this.mutability = 5;\r\n if (parent != null) {\r\n this.inherit(parent);\r\n }\r\n }\r\n\r\n addCell(type, 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 this.checkProducerMover(type);\r\n this.cells.push(new LocalCell(type, c, r));\r\n return true;\r\n }\r\n\r\n removeCell(c, r) {\r\n var check_change = false;\r\n for (var i=0; i 1) {\r\n this.cells.splice(Math.floor(Math.random() * this.cells.length), 1);\r\n return true;\r\n }\r\n }\r\n\r\n if (this.is_mover) {\r\n this.move_range += Math.floor(Math.random() * 4) - 2;\r\n }\r\n return false;\r\n }\r\n\r\n attemptMove(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.cells) {\r\n var real_c = this.c + cell.loc_col;\r\n var real_r = this.r + cell.loc_row;\r\n this.env.changeCell(real_c, real_r, CellTypes.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 getRandomDirection(){\r\n return directions[Math.floor(Math.random() * directions.length)];\r\n }\r\n\r\n // assumes either c1==c2 or r1==r2, returns true if there is a clear path from point a to b\r\n isStraightPath(c1, r1, c2, r2, parent){\r\n // TODO FIX!!!\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.type == CellTypes.empty || cell.owner == this || cell.owner == parent;\r\n }\r\n\r\n isClear(col, row) {\r\n for(var loccell of this.cells) {\r\n var cell = this.getRealCell(loccell, col, row);\r\n if(cell == null || cell.type != CellTypes.empty && cell.owner != this) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n die() {\r\n for (var cell of this.cells) {\r\n var real_c = this.c + cell.loc_col;\r\n var real_r = this.r + cell.loc_row;\r\n this.env.changeCell(real_c, real_r, CellTypes.food, null);\r\n }\r\n this.living = false;\r\n }\r\n\r\n updateGrid() {\r\n for (var cell of this.cells) {\r\n var real_c = this.c + cell.loc_col;\r\n var real_r = this.r + cell.loc_row;\r\n this.env.changeCell(real_c, real_r, cell.type, this);\r\n }\r\n }\r\n\r\n update() {\r\n // this.food_collected++;\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.cells) {\r\n this.getRealCell(cell).performFunction(this.env);\r\n }\r\n if (!this.living){\r\n return this.living\r\n }\r\n if (this.is_mover) {\r\n this.move_count++;\r\n var success = this.attemptMove(this.direction);\r\n if (this.move_count > this.move_range || !success){\r\n this.move_count = 0;\r\n this.direction = this.getRandomDirection()\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){\r\n var real_c = c + local_cell.loc_col;\r\n var real_r = r + local_cell.loc_row;\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.js?"); +eval("const CellTypes = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes.js\");\r\nconst Cell = __webpack_require__(/*! ./Cell */ \"./src/Cell.js\");\r\nconst GridMap = __webpack_require__(/*! ./GridMap */ \"./src/GridMap.js\");\r\nconst LocalCell = __webpack_require__(/*! ./LocalCell */ \"./src/LocalCell.js\");\r\nconst { producer } = __webpack_require__(/*! ./CellTypes */ \"./src/CellTypes.js\");\r\nconst Neighbors = __webpack_require__(/*! ./Neighbors */ \"./src/Neighbors.js\");\r\nvar Hyperparams = __webpack_require__(/*! ./Hyperparameters */ \"./src/Hyperparameters.js\");\r\n\r\nconst directions = [[0,1],[0,-1],[1,0],[-1,0]]\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.cells = [];\r\n this.is_producer = false;\r\n this.is_mover = false;\r\n this.direction = this.getRandomDirection();\r\n this.move_count = 0;\r\n this.move_range = 5;\r\n this.mutability = 5;\r\n if (parent != null) {\r\n this.inherit(parent);\r\n }\r\n }\r\n\r\n addCell(type, 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 this.checkProducerMover(type);\r\n this.cells.push(new LocalCell(type, c, r));\r\n return true;\r\n }\r\n\r\n removeCell(c, r) {\r\n var check_change = false;\r\n for (var i=0; i 1) {\r\n this.cells.splice(Math.floor(Math.random() * this.cells.length), 1);\r\n return true;\r\n }\r\n }\r\n\r\n if (this.is_mover) {\r\n this.move_range += Math.floor(Math.random() * 4) - 2;\r\n }\r\n return false;\r\n }\r\n\r\n attemptMove(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.cells) {\r\n var real_c = this.c + cell.loc_col;\r\n var real_r = this.r + cell.loc_row;\r\n this.env.changeCell(real_c, real_r, CellTypes.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 getRandomDirection(){\r\n return directions[Math.floor(Math.random() * directions.length)];\r\n }\r\n\r\n // assumes either c1==c2 or r1==r2, returns true if there is a clear path from point a to b\r\n isStraightPath(c1, r1, c2, r2, parent){\r\n // TODO FIX!!!\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.type == CellTypes.empty || cell.owner == this || cell.owner == parent || cell.type == CellTypes.food);\r\n }\r\n\r\n isClear(col, row) {\r\n for(var loccell of this.cells) {\r\n var cell = this.getRealCell(loccell, col, row);\r\n if(cell == null || cell.type != CellTypes.empty && cell.owner != this) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n die() {\r\n for (var cell of this.cells) {\r\n var real_c = this.c + cell.loc_col;\r\n var real_r = this.r + cell.loc_row;\r\n this.env.changeCell(real_c, real_r, CellTypes.food, null);\r\n }\r\n this.living = false;\r\n }\r\n\r\n updateGrid() {\r\n for (var cell of this.cells) {\r\n var real_c = this.c + cell.loc_col;\r\n var real_r = this.r + cell.loc_row;\r\n this.env.changeCell(real_c, real_r, cell.type, this);\r\n }\r\n }\r\n\r\n update() {\r\n // this.food_collected++;\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.cells) {\r\n this.getRealCell(cell).performFunction(this.env);\r\n }\r\n if (!this.living){\r\n return this.living\r\n }\r\n if (this.is_mover) {\r\n this.move_count++;\r\n var success = this.attemptMove(this.direction);\r\n if (this.move_count > this.move_range || !success){\r\n this.move_count = 0;\r\n this.direction = this.getRandomDirection()\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){\r\n var real_c = c + local_cell.loc_col;\r\n var real_r = r + local_cell.loc_row;\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.js?"); /***/ }), diff --git a/dist/css/style.css b/dist/css/style.css index 19e6844..e74d1d6 100644 --- a/dist/css/style.css +++ b/dist/css/style.css @@ -1,5 +1,5 @@ body{ - background: #121D29; + background: black; margin: 0; padding: 0; } @@ -25,6 +25,8 @@ canvas { background-color: gray; position: fixed; display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 1fr); } .control-set { @@ -33,6 +35,7 @@ canvas { border: 10px; border-color: black; background-color: lightgray; + max-width: 100%; /* height: 100%; */ } @@ -50,14 +53,22 @@ canvas { #hyperparameters { grid-column: 2; - grid-row: 1 / 2; - /* background-color: green; */ + grid-row: 1 / 3; } -#powers { +#abilities { grid-column: 3; - grid-row: 1 / 2; + grid-row: 1 / 3; /* background-color: yellow; */ +} + +.control-mode-button { + border-color: gray; + background-color: lightgray; +} + +#none-button { + background-color: gray; } \ No newline at end of file diff --git a/dist/html/index.html b/dist/html/index.html index c3f5e7b..51554a1 100644 --- a/dist/html/index.html +++ b/dist/html/index.html @@ -38,8 +38,12 @@ -
-

Powers

+
+

Control Mode

+ + + +
diff --git a/src/CellTypes.js b/src/CellTypes.js index f2b3406..8d2d7a5 100644 --- a/src/CellTypes.js +++ b/src/CellTypes.js @@ -7,7 +7,7 @@ const CellTypes = { mover: 5, killer: 6, armor: 7, - colors: ['#121D29', 'green', 'black', 'orange', 'white', 'blue', 'red', 'purple'], + colors: ['#121D29', 'green', 'gray', 'orange', 'white', 'blue', 'red', 'purple'], getRandomLivingType: function(){ return Math.floor(Math.random() * 5) + 3; } diff --git a/src/ControlModes.js b/src/ControlModes.js new file mode 100644 index 0000000..9801a62 --- /dev/null +++ b/src/ControlModes.js @@ -0,0 +1,8 @@ +const Modes = { + None: 0, + FoodDrop: 1, + WallDrop: 2, + ClickKill: 3 +} + +module.exports = Modes; \ No newline at end of file diff --git a/src/ControlPanel.js b/src/ControlPanel.js index b1d8613..1805365 100644 --- a/src/ControlPanel.js +++ b/src/ControlPanel.js @@ -1,12 +1,16 @@ var Hyperparams = require("./Hyperparameters"); +var Modes = require("./ControlModes"); +const CellTypes = require("./CellTypes"); class ControlPanel { constructor(engine) { this.engine = engine; this.defineEngineSpeedControls(); this.defineHyperparameterControls(); + this.defineModeControls(); this.fps = engine.fps; this.organism_record=0; + this.env_controller = this.engine.env.controller; } defineEngineSpeedControls(){ @@ -21,14 +25,14 @@ class ControlPanel { }.bind(this); $('#pause-button').click(function() { if ($('#pause-button').text() == "Pause" && this.engine.running) { - $('#pause-button').text("Play") + $('#pause-button').text("Play"); this.engine.stop(); } else if (!this.engine.running){ - $('#pause-button').text("Pause") + $('#pause-button').text("Pause"); + console.log(this.fps) this.engine.start(this.fps); } - console.log() }.bind(this)); } @@ -57,6 +61,28 @@ class ControlPanel { }.bind(this)); } + defineModeControls() { + var self = this; + $('.control-mode-button').click( function() { + switch(this.id){ + case "food-button": + self.env_controller.mode = Modes.FoodDrop; + break; + case "wall-button": + self.env_controller.mode = Modes.WallDrop; + break; + case "kill-button": + self.env_controller.mode = Modes.ClickKill; + break; + case "none-button": + self.env_controller.mode = Modes.None; + break; + } + $(".control-mode-button" ).css( "background-color", "lightgray" ); + $("#"+this.id).css("background-color", "darkgray"); + }); + } + changeEngineSpeed(change_val) { this.engine.stop(); this.engine.start(change_val) @@ -70,7 +96,7 @@ class ControlPanel { if (org_count > this.organism_record) this.organism_record = org_count; $('#org-record').text("Highest count: " + this.organism_record); - + // this.env_controller.performModeAction(); } } diff --git a/src/Engine.js b/src/Engine.js index 7d5c3a8..0e86928 100644 --- a/src/Engine.js +++ b/src/Engine.js @@ -1,9 +1,11 @@ const Environment = require('./Environment'); const ControlPanel = require('./ControlPanel'); +const render_speed = 60; + class Engine{ constructor(){ - this.fps = 0; + this.fps = 60; this.env = new Environment(5); this.controlpanel = new ControlPanel(this); this.env.OriginOfLife(); @@ -21,7 +23,7 @@ class Engine{ this.fps = fps; this.game_loop = setInterval(function(){this.update();}.bind(this), 1000/fps); this.running = true; - if (this.fps >= 45) { + if (this.fps >= render_speed) { if (this.render_loop != null) { clearInterval(this.render_loop); this.render_loop = null; @@ -39,7 +41,7 @@ class Engine{ setRenderLoop() { if (this.render_loop == null) { - this.render_loop = setInterval(function(){this.env.render();}.bind(this), 1000/45); + this.render_loop = setInterval(function(){this.env.render();this.controlpanel.update();}.bind(this), 1000/render_speed); } } @@ -48,9 +50,12 @@ class Engine{ this.delta_time = Date.now() - this.last_update; this.last_update = Date.now(); this.env.update(this.delta_time); - this.env.render(); this.actual_fps = 1/this.delta_time*1000; - this.controlpanel.update(); + if(this.render_loop == null){ + this.env.render(); + this.controlpanel.update(); + } + } } diff --git a/src/Environment.js b/src/Environment.js index eb9cd6e..1cf1823 100644 --- a/src/Environment.js +++ b/src/Environment.js @@ -21,7 +21,7 @@ class Environment{ var to_remove = []; for (var i in this.organisms) { var org = this.organisms[i]; - if (!org.update()) { + if (!org.living || !org.update()) { to_remove.push(i); } } @@ -42,9 +42,9 @@ class Environment{ OriginOfLife() { var center = this.grid_map.getCenter(); var org = new Organism(center[0], center[1], this); - org.addCell(CellTypes.mouth, -1, -1); - org.addCell(CellTypes.producer, 0, 0); org.addCell(CellTypes.mouth, 1, 1); + org.addCell(CellTypes.producer, 0, 0); + // org.addCell(CellTypes.mouth, 1, -1); this.addOrganism(org); } diff --git a/src/EnvironmentController.js b/src/EnvironmentController.js index 21ba34e..a15e967 100644 --- a/src/EnvironmentController.js +++ b/src/EnvironmentController.js @@ -1,3 +1,5 @@ +var Modes = require("./ControlModes"); +const CellTypes = require("./CellTypes"); class EnvironmentController{ constructor(env, canvas) { @@ -7,21 +9,15 @@ class EnvironmentController{ this.mouse_y; this.mouse_c; this.mouse_r; - this.mouse_down = false; + this.left_click = false; + this.right_click = false; this.cur_cell = null; this.cur_org = null; + this.mode = Modes.None; this.defineEvents(); } defineEvents() { - this.canvas.addEventListener('mousedown', e => { - this.mouse_down=true; - }); - - this.canvas.addEventListener('mouseup', e => { - this.mouse_down=false; - }); - this.canvas.addEventListener('mousemove', e => { var prev_cell = this.cur_cell; var prev_org = this.cur_org; @@ -43,7 +39,67 @@ class EnvironmentController{ this.env.renderer.highlightCell(this.cur_cell, true); } } + this.performModeAction(); }); + + this.canvas.addEventListener('mouseup', function(evt) { + evt.preventDefault(); + this.left_click=false; + this.right_click=false; + }.bind(this)); + + this.canvas.addEventListener('mousedown', function(evt) { + evt.preventDefault(); + if (evt.button == 0) { + this.left_click = true; + } + if (evt.button == 2) + this.right_click = true; + this.performModeAction(); + }.bind(this)); + + this.canvas.addEventListener('contextmenu', function(evt) { + evt.preventDefault(); + }); + + this.canvas.addEventListener('mouseleave', function(){ + this.right_click = false; + this.left_click = false; + }.bind(this)); + + } + + performModeAction() { + var mode = this.mode; + var right_click = this.right_click; + var left_click = this.left_click; + if (mode != Modes.None && (right_click || left_click)) { + var cell = this.cur_cell; + if (cell == null){ + return; + } + switch(mode) { + case Modes.FoodDrop: + if (left_click && cell.type == CellTypes.empty){ + this.env.changeCell(cell.col, cell.row, CellTypes.food, null); + } + else if (right_click && cell.type == CellTypes.food){ + this.env.changeCell(cell.col, cell.row, CellTypes.empty, null); + } + break; + case Modes.WallDrop: + if (left_click && (cell.type == CellTypes.empty || cell.type == CellTypes.food)){ + this.env.changeCell(cell.col, cell.row, CellTypes.wall, null); + } + else if (right_click && cell.type == CellTypes.wall){ + this.env.changeCell(cell.col, cell.row, CellTypes.empty, null); + } + break; + case Modes.ClickKill: + if (this.cur_org != null) + this.cur_org.die(); + } + } } diff --git a/src/Organism.js b/src/Organism.js index 7c0b544..11cc0fa 100644 --- a/src/Organism.js +++ b/src/Organism.js @@ -89,7 +89,7 @@ class Organism { //produce mutated child //check nearby locations (is there room and a direct path) var org = new Organism(0, 0, this.env, this); - if (Math.random() * 100 <= this.mutability) { + if (Math.random() * 100 <= 3) { org.mutate(); } if (Math.random() <= 0.5) @@ -107,7 +107,7 @@ class Organism { var new_c = this.c + (direction_c*this.cells.length*2) + (direction_c*offset); var new_r = this.r + (direction_r*this.cells.length*2) + (direction_r*offset); - if (org.isClear(new_c, new_r)){// && org.isStraightPath(new_c, new_r, this.c, this.r, this)){ + if (org.isClear(new_c, new_r) && org.isStraightPath(new_c, new_r, this.c, this.r, this)){ org.c = new_c; org.r = new_r; this.env.addOrganism(org); @@ -125,13 +125,13 @@ class Organism { // add cell var type = CellTypes.getRandomLivingType(); var num_to_add = Math.floor(Math.random() * 3) + 1; - for (var i=0; i