Skip to content

Instantly share code, notes, and snippets.

@Xyvyrianeth
Created March 25, 2021 03:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xyvyrianeth/df0b80815a822b08c17ed70941383010 to your computer and use it in GitHub Desktop.
Save Xyvyrianeth/df0b80815a822b08c17ed70941383010 to your computer and use it in GitHub Desktop.
Conway's Game of Life
<!DOCTYPE html>
<body oncontextmenu="return false">
<canvas id="conway" height=900 width=900></canvas>
<div id="player">
<text class="left">PLAYER</text>
<text class="right">CANVAS</text><br>
<button class="left player" id="pause" onclick="ruleChange(0); blur()" title="Start the engine" oncontextmenu="blur()">PLAY</button>
<button class="right player" onclick="random(); blur()" title="Randomize the activity of every cell in the canvas" oncontextmenu="blur()">RANDOM</button><br>
<button class="left player" onclick="table.frame = true; blur()" title="Generate the next frame (engine must be paused)" oncontextmenu="blur()">STEP</button>
<button class="right player" id="clear" onclick="blur()" title="Set all cells to inactive" oncontextmenu="blur()">CLEAR</button><br>
<text class="middle">CELL COUNT</text><br>
<button class="middle" id="activeCount" title="Active Cells" oncontextmenu="blur()" disabled>0</button>
<button class="middle" id="inactiveCount" title="Inactive Cells" oncontextmenu="blur()" disabled>0</button><br>
TABLE AND SETTINGS<br>
<div class="left activation">
<button class="setting" title="For a given active cell, the number of adjacent cells that must be active for it to become inactive" oncontextmenu="blur()" disabled>DEATH</button>
<button class="rule true" id="death1" onclick="ruleChange(1); blur()" title="Active active cells with 0 active adjacent cells will become inactive" oncontextmenu="blur()">0</button>
<button class="rule true" id="death2" onclick="ruleChange(2); blur()" title="Active active cells with 1 active adjacent cells will become inactive" oncontextmenu="blur()">1</button>
<button class="rule false" id="death3" onclick="ruleChange(3); blur()" title="Active active cells with 2 active adjacent cells will become inactive" oncontextmenu="blur()">2</button><br>
<button class="rule false" id="death4" onclick="ruleChange(4); blur()" title="Active active cells with 3 active adjacent cells will become inactive" oncontextmenu="blur()">3</button>
<button class="rule true" id="death5" onclick="ruleChange(5); blur()" title="Active active cells with 4 active adjacent cells will become inactive" oncontextmenu="blur()">4</button>
<button class="rule true" id="death6" onclick="ruleChange(6); blur()" title="Active active cells with 5 active adjacent cells will become inactive" oncontextmenu="blur()">5</button><br>
<button class="rule true" id="death7" onclick="ruleChange(7); blur()" title="Active active cells with 6 active adjacent cells will become inactive" oncontextmenu="blur()">6</button>
<button class="rule true" id="death8" onclick="ruleChange(8); blur()" title="Active active cells with 7 active adjacent cells will become inactive" oncontextmenu="blur()">7</button>
<button class="rule true" id="death9" onclick="ruleChange(9); blur()" title="Active active cells with 8 active adjacent cells will become inactive" oncontextmenu="blur()">8</button><br>
</div>
<div class="right activation">
<button class="setting" title="For a given inactive cell, the number of adjacent cells that must be active for it to become active" oncontextmenu="blur()" disabled>BIRTH</button>
<button class="rule false" id="birth1" onclick="ruleChange(10); blur()" title="Active inactive cells with 0 active adjacent cells will become active" oncontextmenu="blur()">0</button>
<button class="rule false" id="birth2" onclick="ruleChange(11); blur()" title="Active inactive cells with 1 active adjacent cells will become active" oncontextmenu="blur()">1</button>
<button class="rule false" id="birth3" onclick="ruleChange(12); blur()" title="Active inactive cells with 2 active adjacent cells will become active" oncontextmenu="blur()">2</button><br>
<button class="rule true" id="birth4" onclick="ruleChange(13); blur()" title="Active inactive cells with 3 active adjacent cells will become active" oncontextmenu="blur()">3</button>
<button class="rule false" id="birth5" onclick="ruleChange(14); blur()" title="Active inactive cells with 4 active adjacent cells will become active" oncontextmenu="blur()">4</button>
<button class="rule false" id="birth6" onclick="ruleChange(15); blur()" title="Active inactive cells with 5 active adjacent cells will become active" oncontextmenu="blur()">5</button><br>
<button class="rule false" id="birth7" onclick="ruleChange(16); blur()" title="Active inactive cells with 6 active adjacent cells will become active" oncontextmenu="blur()">6</button>
<button class="rule false" id="birth8" onclick="ruleChange(17); blur()" title="Active inactive cells with 7 active adjacent cells will become active" oncontextmenu="blur()">7</button>
<button class="rule false" id="birth9" onclick="ruleChange(18); blur()" title="Active inactive cells with 8 active adjacent cells will become active" oncontextmenu="blur()">8</button><br>
</div>
<button class="middle setting true" id="wrap" onclick="ruleChange(21); blur()" title="Cells ignore the canvas borders and are able to affect cells on the opposite edge" oncontextmenu="blur()">WRAP</button><br>
<button class="middle setting false" id="grid" onclick="ruleChange(24); blur()" title="All cells have a light border around them" oncontextmenu="blur()">GRID</button><br>
<button class="middle setting nocolor" id="color" onclick="ruleChange(22); blur()" title="Change the color of active cells that have been active for fewer than 16 frames&#10;* May impact framerate" oncontextmenu="ruleChange(23); blur()">COLOR</button><br>
<button class="middle setting true" id="invert" onclick="preset(); blur()" title="Enable all inactive table and disable all active table" oncontextmenu="blur()">INVERT</button><br>
<button class="middle speed" onclick="ruleChange(19); blur()" title="Increase the FPS" oncontextmenu="blur()">+</button>
<button class="middle setting" id="speed" title="How many frames per second (FPS) are rendered" oncontextmenu="blur()" disabled>60 FPS</button>
<button class="middle speed" onclick="ruleChange(20); blur()" title="Decrease the FPS" oncontextmenu="blur()">-</button><br>
RULE PRESETS<br>
<button class="left" onclick="preset(0); blur()" oncontextmenu="blur()">LIFE</button>
<button class="right" onclick="preset(1); blur()" oncontextmenu="blur()">INVERTED LIFE</button><br>
<button class="left" onclick="preset(2); blur()" oncontextmenu="blur()">LONG LIFE</button>
<button class="right" onclick="preset(3); blur()" oncontextmenu="blur()">HIGH LIFE</button><br>
<button class="left" onclick="preset(4); blur()" oncontextmenu="blur()">AMOEBA</button>
<button class="right" onclick="preset(5); blur()" oncontextmenu="blur()">DIAMOEBA</button><br>
<button class="left" onclick="preset(6); blur()" oncontextmenu="blur()">MAZE</button>
<button class="right" onclick="preset(7); blur()" oncontextmenu="blur()">REPLICATOR</button><br>
<button class="left" onclick="preset(8); blur()" oncontextmenu="blur()">WALLED CITIES</button>
<button class="right" onclick="preset(9); blur()" oncontextmenu="blur()">CORAL</button><br>
<button class="left" onclick="preset(10); blur()" oncontextmenu="blur()">DAY AND NIGHT</button>
<button class="right" onclick="preset(11); blur()" oncontextmenu="blur()">STAINS</button>
</div>
</body>
<html>
<style>
body { user-select: none; }
button {
background-color: #bcf;
border-radius: 5px;
border-color: #abf;
color: #000;
font-size: 28px;
height: 38px; }
canvas {
border-width: 2px;
border-style: outset;
border-color: #abc;
border-radius: 3px; }
#activeCount {
background-color: #000;
color: #fff;
width: 100px; }
#color.dark {
background-image: linear-gradient(to right, #eee, #000);
color: #fff; }
#color.invert {
background-color: #fff;
color: #000; }
#color.darkinvert {
background-image: linear-gradient(to left, #eee, #000);
color: #fff; }
#color.redlight {
background-image: linear-gradient(to right, #fdd, #f00, #000);
color: #fff; }
#color.reddark {
background-image: linear-gradient(to right,#f00, #000);
color: #fff; }
#color.redlightinvert {
background-image: linear-gradient(to left, #fdd, #f00);
color: #fff; }
#color.reddarkinvert {
background-image: linear-gradient(to left,#f00, #000);
color: #fff; }
#color.greenlight {
background-image: linear-gradient(to right, #dfd, #0f0, #000);
color: #fff; }
#color.greendark {
background-image: linear-gradient(to right,#0f0, #000);
color: #fff; }
#color.greenlightinvert {
background-image: linear-gradient(to left, #dfd, #0f0);
color: #fff; }
#color.greendarkinvert {
background-image: linear-gradient(to left,#0f0, #000);
color: #fff; }
#color.bluelight {
background-image: linear-gradient(to right, #ddf, #00f, #000);
color: #fff; }
#color.bluedark {
background-image: linear-gradient(to right,#00f, #000);
color: #fff; }
#color.bluelightinvert {
background-image: linear-gradient(to left, #ddf, #00f);
color: #fff; }
#color.bluedarkinvert {
background-image: linear-gradient(to left,#00f, #000);
color: #fff; }
#color.nocolor {
background-color: #000;
color: #fff; }
#color.rainbow {
background-image: linear-gradient(to right, #f00, #aa0, #0f0, #0aa, #00f, #808, #000);
color: #fff; }
#dotCount { background-image: linear-gradient(to right, #111, #fff); }
#inactiveCount {
background-color: #fff;
color: #000;
width: 100px; }
#player {
position: fixed;
top: 8px;
left: 915px;
width: 400px;
text-align: center;
line-height: 40px;
font-size: 200%; }
.activation {
background-color: #789;
width: 120px;
height: 162px;
border-radius: 5px 5px 4px 4px; }
.activation > .setting {
position: relative;
top: -3px; }
.activation > .rule {
position: relative;
top: -3px;
width: 38px;
margin: 1px -3px 0px -3px; }
.false { background-color: #dc143c; }
.left {
position: absolute;
left: 0px; }
.middle {
position: relative;
right: 4px;
bottom: 3px; }
.player {
width: 140px;
text-align: center; }
.right {
position: absolute;
right: 8px; }
.setting {
padding: 0px;
white-space: nowrap;
width: 120px; }
.speed { width: 38px; }
.true { background-color: #7fff00; }
</style>
<script>
var convas = document.getElementById("conway");
var ctx = convas.getContext("2d");
var table = {
birth: [false, false, false, true, false, false, false, false, false],
board: [],
color: 0,
cursor: false,
death: [true, true, false, false, true, true, true, true, true],
drawType: 0,
grid: false,
paused: true,
speed: 60,
wrap: true
}
draw = () => {
let data = ctx.getImageData(0, 0, 900, 900);
let count = [0, 0];
for (let y = 150; y--;)
{
for (let x = 150; x--;)
{
let a = table.board[y][x];
for (let i = 0; i < 36; i++)
{
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 3] = 255;
let r, g, b;
switch (table.color)
{ // 0 = black | white
case 0: r = g = b = a > 0 ? 0 : 255; break;
// 1 = white | black
case 1: r = g = b = a > 0 ? 255 : 0; break;
// 2 = white > black | white
case 2: r = g = b = a > 0 ? 255 - a * (255 / 16) : 255; break;
// 3 = black > white | black
case 3: r = g = b = a > 0 ? a * (255 / 16) : 0; break;
// 4 = white > red > black | white
case 4: r = a > 0 ? 510 - (a * (255 / 8)) : 255;
g = b = a > 0 ? 255 - (a * (255 / 8)) : 255; break;
// 5 = white > green > black | white
case 5: g = a > 0 ? 510 - (a * (255 / 8)) : 255;
r = b = a > 0 ? 255 - (a * (255 / 8)) : 255; break;
// 6 = white > blue > black | white
case 6: b = a > 0 ? 510 - (a * (255 / 8)) : 255;
r = g = a > 0 ? 255 - (a * (255 / 8)) : 255; break;
// 7 = red > black | white
case 7: r = a > 0 ? 255 - (a * (255 / 16)) : 255;
g = b = 0; break;
// 8 = green > black | white
case 8: g = a > 0 ? 255 - (a * (255 / 16)) : 255;
r = b = 0; break;
// 9 = blue > black | white
case 9: b = a > 0 ? 255 - (a * (255 / 16)) : 255;
r = g = 0; break;
// 10 = black > red > white | black
case 10:r = a > 0 ? a * (510 / 16) : 0;
g = b = (a * (510 / 16)) - 255; break;
// 11 = black > green > white | black
case 11:g = a > 0 ? a * (510 / 16) : 0;
r = b = (a * (510 / 16)) - 255; break;
// 12 = black > blue > white | black
case 12:b = a > 0 ? a * (510 / 16) : 0;
r = g = (a * (510 / 16)) - 255; break;
// 13 = red > white | black
case 13:r = 255;
g = b = a > 0 ? a * (255 / 16) : 0; break;
// 14 = green > white | black
case 14:g = 255;
r = b = a > 0 ? a * (255 / 16) : 0; break;
// 15 = blue > white | black
case 15:b = 255;
r = g = a > 0 ? a * (255 / 16) : 0; break;
// 16 = rainbow > black | white
case 16:r = a > 0 ? a <= 5 || a >= 12 ? Math.cos(((a - (a <= 5 ? 1 : 11)) * Math.PI) / 10) * 255 * (a >= 12 ? (a - 11) / 5 : 1) : 0 : 255;
g = a > 0 ? Math.sin(((a - 1) * Math.PI) / 10) * 255 : 255;
b = a > 0 ? a >= 7 ? Math.sin(((a - 6) * Math.PI) / 10) * 255 * (a >= 12 ? (5 - (a - 11)) / 5 : 1) : 0 : 255; break;
// 17 = rainbow > white | black
case 17:r = a > 0 ? a <= 5 || a >= 12 ? Math.cos(((a - (a <= 5 ? 1 : 11)) * Math.PI) / 10) * 255 * (a >= 12 ? (a - 11) / 5 : 1) : 0 : 255;
g = a > 0 ? Math.sin(((16 - a) * Math.PI) / 10) * 255 : 255;
b = a > 0 ? a >= 7 ? Math.sin(((a - 6) * Math.PI) / 10) * 255 * (a >= 12 ? (5 - (a - 11)) / 5 : 1) : 0 : 255; break;
}
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 0] = r;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 1] = g;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 2] = b;
if (table.grid)
if (i < 6 || i > 29 ||i % 6 == 0 || i % 6 == 5)
{
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 0] += 100;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 1] += 100;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 2] += 100;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 3] = 255;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 0] /= 2;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 1] /= 2;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 2] /= 2;
}
if (table.cursor && (
(x == table.cursor[0] + 1 && y == table.cursor[1] && i % 6 < 2) ||
(x == table.cursor[0] - 1 && y == table.cursor[1] && i % 6 > 3) ||
(y == table.cursor[1] + 1 && x == table.cursor[0] && i < 12) ||
(y == table.cursor[1] - 1 && x == table.cursor[0] && i > 23) ||
(x == table.cursor[0] + 1 && y == table.cursor[1] + 1 && i == 0) ||
(x == table.cursor[0] - 1 && y == table.cursor[1] + 1 && i == 5) ||
(x == table.cursor[0] + 1 && y == table.cursor[1] - 1 && i == 30) ||
(x == table.cursor[0] - 1 && y == table.cursor[1] - 1 && i == 35)))
{
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 0] = a > 0 ? 255 - data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 0] : 0;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 1] = a > 0 ? 255 - data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 1] : 0;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 2] = a > 0 ? 255 - data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 2] : 0;
data.data[((y * 6 + (i / 6 | 0)) * 900 + (x * 6 + (i % 6))) * 4 + 3] = 255;
}
}
if (a > 0)
count[0]++;
else
count[1]++;
}
}
document.getElementById("activeCount").innerText = count[0];
document.getElementById("inactiveCount").innerText = count[1];
ctx.putImageData(data, 0, 0);
}
random = () => {
table.board = [];
for (let y = 150; y--;)
{
let a = [];
for (let x = 150; x--;)
{
let b = Math.random() * 2 | 0;
a.push(b);
}
table.board.push(a);
}
}
clear = () => {
table.board = [];
for (let y = 150; y--;)
{
let a = [];
for (let x = 150; x--;)
a.push(0);
table.board.push(a);
}
}
step = () => {
if (!table.paused || table.frame)
{
table.frame = false;
let clone = [];
ctx.scale(1 / 3, 1 / 3);
for (let y = 0; y < 150; y++)
{
let a = [];
for (let x = 0; x < 150; x++)
{
let adj = 0;
let b;
for (let d = 0; d < 8; d++)
{
if (table.wrap)
adj += table.board[y + [y == 0 ? 149 : -1, y == 0 ? 149 : -1, 0, y == 149 ? -149 : 1, y == 149 ? -149 : 1, y == 149 ? -149 : 1, 0, y == 0 ? 149 : -1][d]][x + [0, x == 149 ? -149 : 1, x == 149 ? -149 : 1, x == 149 ? -149 : 1, 0, x == 0 ? 149 : -1, x == 0 ? 149 : -1, x == 0 ? 149 : -1][d]] > 0 ? 1 : 0;
else
if (!((y == 0 && [0, 1, 7].includes(d)) ||
(y == 149 && [3, 4, 5].includes(d)) ||
(x == 0 && [5, 6, 7].includes(d)) ||
(x == 149 && [1, 2, 3].includes(d))))
adj += table.board[y + [-1, -1, 0, 1, 1, 1, 0, -1][d]][x + [0, 1, 1, 1, 0, -1, -1, -1][d]] > 0 ? 1 : 0;
}
if (table.board[y][x] > 0 && table.death[adj])
b = 0;
else
if (table.board[y][x] == 0 && table.birth[adj])
b = 1;
else
if (table.board[y][x] > 0 && table.board[y][x] < 16)
b = table.board[y][x] + 1;
else
b = table.board[y][x];
a.push(b);
}
clone.push(a);
}
table.board = clone;
}
draw();
setTimeout(() => step(), 1000 / table.speed);
}
ruleChange = (rule) => {
// PAUSE
if (rule == 0)
{
pause = document.getElementById("pause");
table.paused = !table.paused;
if (table.paused)
{
pause.innerText = "PLAY";
pause.title = "Start the engine";
}
else
{
pause.innerText = "PAUSE";
pause.title = "Stop the engine";
}
}
// ACTIVATION RULES
if (rule > 0 && rule < 19)
{
if (rule < 10)
{
let death = document.getElementById("death" + rule);
table.death[rule - 1] = !table.death[rule - 1];
death.classList.remove(!table.death[rule - 1]);
death.classList.add(table.death[rule - 1]);
}
else
{
let birth = document.getElementById("birth" + (rule - 9));
table.birth[rule - 10] = !table.birth[rule - 10];
birth.classList.remove(!table.birth[rule - 10]);
birth.classList.add(table.birth[rule - 10]);
}
}
// SPEED +
if (rule == 19 && table.speed < 100)
{
if (table.speed >= 60)
table.speed += 10
else
if (table.speed >= 40)
table.speed += 5;
else
if (table.speed >= 20)
table.speed += 4;
else
if (table.speed >= 8)
table.speed += 2;
else
table.speed += 1;
document.getElementById("speed").innerText = table.speed + " FPS";
}
// SPEED -
if (rule == 20 && table.speed > 1)
{
if (table.speed > 60)
table.speed -= 10
else
if (table.speed > 40)
table.speed -= 5;
else
if (table.speed > 20)
table.speed -= 4;
else
if (table.speed > 8)
table.speed -= 2;
else
table.speed -= 1;
document.getElementById("speed").innerText = table.speed + " FPS";
}
// WRAP
if (rule == 21)
{
let wrap = document.getElementById("wrap");
table.wrap = !table.wrap;
wrap.classList.remove(!table.wrap);
wrap.classList.add(table.wrap);
}
// COLOR NEXT
if (rule == 22)
{
let color = document.getElementById("color");
table.color = table.color == 17 ? 0 : table.color + 1;
color.classList.remove(["rainbow", "rainbowinvert", "nocolor", "invert", "dark", "darkinvert", "redlight", "greenlight", "bluelight", "reddark", "greendark", "bluedark", "redlightinvert", "greenlightinvert", "bluelightinvert", "reddarkinvert", "greendarkinvert", "bluedarkinvert"][table.color]);
color.classList.add(["nocolor", "invert", "dark", "darkinvert", "redlight", "greenlight", "bluelight", "reddark", "greendark", "bluedark", "redlightinvert", "greenlightinvert", "bluelightinvert", "reddarkinvert", "greendarkinvert", "bluedarkinvert", "rainbow", "rainbowinvert"][table.color]);
}
// COLOR PREV
if (rule == 23)
{
let color = document.getElementById("color");
table.color = table.color == 0 ? 17 : table.color - 1;
color.classList.remove(["invert", "dark", "darkinvert", "redlight", "greenlight", "bluelight", "reddark", "greendark", "bluedark", "redlightinvert", "greenlightinvert", "bluelightinvert", "reddarkinvert", "greendarkinvert", "bluedarkinvert", "rainbow", "rainbowinvert", "nocolor"][table.color]);
color.classList.add(["nocolor", "invert", "dark", "darkinvert", "redlight", "greenlight", "bluelight", "reddark", "greendark", "bluedark", "redlightinvert", "greenlightinvert", "bluelightinvert", "reddarkinvert", "greendarkinvert", "bluedarkinvert", "rainbow", "rainbowinvert"][table.color]);
}
// GRID
if (rule == 24)
{
let grid = document.getElementById("grid");
table.grid = !table.grid;
grid.classList.remove(!table.grid);
grid.classList.add(table.grid);
}
}
preset = (a) => {
if (typeof a != "undefined")
{
let p = [
// LIFE
{ death: [true, true, false, false, true, true, true, true, true],
birth: [false, false, false, true, false, false, false, false, false] },
// INVERSE LIFE
{ death: [true, true, true, false, false, true, false, false, false],
birth: [true, true, true, true, true, false, false, true, true] },
// LONG LIFE
{ death: [true, true, true, true, true, false, true, true, true],
birth: [false, false, false, true, true, true, false, false, false] },
// HIGH LIFE
{ death: [true, true, false, false, true, true, true, true, true],
birth: [false, false, false, true, false, false, true, false, false] },
// AMOEBA
{ death: [true, false, true, false, true, false, true, true, false],
birth: [false, false, false, true, false, true, false, true, false] },
// DIAMOEBA
{ death: [true, true, true, true, true, false, false, false, false],
birth: [false, false, false, true, false, true, true, true, true] },
// MAZE
{ death: [true, false, false, false, false, false, true, true, true],
birth: [false, false, false, true, false, false, false, false, false] },
// REPLICATOR
{ death: [true, false, true, false, true, false, true, false, true],
birth: [false, true, false, true, false, true, false, true, false] },
// WALLED CITIES
{ death: [true, true, false, false, false, false, true, true, true],
birth: [false, false, false, false, true, true, true, true, true] },
// CORAL
{ death: [true, true, true, true, false, false, false, false, false],
birth: [false, false, false, true, false, false, false, false, false] },
// DAY AND NIGHT
{ death: [true, true, true, false, false, true, false, false, false],
birth: [false, false, false, true, false, false, true, true, true] },
// STAINS
{ death: [true, true, false, false, true, false, false, false, false],
birth: [false, false, false, true, false, false, true, true, true] }
][a];
for (let i = 0; i < 9; i++)
{
if (table.death[i] != p.death[i])
{
let death = document.getElementById("death" + (i + 1));
table.death[i] = !table.death[i];
death.classList.remove(!table.death[i]);
death.classList.add(table.death[i]);
}
if (table.birth[i] != p.birth[i])
{
let birth = document.getElementById("birth" + (i + 1));
table.birth[i] = !table.birth[i];
birth.classList.remove(!table.birth[i]);
birth.classList.add(table.birth[i]);
}
}
}
else
{
let invert = document.getElementById("invert");
if (invert.classList.contains("true"))
{
invert.classList.remove("true");
invert.classList.add("false");
}
else
{
invert.classList.remove("false");
invert.classList.add("true");
}
for (let i = 9; i--;)
{
let death = document.getElementById("death" + (i + 1));
table.death[i] = !table.death[i];
death.classList.remove(!table.death[i]);
death.classList.add(table.death[i]);
let birth = document.getElementById("birth" + (i + 1));
table.birth[i] = !table.birth[i];
birth.classList.remove(!table.birth[i]);
birth.classList.add(table.birth[i]);
}
}
}
document.getElementById("clear").addEventListener("click", () => clear());
document.addEventListener("keydown", (e) => {
switch (e.key)
{
case " ": ruleChange(0);
}
});
convas.addEventListener("mousemove", (e) => {
findxy('move', e)
}, false);
convas.addEventListener("mousedown", (e) => {
findxy('down', e);
blur();
}, false);
convas.addEventListener("mouseup", (e) => {
findxy('up', e)
}, false);
convas.addEventListener("mouseout", (e) => {
findxy('out', e)
}, false);
findxy = (res, e) => {
if (res == 'down') {
let prevX = table.cursor[0];
let prevY = table.cursor[1];
let currX = e.offsetX / 6 | 0;
let currY = e.offsetY / 6 | 0;
table.drawType = e.button == 0 ? 1 : 0;
table.board[currY][currX] = table.drawType;
table.flag = true;
table.cursor = [currX, currY];
draw();
}
if (res == 'up' || res == "out") {
table.flag = false;
table.cursor = false;
}
if (res == 'move') {
let prevX = table.cursor[0];
let prevY = table.cursor[1];
let currX = e.offsetX / 6 | 0;
let currY = e.offsetY / 6 | 0;
table.cursor = [currX, currY];
if (table.flag)
{
for (let i = 0; i <= Math.sqrt((Math.abs(prevX - currX) ** 2) + (Math.abs(prevY - currY) ** 2) | 0); i++)
table.board[prevY + ((currY - prevY) / (i == 0 ? 1 : i)) | 0][prevX + ((currX - prevX) / (i == 0 ? 1 : i)) | 0] = table.drawType;
}
}
}
random();
step();
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment