import template from './template.js'; import scenarios from './scenarios.js'; import * as logic from './logic.js'; import * as constants from './constants.js'; import {clone} from './utils.js'; let state, tree; const init = function(wrapper) { state = {}; tree = template(state); const element = petitDom.mount(tree); wrapper.append(element); }; const render = function() { const newTree = template(state); petitDom.patch(newTree, tree); tree = newTree; }; const on = function(eventType, selector, fn) { document.addEventListener(eventType, function(event) { const target = event.target.closest(selector); if (target) { fn.call(target, state, event); render(); } }); }; const play = function() { if (!state.game.playing) { return; } if (state.game.steps) { state.game.steps -= 1; if (!state.game.steps) { state.game.playing = false; } } logic.step(state); render(); const speed = document.querySelector('[name="speed"]').value; const timeout = 2000 * Math.pow(0.95, speed); setTimeout(play, timeout); }; const createGame = function(scenario) { return { board: clone(scenario.board), description: scenario.description, winCondition: scenario.winCondition, tileLimit: scenario.tileLimit || Infinity, limitBuildSpace: scenario.limitBuildSpace, sandbox: false, currentPlayer: 1, playing: false, steps: 0, turnCounter: 0, winState: null, resetGame: { board: clone(scenario.board), tileLimit: scenario.tileLimit || Infinity, turnCounter: 0, }, restartGame: { board: clone(scenario.board), tileLimit: scenario.tileLimit || Infinity, turnCounter: 0, }, }; }; on('mousedown', '.board-cell', function(state, event) { if (state.game.playing) { return; } if (event.buttons !== 1) { return; } const row = this.parentElement; const board = row.parentElement; const x = Array.prototype.indexOf.call(row.children, this); const y = Array.prototype.indexOf.call(board.children, row); const currentPlayer = state.game.currentPlayer === constants.EMPTY ? constants.GAIA : state.game.currentPlayer; if ( (state.game.limitBuildSpace) && (x < state.game.limitBuildSpace.x1 || x > state.game.limitBuildSpace.x2 || y < state.game.limitBuildSpace.y1 || y > state.game.limitBuildSpace.y2) ) return; if (state.game.board[y][x] === currentPlayer) { state.game.board[y][x] = constants.EMPTY; state.game.tileLimit += 1; } else if (state.game.board[y][x] === constants.EMPTY) { if (state.game.tileLimit < 1) return; state.game.tileLimit -= 1; state.game.board[y][x] = currentPlayer; } state.game.resetGame.board = clone(state.game.board); state.game.resetGame.turnCounter = state.game.turnCounter; state.game.resetGame.tileLimit = state.game.tileLimit; }); on('click', '.js-next-gen', function(state) { state.game.steps = document.querySelector('[name="steps"]').value; state.game.playing = true; play(); }); on('click', '.js-play', function(state) { state.game.playing = !state.game.playing; play(); }); on('click', '.js-reset', function(state) { state.game.playing = false; state.game.winState = null; state.game.board = clone(state.game.resetGame.board); state.game.turnCounter = state.game.resetGame.turnCounter; state.game.tileLimit = state.game.resetGame.tileLimit; }); on('click', '.js-restart', function(state) { state.game.playing = false; state.game.winState = null; state.game.board = clone(state.game.restartGame.board); state.game.turnCounter = state.game.restartGame.turnCounter; state.game.tileLimit = state.game.restartGame.tileLimit; }); on('click', '.js-current-player', function(state) { state.game.currentPlayer = (state.game.currentPlayer + 1) % constants.playerCount; }); on('click', '.js-export', function(state) { const download = document.createElement('a'); const s = JSON.stringify(state.game.board); download.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(s); download.download = 'board.json'; download.hidden = true; document.body.appendChild(download); download.click(); download.remove(); }); const onNavigate = function() { var path = location.hash.substr(2).split('/'); if (path[0] === 'sandbox') { state.game = createGame({ board: logic.setupBoard(), }); state.game.sandbox = true; state.scenario = null; } else if (path[0] === 'scenario') { const i = parseInt(path[1], 10); state.game = createGame(scenarios[i]); state.scenario = i; } else { state.game = null; state.scenario = null; } render(); }; window.addEventListener('hashchange', onNavigate); init(document.body); onNavigate();