-
Notifications
You must be signed in to change notification settings - Fork 0
/
conway.c
169 lines (153 loc) · 3.96 KB
/
conway.c
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#define TB_IMPL
#include "termbox2.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
void nextGeneration(int H, int W, int matrix[H][W]);
void printMatrix(int H, int W, int matrix[H][W], char CHAR);
void configParse(int H, int W, int matrix[H][W], int RAND);
void exitCheck();
void argParse(int argc, char* argv[], int* delay, char* aliveChar, int* rand, int* limit);
int main(int argc, char* argv[]) {
// input
int DELAY = 100;
char CHAR = '@';
int RAND = 0;
int LIMIT = 0;
argParse(argc, argv, &DELAY, &CHAR, &RAND, &LIMIT);
// start termbox2
if (tb_init() != 0) {
printf("Something very very very bad happened with termbox\n");
return 1;
}
tb_clear();
// terminal size
int H = tb_width();
int W = tb_height();
// initial generation
int matrix[H][W];
memset(matrix, 0, sizeof(matrix));
configParse(H, W, matrix, RAND);
// loop
while(1) {
exitCheck();
nextGeneration(H, W, matrix);
printMatrix(H, W, matrix, CHAR);
usleep(DELAY * 1000);
if (LIMIT > 0) {
LIMIT--;
if (LIMIT == 0) {
tb_shutdown();
exit(0);
}
}
}
}
void nextGeneration(int H, int W, int matrix[H][W]) {
// itinerate matrix
int nextgen[H][W];
for(int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
// moore neighbourhood
int count = 0;
for(int dy = -1; dy < 2; dy++) {
for(int dx = -1; dx < 2; dx++) {
if (dy == 0 && dx == 0) continue;
int ny = (y + dy + H) % H;
int nx = (x + dx + W) % W;
count += matrix[ny][nx];
}
}
nextgen[y][x] = count;
}
}
// update current generation
for(int y = 0; y < H; y++) {
for(int x = 0; x < W; x++) {
// dae rules
if (matrix[y][x] && (nextgen[y][x] < 2 || nextgen[y][x] > 3)) {
matrix[y][x] = 0; // cell dies
} else if (!matrix[y][x] && nextgen[y][x] == 3) {
matrix[y][x] = 1; // cell is born
}
}
}
}
void printMatrix(int H, int W, int matrix[H][W], char CHAR) {
for (int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
tb_set_cell(y, x, matrix[y][x] ? CHAR : ' ', TB_WHITE, TB_DEFAULT);
}
}
tb_present();
}
void configParse(int H, int W, int matrix[H][W], int RAND) {
if (RAND) {
srand(time(NULL));
for(int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) {
matrix[y][x] = rand() % 2;
}
}
} else {
H = H / 2 - 1;
W = W / 2 - 1;
matrix[H][W + 1] = 1;
matrix[H][W + 2] = 1;
matrix[H + 1][W] = 1;
matrix[H + 1][W + 1] = 1;
matrix[H + 2][W + 1] = 1;
}
}
void exitCheck() {
static struct tb_event event = {0};
while ((tb_peek_event(&event, 0)) == TB_OK) {
if (event.key == TB_KEY_CTRL_C) {
tb_shutdown();
exit(0);
}
}
}
void argParse(int argc, char* argv[], int* delay, char* aliveChar, int* rand, int* limit) {
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-d") == 0) {
if (i + 1 < argc) {
*delay = atoi(argv[++i]);
} else {
fprintf(stderr, "Error: -d option requires an argument.\n");
exit(1);
}
} else if (strcmp(argv[i], "-c") == 0) {
if (i + 1 < argc) {
*aliveChar = argv[++i][0];
} else {
fprintf(stderr, "Error: -c option requires an argument.\n");
exit(1);
}
} else if (strcmp(argv[i], "-h") == 0) {
printf("Conway's Game of Life - A living world in your terminal!\n\n");
printf("Usage: conway [OPTIONS]\n");
printf("Options:\n");
printf(" -c [char] Character representing a living cell.\n");
printf(" -d [int] Delay time between ticks in milliseconds.\n");
printf(" -r Randomize the initial configuration.\n");
printf(" -l [int] Limit the number of generations before exit\n");
printf(" -h Show this help message.\n");
exit(0);
} else if (strcmp(argv[i], "-r") == 0) {
*rand = 1;
} else if (strcmp(argv[i], "-l") == 0) {
if (i + 1 < argc) {
*limit = atoi(argv[++i]);
} else {
fprintf(stderr, "Error: -l option requires an argument.\n");
exit(1);
}
} else {
fprintf(stderr, "Error: Unknown option %s\n", argv[i]);
exit(1);
}
}
}