aboutsummaryrefslogtreecommitdiffstats
path: root/instructables/cube8/gameoflife.c
blob: 0a3683ae3df5aae99c72e917b426f4896835b5ca (plain)
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
#include <avr/io.h>
#include "gameoflife.h"
#include "cube.h"
#include "draw.h"

// Game of Life for the 4x4x4 and 8x8x8 led cube

#define GOL_CREATE_MIN 3
#define GOL_CREATE_MAX 3

#define GOL_TERMINATE_LONELY 1
#define GOL_TERMINATE_CROWDED 4

#define GOL_X 8
#define GOL_Y 8
#define GOL_Z 8

#define GOL_WRAP 0x01



void gol_play (int iterations, uint16_t delay)
{
	int i;
	
	for (i = 0; i < iterations; i++)
	{
		LED_PORT ^= LED_GREEN;
	
		gol_nextgen();
		
		if (gol_count_changes() == 0)
			return;
		
		tmp2cube();
		
		delay_ms(delay);
		
		//led_red(1);
	}
}

void gol_nextgen (void)
{
	int x,y,z;
	unsigned char neigh;
	
	tmpfill(0x00);
	
	for (x = 0; x < GOL_X; x++)
	{
		for (y = 0; y < GOL_Y; y++)
		{
			for (z = 0; z < GOL_Z; z++)
			{
				neigh = gol_count_neighbors(x, y, z);
				
				// Current voxel is alive.
				if (getvoxel(x,y,z) == 0x01)
				{
					if (neigh <= GOL_TERMINATE_LONELY)
					{
						tmpclrvoxel(x,y,z);
					} else if(neigh >= GOL_TERMINATE_CROWDED)
					{
						tmpclrvoxel(x,y,z);
					} else
					{
						tmpsetvoxel(x,y,z);
					}
				// Current voxel is dead.
				} else
				{
					if (neigh >= GOL_CREATE_MIN && neigh <= GOL_CREATE_MAX)
						tmpsetvoxel(x,y,z);
				}
			}
		}
	}
}

unsigned char gol_count_neighbors (int x, int y, int z)
{
	int ix, iy, iz; // offset 1 in each direction in each dimension
	int nx, ny, nz; // neighbours address.
	
	unsigned char neigh = 0; // number of alive neighbours.
	
	for (ix = -1; ix < 2; ix++)
	{
		for (iy = -1; iy < 2; iy++)
		{
			for (iz = -1; iz < 2; iz++)
			{
				// Your not your own neighbour, exclude 0,0,0, offset.
				if ( !(ix == 0 && iy == 0 && iz == 0) )
				{
					if (GOL_WRAP == 0x01)
					{
						nx = (x+ix)%GOL_X;
						ny = (y+iy)%GOL_Y;
						nz = (z+iz)%GOL_Z;
					} else
					{
						nx = x+ix;
						ny = y+iy;
						nz = z+iz;
					}
					
					if ( getvoxel(nx, ny, nz) )
						neigh++;
				}
			}
		}
	}
	return neigh;
}

int gol_count_changes (void)
{
	int x,y;
	int i = 0;
	
	for (x = 0; x < GOL_X; x++)
	{
		for (y = 0; y < GOL_Y; y++)
		{
			if (fb[x][y] != cube[x][y])
				i++;
		}
	}
	
	return i;
}