#include <Arduino.h> #include "display.h" #include "gameoflife.h" // https://github.com/Stavrosfil/game-of-life-esp32 int g[SCREEN_HEIGHT][SCREEN_WIDTH]; int arrayCopy[SCREEN_HEIGHT][SCREEN_WIDTH]; bool runGame = true; bool gameOver = false; int currentTick; int finalTicks; int cellsAliveBefore; int noEvolutionTicks; const uint scoreScreenTimeout = 5000; unsigned long currentMillis; void setupGameOfLife() { gameOver = false; currentTick = 0; finalTicks = 0; cellsAliveBefore = 0; noEvolutionTicks = 0; randomSeed(analogRead(34)); createRandomMatrix(g); for (int i = 0; i < 10; i++) { addGlider(random(SCREEN_HEIGHT), random(SCREEN_WIDTH), g); } } void createRandomMatrix(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) { for (int i = 0; i < SCREEN_HEIGHT; i++) { for (int j = 0; j < SCREEN_WIDTH; j++) { a[i][j] = random(100) < 25 ? 1 : 0; } } } void gameOfLife(int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) { currentTick++; int cellsAliveNow = 0; for (int i = 0; i < SCREEN_HEIGHT; i++) { for (int j = 0; j < SCREEN_WIDTH; j++) { arrayCopy[i][j] = a[i][j]; } } for (int i = 0; i < SCREEN_HEIGHT; i++) { for (int j = 0; j < SCREEN_WIDTH; j++) { int total = (a[i][(j - 1) % SCREEN_WIDTH] + a[i][(j + 1) % SCREEN_WIDTH] + a[(i - 1) % SCREEN_HEIGHT][j] + a[(i + 1) % SCREEN_HEIGHT][j] + a[(i - 1) % SCREEN_HEIGHT][(j - 1) % SCREEN_WIDTH] + a[(i - 1) % SCREEN_HEIGHT][(j + 1) % SCREEN_WIDTH] + a[(i + 1) % SCREEN_HEIGHT][(j - 1) % SCREEN_WIDTH] + a[(i + 1) % SCREEN_HEIGHT][(j + 1) % SCREEN_WIDTH]); if (a[i][j] == 1) { if (total < 2 || total > 3) { arrayCopy[i][j] = 0; cellsAliveNow--; } } else if (total == 3) { arrayCopy[i][j] = 1; cellsAliveNow++; } } } for (int i = 0; i < SCREEN_HEIGHT; i++) { for (int j = 0; j < SCREEN_WIDTH; j++) { a[i][j] = arrayCopy[i][j]; } } if (currentTick % 2) { cellsAliveBefore = cellsAliveNow; } if (cellsAliveNow >= cellsAliveBefore - 3 && cellsAliveNow <= cellsAliveBefore + 3) { noEvolutionTicks++; } else { noEvolutionTicks = 0; } if (noEvolutionTicks > noEvolutionTicksLimit) { if (!gameOver) { finalTicks = currentTick - noEvolutionTicksLimit; currentMillis = millis(); showEndScreen(finalTicks); gameOver = true; } else { int brightness = 255 * (1 - ((millis() - currentMillis) / scoreScreenTimeout)); fadeOutGame(brightness); } } } void addGlider(int i1, int j1, int (&a)[SCREEN_HEIGHT][SCREEN_WIDTH]) { // 010 // 001 // 111 int glider[3][3] = {{0, 0, 1}, {1, 0, 1}, {0, 1, 1}}; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { a[i1 + i][j1 + j] = glider[i][j]; } } } void gameLoop() { if (runGame) { gameOfLife(g); if (gameOver) { if (millis() - currentMillis > scoreScreenTimeout) { resetGame(); } } } } void resetGame() { setupGameOfLife(); clearDisplay(); }