# Cellular Automata – Conway’s Game of Life in HTML 5

I had to do a school project involving automata so, after searching what this means .. I came to “cellular automaton” and then to the “Conway’s Game of Life” on wikipedia. I remember doing such a project on RentACoder few years ago in Visual Basic but I didn’t knew this fancy name for it … “cellular automata” 🙂

The rules are pretty simple :

• A cell with 0 or 1 neighbor dies because of underpopulation
• A cell with 4 or more neighbors dies because of overpopulation
• If an empty space has exactly 3 cells then a new cell is born in that empty space
• If none of the above rules apply then the space does not change (a live cell remanins alive, and an empty space is still empty)

For implementing it .. I choosed the canvas object from HTML 5 specs as I wanted to learn a little bit about it.

The first step was writing the canvas tags with a default message in case the user’s browser does not support it.

```
Your browser does not support canvas.

```

After this .. came the fun part .. javascript 🙂

The code below is pretty simple :

• We declare how many cells we want on the X/Y axes, how many pixels wide should be a cell and the delay between drawing the next generation of cells
• We create 2 arrays, one for storing the initial colony and one for the next generation
• We randomly fill with live cells the initial colony
• We draw the initial colony and then we process the colony using the game’s rules
```
// Settings
var x = 160; // How many cells on the X axis
var y = 140; // How many cells on the Y axis
var pixels_per_value = 4; // How many pixels wide should be a cell
var delay_between_frames = 400;// In ms

// Calculate the canvas width and height
var canvas_x = x * pixels_per_value;
var canvas_y = y * pixels_per_value;

// Create our matrix
var matrix = new Array(y);
var matrix_tmp = new Array(y);
for (i = 0; i < y; i++)
{
matrix[i] = new Array(x);
matrix_tmp[i] = new Array(x);
}

// Fill with some random points
var random = 1600;
var m,n;
for (i = 0; i < random; i++)
{
m = Math.floor(Math.random()*y);
n = Math.floor(Math.random()*x);
matrix[m][n] = 1;
}

// Get the canvas reference and the 2D context
var canvas = document.getElementById('drawBoard');
// Set canvas size
canvas.width = canvas_x;
canvas.height = canvas_y;
var context = canvas.getContext('2d');

// Draw the first cell generation
draw_matrix();

// Call for the next generation of the cell colony
setTimeout("process_life()", delay_between_frames);

function process_life()
{
var neighbours = 0;
matrix_tmp = matrix.clone();
for (i = 0; i < y; i++)
{
for (j = 0; j < x; j++)
{
neighbours = count_neighbours(i,j);
// Underpopulation
if (neighbours < 2)
{
matrix_tmp[i][j] = 0;
}
// Overcrowding
if (neighbours > 3)
{
matrix_tmp[i][j] = 0;
}
// Birth
if (neighbours == 3)
{
matrix_tmp[i][j] = 1;
}
}
}
matrix = matrix_tmp.clone();
draw_matrix();
setTimeout("process_life()", delay_between_frames);
}

// Added so we can copy the array between steps
Array.prototype.clone = function ()
{
var tmp = new Array();
for (var property in this)
{
tmp[property] = typeof (this[property]) == 'object'  ? this[property].clone() : this[property];
}
return tmp;
}

function count_neighbours(i, j)
{
var count = 0;
// Check for its maximum 8 neighbours
if (matrix[i][j-1] == 1) count++;
if (matrix[i][j+1] == 1) count++;
//
if (matrix[i-1] != undefined)
{
if (matrix[i-1][j] == 1) count++;
if (matrix[i-1][j-1] == 1) count++;
if (matrix[i-1][j+1] == 1) count++;
}
if (matrix[i+1] != undefined)
{
if (matrix[i+1][j] == 1) count++;
if (matrix[i+1][j-1] == 1) count++;
if (matrix[i+1][j+1] == 1) count++;
}
return count;
}

function draw_matrix()
{
for (i = 0; i < y; i++)
{
for (j = 0; j < x; j++)
{
draw_matrix_point(j, i, matrix[i][j]);
}
}
}

function draw_matrix_point(i, j, status)
{
var origin_x = i * pixels_per_value;
var origin_y = j * pixels_per_value;
if (status == 1)
{
context.fillStyle = '#00FF00';
}
else
{
context.fillStyle = '#FF0000';
}
draw_rectangle(context, origin_x, origin_y, pixels_per_value, pixels_per_value);
}

// Draw a rectangle based on x/y origin point and having a specified width and height
function draw_rectangle(context, origin_x, origin_y, width, height)
{
context.beginPath();
context.rect(origin_x, origin_y, width, height);
context.closePath();
context.fill();
}

```

If you have any questions .. feel free to ask 🙂

Click here to see the working project.

This site uses Akismet to reduce spam. Learn how your comment data is processed.