Conway's game of life - derived from another project, turned into a c++ class, and scaled to support up to a 480x272 display, or a lower resolution color display.

Dependents:   GameOfLife

Revision:
1:9e88d16ab21e
Parent:
0:d43dc92ae767
Child:
3:860ae49fedb7
--- a/LifeRules.cpp	Wed Apr 16 22:25:19 2014 +0000
+++ b/LifeRules.cpp	Wed Apr 23 11:40:10 2014 +0000
@@ -1,31 +1,33 @@
-
+// Conway's game of life
+//
+// http://en.wikipedia.org/wiki/Conway's_Game_of_Life
+//
+// A simple cellular automation where pixels are born, live, and die
+// following a simple set of rules. The oddest of the rules is that
+// it takes 3 to create birth of a new life...
+//
+// Early on (back in the 70's), computers were not accessible to
+// most, and yet somehow this simulation flourished. I was one of
+// many that used pencil and graph paper, chalk on a board and
+// even pennies on paper to simulate each cell. It was so much 
+// more animated when I had access to an 8008 micro and a "TV 
+// typewriter" interface.
+//
 #include "LifeRules.h"
 
-
-//#define DEBUG "LIFE"
-// ...
-// INFO("Stuff to show %d", var); // new-line is automatically appended
-//
-#if (defined(DEBUG) && !defined(TARGET_LPC11U24))
-#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
-#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
-#define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
-#else
-#define INFO(x, ...)
-#define WARN(x, ...)
-#define ERR(x, ...)
-#endif
-
-Life::Life(int w, int h, Life::Animation animate)
+// Hopefully, the least obvious thing in this code, once you understand
+// the basic rules of "life" is that access to the pLifeMap, which 
+// takes the 32K Ethernet buffer on the LPC1768. Of course, your 
+// application must not be using either AHBSRAM0 or AHBSRAM1 for this
+// to succeed.
+Life::Life(int w, int h, Life::Animation animate, uint8_t * pMap)
 {
     LIFE_W = w;
     LIFE_H = h;
     maxX = w - 1;
     maxY = h - 1;
     animation = animate;
-    pLifeMap = (uint8_t *)(0x2007C000);     // not using either AHBSRAM0 or AHBSRAM1
-    if ((w * h * (1 << animate) * FRAMES_PER_BIT / 8) > (BYTE_RSVD_RAM))
-        error("ERROR, you've overallocated memory and are doomed!");
+    pLifeMap = pMap;
 }
 
 void Life::setbit(int x, int y, Life::ValueOfLife b, int otherframe)
@@ -40,8 +42,6 @@
         uint8_t curCell = pLifeMap[byteIndex] & ~maskBitsOfInterest;
         uint8_t mask = b << (bitIndex);
         pLifeMap[byteIndex] = curCell | mask;
-        //INFO("set(%d,%2d,%2d,%d) => by %3d, bi %1d, cur %02X of %02X mask %02X [Val: %02X]", x,y,b,frame,byteIndex,bitIndex, curCell, 
-        //    maskBitsOfInterest, mask, pLifeMap[byteIndex]);
     } else {
         ERR(" Out of Bounds value (%d, %d)\r\n", x, y);
     }
@@ -51,8 +51,6 @@
 {
     unsigned long byteIndex = ((x + LIFE_W * y) * (1 << animation) * FRAMES_PER_BIT) / 8;
     unsigned long  bitIndex = (((x + LIFE_W * y) * (1 << animation) * FRAMES_PER_BIT) % 8) + (((frame + otherframe) & 1) * (1 << animation));
-    //INFO("getbit(%d,%2d,%2d)   => byteIndex: %2d, bitIndex: %2d, [Val: %02X]", 
-    //    frame,x,y, byteIndex,bitIndex, pLifeMap[byteIndex]);
    
     if (x >= 0 && x <= maxX && y >= 0 && y <= maxY) {   
         uint8_t maskBitsOfInterest = ((1 << (1 << animation)) -1) << (bitIndex);
@@ -69,9 +67,8 @@
 
 void Life::DestroyAllLife(void)
 {
-    INFO("Destroying all life");
     for (int y = 0; y <= maxY; y++) {
-        for (int x = 0; x <= maxX; x++) { //loop through cells
+        for (int x = 0; x <= maxX; x++) {
             for (int f = 0; f < 2; f++) {
                 setbit(x,y, dead, f);
             }
@@ -79,24 +76,19 @@
     }
 }
 
-// Values:
-//      0 = dead
-//      1 = dying
-//      2 = living
-//      3 = birthing
 int Life::CountNeighbors(int x, int y)
 {
     int total = 0;
     
-    for (int k = -1; k <= 1; k++) {                     //loop through neighbours
+    for (int k = -1; k <= 1; k++) {
         for (int l = -1; l <= 1; l++) {
             ValueOfLife lifeState = getbit((x+LIFE_W+k)%LIFE_W,(y+LIFE_H+l)%LIFE_H);
-            if (lifeState == living) {   //if living neighbour is found increment total
+            if (lifeState == living) {
                 total++;
             }
         }
     }
-    if (getbit(x,y)) { // minus middle of 9 cells (current cell) if it is alive
+    if (getbit(x,y)) { // minus the cell of interest if it is alive
         total--;
     }
     return total;
@@ -104,25 +96,20 @@
 
 void Life::GenerationStep(void)
 {
-    INFO("Generation Step");
-    for (int i = 0; i <= maxX; i++) { //loop through cells
+    for (int i = 0; i <= maxX; i++) {
         for (int j = 0; j <= maxY; j++) {
             int total = CountNeighbors(i, j);
-            INFO("(%d,%d) has %d", i, j, total);
-            CycleOfLife(i, j, total); //check neighbors
+            CycleOfLife(i, j, total);
         }
     }
     frame = (frame + 1) & 1;
 }
 
-// If dying, kill it. If birthing, give it life.
 void Life::UpdateLifeCycle(void)
 {
-    INFO("Update Life Cycle");
     for (int x = 0; x <= maxX; x++) { //loop through cells
         for (int y = 0; y <= maxY; y++) {
             ValueOfLife currently = getbit(x,y);
-            INFO("  (%d,%d) = %d", x,y, currently);
             if (currently == dying)
                 setbit(x,y, dead);
             else if (currently == birthing)