'use strict'; const rules = { "111": "0", "110": "1", "101": "0", "100": "1", "011": "0", "010": "0", "001": "0", "000": "1" } function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max); // The maximum is exclusive and the minimum is inclusive return Math.floor(Math.random() * (max - min) + min); } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function evolve(state, acc) { const [x, y, z, ...xs] = state; if (!xs.length) { return acc + x + acc[0] + acc[1] } else { const rule = x + y + z; const new_acc = acc.concat(rules[rule]); return evolve(y + z + xs.join(""), new_acc) } } function draw(state, context, acc) { const cell_dim = 2 Object.keys(state).forEach( function (key) { if(state[key] == "1") { context.fillStyle="black"; context.moveTo(key * cell_dim, acc * cell_dim) context.fillRect(key * cell_dim, acc * cell_dim, cell_dim, cell_dim) } }) } window.addEventListener("load", async function() { const canvas = document.getElementById("canvas") canvas.width = window.innerWidth canvas.height = window.innerHeight const ctx = canvas.getContext("2d") const initial_state = [...Array(canvas.width)].map( _=> getRandomInt(0, 2).toString() ).join("") var new_state = evolve(initial_state, "") var acc = 0 while(acc < canvas.width) { draw(new_state, ctx, acc) new_state = evolve(new_state, "") acc++ await sleep(100) } })