.
[simple-cellular-automata-suite.git] / engine-sinners.c
blob0b9c99fa09f5a3af4c40b139c91c7e16c71b7773
1 #include <stdlib.h>
3 #include "engine.h"
4 #include "math.h"
6 #define E_UNIMPLEMENTED -1
7 #define E_ILLEGAL_COORDINATES -2
8 #define E_UNINITIALIZED -3
9 #define E_NULLREP -4
10 #define E_MALFORMED_INPUT -5
11 #define E_BAD_VALUES -6
13 struct cell {
14 double alpha;
15 double beta;
16 double c_sin;
17 double n_avg;
18 int xi;
21 static struct cell *grid;
22 static size_t g_len = -1;
24 static long t = 0;
26 static int g_width, g_height;
28 static void compute_sins(void)
30 size_t m;
32 for (m = 0; m < g_len; ++m)
33 grid[m].c_sin = sin(grid[m].beta + t * grid[m].alpha);
36 #define SET_XI(i) { \
37 grid[i].xi = \
38 floor(1.0 / fabs(grid[i].c_sin - grid[i].n_avg)); \
41 #define ADJUST(i) { \
42 if (grid[i].xi % 2) \
43 grid[i].alpha = (asin(grid[i].n_avg) - grid[i].beta) / t; \
44 else \
45 grid[i].beta = asin(grid[i].n_avg) - grid[i].alpha * t; \
48 static void handle_xis(void)
50 size_t i, j;
52 grid[0].n_avg = (grid[1].c_sin +
53 grid[g_width].c_sin +
54 grid[g_width + 1].c_sin) / 3.0;
55 SET_XI(0);
56 ADJUST(0);
58 grid[g_width - 1].n_avg = (grid[g_width - 2].c_sin +
59 grid[2 * g_width - 2].c_sin +
60 grid[2 * g_width - 1].c_sin) / 3.0;
61 SET_XI(g_width - 1);
62 ADJUST(g_width - 1);
64 grid[(g_height - 1) * g_width].n_avg = (grid[(g_height - 2) * g_width].c_sin +
65 grid[(g_height - 2) * g_width + 1].c_sin +
66 grid[(g_height - 1) * g_width + 1].c_sin) / 3.0;
67 SET_XI((g_height - 1) * g_width);
68 ADJUST((g_height - 1) * g_width);
70 grid[g_height * g_width - 1].n_avg = (grid[g_height * g_width - 2].c_sin +
71 grid[(g_height - 1) * g_width - 2].c_sin +
72 grid[(g_height - 1) * g_width - 1].c_sin) / 3.0;
73 SET_XI(g_height * g_width - 1);
74 ADJUST(g_height * g_width - 1);
76 for (i = 1; i < g_width - 1; ++i) {
77 grid[i].n_avg = (grid[i - 1].c_sin +
78 grid[i + 1].c_sin +
79 grid[g_width + i - 1].c_sin +
80 grid[g_width + i].c_sin +
81 grid[g_width + i + 1].c_sin) / 5.0;
82 SET_XI(i);
83 ADJUST(i);
86 for (i = (g_height - 1) * g_width + 1; i < g_height * g_width - 2; ++i) {
87 grid[i].n_avg = (grid[i - 1].c_sin +
88 grid[i + 1].c_sin +
89 grid[i - g_width - 1].c_sin +
90 grid[i - g_width].c_sin +
91 grid[i - g_width + 1].c_sin) / 5.0;
92 SET_XI(i);
93 ADJUST(i);
96 for (j = g_width; j < g_height * g_width; j+= g_width) {
97 grid[j].n_avg = (grid[j - g_width].c_sin +
98 grid[j - g_width + 1].c_sin +
99 grid[j + 1].c_sin +
100 grid[j + g_width].c_sin +
101 grid[j + g_width + 1].c_sin) / 5.0;
102 SET_XI(j);
103 ADJUST(j);
106 for (j = 2 * g_width - 1; j < g_height * g_width - 1; j+= g_width) {
107 grid[j].n_avg = (grid[j - g_width].c_sin +
108 grid[j - g_width - 1].c_sin +
109 grid[j - 1].c_sin +
110 grid[j + g_width].c_sin +
111 grid[j + g_width - 1].c_sin) / 5.0;
112 SET_XI(j);
113 ADJUST(j);
116 for (j = 1; j < g_height - 1; ++j) {
117 for (i = 1; i < g_width - 1; ++i) {
118 grid[j * g_width + i].n_avg = (grid[(j - 1) * g_width + (i - 1)].c_sin +
119 grid[(j - 1) * g_width + (i + 0)].c_sin +
120 grid[(j - 1) * g_width + (i + 1)].c_sin +
121 grid[(j + 0) * g_width + (i - 1)].c_sin +
122 grid[(j + 0) * g_width + (i + 1)].c_sin +
123 grid[(j + 1) * g_width + (i - 1)].c_sin +
124 grid[(j + 1) * g_width + (i + 0)].c_sin +
125 grid[(j + 1) * g_width + (i + 1)].c_sin) / 8.0;
126 SET_XI(j * g_width + i);
127 ADJUST(j * g_width + i);
132 int con_initialize_f(FILE * ifp)
134 int i_width, i_height;
135 int i, j, m = 0;
136 double a, b;
138 if (fscanf(ifp, " %d x %d ", &i_width, &i_height) != 2)
139 return E_MALFORMED_INPUT;
141 if (i_width <= 0 || i_height <= 0)
142 return E_MALFORMED_INPUT;
144 g_width = i_width;
145 g_height = i_height;
146 g_len = (size_t)g_width * (size_t)g_height;
147 grid = calloc(g_len, sizeof(*grid));
149 for (j = 0; j < g_height; ++j) {
150 for (i = 0; i < g_width; ++i) {
151 if (fscanf(ifp, " %lf , %lf ", &a, &b) != 2)
152 return E_MALFORMED_INPUT;
153 grid[m].alpha = a;
154 grid[m].beta = b;
155 m++;
159 compute_sins();
161 return 0;
164 int con_initialize_wh(int width, int height)
166 if (width <= 0 || height <= 0)
167 return E_MALFORMED_INPUT;
169 g_width = width;
170 g_height = height;
171 g_len = (size_t)g_width * (size_t)g_height;
172 grid = calloc(g_len, sizeof(*grid));
174 return 0;
177 int con_width(void)
179 return g_width;
182 int con_height(void)
184 return g_height;
187 int con_step(void)
189 ++t;
190 compute_sins();
191 handle_xis();
193 return 0;
196 static const char *APEX = "^";
197 static const char *HIGH = "'";
198 static const char *NIL = " ";
199 static const char *LOW = ",";
200 static const char *NADIR = "v";
202 int con_rep_at(int x, int y, const char ** const rep)
204 double d;
206 if (x < 0 || y < 0 || x >= g_width || y >= g_height)
207 return E_ILLEGAL_COORDINATES;
209 d = grid[y * g_width + x].c_sin;
211 if (d > 0.6)
212 *rep = APEX;
213 else if (d > 0.2)
214 *rep = HIGH;
215 else if (d > -0.2)
216 *rep = NIL;
217 else if (d > -0.6)
218 *rep = LOW;
219 else
220 *rep = NADIR;
222 return 0;
225 static const char *titles[] = {"Alpha:", "Beta:"};
226 int con_input_titles(int * const n, const char * const ** const o_titles)
228 *n = 2;
229 *o_titles = titles;
231 return 0;
234 int con_set_val(int x, int y, const char ** vals)
236 double a, b;
238 if (x < 0 || y < 0 || x >= g_width || y >= g_height || !vals || !vals[0] ||
239 !vals[1])
240 return E_ILLEGAL_COORDINATES;
242 if (sscanf(vals[0], " %lf ", &a) != 1 || sscanf(vals[1], " %lf ", &b) != 1 )
243 return E_BAD_VALUES;
245 grid[y * g_width + g_height].alpha = a;
246 grid[y * g_width + g_height].beta = b;
248 return 0;
251 int con_teardown(void)
253 if (grid)
254 free(grid);
256 return 0;
259 const char *con_errstring(int errno)
261 switch (errno) {
262 case 0: return "No error";
263 case E_UNIMPLEMENTED: return "Unimplemented function";
264 case E_UNINITIALIZED: return "Uninitialized";
265 case E_ILLEGAL_COORDINATES: return "Illegal coordinates";
266 case E_NULLREP: return "Null pointer passed";
267 case E_MALFORMED_INPUT: return "Malformed input file";
268 case E_BAD_VALUES: return "Non-double values";
269 default: return "Unknown error";