Skip to content
Snippets Groups Projects
gol.c 2.97 KiB
Newer Older
clemo's avatar
clemo committed
#include "gol.h"
#include <stdlib.h>

#ifdef GOL_DEBUG
#include <stdio.h>
#endif

/**
 * @param int width - width in byte (/=8)
 * @param int height - height in bit
 */
gol *gol_setup(unsigned int width, unsigned int height)
{
	gol *gameData = calloc(sizeof(gol), 1);
	gameData->width = width;
	gameData->height = height;
	gameData->next = calloc(width * height, sizeof(unsigned int));
	gameData->current = calloc(width * height, sizeof(unsigned int));
	return gameData;
}
void gol_free(gol *data)
{
	free(data->next);
	free(data->current);
	free(data);
}

unsigned int getCell(gol *g, unsigned int row, unsigned int colmn, unsigned int coffset)
{
	return g->current[row * g->width + colmn] & (1 << (7 - coffset)) ? 1 : 0;
}
unsigned int sumNeighbours(gol *g, unsigned int row, unsigned int colmn, unsigned int coffset)
{
	unsigned int sum = 0;

	//up
	unsigned int urow = row - 1;
	if (row < 1)
	{
		urow = g->height - 1;
	}

	//left
	unsigned int loffset = coffset - 1;
	unsigned int lcolmn = colmn;
	if (coffset < 1)
	{
		loffset = 7;
		lcolmn = colmn - 1;
		if (colmn < 1)
		{
			lcolmn = g->width - 1;
		}
	}

	//right
	unsigned int roffset = coffset + 1;
	unsigned int rcolmn = colmn;
	if (7 < roffset)
	{
		roffset = 0;
		rcolmn += 1;
		if (g->width <= rcolmn)
		{
			rcolmn = 0;
		}
	}

	//down
	unsigned int drow = row + 1;
	if (g->height <= drow)
	{
		drow = 0;
	}
	//up - left
	sum += getCell(g, urow, lcolmn, loffset);
	//up
	sum += getCell(g, urow, colmn, coffset);
	//up -right
	sum += getCell(g, urow, rcolmn, roffset);
	//right
	sum += getCell(g, row, rcolmn, roffset);
	//down -right
	sum += getCell(g, drow, rcolmn, roffset);
	//down
	sum += getCell(g, drow, colmn, coffset);
	//down-left
	sum += getCell(g, drow, lcolmn, loffset);
	//left
	sum += getCell(g, row, lcolmn, loffset);
	return sum;
}
void printBits(unsigned int i, gol_print_colmn colmnFn)
{
	for (unsigned int j = 0; j < 8; j++)
	{
		colmnFn((i & (1 << (7 - j)) ? 1 : 0));
	}
}
void gol_each(gol *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
			printf("<%d:%d>(%d) %d\t", row, colmn, row * g->width + colmn, g->current[row * g->width + colmn]);
#endif
			printBits(g->current[row * g->width + colmn], colmnFn);
		}
		lnFn(row);
	}
}
void gol_tick(gol *g)
{
	for (unsigned int row = 0; row < g->height; row++)
	{
		for (unsigned int colmn = 0; colmn < g->width; colmn++)
		{
			g->next[row * g->width + colmn] = 0;
			for (unsigned int coff = 0; coff < 8; coff++)
			{
				const unsigned int sn = sumNeighbours(g, row, colmn, coff);
				if (getCell(g, row, colmn, coff) == 1)
				{
					//living cell
					if (1 < sn && sn < 4)
					{
						g->next[row * g->width + colmn] |= (1 << (7 - coff));
					}
				}
				else
				{
					//dead cell
					if (sn == 3)
					{
						g->next[row * g->width + colmn] |= (1 << (7 - coff));
					}
				}
			}
		}
	}
	unsigned int *tmp = g->current;
	g->current = g->next;
	g->next = tmp;
}