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:
0:d43dc92ae767
Child:
1:9e88d16ab21e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LifeRules.cpp	Wed Apr 16 22:25:19 2014 +0000
@@ -0,0 +1,153 @@
+
+#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)
+{
+    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!");
+}
+
+void Life::setbit(int x, int y, Life::ValueOfLife b, int otherframe)
+{
+    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));
+    
+    if (animation == monochrome)
+        b = (ValueOfLife)(b & 1);
+    if (x >= 0 && x <= maxX && y >= 0 && y <= maxY) {
+        uint8_t maskBitsOfInterest = ((1 << (1 << animation)) -1) << (bitIndex);
+        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);
+    }
+}
+
+Life::ValueOfLife Life::getbit(int x, int y, int otherframe)
+{
+    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);
+        uint8_t curCell = pLifeMap[byteIndex] & maskBitsOfInterest;
+        ValueOfLife b = (ValueOfLife)(curCell >> (bitIndex));
+        if (animation == monochrome)
+            b = (ValueOfLife)(b & 1);
+        return b;
+    } else {
+        ERR(" Out of Bounds value (%d, %d)\r\n", x, y);
+        return dead;
+    }
+}
+
+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 f = 0; f < 2; f++) {
+                setbit(x,y, dead, f);
+            }
+        }
+    }
+}
+
+// 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 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
+                total++;
+            }
+        }
+    }
+    if (getbit(x,y)) { // minus middle of 9 cells (current cell) if it is alive
+        total--;
+    }
+    return total;
+}
+
+void Life::GenerationStep(void)
+{
+    INFO("Generation Step");
+    for (int i = 0; i <= maxX; i++) { //loop through cells
+        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
+        }
+    }
+    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)
+                setbit(x,y, living);
+        }
+    }
+}
+
+void Life::CycleOfLife(int x, int y, int neighbors)
+{
+    ValueOfLife currently = getbit(x,y);
+    
+    if ((neighbors < 2) || (neighbors > 3)) {
+        if (currently == living)
+            setbit(x,y, dying, 1);
+        else
+            setbit(x,y, dead, 1);
+    }
+    if (neighbors == 3) {
+        if (currently == living)
+            setbit(x,y, living, 1);
+        else
+            setbit(x,y, birthing, 1);
+    }
+    if (neighbors == 2) {
+        setbit(x,y, currently, 1);
+    }
+}
\ No newline at end of file