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.
LifeRules.cpp
- Committer:
- WiredHome
- Date:
- 2014-04-23
- Revision:
- 1:9e88d16ab21e
- Parent:
- 0:d43dc92ae767
- Child:
- 3:860ae49fedb7
File content as of revision 1:9e88d16ab21e:
// 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" // 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 = pMap; } 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; } 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)); 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) { for (int y = 0; y <= maxY; y++) { for (int x = 0; x <= maxX; x++) { for (int f = 0; f < 2; f++) { setbit(x,y, dead, f); } } } } int Life::CountNeighbors(int x, int y) { int total = 0; 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) { total++; } } } if (getbit(x,y)) { // minus the cell of interest if it is alive total--; } return total; } void Life::GenerationStep(void) { for (int i = 0; i <= maxX; i++) { for (int j = 0; j <= maxY; j++) { int total = CountNeighbors(i, j); CycleOfLife(i, j, total); } } frame = (frame + 1) & 1; } void Life::UpdateLifeCycle(void) { for (int x = 0; x <= maxX; x++) { //loop through cells for (int y = 0; y <= maxY; y++) { ValueOfLife currently = getbit(x,y); 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); } }