Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#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;
}