-
clemo authored
Signed-off-by:
clemo <clemo@cbcode.at>
clemo authoredSigned-off-by:
clemo <clemo@cbcode.at>
gol.c 2.66 KiB
#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;
}