summaryrefslogtreecommitdiff
path: root/conway.c
blob: 0fd733b61376c9e01a71efd77c9c61e5132932a3 (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
#include <stdio.h>
#define LOOP(col,line) \
for (int j=0; j< 40; j++) { \
	for (int i=0; i < 80; i++) { \
		col \
	} \
	line \
}

/*
 *Grid where everything is stored, 2nd least significant bit stores current
 *state and least significant bit stores new state.
 * The grid stores column position(x position) in the first field while row
 * position( y position) is in the second field. As per c rules, this means that
 * it is 80 wide by 40 tall, and the underlying datatype is a pointer to 80
 * pointers stored in an array, each of which point to 40 chars stored in an
 * array.
 *
 *We use char because it's close enough to uint8_t w/o having to include the
 * standard into library.
 * There's a glider stored in the first 9x9 bits. We assume that everything is
 * zero'd out
 */
char grid[80][40] = {{0,0,2},{2,0,2},{0,2,2},0};

/*
 *determines whether a node should live(return 1) or die (return 0) based on
 * it's current state
 */
int neighbor (int x, int y) {
	/*neighbor count*/
	int count = 0;
	/*loops through all neighbors based off of y offset j and x offset i*/
	for (int j = -1; j <= 1; j++) {
		for (int i = -1; i <= 1; i++) {
			/* makes sure to not count itself as a neighbor*/
			if (!((i == 0) && (j == 0))) {
				/*
				 * modulo loops the grid back into itself
				 * the addition of the value is required
				 * otherwise strange nondeterministic behavior
				 * occurs
				 */
				if ( grid[(x+i + 80 )%80][(y+j + 40)%40] & 0x02) {
					count++;
				}
			}
		}
	}
	/*
	 * Switch determines the rules of conway's game of life
	 */
	switch (count) {
		/*
		 * The current population of a cell determines whether it lives
		 * or die if it has 2 neighbors
		 */
		case 2: 
			if (grid[x][y] & 0x02) {
				return 1;
			} else {
				return 0;
			}
		case 3:
			return 1;
		default:
			return 0;
	}
}
int main (int argc, char * argv[]) {
	/*
	 * Stores the input character read from stdin. It's initialized to 0
	 * because the main loop depends on it not being 'q'
	 */
	int r = 0;
	/*
	 * A do at least once loop that iterates through the game. It tests for
	 * whether the character read from stdin is 'q'
	 */
	do {
		/*
		 * Input from stdin, this is blocking so it also serves as a delay
		 */
		r = fgetc(stdin);
		/*
		 * First it prints the current state stored in the 2nd least
		 * significant bit. X if it is present, Y if it is not. This
		 * loop is implemented as a macro b/c the entire loop has to be
		 * run 3 different times. The first argument is to be run for
		 * every cell while the 2nd one is to be run at the end of every
		 * row
		 */
		LOOP(if (grid[i][j] & 0x02) {printf("X");}else{printf(",");},printf("\n"););
		/*
		 * Determines the current live/die state, then puts it into the
		 * least significant bit representing the new state of the cell
		 */
		LOOP(grid[i][j] = neighbor(i,j) | (grid[i][j] & 0x02);,);
		/*
		 * Shifts the cell's state up, thereby making the new state the
		 * current state and the new new state 0.
		 */
		LOOP(grid[i][j] = grid[i][j] << 1;,);
	} while (r != 'q');
}