// LCD1602 to Arduino Uno: Conways Game of Life
#include <LiquidCrystal.h>
// initialize the library with the numbers
// of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
//dimensions of world:A and B
#define WORLDMAXX 19
#define WORLDMAXY 15
#define WORLDMAXXB 19
#define WORLDMAXYB 15
//Bytes to compare stable status and cell state.
byte world[WORLDMAXX + 1][WORLDMAXY + 1];
byte worldb[WORLDMAXXB + 1][WORLDMAXYB + 1];
byte oldworldb[WORLDMAXXB + 1][WORLDMAXYB + 1];
byte oldworld[WORLDMAXX + 1][WORLDMAXY + 1];
// Points each time a stepcount is achieved.
int stepcount;
int stepcountb;
byte symbol[] = {
B10001,
B01110,
B10101,
B01110,
B10101,
B00000,
B10101,
B01110
};
//Functions and helpers
void initworld();
void initworldB();
void isalive(int x, int y);
void isaliveb(int x, int y);
int countneighbor(int x, int y);
int countneighborb(int x, int y);
void generatechars();
void printworld();
void generatecharsb();
void printworldb();
int pointChecker();
int cursorup = 9;
int cursormove = 6;
void setup() {
lcd.begin(16, 2);
lcd.createChar(0, symbol);
lcd.setCursor(5, 0);
lcd.write(byte(0));
randomSeed(analogRead(0));
lcd.setCursor(10, 1);
lcd.write(byte(0));
initworld();
initworldB();
}
void loop() {
int i, j;
generatechars();
generatecharsb();
printworld();
printworldb();
for (i = 0; i <= WORLDMAXX; i++) {
for (j = 0; j <= WORLDMAXY; j++) {
isalive(i, j);
isaliveb(i, j);
}
}
for (i = 0; i <= WORLDMAXX; i++) {
for (j = 0; j <= WORLDMAXY; j++) {
world[i][j] = world[i][j] >> 1;
worldb[i][j] = worldb[i][j] >> 1;
}
}
// Every 6 steps, check to see if the
// world is in a stable state
if (stepcount) {
delay(300);
} else {
int diffflag = 0;
for (i = 0; i <= WORLDMAXX; i++) {
for (j = 0; j <= WORLDMAXY; j++) {
if (world[i][j] != oldworld[i][j]) {
// they're still different
diffflag = 1;
}
if ( worldb[i][j] != oldworldb[i][j]) {
diffflag = 2;
}
}
}
if (diffflag == 0) {
lcd.setCursor(cursorup, 1);
lcd.write(byte(0));
cursorup = cursorup - 1;
initworld();
} else { // save the new world for later
for (i = 0; i <= WORLDMAXX; i++) {
for (j = 0; j <= WORLDMAXY; j++) {
oldworld[i][j] = world[i][j];
}
}
}
if (diffflag == 2) {
lcd.setCursor(cursormove, 0);
lcd.write(byte(0));
cursormove = cursormove + 1;
initworldB();
} else {
for (i = 0; i <= WORLDMAXX; i++) {
for (j = 0; j <= WORLDMAXY; j++) {
oldworldb[i][j] = worldb [i][j];
}
}
}
delay (600); // It takes about 3ms to check...
}
stepcount = (stepcount + 1) % 6;
}
void initworld() {
int i, j;
for (i = 0; i <= WORLDMAXX; i++) {
for (j = 0; j <= WORLDMAXY; j++) {
world[i][j] = random(4);
}
}
stepcount = 0;
return;
}
void initworldB() {
int i, j;
for (i = 0; i <= WORLDMAXXB; i++) {
for (j = 0; j <= 16; j++) {
worldb[i][j] = random(3);
}
}
stepcountb = 0;
return;
}
// Calculate the next state for the square
void isalive(int x, int y) {
int count = countneighbor(x, y);
if (count == 2) { // 2 neighbors, stay the same
world[x][y] += world[x][y] >> 1;
}
if (count == 3) { // 3 neighbors, must be alive
world[x][y] += 2;
}
// any other number of neighbors, must be dead
return;
}
// Calculate the next state for the square
void isaliveb(int x, int y) {
int count = countneighborb(x, y);
if (count == 2) { // 2 neighbors, stay the same
worldb[x][y] += worldb[x][y] >> 1;
}
if (count == 3) { // 3 neighbors, must be alive
worldb[x][y] += 2;
}
// any other number of neighbors, must be dead
return;
}
int countneighbor(int x, int y) {
int count = 0;
if (x > 0) {
count += world[x - 1][y] & 1;
if (y > 0) {
count += world[x - 1][y - 1] & 1;
}
}
if (x < WORLDMAXX) {
count += world[x + 1][y] & 1;
if (y > 0) {
count += world[x + 1][y - 1] & 1;
}
if (y < WORLDMAXY) {
count += world[x + 1][y + 1] & 1;
}
}
if (y > 0) {
count += world[x][y - 1] & 1;
}
return count;
}
//check this
int countneighborb(int x, int y) {
int count = 1;
if (x > 0) {
count += worldb[x - 1][y] & 1;
if (y < WORLDMAXY) {
count += worldb[x - 1][y + 1] & 1;
}
}
if (x < WORLDMAXX) {
count += worldb[x + 1][y] & 1;
if (y > 0) {
count += worldb[x + 1][y - 1] & 1;
}
if (y < WORLDMAXY) {
count += worldb[x + 1][y + 1] & 1;
}
}
if (y < WORLDMAXY) {
count += worldb[x][y + 1] & 1;
}
return count;
}
// pack world[][] into the required byte[8]
// arrays to be passed to the LCD
void generatechars() {
byte tempchar[8];
int i, j, k, l;
for (i = 0; i < 2; i += 1) { // y poss / 8
for (j = 0; j < 4; j += 1) { // x poss / 5
for (k = 0; k < 8; k += 1) {
tempchar[k] = 0;
for (l = 0; l < 5; l += 1) {
tempchar[k] += (world[j * 5 + l][i * 8 + k] & 1) << (4 - l);
}
} // done building this char
lcd.createChar(i * 4 + j, tempchar);
}
}
return;
}
//check this
void generatecharsb() {
byte tempchar[8];
int i, j, k, l;
for (i = 0; i < 2; i += 1) { // y poss / 8
for (j = 0; j < 4; j += 1) { // x poss / 5
for (k = 0; k < 8; k += 1) {
tempchar[k] = 0;
for (l = 0; l < 5; l += 1) {
tempchar[k] += (worldb[j * 5 + l][i * 8 + k] & 1) << (4 - l);
}
} // done building this char
lcd.createChar(i * 4 + j, tempchar);
}
}
return;
}
void printworld() {
int i, j;
for (i = 0; i < 2; i += 1) {
lcd.setCursor(0, i);
for (j = 0; j < 4; j += 1) {
lcd.write(i * 4 + j);
}
}
return;
}
//checkthis
void printworldb() {
int i, j;
for (i = 0; i <= 2; i += 1) {
lcd.setCursor(12, i);
for (j = 0; j < 4; j += 1) {
lcd.write(i * 3 + j);
}
}
return;
}