/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.xpuAsNzn4Y$/rev.2369
*
* authors:
* Sean
* Michal Wallace
* Sean Siem
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
/* Conway's Game of Life
* (as implemented in processing by Michal Wallace on 5/19/2011)
* This code is in the public domain.
*/
int kGridW = 50;
int kGridH = 50;
int kCellW = 10;
int kCellH = 10;
int kMaxAge = 16;
int[][] gGrid = new int[kGridW][kGridH];
int[][] gNext = new int[kGridW][kGridH];
void setup()
{
// processing could do it this way, but it breaks sketchpad:
//size(kGridW * kCellW, kGridH * kCellH + 50);
size(500, 550);
frameRate(6);
// initialize to a random grid:
for (int y = 0; y < kGridH; ++y)
{
for (int x = 0; x < kGridW; ++x)
{
gGrid[y][x] = (random(1) > 0.5) ? 1 : 0;
gNext[y][x] = 0;
}
}
}
// I want to color-code the cells by age, so the value will
// be the age of the cell.
int valueAt(int x, int y)
{
// assume anything outside is dead
if ((x < 0)
|| (x >= kGridW)
|| (y < 0)
|| (y >= kGridH))
{
return 0;
}
else
{
return gGrid[y][x];
}
}
// Returns 1 or 0
int count(int x, int y)
{
int v = valueAt(x, y);
return (v==0) ? 0 : 1;
}
// you consider all 8 neighbors :)
int neighborCount(int x, int y)
{
return count(x, y - 1) // N
+ count(x + 1, y - 1) // NE
+ count(x + 1, y) // E
+ count(x + 1, y + 1) // SE
+ count(x, y + 1) // S
+ count(x - 1, y + 1) // SW
+ count(x - 1, y) // W
+ count(x - 1, y - 1) // NW
;
}
void copyGrid(fromGrid, toGrid)
{
for (y = 0; y < kGridH; ++y)
{
for (x = 0; x < kGridW; ++x)
{
toGrid[y][x] = fromGrid[y][x];
}
}
}
// Rules of Life:
// --------------------
// 1. die if neighbors < 2
// 2. stay alive if 2 or 3 neighbors
// 3. die if neigbors > 3
// 4. come alive if exactly 3 live neighbors
void applyRules()
{
int x;
int y;
int neighbors;
for (y = 0; y < kGridH; ++y)
{
for (x = 0; x < kGridW; ++x)
{
// start with a clean copy of the grid:
gNext[y][x] = 0;
neighbors = neighborCount(x, y);
// if alive:
if (count(x, y) == 1)
{
if ((neighbors < 2) || (neighbors > 3))
{
gNext[y][x] = 0; // die
}
else
{
// get older:
gNext[y][x] = constrain(gGrid[y][x] + 1, 0, kMaxAge);
}
}
else if (3 == neighbors)
{
gNext[y][x] = 1; // birth
}
}
}
copyGrid(gNext, gGrid);
}
void draw()
{
int x;
int y;
applyRules();
// reset colors
background(0);
stroke(color(0, 0, 0));
fill(color(255, 255, 255));
// draw the grid:
for (y = 0; y < kGridH; ++y)
{
for (x = 0; x < kGridW; ++x)
{
if (0 != gGrid[y][x])
{
drawCell(x, y);
}
}
}
}
void drawCell(x, y)
{
// draw cells darker as they age:
int shade = 256 - (8 * gGrid[y][x]);
fill(color(shade, shade, shade));
rect(x * kCellW, y * kCellH, kCellW, kCellH);
}
// paint with the mouse:
void mouseDragged()
{
onMouse();
}
void mousePressed()
{
onMouse();
}
void mouseClicked()
{
onMouse();
}
void onMouse()
{
int cellX = int(mouseX / kCellW);
int cellY = int(mouseY / kCellH);
if (cellY < kGridH)
{
gGrid[cellY][cellX] = 1;
drawCell(cellX, cellY);
}
}