var grid = document.getElementById("grid"); var cellsize = 60; var width = Math.ceil(window.innerWidth / cellsize) + 1; var height = Math.ceil(window.innerHeight / (cellsize*Math.sqrt(3)/2)); function xCoord(i, j) { var x = i + j/2; if (x > width - 1) { x = x - width; } return x; } function yCoord(i, j) { return Math.sqrt(3)*j/2; } var cells = new Array(width); for (var i = 0; i < width; ++i) { cells[i] = new Array(height); for (var j = 0; j < height; ++j) { cells[i][j] = document.createElement("div"); cells[i][j].classList.add("cell"); cells[i][j].classList.add("alive"); spiral = document.createElement("img"); spiral.classList.add("spiral"); spiral.src = "spiral.svg"; cells[i][j].appendChild(spiral); hex = document.createElement("img"); hex.classList.add("hex"); hex.src = "hex.svg"; cells[i][j].appendChild(hex); cells[i][j].style.position = "absolute"; cells[i][j].style.left = xCoord(i, j)*cellsize + "px"; cells[i][j].style.bottom = yCoord(i, j)*cellsize + "px"; grid.appendChild(cells[i][j]); } } function prebirth(i, j) { cells[i][j].classList.add("birthing"); } function prekill(i, j) { cells[i][j].classList.add("dying"); } function birth(i, j) { cells[i][j].classList.remove("dead"); cells[i][j].classList.add("alive"); } function kill(i, j) { cells[i][j].classList.remove("alive"); cells[i][j].classList.add("dead"); } function update(i, j) { var cl = cells[i][j].classList; if (cl.contains("birthing")) { cl.remove("birthing"); birth(i, j); } if (cl.contains("dying")) { cl.remove("dying"); kill(i, j); } } function isAlive(i, j) { return !cells[i][j].classList.contains("dead"); } function rotate(a) { a.push(a.shift()); } function arraysEq(a, b) { if (a.length !== b.length) { return false; } for (var i = 0; i < a.length; ++i) { if (a[i] !== b[i]) { return false; } } return true; } function arraysRotatedEq(a, b) { if (a.length !== b.length) { return false; } for (var i = 0; i < a.length; ++i) { if (arraysEq(a, b)) { return true; } rotate(b); } return false; } function mod(m, n) { return ((m % n) + n) % n; } function ip(i) { return mod(i-1, width); } function is(i) { return mod(i+1, width); } function jp(j) { return mod(j-1, height); } function js(j) { return mod(j+1, height); } function ll(i, j) { return isAlive(ip(i), j); } function dl(i, j) { return isAlive(i, jp(j)); } function dr(i, j) { return isAlive(is(i), jp(j)); } function rr(i, j) { return isAlive(is(i), j); } function ur(i, j) { return isAlive(i, js(j)); } function ul(i, j) { return isAlive(ip(i), js(j)); } function neighbors(i, j) { return [ll(i, j), dl(i, j), dr(i, j), rr(i, j), ur(i, j), ul(i, j)]; } function neighborsCount(i, j) { return neighbors(i, j).filter(function (b) { return b; }).length; } function golay(i, j) { var n = neighbors(i, j); var g1 = [true, true, false, false, false, false]; var g2 = [true, false, true, false, false, false]; return (arraysRotatedEq(n, g1) || arraysRotatedEq(n, g2)); } function preston(i, j) { var n = neighbors(i, j); var p1 = [true, true, false, false, false, false]; var p2 = [true, false, true, false, false, false]; return (isAlive(i, j) && (arraysRotatedEq(n, p1) || arraysRotatedEq(n, p2))) || (!isAlive(i, j) && neighborsCount(i, j) === 2); } function golayStep() { for (var i = 0; i < width; ++i) { for (var j = 0; j < height; ++j) { if (golay(i, j)) { prebirth(i, j); } else { prekill(i, j); } } } for (var i = 0; i < width; ++i) { for (var j = 0; j < height; ++j) { update(i, j); } } } function prestonStep() { for (var i = 0; i < width; ++i) { for (var j = 0; j < height; ++j) { if (preston(i, j)) { prebirth(i, j); } else { prekill(i, j); } } } for (var i = 0; i < width; ++i) { for (var j = 0; j < height; ++j) { update(i, j); } } } for (var i = 0; i < width; ++i) { for (var j = 0; j < height; ++j) { if (Math.floor(Math.random()*2) === 0) { kill(i, j); } } } setInterval(prestonStep, 1000);