@@ -8,45 +8,103 @@ uint8_t GameOfLifePlugin::countNeighbours(int row, int col)
88 {
99 for (j = col - 1 ; j <= col + 1 ; j++)
1010 {
11- count += this ->buffer [i * COLS + j];
11+ int r = i;
12+ int c = j;
13+ // OOB handling
14+ if (r > (ROWS-1 )) r = 0 ;
15+ if (r < 0 ) r = ROWS-1 ;
16+ if (c > (COLS-1 )) c = 0 ;
17+ if (c < 0 ) c = COLS-1 ;
18+
19+ count += this ->previous [r * COLS + c];
1220 }
1321 }
14- count -= this ->buffer [row * COLS + col];
22+ count -= this ->previous [row * COLS + col];
1523 return count;
1624};
1725
1826uint8_t GameOfLifePlugin::updateCell (int row, int col)
1927{
2028 uint8_t total = this ->countNeighbours (row, col);
21- if (total > 4 || total < 3 )
29+ if (total > 3 || total < 2 )
2230 {
2331 return 0 ;
2432 }
25- else if (this ->buffer [row * COLS + col] == 0 && total == 3 )
33+ else if (this ->previous [row * COLS + col] == 0 && total == 3 )
2634 {
2735 return 1 ;
2836 }
2937 else
3038 {
31- return this ->buffer [row * COLS + col];
39+ return this ->previous [row * COLS + col];
3240 }
3341};
3442
3543void GameOfLifePlugin::setup ()
3644{
37- Screen.clear ();
45+ this ->state = this ->STATE_END ;
46+ };
3847
39- memset (previous, 0 , ROWS * COLS);
48+ void GameOfLifePlugin::init ()
49+ {
50+ memset (this ->previous2 , 0 , ROWS * COLS);
51+ memset (this ->previous , 0 , ROWS * COLS);
52+ memset (this ->buffer , 0 , ROWS * COLS);
4053 for (int i = 0 ; i < ROWS * COLS; i++)
4154 {
42- this ->buffer [i] = (random (10 )) ? 1 : 0 ;
55+ this ->buffer [i] = (random (2 )) ? 1 : 0 ;
4356 }
44- this ->next ();
45- };
57+
58+ // Simple glider to test rules and wrapping
59+ // uint8_t start[] = {
60+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
63+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
64+ // 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
65+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
66+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
67+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
72+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75+ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76+ // };
77+ // memcpy(this->buffer, start, 256);
78+
79+ for (int j = 0 ; j < 8 ; j++)
80+ {
81+ for (int i = 0 ; i < COLS; i++)
82+ {
83+ if (j < 4 )
84+ { // grayish cover
85+ Screen.setPixel ((i), (j*4 +0 ), 1 , 25 );
86+ Screen.setPixel ((i), (j*4 +1 ), 1 , 25 );
87+ Screen.setPixel ((i), (j*4 +2 ), 1 , 25 );
88+ Screen.setPixel ((i), (j*4 +3 ), 1 , 25 );
89+ } else { // fill in actual cells
90+ j -= 4 ;
91+ Screen.setPixel (i, (j*4 +0 ), this ->buffer [(j*4 +0 ) * COLS + i]);
92+ Screen.setPixel (i, (j*4 +1 ), this ->buffer [(j*4 +1 ) * COLS + i]);
93+ Screen.setPixel (i, (j*4 +2 ), this ->buffer [(j*4 +2 ) * COLS + i]);
94+ Screen.setPixel (i, (j*4 +3 ), this ->buffer [(j*4 +3 ) * COLS + i]);
95+ j += 4 ;
96+ }
97+ delay (50 );
98+ }
99+ }
100+
101+ this ->state = this ->STATE_RUNNING ;
102+ }
46103
47104void GameOfLifePlugin::next ()
48105{
49- Screen.clear ();
106+ memcpy (this ->previous2 , this ->previous , ROWS * COLS);
107+ memcpy (this ->previous , this ->buffer , ROWS * COLS);
50108 for (int i = 0 ; i < ROWS; i++)
51109 {
52110 for (int j = 0 ; j < COLS; j++)
@@ -56,29 +114,69 @@ void GameOfLifePlugin::next()
56114 }
57115}
58116
59- int generations = 30 ;
60- void GameOfLifePlugin::loop ()
117+ void GameOfLifePlugin::show ()
61118{
62- generations--;
63- this ->next ();
119+ Screen.clear ();
64120
65121 for (int i = 0 ; i < ROWS; i++)
66122 {
67123 for (int j = 0 ; j < COLS; j++)
68124 {
69- Screen.setPixelAtIndex (i * COLS + j , this ->buffer [i * COLS + j]);
125+ Screen.setPixel (j, i , this ->buffer [i * COLS + j]);
70126 }
71127 }
72- delay ( 150 );
128+ }
73129
74- if (generations == 0 )
130+ int generations = 120 ;
131+ bool updated;
132+ bool updated2;
133+ void GameOfLifePlugin::loop ()
134+ {
135+ switch (this ->state )
75136 {
76- generations = 30 ;
137+ case this ->STATE_RUNNING :
138+ this ->show ();
139+
140+ generations--;
141+ this ->next ();
142+ updated = memcmp (this ->buffer , this ->previous , ROWS * COLS);
143+ updated2 = memcmp (this ->buffer , this ->previous2 , ROWS * COLS);
144+
145+ // is running in period of 2
146+ if (!updated2) generations -= 5 ;
147+
148+ if (generations < 0 || !updated)
149+ {
150+ generations = 120 ;
151+ delay (gol_delay*4 );
152+ this ->state = this ->STATE_END ;
153+ }
154+ break ;
155+ case this ->STATE_END :
77156 this ->setup ();
157+ break ;
78158 }
159+
160+ delay (gol_delay);
79161};
80162
81163const char *GameOfLifePlugin::getName () const
82164{
83165 return " GameOfLife" ;
84166}
167+
168+ void GameOfLifePlugin::websocketHook (DynamicJsonDocument &request)
169+ {
170+ const char *event = request[" event" ];
171+
172+ if (currentStatus == NONE)
173+ {
174+ if (!strcmp (event, " goldelay" ))
175+ {
176+ uint16_t new_delay = request[" delay" ].as <uint16_t >();
177+ Serial.print (" Changing Game of life delay to " );
178+ Serial.println (new_delay);
179+ gol_delay = new_delay;
180+ }
181+ }
182+ }
0 commit comments