// Conway's Game of Life - Teaching 2D Arrays
//
// processing version
// see: http://www.16kb.com/portfolio/display/automata/

import controlP5.*;
ControlP5 controlP5;

int playerScale = 10; // factor to magnify grid
int cols = 80; // number of cols in world
int rows = 55; // number of rows
int[][] world = new int[cols][rows]; // initialize 2D array that will house the game

int aliveFill = 128;
int backgroundFill = 0;
int systemReset = 0;

Knob speedKnob;

void setup() {
size(800,600);

smooth();

frameRate(10);
background(0);
translate(5,5); // shifts everything to the right and down

controlP5 = new ControlP5(this);
controlP5.addButton("reset",10,-5,560,80,20).setId(1);
speedKnob = controlP5.addKnob("speed",1,30,10,100,560,20);


randomizeBoard();

}

void draw () {
translate(5,5);

if (systemReset == 1) {
systemReset = 0;
randomizeBoard();

}

// check each cell
int num;

for (int x=0; x < cols; x++) { // loop through every column
for (int y=0; y < rows; y++) { // loop through every row
num = checkNeighbours(x,y);

if (world[x][y] == 0 && num == 3) { // bring cell to life
world[x][y] = 8; // 0 = dead, 8 dead, but alive next
drawCell(x, y, 1);
}

if ( world[x][y] == 1 && (num < 2 || num > 3) ) { // kill cell
world[x][y] = -1; // 1 = alive, -1 = alive, but dead next round
drawCell(x, y, 0);
}


}
}

// set all changing state codes (ie. -1 and 8)
for (int x=0; x < cols; x++) { // loop through every column
for (int y=0; y < rows; y++) { // loop through every row
if (world[x][y] == 8)
world[x][y] = 1;
if (world[x][y] == -1)
world[x][y] = 0;
}
}

} // end of draw


void reset(float theValue) {
println("a button event. "+theValue);
systemReset =1;
}



// draw a cell
void drawCell(int x, int y, int alive) {
if (alive == 1) {
fill(aliveFill);
ellipse(x*playerScale, y*playerScale, 8, 8);
} else {
fill(backgroundFill);
noSmooth();
ellipse(x*playerScale, y*playerScale, 8, 8);
smooth();
}
}

// check how neighbours a position has
int checkNeighbours(int x, int y) {
int neighbours = 0;

for (int dx=-1; dx<=1; dx++) {
for (int dy=-1; dy<=1; dy++) {
if (dy==0 && dx==0) // skip checking ourselves
continue;
if ((x+dx >= 0 && x+dx < cols) && (y+dy >= 0 && y+dy < rows) && (world[x+dx][y+dy] == 1 || world[x+dx][y+dy] == -1) ) {
neighbours++;
}
}
}

return neighbours;

}

void randomizeBoard() {
for (int x=0; x < cols; x++) { // loop through every column
for (int y=0; y < rows; y++) { // loop through every row

world[x][y] = int(random(2)); // place a 0 or 1 into the world
if (world[x][y] == 1) {
drawCell(x, y, 1); // if world holds a 1 then draw a circle
} else {
drawCell(x, y, 0); // if world holds a 1 then draw a circle
}

}
}

}

void speed(int value) {
frameRate(value);
}