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

Committer:
WiredHome
Date:
Wed Apr 23 22:54:34 2014 +0000
Revision:
3:860ae49fedb7
Parent:
1:9e88d16ab21e
Remove some of the debug stuff.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 1:9e88d16ab21e 1 // Conway's game of life
WiredHome 1:9e88d16ab21e 2 //
WiredHome 1:9e88d16ab21e 3 // http://en.wikipedia.org/wiki/Conway's_Game_of_Life
WiredHome 1:9e88d16ab21e 4 //
WiredHome 1:9e88d16ab21e 5 // A simple cellular automation where pixels are born, live, and die
WiredHome 1:9e88d16ab21e 6 // following a simple set of rules. The oddest of the rules is that
WiredHome 1:9e88d16ab21e 7 // it takes 3 to create birth of a new life...
WiredHome 1:9e88d16ab21e 8 //
WiredHome 1:9e88d16ab21e 9 // Early on (back in the 70's), computers were not accessible to
WiredHome 1:9e88d16ab21e 10 // most, and yet somehow this simulation flourished. I was one of
WiredHome 1:9e88d16ab21e 11 // many that used pencil and graph paper, chalk on a board and
WiredHome 1:9e88d16ab21e 12 // even pennies on paper to simulate each cell. It was so much
WiredHome 1:9e88d16ab21e 13 // more animated when I had access to an 8008 micro and a "TV
WiredHome 1:9e88d16ab21e 14 // typewriter" interface.
WiredHome 1:9e88d16ab21e 15 //
WiredHome 0:d43dc92ae767 16 #include "LifeRules.h"
WiredHome 0:d43dc92ae767 17
WiredHome 1:9e88d16ab21e 18 // Hopefully, the least obvious thing in this code, once you understand
WiredHome 1:9e88d16ab21e 19 // the basic rules of "life" is that access to the pLifeMap, which
WiredHome 1:9e88d16ab21e 20 // takes the 32K Ethernet buffer on the LPC1768. Of course, your
WiredHome 1:9e88d16ab21e 21 // application must not be using either AHBSRAM0 or AHBSRAM1 for this
WiredHome 1:9e88d16ab21e 22 // to succeed.
WiredHome 1:9e88d16ab21e 23 Life::Life(int w, int h, Life::Animation animate, uint8_t * pMap)
WiredHome 0:d43dc92ae767 24 {
WiredHome 0:d43dc92ae767 25 LIFE_W = w;
WiredHome 0:d43dc92ae767 26 LIFE_H = h;
WiredHome 0:d43dc92ae767 27 maxX = w - 1;
WiredHome 0:d43dc92ae767 28 maxY = h - 1;
WiredHome 0:d43dc92ae767 29 animation = animate;
WiredHome 1:9e88d16ab21e 30 pLifeMap = pMap;
WiredHome 0:d43dc92ae767 31 }
WiredHome 0:d43dc92ae767 32
WiredHome 0:d43dc92ae767 33 void Life::setbit(int x, int y, Life::ValueOfLife b, int otherframe)
WiredHome 0:d43dc92ae767 34 {
WiredHome 0:d43dc92ae767 35 unsigned long byteIndex = ((x + LIFE_W * y) * (1 << animation) * FRAMES_PER_BIT) / 8;
WiredHome 0:d43dc92ae767 36 unsigned long bitIndex = (((x + LIFE_W * y) * (1 << animation) * FRAMES_PER_BIT) % 8) + (((frame + otherframe) & 1) * (1 << animation));
WiredHome 0:d43dc92ae767 37
WiredHome 0:d43dc92ae767 38 if (animation == monochrome)
WiredHome 0:d43dc92ae767 39 b = (ValueOfLife)(b & 1);
WiredHome 0:d43dc92ae767 40 if (x >= 0 && x <= maxX && y >= 0 && y <= maxY) {
WiredHome 0:d43dc92ae767 41 uint8_t maskBitsOfInterest = ((1 << (1 << animation)) -1) << (bitIndex);
WiredHome 0:d43dc92ae767 42 uint8_t curCell = pLifeMap[byteIndex] & ~maskBitsOfInterest;
WiredHome 0:d43dc92ae767 43 uint8_t mask = b << (bitIndex);
WiredHome 0:d43dc92ae767 44 pLifeMap[byteIndex] = curCell | mask;
WiredHome 0:d43dc92ae767 45 } else {
WiredHome 3:860ae49fedb7 46 error(" Out of bounds value (%d, %d)\r\n", x, y);
WiredHome 0:d43dc92ae767 47 }
WiredHome 0:d43dc92ae767 48 }
WiredHome 0:d43dc92ae767 49
WiredHome 0:d43dc92ae767 50 Life::ValueOfLife Life::getbit(int x, int y, int otherframe)
WiredHome 0:d43dc92ae767 51 {
WiredHome 0:d43dc92ae767 52 unsigned long byteIndex = ((x + LIFE_W * y) * (1 << animation) * FRAMES_PER_BIT) / 8;
WiredHome 0:d43dc92ae767 53 unsigned long bitIndex = (((x + LIFE_W * y) * (1 << animation) * FRAMES_PER_BIT) % 8) + (((frame + otherframe) & 1) * (1 << animation));
WiredHome 0:d43dc92ae767 54
WiredHome 0:d43dc92ae767 55 if (x >= 0 && x <= maxX && y >= 0 && y <= maxY) {
WiredHome 0:d43dc92ae767 56 uint8_t maskBitsOfInterest = ((1 << (1 << animation)) -1) << (bitIndex);
WiredHome 0:d43dc92ae767 57 uint8_t curCell = pLifeMap[byteIndex] & maskBitsOfInterest;
WiredHome 0:d43dc92ae767 58 ValueOfLife b = (ValueOfLife)(curCell >> (bitIndex));
WiredHome 0:d43dc92ae767 59 if (animation == monochrome)
WiredHome 0:d43dc92ae767 60 b = (ValueOfLife)(b & 1);
WiredHome 0:d43dc92ae767 61 return b;
WiredHome 0:d43dc92ae767 62 } else {
WiredHome 3:860ae49fedb7 63 error(" Out of Bounds value (%d, %d)\r\n", x, y);
WiredHome 0:d43dc92ae767 64 return dead;
WiredHome 0:d43dc92ae767 65 }
WiredHome 0:d43dc92ae767 66 }
WiredHome 0:d43dc92ae767 67
WiredHome 0:d43dc92ae767 68 void Life::DestroyAllLife(void)
WiredHome 0:d43dc92ae767 69 {
WiredHome 0:d43dc92ae767 70 for (int y = 0; y <= maxY; y++) {
WiredHome 1:9e88d16ab21e 71 for (int x = 0; x <= maxX; x++) {
WiredHome 0:d43dc92ae767 72 for (int f = 0; f < 2; f++) {
WiredHome 0:d43dc92ae767 73 setbit(x,y, dead, f);
WiredHome 0:d43dc92ae767 74 }
WiredHome 0:d43dc92ae767 75 }
WiredHome 0:d43dc92ae767 76 }
WiredHome 0:d43dc92ae767 77 }
WiredHome 0:d43dc92ae767 78
WiredHome 0:d43dc92ae767 79 int Life::CountNeighbors(int x, int y)
WiredHome 0:d43dc92ae767 80 {
WiredHome 0:d43dc92ae767 81 int total = 0;
WiredHome 0:d43dc92ae767 82
WiredHome 1:9e88d16ab21e 83 for (int k = -1; k <= 1; k++) {
WiredHome 0:d43dc92ae767 84 for (int l = -1; l <= 1; l++) {
WiredHome 0:d43dc92ae767 85 ValueOfLife lifeState = getbit((x+LIFE_W+k)%LIFE_W,(y+LIFE_H+l)%LIFE_H);
WiredHome 1:9e88d16ab21e 86 if (lifeState == living) {
WiredHome 0:d43dc92ae767 87 total++;
WiredHome 0:d43dc92ae767 88 }
WiredHome 0:d43dc92ae767 89 }
WiredHome 0:d43dc92ae767 90 }
WiredHome 1:9e88d16ab21e 91 if (getbit(x,y)) { // minus the cell of interest if it is alive
WiredHome 0:d43dc92ae767 92 total--;
WiredHome 0:d43dc92ae767 93 }
WiredHome 0:d43dc92ae767 94 return total;
WiredHome 0:d43dc92ae767 95 }
WiredHome 0:d43dc92ae767 96
WiredHome 0:d43dc92ae767 97 void Life::GenerationStep(void)
WiredHome 0:d43dc92ae767 98 {
WiredHome 1:9e88d16ab21e 99 for (int i = 0; i <= maxX; i++) {
WiredHome 0:d43dc92ae767 100 for (int j = 0; j <= maxY; j++) {
WiredHome 0:d43dc92ae767 101 int total = CountNeighbors(i, j);
WiredHome 1:9e88d16ab21e 102 CycleOfLife(i, j, total);
WiredHome 0:d43dc92ae767 103 }
WiredHome 0:d43dc92ae767 104 }
WiredHome 0:d43dc92ae767 105 frame = (frame + 1) & 1;
WiredHome 0:d43dc92ae767 106 }
WiredHome 0:d43dc92ae767 107
WiredHome 0:d43dc92ae767 108 void Life::UpdateLifeCycle(void)
WiredHome 0:d43dc92ae767 109 {
WiredHome 0:d43dc92ae767 110 for (int x = 0; x <= maxX; x++) { //loop through cells
WiredHome 0:d43dc92ae767 111 for (int y = 0; y <= maxY; y++) {
WiredHome 0:d43dc92ae767 112 ValueOfLife currently = getbit(x,y);
WiredHome 0:d43dc92ae767 113 if (currently == dying)
WiredHome 0:d43dc92ae767 114 setbit(x,y, dead);
WiredHome 0:d43dc92ae767 115 else if (currently == birthing)
WiredHome 0:d43dc92ae767 116 setbit(x,y, living);
WiredHome 0:d43dc92ae767 117 }
WiredHome 0:d43dc92ae767 118 }
WiredHome 0:d43dc92ae767 119 }
WiredHome 0:d43dc92ae767 120
WiredHome 0:d43dc92ae767 121 void Life::CycleOfLife(int x, int y, int neighbors)
WiredHome 0:d43dc92ae767 122 {
WiredHome 0:d43dc92ae767 123 ValueOfLife currently = getbit(x,y);
WiredHome 0:d43dc92ae767 124
WiredHome 0:d43dc92ae767 125 if ((neighbors < 2) || (neighbors > 3)) {
WiredHome 0:d43dc92ae767 126 if (currently == living)
WiredHome 0:d43dc92ae767 127 setbit(x,y, dying, 1);
WiredHome 0:d43dc92ae767 128 else
WiredHome 0:d43dc92ae767 129 setbit(x,y, dead, 1);
WiredHome 0:d43dc92ae767 130 }
WiredHome 0:d43dc92ae767 131 if (neighbors == 3) {
WiredHome 0:d43dc92ae767 132 if (currently == living)
WiredHome 0:d43dc92ae767 133 setbit(x,y, living, 1);
WiredHome 0:d43dc92ae767 134 else
WiredHome 0:d43dc92ae767 135 setbit(x,y, birthing, 1);
WiredHome 0:d43dc92ae767 136 }
WiredHome 0:d43dc92ae767 137 if (neighbors == 2) {
WiredHome 0:d43dc92ae767 138 setbit(x,y, currently, 1);
WiredHome 0:d43dc92ae767 139 }
WiredHome 0:d43dc92ae767 140 }