#include "gol.h" #include <stdlib.h> #ifdef GOL_DEBUG #include <stdio.h> #endif /** * @param int width * @param int height */ gol_t *gol_setup(int width, int height) { div_t bytes = div(width * height, 8); gol_t *gameData = calloc(sizeof(gol_t), 1); gameData->width = width; gameData->height = height; if (bytes.rem == 0) { gameData->next = calloc(bytes.quot, sizeof(int)); gameData->current = calloc(bytes.quot, sizeof(int)); } else { gameData->next = calloc(bytes.quot + 1, sizeof(int)); gameData->current = calloc(bytes.quot + 1, sizeof(int)); } return gameData; } void gol_free(gol_t *g) { free(g->next); free(g->current); free(g); } int pMod(int x, int y) { return (x + y) % y; } int getCell(gol_t *g, int cell) { cell = pMod(cell, g->width * g->height); div_t d = div(cell, 8); return g->current[d.quot] & (1 << (d.rem)) ? 1 : 0; } int sumNeighbours(gol_t *g, int cell) { int sum = 0; div_t row = div(cell, g->width); //left int lcell = cell - 1; if (row.rem == 0) { lcell += g->width; } //right int rcell = cell + 1; if (row.rem == (g->width - 1)) { rcell -= g->width; } //up - left sum += getCell(g, lcell - g->width); //up sum += getCell(g, cell - g->width); //up -right sum += getCell(g, rcell - g->width); //left sum += getCell(g, lcell); //right sum += getCell(g, rcell); //down-left sum += getCell(g, lcell + g->width); //down sum += getCell(g, cell + g->width); //down -right sum += getCell(g, rcell + g->width); return sum; } /** * @brief iterate over each cell, and call callbacks **/ void gol_each(gol_t *g, gol_print_colmn colmnFn, gol_print_ln lnFn) { for (unsigned int row = 0; row < g->height; row++) { for (unsigned int colmn = 0; colmn < g->width; colmn++) { #ifdef GOL_DEBUG if ((row * g->width + colmn) % 8 == 0) { printf("\t<%d:%d>(%d) %d: ", row, colmn, row * g->width + colmn, g->current[(row * g->width + colmn) / 8]); } #endif colmnFn(getCell(g, row * g->width + colmn)); } if (lnFn != NULL) { lnFn(row); } } } /** * @brief progress one timestep **/ void gol_tick(gol_t *g) { for (unsigned int row = 0; row < g->height; row++) { for (unsigned int colmn = 0; colmn < g->width; colmn++) { int cell = (row * g->width) + colmn; div_t d = div(cell, 8); if (d.rem == 0) { g->next[d.quot] = 0; } const unsigned int sn = sumNeighbours(g, cell); if (getCell(g, cell) == 1) { //living cell if (1 < sn && sn < 4) { g->next[d.quot] |= (1 << d.rem); } } else { //dead cell if (sn == 3) { g->next[d.quot] |= (1 << d.rem); } } } } unsigned int *tmp = g->current; g->current = g->next; g->next = tmp; }