@@ -5197,7 +5197,7 @@ static const char _data_FX_MODE_2DFRIZZLES[] PROGMEM = "Frizzles@X frequency,Y f
51975197// 2D Cellular Automata Game of life //
51985198// /////////////////////////////////////////
51995199typedef struct Cell {
5200- uint8_t alive : 1 , faded : 1 , toggleStatus : 1 , edgeCell: 1 , oscillatorCheck : 1 , spaceshipCheck : 1 , unused : 2 ;
5200+ uint8_t alive : 1 , faded : 1 , toggleStatus : 1 , edgeCell: 1 , oscillatorCheck : 1 , spaceshipCheck : 1 , unused : 2 ;
52015201} Cell;
52025202
52035203uint16_t mode_2Dgameoflife (void ) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/
@@ -5207,7 +5207,7 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
52075207 const unsigned maxIndex = cols * rows;
52085208
52095209 if (!SEGENV.allocateData (SEGMENT.length () * sizeof (Cell))) return mode_static (); // allocation failed
5210-
5210+
52115211 Cell *cells = reinterpret_cast <Cell*> (SEGENV.data );
52125212
52135213 uint16_t & generation = SEGENV.aux0 , &gliderLength = SEGENV.aux1 ; // rename aux variables for clarity
@@ -5230,43 +5230,42 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
52305230
52315231 // Setup New Game of Life
52325232 if ((!paused && generation == 0 ) || setup) {
5233- SEGENV.step = strip.now + 1250 ; // show initial state for 1.25 seconds
5233+ SEGENV.step = strip.now + 1280 ; // show initial state for 1.28 seconds
52345234 generation = 1 ;
52355235 paused = true ;
52365236 // Setup Grid
52375237 memset (cells, 0 , maxIndex * sizeof (Cell));
52385238
5239- for (unsigned i = maxIndex ; i--; ) {
5239+ for (unsigned i = 0 ; i < maxIndex; i++ ) {
52405240 bool isAlive = !hw_random8 (3 ); // ~33%
52415241 cells[i].alive = isAlive;
52425242 cells[i].faded = !isAlive;
52435243 unsigned x = i % cols, y = i / cols;
52445244 cells[i].edgeCell = (x == 0 || x == cols-1 || y == 0 || y == rows-1 );
52455245
5246- SEGMENT.setPixelColorXY (x, y , isAlive ? SEGMENT.color_from_palette (hw_random8 (), false , PALETTE_SOLID_WRAP, 0 ) : bgColor);
5246+ SEGMENT.setPixelColor (i , isAlive ? SEGMENT.color_from_palette (hw_random8 (), false , PALETTE_SOLID_WRAP, 0 ) : bgColor);
52475247 }
52485248 }
52495249
52505250 if (paused || (strip.now - SEGENV.step < 1000 / map (SEGMENT.speed ,0 ,255 ,1 ,42 ))) {
52515251 // Redraw if paused or between updates to remove blur
52525252 for (unsigned i = maxIndex; i--; ) {
52535253 if (!cells[i].alive ) {
5254- uint32_t cellColor = SEGMENT.getPixelColorXY (i % cols, i / cols );
5254+ uint32_t cellColor = SEGMENT.getPixelColor (i );
52555255 if (cellColor != bgColor) {
52565256 uint32_t newColor;
52575257 bool needsColor = false ;
5258- if (cells[i].faded ) { newColor = bgColor; needsColor = true ; }
5258+ if (cells[i].faded ) { newColor = bgColor; needsColor = true ; }
52595259 else {
52605260 uint32_t blended = color_blend (cellColor, bgColor, 2 );
52615261 if (blended == cellColor) { blended = bgColor; cells[i].faded = 1 ; }
52625262 newColor = blended; needsColor = true ;
52635263 }
5264- if (needsColor) SEGMENT.setPixelColorXY (i % cols, i / cols , newColor);
5264+ if (needsColor) SEGMENT.setPixelColor (i , newColor);
52655265 }
52665266 }
52675267 }
52685268 return FRAMETIME;
5269-
52705269 }
52715270
52725271 // Repeat detection
@@ -5286,55 +5285,55 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
52865285
52875286 unsigned neighbors = 0 , aliveParents = 0 , parentIdx[3 ];
52885287 // Count alive neighbors
5289- for (int i = 1 ; i >= - 1 ; i-- ) for (int j = 1 ; j >= - 1 ; j-- ) if (i || j) {
5290- int nX = x + j, nY = y + i;
5288+ for (int i = - 1 ; i <= 1 ; i++ ) for (int j = - 1 ; j <= 1 ; j++ ) if (i || j) {
5289+ int nX = x + j, nY = y + i;
52915290 if (cell.edgeCell ) {
52925291 nX = (nX + cols) % cols;
52935292 nY = (nY + rows) % rows;
52945293 }
52955294 unsigned nIndex = nX + nY * cols;
52965295 Cell& neighbor = cells[nIndex];
52975296 if (neighbor.alive ) {
5298- if (++neighbors > 3 ) break ;
5299- if (!neighbor.toggleStatus ) { // Alive and not dying
5297+ neighbors++ ;
5298+ if (!neighbor.toggleStatus && neighbors < 4 ) { // Alive and not dying
53005299 parentIdx[aliveParents++] = nIndex;
53015300 }
53025301 }
53035302 }
53045303
53055304 uint32_t newColor;
53065305 bool needsColor = false ;
5307-
5306+
53085307 if (cell.alive && (neighbors < 2 || neighbors > 3 )) { // Loneliness or Overpopulation
53095308 cell.toggleStatus = 1 ;
53105309 if (blur == 255 ) cell.faded = 1 ;
5311- newColor = cell.faded ? bgColor : color_blend (SEGMENT.getPixelColorXY (x, y ), bgColor, blur);
5310+ newColor = cell.faded ? bgColor : color_blend (SEGMENT.getPixelColor (cIndex ), bgColor, blur);
53125311 needsColor = true ;
53135312 }
53145313 else if (!cell.alive ) {
5315- if (neighbors == 3 && (! mutate || hw_random8 (128 )) || // Normal birth with 1/128 failure chance if mutate
5316- (mutate && neighbors == 2 && ! hw_random8 ( 128 ))) { // Mutation birth with 2 neighbors with 1/128 chance if mutate
5314+ byte mutationRoll = mutate ? hw_random8 (128 ) : 1 ; // if 0: 3 neighbor births fail and 2 neighbor births mutate
5315+ if ((neighbors == 3 && mutationRoll) || (mutate && neighbors == 2 && !mutationRoll)) { // Reproduction or Mutation
53175316 cell.toggleStatus = 1 ;
53185317 cell.faded = 0 ;
5319-
5318+
53205319 if (aliveParents) {
53215320 // Set color based on random neighbor
53225321 unsigned parentIndex = parentIdx[random8 (aliveParents)];
5323- birthColor = SEGMENT.getPixelColorXY (parentIndex % cols, parentIndex / cols );
5322+ birthColor = SEGMENT.getPixelColor (parentIndex);
53245323 }
53255324 newColor = birthColor;
53265325 needsColor = true ;
53275326 }
53285327 else if (!cell.faded ) {// No change, fade dead cells
5329- uint32_t cellColor = SEGMENT.getPixelColorXY (x, y );
5328+ uint32_t cellColor = SEGMENT.getPixelColor (cIndex );
53305329 uint32_t blended = color_blend (cellColor, bgColor, blur);
53315330 if (blended == cellColor) { blended = bgColor; cell.faded = 1 ; }
53325331 newColor = blended;
53335332 needsColor = true ;
53345333 }
53355334 }
53365335
5337- if (needsColor) SEGMENT.setPixelColorXY (x, y , newColor);
5336+ if (needsColor) SEGMENT.setPixelColor (cIndex , newColor);
53385337 }
53395338 // Loop through cells, if toggle, swap alive status
53405339 for (unsigned i = maxIndex; i--; ) {
@@ -5344,8 +5343,8 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https:
53445343
53455344 if (repeatingOscillator || repeatingSpaceship || emptyGrid) {
53465345 generation = 0 ; // reset on next call
5347- SEGENV.step += 1000 ; // pause final generation for 1 second
5348- }
5346+ SEGENV.step += 1024 ; // pause final generation for ~ 1 second
5347+ }
53495348 else {
53505349 ++generation;
53515350 SEGENV.step = strip.now ;
0 commit comments