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@3:860ae49fedb7, 2014-04-23 (annotated)
- 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?
User | Revision | Line number | New 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 | } |