int neighborValue(const Raster &raster, int x, int y, bool isTorus) { int numNeighbours = 0; for (int yy = y-1; yy <= y+1; yy++) { for (int xx = x-1; xx <= x+1; xx++) { if (xx == x && yy == y) { continue; // not a neighbour } bool inBounds = raster.inBounds(xx,yy); if (!isTorus && !inBounds) { continue; // i.e. dead } int actualX = xx; int actualY = yy; if (!inBounds) { // transform to torus actualX = (xx + raster.width) % raster.width; actualY = (yy + raster.height) % raster.height; } const int currentCellState = raster.data[raster.index(actualX, actualY)]; if (currentCellState == ALIVE) { numNeighbours++; } } } const int cellState = raster.data[raster.index(x,y)]; // apply rules int newState = DEAD; if (cellState == DEAD && numNeighbours == 3) { newState = ALIVE; } else if (cellState == ALIVE && (numNeighbours == 2 || numNeighbours == 3)) { newState = ALIVE; } return newState; }
void simulateNextState(Raster &raster, bool isTorus) { const int width = raster.width; const int height = raster.height; int* data = new int[width*height]; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int index = raster.index(x,y); data[index] = neighborValue(raster, x, y, isTorus); } } delete[] raster.data; raster.data = data; }
void simulateInvasion(Raster &raster, float invasionFactor) { if (invasionFactor <= 0) { return; } for (int y = 0; y < raster.height; ++y) { for (int x = 0; x < raster.width; ++x) { float random = static_cast<float>(rand()) / static_cast<float>(RAND_MAX); if (random < invasionFactor) { int index = raster.index(x,y); // flip cell state raster.data[index] = (raster.data[index] + 1) % 2; } } } }