Game of Life and Death Apr ’20 Math Async Cellular Automata ECMAScript 2018 Math Life is finite Source code ~(async () => { const canvas = document.querySelector('canvas') const context = canvas.getContext('2d') const [WIDTH, HEIGHT] = [canvas.width / 16, canvas.height / 16] const grid = Array.from(Array(HEIGHT), row => Array(WIDTH).fill(false)) .map(row => row.map(cell => Math.random() > .75 ? true : false)) const counts = Array.from(Array(HEIGHT), row => Array(WIDTH).fill(0)) const render = () => { grid.forEach((row, rowIndex) => { row.forEach((cell, cellIndex) => { context.fillStyle = cell ? 'black' : 'white' context.fillRect(cellIndex * 16, rowIndex * 16, 15, 15) }) }) } const judge = () => { grid.forEach((row, rowIndex) => { row.forEach((_, cellIndex) => { let count = 0 for (let y = -1; y <= 1; y++) { for (let x = -1; x <= 1; x++) { if (x != 0 || y != 0) { if (grid[rowIndex + y] && grid[rowIndex + y][cellIndex + x]) { count += grid[rowIndex + y][cellIndex + x] ? 1 : 0 } } } } counts[rowIndex][cellIndex] = count }) }) } const evolve = () => { grid.forEach((row, rowIndex) => { row.forEach((cell, cellIndex) => { const count = counts[rowIndex][cellIndex] row[cellIndex] = cell && (count == 2 || count == 3) || !cell && count == 3 }) }) } for (;;) { render() judge() evolve() await new Promise(resolve => setTimeout(resolve, 250)) } })() game-of-life.js