# Conway’s Game of Life

## What is this?

This is an implementation of Conway’s Game of Life I wrote in a day in 2018. But Ben, what is Conway’s Game of Life, you ask?

From Wikipedia:

The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970. It is a zero-player game, meaning that its evolution is determined by its initial state, requiring no further input. One interacts with the Game of Life by creating an initial configuration and observing how it evolves. It is Turing complete and can simulate a universal constructor or any other Turing machine.

## Try it

Right click to toggle the game ‘rules’. Left click to place new cells. The number inside the cell shows its age.

```

var canvas = document.getElementById('c');
var ctx = canvas.getContext("2d");

var gameOn = 1;

ev.preventDefault();
if(ev.buttons == 1) {
let coord = [Math.floor((ev.offsetY - 0) / 16), Math.floor((ev.offsetX- 0) / 16)];
board[coord][coord].toggle();
}
});
ev.preventDefault();
gameOn *= -1;
});

function cellObj(alive = false, generation = 0, neighborCount = 0) {
this.alive = alive;
this.generation = generation;
this.neighborCount = neighborCount;
return this;
}
cellObj.prototype.live = function() {
this.alive = true;
this.generation++;
return true;
}
cellObj.prototype.die = function() {
this.alive = false;
this.generation = 0;
return false;
}
cellObj.prototype.toggle = function() {
this.alive = this.alive ? this.die() : this.live();
return this;
}

function boardInit(oldBoard = []) {

let grid = [];
for(let y = 0; y < Math.floor(canvas.height / 16); y++) {
grid[y] = [];

for(let x = 0; x < Math.floor(canvas.width / 16); x++) {

grid[y][x] = new cellObj();

if((oldBoard.length !== 0)) {
if(typeof oldBoard[y] !== "undefined") {
if(typeof oldBoard[y][x] !== "undefined") {

let oldCell = oldBoard[y][x];
grid[y][x] = new cellObj(oldCell.alive, oldCell.generation, oldCell.neighborCount);
}
}
}
}
}
return grid;
}

function rules() {

let nextGeneration = boardInit(board);

for(let y = 0; y < board.length; y++) {
for(let x = 0; x < board[y].length; x++) {

let xm = x != 0 ? x - 1 : board[y].length - 2;
let xp = x != board[y].length - 1 ? x + 1 : 1;
let ym = y != 0 ? y - 1 : board.length - 2;
let yp = y != board.length - 1 ? y + 1 : 1;
let carray = [[y,xp], [y,xm], [yp,x], [yp,xp], [yp,xm], [ym,x], [ym,xp], [ym,xm]];

let neighborCount = 0;

carray.forEach(el => {
if(board[el][el].alive) { neighborCount++; }
});
nextGeneration[y][x].neighborCount = neighborCount;
nextGeneration[y][x].generation = board[y][x].generation;

if(board[y][x].alive && (neighborCount < 2 || neighborCount > 3)) { nextGeneration[y][x].die(); }
else if(board[y][x].alive && (neighborCount == 2 || neighborCount == 3)) { nextGeneration[y][x].live(); }
else if(!board[y][x].alive && neighborCount == 3) { nextGeneration[y][x].live() }

}
}

board = nextGeneration;
}

function drawBoard() {

ctx.fillStyle = 'black';
ctx.strokeStyle = 'white';

ctx.fillRect(0, 0, canvas.width, canvas.height);

for(let y = 0; y < board.length; y++) {

ctx.fillStyle = "#" + Math.round(Math.random() * 9) + "" + Math.round(Math.random() * 9) + "" + Math.round(Math.random() * 9) + "" + Math.round(Math.random() * 9) + "" + Math.round(Math.random() * 9) + "" + Math.round(Math.random() * 9);

for(let x = 0; x < board[y].length; x++) {

if(board[y][x].alive) {
ctx.fillRect(x * 16, y * 16, 16, 16);
ctx.strokeText(board[y][x].generation < 99 ? String(board[y][x].generation) : "9x", (x * 16) + 3, (y * 16) + 12);
}

}
}

ctx.fillStyle = 'white';

ctx.fillText("Right click to toggle rules, left click to toggle life.",16, canvas.height - 16);
}

canvas.width = 640;
canvas.height = 480;

board = boardInit();

setInterval(function() {

drawBoard();
if(gameOn == 1) { rules(); }

}, 100);
}

window.onresize = function() {

canvas.width = window.innerWidth - 16;
canvas.height = window.innerHeight - 16;
board = boardInit(board);
drawBoard();
}

```