.
[simple-cellular-automata-suite.git] / engine-conway.c
blob6026885d537fbe083c81afceae798fbe32f41271
1 /* A pretty dumb implementation of Conway's rules. Really only used
2 * for testing the driver
3 */
5 #include <string.h>
6 #include <stdlib.h>
8 #include "engine.h"
10 #define E_UNIMPLEMENTED -1
11 #define E_ILLEGAL_COORDINATES -2
12 #define E_UNINITIALIZED -3
13 #define E_NULLREP -4
14 #define E_MALFORMED_INPUT -5
16 static const char *ALIVE = ".";
17 static const char *DEAD = " ";
19 static char *alive_stat = NULL;
20 static char *nigh_count = NULL;
21 static char *freeze_alive_stat = NULL;
22 static char *freeze_nigh_count = NULL;
23 static int g_width, g_height;
25 static void n_add(int x, int y, int mod)
27 if (x - 1 >= 0) {
28 if (y - 1 >= 0) nigh_count[g_width * (y - 1) + (x - 1)] += mod;
29 nigh_count[g_width * (y ) + (x - 1)] += mod;
30 if (y + 1 < g_height) nigh_count[g_width * (y + 1) + (x - 1)] += mod;
33 if (y - 1 >= 0) nigh_count[g_width * (y - 1) + (x )] += mod;
34 if (y + 1 < g_height) nigh_count[g_width * (y + 1) + (x )] += mod;
36 if (x + 1 < g_width) {
37 if (y - 1 >= 0) nigh_count[g_width * (y - 1) + (x + 1)] += mod;
38 nigh_count[g_width * (y ) + (x + 1)] += mod;
39 if (y + 1 < g_height) nigh_count[g_width * (y + 1) + (x + 1)] += mod;
44 int con_initialize_f(FILE * ifp){
45 int i_width, i_height;
46 int c = EOF;
47 int i, j;
48 size_t m = 0;
50 if (fscanf(ifp, " %d x %d ", &i_width, &i_height) != 2)
51 return E_MALFORMED_INPUT;
53 if (i_width <= 0 || i_height <= 0)
54 return E_MALFORMED_INPUT;
56 g_width = i_width;
57 g_height = i_height;
58 alive_stat = calloc(g_width * g_height, sizeof(*alive_stat));
59 nigh_count = calloc(g_width * g_height, sizeof(*nigh_count));
60 freeze_alive_stat = malloc(g_width * g_height * sizeof(*alive_stat));
61 freeze_nigh_count = malloc(g_width * g_height * sizeof(*nigh_count));
64 for (j = 0; j < g_height; ++j) {
65 for (i = 0; i < g_width; ++i) {
66 do {
67 c = fgetc(ifp);
68 } while (c != ' ' && c != '.' && c != EOF);
70 if (c == EOF)
71 return E_MALFORMED_INPUT;
72 else if (c == '.') {
73 alive_stat[m] = 1;
74 n_add(i, j, 1);
76 m++;
80 return 0;
83 int con_initialize_wh(int width, int height)
85 if (width <= 0 || height <= 0)
86 return E_MALFORMED_INPUT;
88 alive_stat = calloc(width * height, sizeof(*alive_stat));
89 nigh_count = calloc(width * height, sizeof(*nigh_count));
90 freeze_alive_stat = malloc(width * height * sizeof(*alive_stat));
91 freeze_nigh_count = malloc(width * height * sizeof(*nigh_count));
92 g_width = width;
93 g_height = height;
95 return 0;
98 static const char *title = "Alive? [0/1]";
100 int con_input_titles(int * const n, const char * const ** const titles)
102 *n = 1;
103 *titles = &title;
104 return 0;
107 int con_set_val(int x, int y, const char ** vals)
109 char v;
111 if (!alive_stat)
112 return E_UNINITIALIZED;
114 if (x < 0 || y < 0 || x >= g_width || y >= g_height || !vals || !vals[0])
115 return E_ILLEGAL_COORDINATES;
117 v = (vals[0][0] == '1' || vals[0][0] == '.');
119 if (!v && alive_stat[y * g_width + x]) {
120 n_add(x, y, -1);
121 alive_stat[y * g_width + x] = 0;
122 } else if (v && !alive_stat[y * g_width + x]) {
123 n_add(x, y, 1);
124 alive_stat[y * g_width + x] = 1;
127 return 0;
129 int con_set_p(int x, int y, void *val){ return E_UNIMPLEMENTED; }
131 int con_width(void)
133 if (!alive_stat)
134 return E_UNINITIALIZED;
136 return g_width;
139 int con_height(void)
141 if (!alive_stat)
142 return E_UNINITIALIZED;
144 return g_height;
147 int con_step(void)
149 int x, y;
150 size_t m = 0;
152 if (!alive_stat)
153 return E_UNINITIALIZED;
155 memcpy(freeze_alive_stat, alive_stat,
156 g_width * g_height * sizeof (*alive_stat));
157 memcpy(freeze_nigh_count, nigh_count,
158 g_width * g_height * sizeof (*nigh_count));
160 for (y = 0; y < g_height; ++y) {
161 for (x = 0; x < g_width; ++x) {
162 if (freeze_alive_stat[m]
163 && (freeze_nigh_count[m] < 2 || freeze_nigh_count[m] > 3)) {
164 alive_stat[m] = 0;
165 n_add(x, y, -1);
166 } else if (!freeze_alive_stat[m] && freeze_nigh_count[m] == 3) {
167 alive_stat[m] = 1;
168 n_add(x, y, 1);
170 ++m;
173 return 0;
175 int con_rep_at(int x, int y, const char ** const rep)
177 if (!alive_stat)
178 return E_UNINITIALIZED;
180 if (!rep)
181 return E_NULLREP;
183 if (x < 0 || y < 0 || x >= g_width || y >= g_height)
184 return E_ILLEGAL_COORDINATES;
186 if (alive_stat[y * g_width + x])
187 *rep = ALIVE;
188 else
189 *rep = DEAD;
191 return 0;
194 int con_teardown(void)
196 if (alive_stat)
197 free(alive_stat);
198 if (nigh_count)
199 free(nigh_count);
200 if (freeze_alive_stat)
201 free(freeze_alive_stat);
202 if (freeze_nigh_count)
203 free(freeze_nigh_count);
205 return 0;
208 const char *con_errstring(int errno)
210 switch (errno) {
211 case 0: return "No error";
212 case E_UNIMPLEMENTED: return "Unimplemented function";
213 case E_UNINITIALIZED: return "Uninitialized";
214 case E_ILLEGAL_COORDINATES: return "Illegal coordinates";
215 case E_NULLREP: return "Null pointer passed";
216 case E_MALFORMED_INPUT: return "Malformed input file";
217 default: return "Unknown error";