1 /*
2 * XLife Copyright 1989 Jon Bennett jb7m+@andrew.cmu.edu, jcrb@cs.cmu.edu
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The copyright holders make no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * CMU SUCKS
23 */
24
25 /*
26 A lot of modifications were added at 2001, 2011-13 by Vladimir Lidovski vol.litwr@gmail.com
27 (C) This version of XLife may be used under the same conditions as mentioned above
28 $Id: generate.c 270 2014-01-11 15:25:55Z litwr $
29 */
30
31 /*
32 * This module contains the evolution and rule-setting code. It has three
33 * entry points:
34 *
35 * evolve() --- perform evolution on the board
36 * newrules() --- prompt for & accept new 2-state/generated/named/historical+topology rules
37 * readrules() --- read N-state rules+topology from given file
38 */
39
40 #include <stdlib.h>
41 #include <errno.h>
42 #include "defs.h"
43 #include "tab.h"
44 #include "tile.h"
45 #include "file.h"
46 #include "colors.h"
47 #include "history.h"
48 #include "topology.h"
49
50 static float payoffs[2][2] = {1, 0, 0, 0};
51 static unsigned long dm_given;
52 #define NMAX ((MAXSTATES > 64) ? 64 : MAXSTATES)
53
54 /* strategy indices */
55 #define COOPERATE 0
56 #define DEFECT 1
57
58 /* cell state values */
59 #define COOPERATOR 1
60 #define DEFECTOR 2
61
62 #define adjucency_links(istate, live1, live2)\
63 cptrup = cptr->up;\
64 cptrdn = cptr->dn;\
65 cptrlf = cptr->lf;\
66 cptrrt = cptr->rt;\
67 t1 = live1 &0xff;\
68 if (t1) {\
69 if (cptrup == NULL) {\
70 cptrup = maketile(context, cptr->x, cptr->y - BOXSIZE);\
71 cptrup->dn = cptr;\
72 }\
73 t2 = tab1[t1];\
74 cptrup->cells.istate.on[7] += t2;\
75 cptr->cells.istate.on[1] += t2;\
76 cptr->cells.istate.on[0] += tab2[t1];\
77 }\
78 t1 = (live2 & 0xff000000) >> 24;\
79 if (t1) {\
80 if (cptrdn == NULL) {\
81 cptrdn = maketile(context, cptr->x, cptr->y + BOXSIZE);\
82 cptrdn->up = cptr;\
83 }\
84 t2 = tab1[t1];\
85 cptrdn->cells.istate.on[0] += t2;\
86 cptr->cells.istate.on[6] += t2;\
87 cptr->cells.istate.on[7] += tab2[t1];\
88 }\
89 t1 = live1;\
90 t2 = live2;\
91 if (t1 & 0x1010101) {\
92 if (cptrlf == NULL) {\
93 cptrlf = maketile(context, cptr->x - BOXSIZE, cptr->y);\
94 cptrlf->rt = cptr;\
95 }\
96 if (t1 & 0x1) {\
97 cptrlf->cells.istate.on[0] += 0x10000000;\
98 cptrlf->cells.istate.on[1] += 0x10000000;\
99 if (cptrlf->up == NULL)\
100 cptrlf->up = maketile(context, cptr->x - BOXSIZE, cptr->y - BOXSIZE);\
101 cptrlf->up->cells.istate.on[7] += 0x10000000;\
102 cptrlf->up->dn = cptrlf;\
103 }\
104 if (t1 & 0x100) {\
105 cptrlf->cells.istate.on[0] += 0x10000000;\
106 cptrlf->cells.istate.on[1] += 0x10000000;\
107 cptrlf->cells.istate.on[2] += 0x10000000;\
108 }\
109 if (t1 & 0x10000) {\
110 cptrlf->cells.istate.on[1] += 0x10000000;\
111 cptrlf->cells.istate.on[2] += 0x10000000;\
112 cptrlf->cells.istate.on[3] += 0x10000000;\
113 }\
114 if (t1 & 0x1000000) {\
115 cptrlf->cells.istate.on[2] += 0x10000000;\
116 cptrlf->cells.istate.on[3] += 0x10000000;\
117 cptrlf->cells.istate.on[4] += 0x10000000;\
118 }\
119 }\
120 if (t2 & 0x1010101) {\
121 if (cptrlf == NULL) {\
122 cptrlf = maketile(context, cptr->x - BOXSIZE, cptr->y);\
123 cptrlf->rt = cptr;\
124 }\
125 if (t2 & 0x1) {\
126 cptrlf->cells.istate.on[3] += 0x10000000;\
127 cptrlf->cells.istate.on[4] += 0x10000000;\
128 cptrlf->cells.istate.on[5] += 0x10000000;\
129 }\
130 if (t2 & 0x100) {\
131 cptrlf->cells.istate.on[4] += 0x10000000;\
132 cptrlf->cells.istate.on[5] += 0x10000000;\
133 cptrlf->cells.istate.on[6] += 0x10000000;\
134 }\
135 if (t2 & 0x10000) {\
136 cptrlf->cells.istate.on[5] += 0x10000000;\
137 cptrlf->cells.istate.on[6] += 0x10000000;\
138 cptrlf->cells.istate.on[7] += 0x10000000;\
139 }\
140 if (t2 & 0x1000000) {\
141 cptrlf->cells.istate.on[6] += 0x10000000;\
142 cptrlf->cells.istate.on[7] += 0x10000000;\
143 if (cptrlf->dn == NULL)\
144 cptrlf->dn = maketile(context, cptr->x - BOXSIZE, cptr->y + BOXSIZE);\
145 cptrlf->dn->cells.istate.on[0] += 0x10000000;\
146 cptrlf->dn->up = cptrlf;\
147 }\
148 }\
149 if (t1 & 0x80808080) {\
150 if (cptrrt == NULL) {\
151 cptrrt = maketile(context, cptr->x + BOXSIZE, cptr->y);\
152 cptrrt->lf = cptr;\
153 }\
154 if (t1 & 0x80) {\
155 cptrrt->cells.istate.on[0] += 0x1;\
156 cptrrt->cells.istate.on[1] += 0x1;\
157 if (cptrrt->up == NULL)\
158 cptrrt->up = maketile(context, cptr->x + BOXSIZE, cptr->y - BOXSIZE);\
159 cptrrt->up->cells.istate.on[7] += 0x1;\
160 cptrrt->up->dn = cptrrt;\
161 }\
162 if (t1 & 0x8000) {\
163 cptrrt->cells.istate.on[0] += 0x1;\
164 cptrrt->cells.istate.on[1] += 0x1;\
165 cptrrt->cells.istate.on[2] += 0x1;\
166 }\
167 if (t1 & 0x800000) {\
168 cptrrt->cells.istate.on[1] += 0x1;\
169 cptrrt->cells.istate.on[2] += 0x1;\
170 cptrrt->cells.istate.on[3] += 0x1;\
171 }\
172 if (t1 & 0x80000000) {\
173 cptrrt->cells.istate.on[2] += 0x1;\
174 cptrrt->cells.istate.on[3] += 0x1;\
175 cptrrt->cells.istate.on[4] += 0x1;\
176 }\
177 }\
178 if (t2 & 0x80808080) {\
179 if (cptrrt == NULL) {\
180 cptrrt = maketile(context, cptr->x + BOXSIZE, cptr->y);\
181 cptrrt->lf = cptr;\
182 }\
183 if (t2 & 0x80) {\
184 cptrrt->cells.istate.on[3] += 0x1;\
185 cptrrt->cells.istate.on[4] += 0x1;\
186 cptrrt->cells.istate.on[5] += 0x1;\
187 }\
188 if (t2 & 0x8000) {\
189 cptrrt->cells.istate.on[4] += 0x1;\
190 cptrrt->cells.istate.on[5] += 0x1;\
191 cptrrt->cells.istate.on[6] += 0x1;\
192 }\
193 if (t2 & 0x800000) {\
194 cptrrt->cells.istate.on[5] += 0x1;\
195 cptrrt->cells.istate.on[6] += 0x1;\
196 cptrrt->cells.istate.on[7] += 0x1;\
197 }\
198 if (t2 & 0x80000000) {\
199 cptrrt->cells.istate.on[6] += 0x1;\
200 cptrrt->cells.istate.on[7] += 0x1;\
201 if (cptrrt->dn == NULL)\
202 cptrrt->dn = maketile(context, cptr->x + BOXSIZE, cptr->y + BOXSIZE);\
203 cptrrt->dn->cells.istate.on[0] += 0x1;\
204 cptrrt->dn->up = cptrrt;\
205 }\
206 }\
207 t1 = (live1 & 0xff00) >> 8;\
208 t2 = (live1 & 0xff0000) >> 16;\
209 if (t1) {\
210 t3 = tab1[t1];\
211 cptr->cells.istate.on[1] += tab2[t1];\
212 cptr->cells.istate.on[0] += t3;\
213 cptr->cells.istate.on[2] += t3;\
214 }\
215 t1 = (live1 & 0xff000000) >> 24;\
216 if (t2) {\
217 t3 = tab1[t2];\
218 cptr->cells.istate.on[2] += tab2[t2];\
219 cptr->cells.istate.on[1] += t3;\
220 cptr->cells.istate.on[3] += t3;\
221 }\
222 t2 = (live2 & 0xff);\
223 if (t1) {\
224 t3 = tab1[t1];\
225 cptr->cells.istate.on[3] += tab2[t1];\
226 cptr->cells.istate.on[2] += t3;\
227 cptr->cells.istate.on[4] += t3;\
228 }\
229 t1 = (live2 & 0xff00) >> 8;\
230 if (t2) {\
231 t3 = tab1[t2];\
232 cptr->cells.istate.on[4] += tab2[t2];\
233 cptr->cells.istate.on[3] += t3;\
234 cptr->cells.istate.on[5] += t3;\
235 }\
236 t2 = (live2 & 0xff0000) >> 16;\
237 if (t1) {\
238 t3 = tab1[t1];\
239 cptr->cells.istate.on[5] += tab2[t1];\
240 cptr->cells.istate.on[4] += t3;\
241 cptr->cells.istate.on[6] += t3;\
242 }\
243 if (t2) {\
244 t3 = tab1[t2];\
245 cptr->cells.istate.on[6] += tab2[t2];\
246 cptr->cells.istate.on[5] += t3;\
247 cptr->cells.istate.on[7] += t3;\
248 }\
249 cptr->up = cptrup;\
250 cptr->dn = cptrdn;\
251 cptr->lf = cptrlf;\
252 cptr->rt = cptrrt;
253
254 #define gather_statistics()\
255 t1 = cptr->cells.twostate.live1;\
256 if (t1 || t2) {\
257 cptr->dead = 0;\
258 if (oscillators) osc_values(context, cptr);\
259 live_total++;\
260 if (dispboxes)\
261 context->cellcount[1] += tab3[t1 & 0xff] + tab3[t1 >> 8 & 0xff]\
262 + tab3[t1 >> 16 & 0xff] + tab3[t1 >> 24]\
263 + tab3[t2 & 0xff] + tab3[t2 >> 8 & 0xff]\
264 + tab3[t2 >> 16 & 0xff] + tab3[t2 >> 24];\
265 }\
266 else\
267 cptr->dead++;\
268 t1 ^= cptr->cells.twostate.olive1;\
269 t2 ^= cptr->cells.twostate.olive2;\
270 if (t1 || t2) {\
271 if (truehistory && context == &active) add2history(cptr);\
272 if (dispchanges)\
273 context->chgcount += tab3[t1 & 0xff] + tab3[t1 >> 8 & 0xff]\
274 + tab3[t1 >> 16 & 0xff] + tab3[t1 >> 24]\
275 + tab3[t2 & 0xff] + tab3[t2 >> 8 & 0xff]\
276 + tab3[t2 >> 16 & 0xff] + tab3[t2 >> 24];\
277 else\
278 context->chgcount++;}
279
osc_values(pattern * context,tile * cptr)280 static void osc_values(pattern *context, tile *cptr) {
281 long t;
282 if (ev_mode == VALENCE_DRIVEN) {
283 context->osc1 += ((cptr->y >> 3) + cptr->cells.twostate.live1)*((cptr->x >> 3)
284 + cptr->cells.twostate.live2);
285 t = (cptr->cells.twostate.live1 ^ cptr->cells.twostate.live2) + cptr->x;
286 context->osc2 += (u32bits)((double) t*t);
287 t = (cptr->cells.twostate.live1 ^ cptr->cells.twostate.live2) + cptr->y;
288 context->osc3 += (u32bits)((double) t*t);
289 context->osc4 += cptr->cells.twostate.live1 << 1 ^ cptr->cells.twostate.live2;
290 context->osc5 += cptr->cells.twostate.live1 ^ cptr->cells.twostate.live2 << 1;
291 }
292 else {
293 context->osc1 += ((cptr->y >> 3) + cptr->cells.nstate.live[7][0]
294 + cptr->cells.nstate.live[5][1])*((cptr->x >> 3) + cptr->cells.nstate.live[3][0]
295 + cptr->cells.nstate.live[1][1]);
296 t = ((cptr->cells.nstate.live[4][0] ^ cptr->cells.nstate.live[4][1])
297 ^ (cptr->cells.nstate.live[5][0] ^ cptr->cells.nstate.live[5][1]) << 1
298 ^ (cptr->cells.nstate.live[6][0] ^ cptr->cells.nstate.live[6][1]) << 2
299 ^ (cptr->cells.nstate.live[7][0] ^ cptr->cells.nstate.live[7][1]) << 3) + cptr->x;
300 context->osc2 += (u32bits)((double) t*t);
301 t = ((cptr->cells.nstate.live[0][0] ^ cptr->cells.nstate.live[0][1])
302 ^ (cptr->cells.nstate.live[1][0] ^ cptr->cells.nstate.live[1][1]) << 1
303 ^ (cptr->cells.nstate.live[2][0] ^ cptr->cells.nstate.live[2][1]) << 2
304 ^ (cptr->cells.nstate.live[3][0] ^ cptr->cells.nstate.live[3][1]) << 3) + cptr->y;
305 context->osc3 += (u32bits)((double) t*t);
306 context->osc4 += (cptr->cells.nstate.live[4][0] ^ cptr->cells.nstate.live[4][1]) << 3
307 ^ (cptr->cells.nstate.live[5][0] ^ cptr->cells.nstate.live[5][1]) << 2
308 ^ (cptr->cells.nstate.live[6][0] ^ cptr->cells.nstate.live[6][1]) << 1
309 ^ (cptr->cells.nstate.live[7][0] ^ cptr->cells.nstate.live[7][1]);
310 context->osc5 += (cptr->cells.nstate.live[0][0] ^ cptr->cells.nstate.live[0][1]) << 3
311 ^ (cptr->cells.nstate.live[2][0] ^ cptr->cells.nstate.live[1][1]) << 2
312 ^ (cptr->cells.nstate.live[1][0] ^ cptr->cells.nstate.live[2][1]) << 1
313 ^ (cptr->cells.nstate.live[3][0] ^ cptr->cells.nstate.live[3][1]);
314 }
315 }
316
317 static const u32bits invmask = 0xffffffff;
318
evolve2b0(pattern * context)319 static void evolve2b0(pattern *context) {
320 register u32bits t1, t2, t3;
321 u32bits *tmpptr, live_total = 0;
322 register tile *cptr;
323 tile *cptrup, *cptrdn, *cptrlf, *cptrrt;
324
325 cptr = context->tiles;
326 if (context->cellmass) {
327 int live8st = !!(live & 0x100);
328 tile *cptrul, *cptrur, *cptrdl, *cptrdr;
329
330 for (; cptr; cptr = cptr->next) {
331 if ((cptr->cells.twostate.live1 | cptr->cells.twostate.live2) == 0)
332 continue;
333 maketile(context, cptr->x, cptr->y - BOXSIZE);
334 maketile(context, cptr->x, cptr->y + BOXSIZE);
335 maketile(context, cptr->x - BOXSIZE, cptr->y);
336 maketile(context, cptr->x - BOXSIZE, cptr->y - BOXSIZE);
337 maketile(context, cptr->x - BOXSIZE, cptr->y + BOXSIZE);
338 maketile(context, cptr->x + BOXSIZE, cptr->y);
339 maketile(context, cptr->x + BOXSIZE, cptr->y - BOXSIZE);
340 maketile(context, cptr->x + BOXSIZE, cptr->y + BOXSIZE);
341 }
342 for (cptr = context->tiles; cptr; cptr = cptr->next) {
343 cptr->cells.twostate.live1 ^= invmask;
344 cptr->cells.twostate.live2 ^= invmask;
345 cptrup = fetchtile(context, cptr->x, cptr->y - BOXSIZE);
346 cptrdn = fetchtile(context, cptr->x, cptr->y + BOXSIZE);
347 cptrlf = fetchtile(context, cptr->x - BOXSIZE, cptr->y);
348 cptrrt = fetchtile(context, cptr->x + BOXSIZE, cptr->y);
349 cptrul = fetchtile(context, cptr->x - BOXSIZE, cptr->y - BOXSIZE);
350 cptrur = fetchtile(context, cptr->x + BOXSIZE, cptr->y - BOXSIZE);
351 cptrdl = fetchtile(context, cptr->x - BOXSIZE, cptr->y + BOXSIZE);
352 cptrdr = fetchtile(context, cptr->x + BOXSIZE, cptr->y + BOXSIZE);
353 if (!cptrup) cptr->cells.twostate.on[0] += 0x23333332;
354 if (!cptrdn) cptr->cells.twostate.on[7] += 0x23333332;
355 if (!cptrlf) {
356 cptr->cells.twostate.on[0] += 2;
357 cptr->cells.twostate.on[1] += 3;
358 cptr->cells.twostate.on[2] += 3;
359 cptr->cells.twostate.on[3] += 3;
360 cptr->cells.twostate.on[4] += 3;
361 cptr->cells.twostate.on[5] += 3;
362 cptr->cells.twostate.on[6] += 3;
363 cptr->cells.twostate.on[7] += 2;
364 }
365 if (!cptrrt) {
366 cptr->cells.twostate.on[0] += 0x20000000;
367 cptr->cells.twostate.on[1] += 0x30000000;
368 cptr->cells.twostate.on[2] += 0x30000000;
369 cptr->cells.twostate.on[3] += 0x30000000;
370 cptr->cells.twostate.on[4] += 0x30000000;
371 cptr->cells.twostate.on[5] += 0x30000000;
372 cptr->cells.twostate.on[6] += 0x30000000;
373 cptr->cells.twostate.on[7] += 0x20000000;
374 }
375 if (!cptrul) cptr->cells.twostate.on[0] += 1;
376 if (!cptrur) cptr->cells.twostate.on[0] += 0x10000000;
377 if (!cptrdl) cptr->cells.twostate.on[7] += 1;
378 if (!cptrdr) cptr->cells.twostate.on[7] += 0x10000000;
379 if ((cptr->cells.twostate.live1 | cptr->cells.twostate.live2) == 0)
380 continue;
381
382 t1 = cptr->cells.twostate.live1 &0xff;
383 if (t1) {
384 t2 = tab1[t1];
385 if (cptrup) cptrup->cells.twostate.on[7] += t2;
386 cptr->cells.twostate.on[1] += t2;
387 cptr->cells.twostate.on[0] += tab2[t1];
388 }
389
390 t1 = (cptr->cells.twostate.live2 & 0xff000000) >> 24;
391 if (t1) {
392 t2 = tab1[t1];
393 if (cptrdn) cptrdn->cells.twostate.on[0] += t2;
394 cptr->cells.twostate.on[6] += t2;
395 cptr->cells.twostate.on[7] += tab2[t1];
396 }
397
398 t1 = cptr->cells.twostate.live1;
399 t2 = cptr->cells.twostate.live2;
400 if (t1&0x1010101 && cptrlf) {
401 if (t1 & 0x1) {
402 cptrlf->cells.twostate.on[0] += 0x10000000;
403 cptrlf->cells.twostate.on[1] += 0x10000000;
404 }
405 if (t1 & 0x100) {
406 cptrlf->cells.twostate.on[0] += 0x10000000;
407 cptrlf->cells.twostate.on[1] += 0x10000000;
408 cptrlf->cells.twostate.on[2] += 0x10000000;
409 }
410 if (t1 & 0x10000) {
411 cptrlf->cells.twostate.on[1] += 0x10000000;
412 cptrlf->cells.twostate.on[2] += 0x10000000;
413 cptrlf->cells.twostate.on[3] += 0x10000000;
414 }
415 if (t1 & 0x1000000) {
416 cptrlf->cells.twostate.on[2] += 0x10000000;
417 cptrlf->cells.twostate.on[3] += 0x10000000;
418 cptrlf->cells.twostate.on[4] += 0x10000000;
419 }
420 }
421 if (t1&0x1 && cptrul) cptrul->cells.twostate.on[7] += 0x10000000;
422
423 if (t2&0x1010101 && cptrlf) {
424 if (t2 & 0x1) {
425 cptrlf->cells.twostate.on[3] += 0x10000000;
426 cptrlf->cells.twostate.on[4] += 0x10000000;
427 cptrlf->cells.twostate.on[5] += 0x10000000;
428 }
429 if (t2 & 0x100) {
430 cptrlf->cells.twostate.on[4] += 0x10000000;
431 cptrlf->cells.twostate.on[5] += 0x10000000;
432 cptrlf->cells.twostate.on[6] += 0x10000000;
433 }
434 if (t2 & 0x10000) {
435 cptrlf->cells.twostate.on[5] += 0x10000000;
436 cptrlf->cells.twostate.on[6] += 0x10000000;
437 cptrlf->cells.twostate.on[7] += 0x10000000;
438 }
439 if (t2 & 0x1000000) {
440 cptrlf->cells.twostate.on[6] += 0x10000000;
441 cptrlf->cells.twostate.on[7] += 0x10000000;
442 }
443 }
444 if (t2&0x1000000 && cptrdl) cptrdl->cells.twostate.on[0] += 0x10000000;
445
446 if (t1&0x80808080 && cptrrt) {
447 if (t1 & 0x80) {
448 cptrrt->cells.twostate.on[0] += 0x1;
449 cptrrt->cells.twostate.on[1] += 0x1;
450 }
451 if (t1 & 0x8000) {
452 cptrrt->cells.twostate.on[0] += 0x1;
453 cptrrt->cells.twostate.on[1] += 0x1;
454 cptrrt->cells.twostate.on[2] += 0x1;
455 }
456 if (t1 & 0x800000) {
457 cptrrt->cells.twostate.on[1] += 0x1;
458 cptrrt->cells.twostate.on[2] += 0x1;
459 cptrrt->cells.twostate.on[3] += 0x1;
460 }
461 if (t1 & 0x80000000) {
462 cptrrt->cells.twostate.on[2] += 0x1;
463 cptrrt->cells.twostate.on[3] += 0x1;
464 cptrrt->cells.twostate.on[4] += 0x1;
465 }
466 }
467 if (t1&0x80 && cptrur) cptrur->cells.twostate.on[7] += 0x1;
468
469 if (t2&0x80808080 && cptrrt) {
470 if (t2 & 0x80) {
471 cptrrt->cells.twostate.on[3] += 0x1;
472 cptrrt->cells.twostate.on[4] += 0x1;
473 cptrrt->cells.twostate.on[5] += 0x1;
474 }
475 if (t2 & 0x8000) {
476 cptrrt->cells.twostate.on[4] += 0x1;
477 cptrrt->cells.twostate.on[5] += 0x1;
478 cptrrt->cells.twostate.on[6] += 0x1;
479 }
480 if (t2 & 0x800000) {
481 cptrrt->cells.twostate.on[5] += 0x1;
482 cptrrt->cells.twostate.on[6] += 0x1;
483 cptrrt->cells.twostate.on[7] += 0x1;
484 }
485 if (t2 & 0x80000000) {
486 cptrrt->cells.twostate.on[6] += 0x1;
487 cptrrt->cells.twostate.on[7] += 0x1;
488 }
489 }
490 if (t2&0x80000000 && cptrdr) cptrdr->cells.twostate.on[0] += 0x1;
491
492 t1 = (cptr->cells.twostate.live1 & 0xff00) >> 8;
493 t2 = (cptr->cells.twostate.live1 & 0xff0000) >> 16;
494 if (t1) {
495 t3 = tab1[t1];
496 cptr->cells.twostate.on[1] += tab2[t1];
497 cptr->cells.twostate.on[0] += t3;
498 cptr->cells.twostate.on[2] += t3;
499 }
500
501 t1 = (cptr->cells.twostate.live1 & 0xff000000) >> 24;
502 if (t2) {
503 t3 = tab1[t2];
504 cptr->cells.twostate.on[2] += tab2[t2];
505 cptr->cells.twostate.on[1] += t3;
506 cptr->cells.twostate.on[3] += t3;
507 }
508
509 t2 = (cptr->cells.twostate.live2 & 0xff);
510 if (t1) {
511 t3 = tab1[t1];
512 cptr->cells.twostate.on[3] += tab2[t1];
513 cptr->cells.twostate.on[2] += t3;
514 cptr->cells.twostate.on[4] += t3;
515 }
516
517 t1 = (cptr->cells.twostate.live2 & 0xff00) >> 8;
518 if (t2) {
519 t3 = tab1[t2];
520 cptr->cells.twostate.on[4] += tab2[t2];
521 cptr->cells.twostate.on[3] += t3;
522 cptr->cells.twostate.on[5] += t3;
523 }
524
525 t2 = (cptr->cells.twostate.live2 & 0xff0000) >> 16;
526 if (t1) {
527 t3 = tab1[t1];
528 cptr->cells.twostate.on[5] += tab2[t1];
529 cptr->cells.twostate.on[4] += t3;
530 cptr->cells.twostate.on[6] += t3;
531 }
532 if (t2) {
533 t3 = tab1[t2];
534 cptr->cells.twostate.on[6] += tab2[t2];
535 cptr->cells.twostate.on[5] += t3;
536 cptr->cells.twostate.on[7] += t3;
537 }
538 cptr->up = cptrup;
539 cptr->dn = cptrdn;
540 cptr->lf = cptrlf;
541 cptr->rt = cptrrt;
542 }
543 /*
544 * Perform actual evolution.
545 */
546 fix_plain(cptrup);
547 context->cellmass = live8st;
548 for (cptr = context->tiles; cptr; cptr = cptr->next) {
549 cptr->cells.twostate.olive1 = (t1 = cptr->cells.twostate.live1) ^ invmask;
550 tmpptr = cptr->cells.twostate.on;
551 t2 = 0;
552 t3 = *tmpptr;
553 t2 = lookup[(t3 & 0xffff) << 4 | (t1&0xf)];
554 t2 |= lookup[(t3 & 0xffff0000) >> 12 | (t1 >> 4 & 0xf)] << 4;
555 *tmpptr = 0;
556 t3 = *++tmpptr;
557 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>8)&0xf)] << 8;
558 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>12)&0xf)] << 12;
559 *tmpptr = 0;
560 t3= *++tmpptr;
561 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>16)&0xf)] << 16;
562 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>20)&0xf)] << 20;
563 *tmpptr = 0;
564 t3 = *++tmpptr;
565 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>24)&0xf)] << 24;
566 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>28)&0xf)] << 28;
567 *tmpptr = 0;
568 t3 = *++tmpptr;
569 cptr->cells.twostate.live1 = t2 ^ (invmask*live8st);
570 cptr->cells.twostate.olive2 = (t1 = cptr->cells.twostate.live2) ^ invmask;
571 t2 = 0;
572
573 t2 = lookup[(t3 & 0xffff)<<4 | (t1&0xf)];
574 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>4)&0xf)] << 4;
575 *tmpptr = 0;
576 t3 = *++tmpptr;
577 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>8)&0xf)] << 8;
578 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>12)&0xf)] << 12;
579 *tmpptr = 0;
580 t3 = *++tmpptr;
581 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>16)&0xf)] << 16;
582 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>20)&0xf)] << 20;
583 *tmpptr = 0;
584 t3 = *++tmpptr;
585 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>24)&0xf)] << 24;
586 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>28)&0xf)] << 28;
587 *tmpptr = 0;
588 cptr->cells.twostate.live2 = t2 ^= invmask*live8st;
589
590 /*
591 * Box-aging and statistics gathering.
592 */
593 gather_statistics();
594 }
595 }
596 else {
597 for (; cptr; cptr = cptr->next) {
598 if ((cptr->cells.twostate.live1 | cptr->cells.twostate.live2) == 0)
599 continue;
600 adjucency_links(twostate, cptr->cells.twostate.live1, cptr->cells.twostate.live2); /* macro */
601 }
602
603 /*
604 * Perform actual evolution.
605 */
606 fix_plain(cptrup);
607 context->cellmass = 1;
608 for (cptr = context->tiles; cptr; cptr = cptr->next) {
609 cptr->cells.twostate.olive1 = t1 = cptr->cells.twostate.live1;
610 tmpptr = cptr->cells.twostate.on;
611 t2 = 0;
612 t3 = *tmpptr;
613 t2 = lookup[(t3 & 0xffff) << 4 | (t1&0xf)];
614 t2 |= lookup[(t3 & 0xffff0000) >> 12 | (t1 >> 4 & 0xf)] << 4;
615 *tmpptr = 0;
616 t3 = *++tmpptr;
617 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>8)&0xf)] << 8;
618 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>12)&0xf)] << 12;
619 *tmpptr = 0;
620 t3= *++tmpptr;
621 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>16)&0xf)] << 16;
622 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>20)&0xf)] << 20;
623 *tmpptr = 0;
624 t3 = *++tmpptr;
625 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>24)&0xf)] << 24;
626 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>28)&0xf)] << 28;
627 *tmpptr = 0;
628 t3 = *++tmpptr;
629 cptr->cells.twostate.live1 = t2 ^ invmask;
630 cptr->cells.twostate.olive2 = t1 = cptr->cells.twostate.live2;
631 t2 = 0;
632
633 t2 = lookup[(t3 & 0xffff)<<4 | (t1&0xf)];
634 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>4)&0xf)] << 4;
635 *tmpptr = 0;
636 t3 = *++tmpptr;
637 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>8)&0xf)] << 8;
638 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>12)&0xf)] << 12;
639 *tmpptr = 0;
640 t3 = *++tmpptr;
641 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>16)&0xf)] << 16;
642 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>20)&0xf)] << 20;
643 *tmpptr = 0;
644 t3 = *++tmpptr;
645 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>24)&0xf)] << 24;
646 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>28)&0xf)] << 28;
647 *tmpptr = 0;
648 cptr->cells.twostate.live2 = t2 ^= invmask;
649
650 /*
651 * Box-aging and statistics gathering.
652 */
653 gather_statistics();
654 }
655 }
656 if (live_total == 0 || context->chgcount == 0)
657 state = STOP;
658 }
659
evolve2(pattern * context)660 static void evolve2(pattern *context) {
661 register u32bits t1, t2, t3;
662 u32bits *tmpptr, live_total = 0;
663 register tile *cptr;
664 tile *cptrup, *cptrdn, *cptrlf, *cptrrt;
665
666 for (cptr = context->tiles; cptr; cptr = cptr->next)
667 if (cptr->cells.twostate.live1 | cptr->cells.twostate.live2) {
668 adjucency_links(twostate, cptr->cells.twostate.live1, cptr->cells.twostate.live2); /* macro */
669 }
670
671 /*
672 * Perform actual evolution.
673 */
674 fix_plain(cptrup);
675 for (cptr = context->tiles; cptr; cptr = cptr->next) {
676 cptr->cells.twostate.olive1 = t1 = cptr->cells.twostate.live1;
677 tmpptr = cptr->cells.twostate.on;
678 t2 = 0;
679 t3 = *tmpptr;
680 if (t3 &0xffff)
681 t2 = lookup[(t3 & 0xffff) << 4 | (t1&0xf)];
682 if (t3 &0xffff0000)
683 t2 |= lookup[(t3 & 0xffff0000) >> 12 | (t1 >> 4 & 0xf)] << 4;
684 *tmpptr = 0;
685 t3 = *++tmpptr;
686 if (t3 &0xffff)
687 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>8)&0xf)] << 8;
688 if (t3 &0xffff0000)
689 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>12)&0xf)] << 12;
690 *tmpptr = 0;
691 t3= *++tmpptr;
692 if (t3 &0xffff)
693 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>16)&0xf)] << 16;
694 if (t3 &0xffff0000)
695 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>20)&0xf)] << 20;
696 *tmpptr = 0;
697 t3 = *++tmpptr;
698 if (t3 &0xffff)
699 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>24)&0xf)] << 24;
700 if (t3 &0xffff0000)
701 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>28)&0xf)] << 28;
702 *tmpptr = 0;
703 t3 = *++tmpptr;
704 cptr->cells.twostate.live1 = t2;
705 t1 = cptr->cells.twostate.olive2 = cptr->cells.twostate.live2;
706 t2 = 0;
707
708 if (t3 &0xffff)
709 t2 = lookup[(t3 & 0xffff)<<4 | (t1&0xf)];
710 if (t3 &0xffff0000)
711 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>4)&0xf)] << 4;
712 *tmpptr = 0;
713 t3 = *++tmpptr;
714 if (t3 &0xffff)
715 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>8)&0xf)] << 8;
716 if (t3 &0xffff0000)
717 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>12)&0xf)] << 12;
718 *tmpptr = 0;
719 t3 = *++tmpptr;
720 if (t3 &0xffff)
721 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>16)&0xf)] << 16;
722 if (t3 &0xffff0000)
723 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>20)&0xf)] << 20;
724 *tmpptr = 0;
725 t3 = *++tmpptr;
726 if (t3 &0xffff)
727 t2 |= lookup[(t3 & 0xffff)<<4 | ((t1>>24)&0xf)] << 24;
728 if (t3 &0xffff0000)
729 t2 |= lookup[(t3 & 0xffff0000)>>12 | ((t1>>28)&0xf)] << 28;
730 *tmpptr = 0;
731 cptr->cells.twostate.live2 = t2;
732
733 /*
734 * Box-aging and statistics gathering.
735 */
736 gather_statistics();
737 }
738 if (live_total == 0 || context->chgcount == 0)
739 state = STOP;
740 }
741
742 #define get_live12() {\
743 if (maxstates <= 4) {\
744 t1 = cptr->cells.gstate.live[0][0] | cptr->cells.gstate.live[0][1] << 2 | cptr->cells.gstate.live[1][0] << 4 | cptr->cells.gstate.live[1][1] << 6;\
745 t2 = cptr->cells.gstate.live[2][0] | cptr->cells.gstate.live[2][1] << 2 | cptr->cells.gstate.live[3][0] << 4 | cptr->cells.gstate.live[3][1] << 6;\
746 live1 = tab6[t1&0xffff] | tab6[t1 >> 16] << 2\
747 | tab6[t2&0xffff] << 16 | tab6[t2 >> 16] << 18;\
748 t1 = cptr->cells.gstate.live[4][0] | cptr->cells.gstate.live[4][1] << 2 | cptr->cells.gstate.live[5][0] << 4 | cptr->cells.gstate.live[5][1] << 6;\
749 t2 = cptr->cells.gstate.live[6][0] | cptr->cells.gstate.live[6][1] << 2 | cptr->cells.gstate.live[7][0] << 4 | cptr->cells.gstate.live[7][1] << 6;\
750 live2 = tab6[t1&0xffff] | tab6[t1 >> 16] << 2\
751 | tab6[t2&0xffff] << 16 | tab6[t2 >> 16] << 18;\
752 }\
753 else if (maxstates <= 16) {\
754 t1 = cptr->cells.gstate.live[0][0] | cptr->cells.gstate.live[0][1] << 4;\
755 t2 = cptr->cells.gstate.live[1][0] | cptr->cells.gstate.live[1][1] << 4;\
756 t3 = cptr->cells.gstate.live[2][0] | cptr->cells.gstate.live[2][1] << 4;\
757 live1 = cptr->cells.gstate.live[3][0] | cptr->cells.gstate.live[3][1] << 4;\
758 live1 = tab4[t1&0xffff] | tab4[t1 >> 16] << 2\
759 | tab4[t2&0xffff] << 8 | tab4[t2 >> 16] << 10\
760 | tab4[t3&0xffff] << 16 | tab4[t3 >> 16] << 18\
761 | tab4[live1&0xffff] << 24 | tab4[live1 >> 16] << 26;\
762 t1 = cptr->cells.gstate.live[4][0] | cptr->cells.gstate.live[4][1] << 4;\
763 t2 = cptr->cells.gstate.live[5][0] | cptr->cells.gstate.live[5][1] << 4;\
764 t3 = cptr->cells.gstate.live[6][0] | cptr->cells.gstate.live[6][1] << 4;\
765 live2 = cptr->cells.gstate.live[7][0] | cptr->cells.gstate.live[7][1] << 4;\
766 live2 = tab4[t1&0xffff] | tab4[t1 >> 16] << 2\
767 | tab4[t2&0xffff] << 8 | tab4[t2 >> 16] << 10\
768 | tab4[t3&0xffff] << 16 | tab4[t3 >> 16] << 18\
769 | tab4[live2&0xffff] << 24 | tab4[live2 >> 16] << 26;\
770 }\
771 else {\
772 live1 = tab4[cptr->cells.gstate.slive[0][0]]\
773 | tab4[cptr->cells.gstate.slive[0][1]] << 2\
774 | tab4[cptr->cells.gstate.slive[0][2]] << 4\
775 | tab4[cptr->cells.gstate.slive[0][3]] << 6\
776 | tab4[cptr->cells.gstate.slive[1][0]] << 8\
777 | tab4[cptr->cells.gstate.slive[1][1]] << 10\
778 | tab4[cptr->cells.gstate.slive[1][2]] << 12\
779 | tab4[cptr->cells.gstate.slive[1][3]] << 14\
780 | tab4[cptr->cells.gstate.slive[2][0]] << 16\
781 | tab4[cptr->cells.gstate.slive[2][1]] << 18\
782 | tab4[cptr->cells.gstate.slive[2][2]] << 20\
783 | tab4[cptr->cells.gstate.slive[2][3]] << 22\
784 | tab4[cptr->cells.gstate.slive[3][0]] << 24\
785 | tab4[cptr->cells.gstate.slive[3][1]] << 26\
786 | tab4[cptr->cells.gstate.slive[3][2]] << 28\
787 | tab4[cptr->cells.gstate.slive[3][3]] << 30;\
788 live2 = tab4[cptr->cells.gstate.slive[4][0]]\
789 | tab4[cptr->cells.gstate.slive[4][1]] << 2\
790 | tab4[cptr->cells.gstate.slive[4][2]] << 4\
791 | tab4[cptr->cells.gstate.slive[4][3]] << 6\
792 | tab4[cptr->cells.gstate.slive[5][0]] << 8\
793 | tab4[cptr->cells.gstate.slive[5][1]] << 10\
794 | tab4[cptr->cells.gstate.slive[5][2]] << 12\
795 | tab4[cptr->cells.gstate.slive[5][3]] << 14\
796 | tab4[cptr->cells.gstate.slive[6][0]] << 16\
797 | tab4[cptr->cells.gstate.slive[6][1]] << 18\
798 | tab4[cptr->cells.gstate.slive[6][2]] << 20\
799 | tab4[cptr->cells.gstate.slive[6][3]] << 22\
800 | tab4[cptr->cells.gstate.slive[7][0]] << 24\
801 | tab4[cptr->cells.gstate.slive[7][1]] << 26\
802 | tab4[cptr->cells.gstate.slive[7][2]] << 28\
803 | tab4[cptr->cells.gstate.slive[7][3]] << 30;\
804 }\
805 }
806
evolve3(pattern * context)807 static void evolve3(pattern *context) {
808 register u32bits t1, t2, t3, live1, live2;
809 u32bits *tmpptr, live_total = 0;
810 register tile *cptr;
811 tile *cptrup, *cptrdn, *cptrlf, *cptrrt;
812 union {
813 u32bits olive[BOXSIZE][2];
814 cell_t ocell[BOXSIZE][BOXSIZE];
815 } ocell;
816
817 for (cptr = context->tiles; cptr; cptr = cptr->next) {
818 if (cptr->dead) continue;
819 get_live12();
820 if ((live1 | live2) == 0) continue;
821 adjucency_links(gstate, live1, live2); /* macro */
822 }
823 /*
824 * Perform actual evolution.
825 */
826 fix_plain(cptrup);
827 for (cptr = context->tiles; cptr; cptr = cptr->next) {
828 memcpy(ocell.ocell, cptr->cells.gstate.cell, 64);
829 tmpptr = cptr->cells.gstate.on;
830 live2 = live1 = 0;
831 for (t1 = 0; t1 < BOXSIZE; t1++) {
832 t3 = *tmpptr;
833 if (maxstates <= 4) {
834 live1 |= cptr->cells.gstate.live[t1][0] = t2 =
835 lookup4[(t3 << 8 & 0xffff00) | (cptr->cells.gstate.cell[t1][3] << 6)
836 | (cptr->cells.gstate.cell[t1][2] << 4) | (cptr->cells.gstate.cell[t1][1] << 2)
837 | cptr->cells.gstate.cell[t1][0]];
838 live1 |= cptr->cells.gstate.live[t1][1] = t3 =
839 lookup4[(t3 >> 8 & 0xffff00) | (cptr->cells.gstate.cell[t1][7] << 6)
840 | (cptr->cells.gstate.cell[t1][6] << 4) | (cptr->cells.gstate.cell[t1][5] << 2)
841 | cptr->cells.gstate.cell[t1][4]];
842 }
843 else if (maxstates <= 16) {
844 live1 |= cptr->cells.gstate.live[t1][0] = t2 =
845 lookup2[((t3 & 0xff) << 8) | (cptr->cells.gstate.cell[t1][1] << 4)
846 | cptr->cells.gstate.cell[t1][0]]
847 | lookup2[(t3 & 0xff00) | (cptr->cells.gstate.cell[t1][3] << 4)
848 | cptr->cells.gstate.cell[t1][2]] << 16;
849 live1 |= cptr->cells.gstate.live[t1][1] = t3 =
850 lookup2[((t3 & 0xff0000) >> 8) | (cptr->cells.gstate.cell[t1][5] << 4)
851 | cptr->cells.gstate.cell[t1][4]]
852 | lookup2[((t3 & 0xff000000) >> 16) | (cptr->cells.gstate.cell[t1][7] << 4)
853 | cptr->cells.gstate.cell[t1][6]] << 16;
854 }
855 else {
856 live1 |= cptr->cells.gstate.live[t1][0] = t2 =
857 lookup[((t3 & 0xf) << 8) | cptr->cells.gstate.cell[t1][0]]
858 | lookup[((t3 & 0xf0) << 4) | cptr->cells.gstate.cell[t1][1]] << 8
859 | lookup[(t3 & 0xf00) | cptr->cells.gstate.cell[t1][2]] << 16
860 | lookup[((t3 & 0xf000) >> 4) | cptr->cells.gstate.cell[t1][3]] << 24;
861 live1 |= cptr->cells.gstate.live[t1][1] = t3 =
862 lookup[((t3 & 0xf0000) >> 8) | cptr->cells.gstate.cell[t1][4]]
863 | lookup[((t3 & 0xf00000) >> 12) | cptr->cells.gstate.cell[t1][5]] << 8
864 | lookup[((t3 & 0xf000000) >> 16) | cptr->cells.gstate.cell[t1][6]] << 16
865 | lookup[((t3 & 0xf0000000) >> 20) | cptr->cells.gstate.cell[t1][7]] << 24;
866 }
867 live2 = live2 || t2 != ocell.olive[t1][0] || t3 != ocell.olive[t1][1];
868 *tmpptr++ = 0;
869 }
870 /*
871 * Box-aging and statistics gathering.
872 */
873 if (live2) {
874 if (truehistory && context == &active) add2history(cptr);
875 if (dispchanges) {
876 for (t1 = 0; t1 < BOXSIZE; t1++)
877 for (t2 = 0; t2 < BOXSIZE; t2++)
878 if (ocell.ocell[t2][t1] != cptr->cells.gstate.cell[t2][t1])
879 context->chgcount++;
880 }
881 else
882 context->chgcount++;
883 }
884 if (live1) {
885 cptr->dead = 0;
886 if (oscillators) osc_values(context, cptr);
887 live_total++;
888 if (dispboxes)
889 for (t1 = 0; t1 < BOXSIZE; t1++)
890 for (t2 = 0; t2 < BOXSIZE; t2++)
891 if (t3 = cptr->cells.gstate.cell[t2][t1])
892 context->cellcount[t3]++;
893 }
894 else
895 cptr->dead++;
896 }
897 if (live_total == 0 || context->chgcount == 0)
898 state = STOP;
899 }
900
901 static u8bits tr1[7][7] = {
902 {1, 0, 1, 255, 255, 255, 255}, {1, 2, 1, 255, 255, 255, 255}, {255, 2, 1, 255, 255, 255, 255},
903 {3, 4, 255, 4, 3, 255, 255}, {255, 4, 3, 4, 3, 255, 255}, {5, 4, 255, 255, 5, 4, 255},
904 {6, 6, 6, 6, 6, 6, 6}},
905 tr2[7][7] = {
906 {255, 1, 0, 255, 255, 255, 255}, {2, 1, 255, 255, 255, 255, 255}, {255, 1, 2, 255, 255, 255, 255},
907 {4, 3, 255, 255, 255, 255, 255}, {255, 3, 4, 255, 255, 255, 255}, {4, 5, 255, 255, 255, 255, 255},
908 {6, 6, 6, 6, 6, 6, 6}};
909
evolve3b0(pattern * context)910 static void evolve3b0(pattern *context) {
911 register u32bits t1, t2, t3, live1, live2;
912 u32bits *tmpptr, live_total = 0;
913 register tile *cptr;
914 tile *cptrup, *cptrdn, *cptrlf, *cptrrt;
915 union {
916 u32bits olive[BOXSIZE][2];
917 cell_t ocell[BOXSIZE][BOXSIZE];
918 } ocell;
919
920 cptr = context->tiles;
921 if (context->cellmass) {
922 int live8st = !!(live & 0x100);
923 tile *cptrul, *cptrur, *cptrdl, *cptrdr;
924
925 for (; cptr; cptr = cptr->next) {
926 get_live12();
927 if ((live1 | live2) == 0) continue;
928 maketile(context, cptr->x, cptr->y - BOXSIZE);
929 maketile(context, cptr->x, cptr->y + BOXSIZE);
930 maketile(context, cptr->x - BOXSIZE, cptr->y);
931 maketile(context, cptr->x - BOXSIZE, cptr->y - BOXSIZE);
932 maketile(context, cptr->x - BOXSIZE, cptr->y + BOXSIZE);
933 maketile(context, cptr->x + BOXSIZE, cptr->y);
934 maketile(context, cptr->x + BOXSIZE, cptr->y - BOXSIZE);
935 maketile(context, cptr->x + BOXSIZE, cptr->y + BOXSIZE);
936 }
937 for (cptr = context->tiles; cptr; cptr = cptr->next) {
938 memcpy(ocell.ocell, cptr->cells.gstate.cell, 64);
939 for (t1 = 0; t1 < BOXSIZE; t1++)
940 for (t2 = 0; t2 < 2; t2++)
941 cptr->cells.gstate.live[t1][t2] = cptr->cells.gstate.live[t1][t2]&0x1010101 ^ 0x1010101;
942 get_live12();
943 for (t1 = 0; t1 < BOXSIZE; t1++)
944 for (t2 = 0; t2 < 2; t2++)
945 cptr->cells.gstate.live[t1][t2] += ocell.olive[t1][t2] << 4;
946 cptrup = fetchtile(context, cptr->x, cptr->y - BOXSIZE);
947 cptrdn = fetchtile(context, cptr->x, cptr->y + BOXSIZE);
948 cptrlf = fetchtile(context, cptr->x - BOXSIZE, cptr->y);
949 cptrrt = fetchtile(context, cptr->x + BOXSIZE, cptr->y);
950 cptrul = fetchtile(context, cptr->x - BOXSIZE, cptr->y - BOXSIZE);
951 cptrur = fetchtile(context, cptr->x + BOXSIZE, cptr->y - BOXSIZE);
952 cptrdl = fetchtile(context, cptr->x - BOXSIZE, cptr->y + BOXSIZE);
953 cptrdr = fetchtile(context, cptr->x + BOXSIZE, cptr->y + BOXSIZE);
954 if (!cptrup) cptr->cells.gstate.on[0] += 0x23333332;
955 if (!cptrdn) cptr->cells.gstate.on[7] += 0x23333332;
956 if (!cptrlf) {
957 cptr->cells.gstate.on[0] += 2;
958 cptr->cells.gstate.on[1] += 3;
959 cptr->cells.gstate.on[2] += 3;
960 cptr->cells.gstate.on[3] += 3;
961 cptr->cells.gstate.on[4] += 3;
962 cptr->cells.gstate.on[5] += 3;
963 cptr->cells.gstate.on[6] += 3;
964 cptr->cells.gstate.on[7] += 2;
965 }
966 if (!cptrrt) {
967 cptr->cells.gstate.on[0] += 0x20000000;
968 cptr->cells.gstate.on[1] += 0x30000000;
969 cptr->cells.gstate.on[2] += 0x30000000;
970 cptr->cells.gstate.on[3] += 0x30000000;
971 cptr->cells.gstate.on[4] += 0x30000000;
972 cptr->cells.gstate.on[5] += 0x30000000;
973 cptr->cells.gstate.on[6] += 0x30000000;
974 cptr->cells.gstate.on[7] += 0x20000000;
975 }
976 if (!cptrul) cptr->cells.gstate.on[0] += 1;
977 if (!cptrur) cptr->cells.gstate.on[0] += 0x10000000;
978 if (!cptrdl) cptr->cells.gstate.on[7] += 1;
979 if (!cptrdr) cptr->cells.gstate.on[7] += 0x10000000;
980 if ((live1 | live2) == 0)
981 continue;
982
983 t1 = live1 &0xff;
984 if (t1) {
985 t2 = tab1[t1];
986 if (cptrup) cptrup->cells.gstate.on[7] += t2;
987 cptr->cells.gstate.on[1] += t2;
988 cptr->cells.gstate.on[0] += tab2[t1];
989 }
990
991 t1 = (live2 & 0xff000000) >> 24;
992 if (t1) {
993 t2 = tab1[t1];
994 if (cptrdn) cptrdn->cells.gstate.on[0] += t2;
995 cptr->cells.gstate.on[6] += t2;
996 cptr->cells.gstate.on[7] += tab2[t1];
997 }
998
999 t1 = live1;
1000 t2 = live2;
1001 if (t1&0x1010101 && cptrlf) {
1002 if (t1 & 0x1) {
1003 cptrlf->cells.gstate.on[0] += 0x10000000;
1004 cptrlf->cells.gstate.on[1] += 0x10000000;
1005 }
1006 if (t1 & 0x100) {
1007 cptrlf->cells.gstate.on[0] += 0x10000000;
1008 cptrlf->cells.gstate.on[1] += 0x10000000;
1009 cptrlf->cells.gstate.on[2] += 0x10000000;
1010 }
1011 if (t1 & 0x10000) {
1012 cptrlf->cells.gstate.on[1] += 0x10000000;
1013 cptrlf->cells.gstate.on[2] += 0x10000000;
1014 cptrlf->cells.gstate.on[3] += 0x10000000;
1015 }
1016 if (t1 & 0x1000000) {
1017 cptrlf->cells.gstate.on[2] += 0x10000000;
1018 cptrlf->cells.gstate.on[3] += 0x10000000;
1019 cptrlf->cells.gstate.on[4] += 0x10000000;
1020 }
1021 }
1022 if (t1&0x1 && cptrul) cptrul->cells.gstate.on[7] += 0x10000000;
1023
1024 if (t2&0x1010101 && cptrlf) {
1025 if (t2 & 0x1) {
1026 cptrlf->cells.gstate.on[3] += 0x10000000;
1027 cptrlf->cells.gstate.on[4] += 0x10000000;
1028 cptrlf->cells.gstate.on[5] += 0x10000000;
1029 }
1030 if (t2 & 0x100) {
1031 cptrlf->cells.gstate.on[4] += 0x10000000;
1032 cptrlf->cells.gstate.on[5] += 0x10000000;
1033 cptrlf->cells.gstate.on[6] += 0x10000000;
1034 }
1035 if (t2 & 0x10000) {
1036 cptrlf->cells.gstate.on[5] += 0x10000000;
1037 cptrlf->cells.gstate.on[6] += 0x10000000;
1038 cptrlf->cells.gstate.on[7] += 0x10000000;
1039 }
1040 if (t2 & 0x1000000) {
1041 cptrlf->cells.gstate.on[6] += 0x10000000;
1042 cptrlf->cells.gstate.on[7] += 0x10000000;
1043 }
1044 }
1045 if (t2&0x1000000 && cptrdl) cptrdl->cells.gstate.on[0] += 0x10000000;
1046
1047 if (t1&0x80808080 && cptrrt) {
1048 if (t1 & 0x80) {
1049 cptrrt->cells.gstate.on[0] += 0x1;
1050 cptrrt->cells.gstate.on[1] += 0x1;
1051 }
1052 if (t1 & 0x8000) {
1053 cptrrt->cells.gstate.on[0] += 0x1;
1054 cptrrt->cells.gstate.on[1] += 0x1;
1055 cptrrt->cells.gstate.on[2] += 0x1;
1056 }
1057 if (t1 & 0x800000) {
1058 cptrrt->cells.gstate.on[1] += 0x1;
1059 cptrrt->cells.gstate.on[2] += 0x1;
1060 cptrrt->cells.gstate.on[3] += 0x1;
1061 }
1062 if (t1 & 0x80000000) {
1063 cptrrt->cells.gstate.on[2] += 0x1;
1064 cptrrt->cells.gstate.on[3] += 0x1;
1065 cptrrt->cells.gstate.on[4] += 0x1;
1066 }
1067 }
1068 if (t1&0x80 && cptrur) cptrur->cells.gstate.on[7] += 0x1;
1069
1070 if (t2&0x80808080 && cptrrt) {
1071 if (t2 & 0x80) {
1072 cptrrt->cells.gstate.on[3] += 0x1;
1073 cptrrt->cells.gstate.on[4] += 0x1;
1074 cptrrt->cells.gstate.on[5] += 0x1;
1075 }
1076 if (t2 & 0x8000) {
1077 cptrrt->cells.gstate.on[4] += 0x1;
1078 cptrrt->cells.gstate.on[5] += 0x1;
1079 cptrrt->cells.gstate.on[6] += 0x1;
1080 }
1081 if (t2 & 0x800000) {
1082 cptrrt->cells.gstate.on[5] += 0x1;
1083 cptrrt->cells.gstate.on[6] += 0x1;
1084 cptrrt->cells.gstate.on[7] += 0x1;
1085 }
1086 if (t2 & 0x80000000) {
1087 cptrrt->cells.gstate.on[6] += 0x1;
1088 cptrrt->cells.gstate.on[7] += 0x1;
1089 }
1090 }
1091 if (t2&0x80000000 && cptrdr) cptrdr->cells.gstate.on[0] += 0x1;
1092
1093 t1 = (live1 & 0xff00) >> 8;
1094 t2 = (live1 & 0xff0000) >> 16;
1095 if (t1) {
1096 t3 = tab1[t1];
1097 cptr->cells.gstate.on[1] += tab2[t1];
1098 cptr->cells.gstate.on[0] += t3;
1099 cptr->cells.gstate.on[2] += t3;
1100 }
1101
1102 t1 = (live1 & 0xff000000) >> 24;
1103 if (t2) {
1104 t3 = tab1[t2];
1105 cptr->cells.gstate.on[2] += tab2[t2];
1106 cptr->cells.gstate.on[1] += t3;
1107 cptr->cells.gstate.on[3] += t3;
1108 }
1109
1110 t2 = (live2 & 0xff);
1111 if (t1) {
1112 t3 = tab1[t1];
1113 cptr->cells.gstate.on[3] += tab2[t1];
1114 cptr->cells.gstate.on[2] += t3;
1115 cptr->cells.gstate.on[4] += t3;
1116 }
1117
1118 t1 = (live2 & 0xff00) >> 8;
1119 if (t2) {
1120 t3 = tab1[t2];
1121 cptr->cells.gstate.on[4] += tab2[t2];
1122 cptr->cells.gstate.on[3] += t3;
1123 cptr->cells.gstate.on[5] += t3;
1124 }
1125
1126 t2 = (live2 & 0xff0000) >> 16;
1127 if (t1) {
1128 t3 = tab1[t1];
1129 cptr->cells.gstate.on[5] += tab2[t1];
1130 cptr->cells.gstate.on[4] += t3;
1131 cptr->cells.gstate.on[6] += t3;
1132 }
1133 if (t2) {
1134 t3 = tab1[t2];
1135 cptr->cells.gstate.on[6] += tab2[t2];
1136 cptr->cells.gstate.on[5] += t3;
1137 cptr->cells.gstate.on[7] += t3;
1138 }
1139 cptr->up = cptrup;
1140 cptr->dn = cptrdn;
1141 cptr->lf = cptrlf;
1142 cptr->rt = cptrrt;
1143 }
1144 /*
1145 * Perform actual evolution.
1146 */
1147 fix_plain(cptrup);
1148 context->cellmass = live8st;
1149 for (cptr = context->tiles; cptr; cptr = cptr->next) {
1150 for (t1 = 0; t1 < BOXSIZE; t1++)
1151 for (t2 = 0; t2 < 2; t2++) {
1152 ocell.olive[t1][t2] = cptr->cells.gstate.live[t1][t2] >> 4 & 0xf0f0f0f;
1153 cptr->cells.gstate.live[t1][t2] &= 0xf0f0f0f;
1154 }
1155 tmpptr = cptr->cells.gstate.on;
1156 for (t1 = 0; t1 < BOXSIZE; t1++) {
1157 t3 = *tmpptr;
1158 cptr->cells.gstate.live[t1][0] =
1159 lookup2[((t3 & 0xff) << 8) | (cptr->cells.gstate.cell[t1][1] << 4)
1160 | cptr->cells.gstate.cell[t1][0]]
1161 | lookup2[(t3 & 0xff00) | (cptr->cells.gstate.cell[t1][3] << 4)
1162 | cptr->cells.gstate.cell[t1][2]] << 16;
1163 cptr->cells.gstate.live[t1][1] =
1164 lookup2[((t3 & 0xff0000) >> 8) | (cptr->cells.gstate.cell[t1][5] << 4)
1165 | cptr->cells.gstate.cell[t1][4]]
1166 | lookup2[((t3 & 0xff000000) >> 16) | (cptr->cells.gstate.cell[t1][7] << 4)
1167 | cptr->cells.gstate.cell[t1][6]] << 16;
1168 *tmpptr++ = 0;
1169 }
1170 if (live8st)
1171 for (t1 = 0; t1 < BOXSIZE; t1++)
1172 for (t2 = 0; t2 < BOXSIZE; t2++)
1173 cptr->cells.gstate.cell[t1][t2]
1174 = tr1[ocell.ocell[t1][t2]][cptr->cells.gstate.cell[t1][t2]];
1175 else
1176 for (t1 = 0; t1 < BOXSIZE; t1++)
1177 for (t2 = 0; t2 < BOXSIZE; t2++)
1178 cptr->cells.gstate.cell[t1][t2]
1179 = tr2[ocell.ocell[t1][t2]][cptr->cells.gstate.cell[t1][t2]];
1180 live2 = live1 = 0;
1181 for (t1 = 0; t1 < BOXSIZE; t1++)
1182 for (t2 = 0; t2 < 2; t2++) {
1183 live1 = live1 || cptr->cells.gstate.live[t1][t2];
1184 live2 = live2 || cptr->cells.gstate.live[t1][t2] != ocell.olive[t1][t2];
1185 }
1186 /*
1187 * Box-aging and statistics gathering.
1188 */
1189 if (live2)
1190 if (dispchanges) {
1191 for (t1 = 0; t1 < BOXSIZE; t1++)
1192 for (t2 = 0; t2 < BOXSIZE; t2++)
1193 if (ocell.ocell[t2][t1] != cptr->cells.gstate.cell[t2][t1])
1194 context->chgcount++;
1195 }
1196 else
1197 context->chgcount++;
1198 if (live1) {
1199 if (oscillators) osc_values(context, cptr);
1200 cptr->dead = 0;
1201 live_total++;
1202 if (dispboxes)
1203 for (t1 = 0; t1 < BOXSIZE; t1++)
1204 for (t2 = 0; t2 < BOXSIZE; t2++)
1205 if (t3 = cptr->cells.gstate.cell[t2][t1])
1206 context->cellcount[t3]++;
1207 }
1208 else
1209 cptr->dead++;
1210 }
1211 }
1212 else {
1213 for (; cptr; cptr = cptr->next) {
1214 t1 = cptr->cells.gstate.live[0][0] | cptr->cells.gstate.live[0][1] << 4;
1215 t2 = cptr->cells.gstate.live[1][0] | cptr->cells.gstate.live[1][1] << 4;
1216 t3 = cptr->cells.gstate.live[2][0] | cptr->cells.gstate.live[2][1] << 4;
1217 live1 = cptr->cells.gstate.live[3][0] | cptr->cells.gstate.live[3][1] << 4;
1218 live1 = tab4[t1&0xffff] | tab4[t1 >> 16] << 2
1219 | tab4[t2&0xffff] << 8 | tab4[t2 >> 16] << 10
1220 | tab4[t3&0xffff] << 16 | tab4[t3 >> 16] << 18
1221 | tab4[live1&0xffff] << 24 | tab4[live1 >> 16] << 26;
1222 t1 = cptr->cells.gstate.live[4][0] | cptr->cells.gstate.live[4][1] << 4;
1223 t2 = cptr->cells.gstate.live[5][0] | cptr->cells.gstate.live[5][1] << 4;
1224 t3 = cptr->cells.gstate.live[6][0] | cptr->cells.gstate.live[6][1] << 4;
1225 live2 = cptr->cells.gstate.live[7][0] | cptr->cells.gstate.live[7][1] << 4;
1226 live2 = tab4[t1&0xffff] | tab4[t1 >> 16] << 2
1227 | tab4[t2&0xffff] << 8 | tab4[t2 >> 16] << 10
1228 | tab4[t3&0xffff] << 16 | tab4[t3 >> 16] << 18
1229 | tab4[live2&0xffff] << 24 | tab4[live2 >> 16] << 26;
1230 if ((live1 | live2) == 0)
1231 continue;
1232 adjucency_links(gstate, live1, live2); /* macro */
1233 }
1234
1235 /*
1236 * Perform actual evolution.
1237 */
1238 fix_plain(cptrup);
1239 context->cellmass = 1;
1240 for (cptr = context->tiles; cptr; cptr = cptr->next) {
1241 memcpy(ocell.ocell, cptr->cells.gstate.cell, 64);
1242 tmpptr = cptr->cells.gstate.on;
1243 for (t1 = 0; t1 < BOXSIZE; t1++) {
1244 t3 = *tmpptr;
1245 cptr->cells.gstate.live[t1][0] =
1246 lookup2[((t3 & 0xff) << 8) | (cptr->cells.gstate.cell[t1][1] << 4)
1247 | cptr->cells.gstate.cell[t1][0]]
1248 | lookup2[(t3 & 0xff00) | (cptr->cells.gstate.cell[t1][3] << 4)
1249 | cptr->cells.gstate.cell[t1][2]] << 16;
1250 cptr->cells.gstate.live[t1][1] =
1251 lookup2[((t3 & 0xff0000) >> 8) | (cptr->cells.gstate.cell[t1][5] << 4)
1252 | cptr->cells.gstate.cell[t1][4]]
1253 | lookup2[((t3 & 0xff000000) >> 16) | (cptr->cells.gstate.cell[t1][7] << 4)
1254 | cptr->cells.gstate.cell[t1][6]] << 16;
1255 *tmpptr++ = 0;
1256 }
1257 for (t1 = 0; t1 < BOXSIZE; t1++)
1258 for (t2 = 0; t2 < BOXSIZE; t2++)
1259 cptr->cells.gstate.cell[t1][t2]
1260 = tr1[ocell.ocell[t1][t2]][cptr->cells.gstate.cell[t1][t2]];
1261 live2 = live1 = 0;
1262 for (t1 = 0; t1 < BOXSIZE; t1++)
1263 for (t2 = 0; t2 < 2; t2++) {
1264 live1 = live1 || cptr->cells.gstate.live[t1][t2];
1265 live2 = live2 || cptr->cells.gstate.live[t1][t2] != ocell.olive[t1][t2];
1266 }
1267 /*
1268 * Box-aging and statistics gathering.
1269 */
1270 if (live2)
1271 if (dispchanges) {
1272 for (t1 = 0; t1 < BOXSIZE; t1++)
1273 for (t2 = 0; t2 < BOXSIZE; t2++)
1274 if (ocell.ocell[t2][t1] != cptr->cells.gstate.cell[t2][t1])
1275 context->chgcount++;
1276 }
1277 else
1278 context->chgcount++;
1279 if (live1) {
1280 cptr->dead = 0;
1281 if (oscillators) osc_values(context, cptr);
1282 live_total++;
1283 if (dispboxes)
1284 for (t1 = 0; t1 < BOXSIZE; t1++)
1285 for (t2 = 0; t2 < BOXSIZE; t2++)
1286 if (t3 = cptr->cells.gstate.cell[t2][t1])
1287 context->cellcount[t3]++;
1288 }
1289 else
1290 cptr->dead++;
1291 }
1292 }
1293 if (live_total == 0 || context->chgcount == 0)
1294 state = STOP;
1295 }
1296
setinipattern()1297 static void setinipattern() {
1298 tile *ptr;
1299 int dx, dy;
1300
1301 FOR_CELLS(&active, ptr, dx, dy)
1302 if (getcell(&ptr->cells, dx, dy) == 1)
1303 setcell(&ptr->cells, dx, dy, 5);
1304 }
1305
file_rules(char * ptr)1306 int file_rules(char* ptr) { /* get and accept 2-state/generated/named/pd rules from file's #T line */
1307 char *optr = ptr, *p, b[10], s[10];
1308 int hm = historymode;
1309 unsigned long cc;
1310 historymode = 0;
1311 if (palettemod) DefaultPalette();
1312 palettemod = 0;
1313 if (!strcasecmp(ptr, "wireworld")) {
1314 set_active_rules(ptr, 1);
1315 born = 6;
1316 alloc_states(GEN_DRIVEN, 4);
1317 gentab3();
1318 genatab4();
1319 }
1320 else if (!strcmp(ptr, "lifehistory") || !strcasecmp(ptr, "life+")) {
1321 born = 8;
1322 live = 12;
1323 goto l3;
1324 }
1325 else if (!strncasecmp(ptr, "brian", 5)) {
1326 born = 4;
1327 live = 0;
1328 alloc_states(GEN_DRIVEN, 3);
1329 goto l2;
1330 }
1331 else if (!strcasecmp(ptr, "life")) {
1332 born = 8;
1333 live = 12;
1334 goto l1;
1335 }
1336 else if (strchr(ptr, '$')) {
1337 set_active_rules(ptr, 1);
1338 if (sscanf(ptr, "%f$%f", &payoffs[DEFECT][COOPERATE],
1339 &payoffs[COOPERATE][DEFECT]) != 2) return 1;
1340 alloc_states(PAYOFF_DRIVEN, 5); /* must alloc 5 states to get pseudocolors */
1341 sprintf(active_rules, "%.2f$%.2f",
1342 payoffs[DEFECT][COOPERATE], payoffs[COOPERATE][DEFECT]);
1343 set_active_rules(active_rules, 1);
1344 }
1345 else if (sscanf(ptr, " %*[sS]%[0-9] %*[bB]%[0-9] ", s, b) == 2
1346 || sscanf(ptr, " %*[sS]%[0-9] / %*[bB]%[0-9] ", s, b) == 2
1347 || sscanf(ptr, " %*[bB]%[0-9] / %*[sS]%[0-9] ", b, s) == 2
1348 || sscanf(ptr, " %*[bB]%[0-9] %*[sS]%[0-9] ", b, s) == 2) {
1349 p = s;
1350 born = live = 0;
1351 while (*p >= '0' && *p <= '9')
1352 live |= 1 << *p++ - '0';
1353 p = b;
1354 while (*p >= '0' && *p <= '9')
1355 born |= 1 << *p++ - '0';
1356 sprintf(ptr, "B%s/S%s", b, s);
1357 goto l1;
1358 }
1359 else if (strchr(ptr, '/')) {
1360 born = live = 0;
1361 while (*ptr >= '0' && *ptr <= '9')
1362 live |= 1 << *ptr++ - '0';
1363 if (*ptr == '/') {
1364 ptr++;
1365 while (*ptr >= '0' && *ptr <= '9')
1366 born |= 1 << *ptr++ - '0';
1367 }
1368 if (optr == ptr) return 1;
1369 if (*ptr == '/') {
1370 unsigned agelimit;
1371 if (sscanf(++ptr, "%u", &agelimit) != 1 || agelimit > MAXSTATES
1372 || agelimit < 3 || agelimit > 256)
1373 return 1;
1374 if (born & 1) return 1; /* B0 is not supported */
1375 set_active_rules(optr, 1);
1376 alloc_states(GEN_DRIVEN, agelimit);
1377 if (born == 4 && live == 0 && maxstates == 3)
1378 l2: set_active_rules("brian's brain", 1);
1379 gentab2();
1380 genatab4();
1381 }
1382 else if (*ptr == '+') {
1383 l3:
1384 cc = active.generations;
1385 alloc_states(GEN_DRIVEN, 7);
1386 active.generations = cc;
1387 if (born == 8 && live == 12)
1388 set_active_rules("life+", 1);
1389 else
1390 set_active_rules(optr, 1);
1391 historymode = 1;
1392 setinipattern();
1393 gentab4();
1394 genatab5();
1395 HistoryPalette();
1396 palettemod = 1;
1397 }
1398 else {
1399 l1:
1400 if (hm) cc = active.generations;
1401 alloc_states(VALENCE_DRIVEN, 2);
1402 if (hm) active.generations = cc;
1403 if (born == 8 && live == 12)
1404 set_active_rules("life", 1);
1405 else if (born == 4 && live == 0)
1406 set_active_rules("seeds", 1);
1407 else
1408 set_active_rules(optr, 1);
1409 if (active.cellmass) active.cellmass = born&1;
1410 gentab();
1411 }
1412 }
1413 else
1414 return 10;
1415 showrules();
1416 set_paintcolor();
1417 return *pathtorules = 0;
1418 }
1419
newrules(void)1420 void newrules(void) {
1421 /* prompt for and accept 2-state, 3-component, or named rules */
1422 int i, k;
1423 char *ptr = inpbuf, *p, ptrbuf[RULESNAMELEN];
1424 strcpy(ptr, "Rules: ");
1425 ptr = ptr + 7;
1426 if (ev_mode == VALENCE_DRIVEN) {
1427 k = live;
1428 for (i = 0; i < 9; i++) {
1429 if (k&1)
1430 *ptr++ = i + '0';
1431 k >>= 1;
1432 }
1433 *ptr++ = '/';
1434 k = born;
1435 for (i = 0; i < 9; i++) {
1436 if (k&1)
1437 *ptr++ = i + '0';
1438 k >>= 1;
1439 }
1440 }
1441 else {
1442 strcpy(ptr, active_rules);
1443 ptr += strlen(ptr);
1444 }
1445 strcpy(ptr, " New Rules: ");
1446 minbuflen = strlen(inpbuf);
1447 DoExpose(inputw);
1448 getxstring();
1449 if (*strcpy(ptrbuf, inpbuf + minbuflen) == 0)
1450 return;
1451 if (p = strrchr(ptrbuf, ':')) *p = 0;
1452 if (file_rules(ptrbuf)) {
1453 sprintf(inpbuf, "Can't set rules %s", ptrbuf);
1454 announce_and_wait(RED_EVER);
1455 if (*pathtorules)
1456 use_rules(pathtorules, 0);
1457 else
1458 file_rules(active_rules);
1459 }
1460 else if (p)
1461 if (set_topology(p + 1) > 0) {
1462 sprintf(inpbuf, "Can't set topology %s", p + 1);
1463 announce_and_wait(RED_EVER);
1464 }
1465 else
1466 {
1467 center();
1468 if (bounding_box(&active))
1469 make_tentative(active.xmin, active.ymin, active.xmax, active.ymax);
1470 redraw_lifew();
1471 }
1472 }
1473
1474
1475 /* now the n-state case... */
1476 /*
1477 * These macros unroll a bunch of loops inside the tile-evolution function.
1478 * They aren't parametrized for BOXSIZE, but have the double benefit of
1479 * eliminating loop overhead and allowing the optimizer to fold constant
1480 * array references. On a machine with character-addressable memory the
1481 * results ought to run like a banshee.
1482 */
1483 /* first, macros to test whether a tile edge is changed */
1484 #define V_CHNG(h) (cptr->cells.pstate.ocell[h][1] != cptr->cells.pstate.cell[h][1] \
1485 | cptr->cells.pstate.ocell[h][2] != cptr->cells.pstate.cell[h][2] \
1486 | cptr->cells.pstate.ocell[h][3] != cptr->cells.pstate.cell[h][3] \
1487 | cptr->cells.pstate.ocell[h][4] != cptr->cells.pstate.cell[h][4] \
1488 | cptr->cells.pstate.ocell[h][5] != cptr->cells.pstate.cell[h][5] \
1489 | cptr->cells.pstate.ocell[h][6] != cptr->cells.pstate.cell[h][6])
1490 /*#define V_CHNG(h) (memcmp(cptr->cells.pstate.ocell[h]+1, cptr->cells.pstate.cell[h]+1, 6))*/
1491 #define H_CHNG(r) (cptr->cells.pstate.ocell[1][r] != cptr->cells.pstate.cell[1][r] \
1492 | cptr->cells.pstate.ocell[2][r] != cptr->cells.pstate.cell[2][r] \
1493 | cptr->cells.pstate.ocell[3][r] != cptr->cells.pstate.cell[3][r] \
1494 | cptr->cells.pstate.ocell[4][r] != cptr->cells.pstate.cell[4][r] \
1495 | cptr->cells.pstate.ocell[5][r] != cptr->cells.pstate.cell[5][r] \
1496 | cptr->cells.pstate.ocell[6][r] != cptr->cells.pstate.cell[6][r])
1497 #define X_CHNG(r,h) (cptr->cells.pstate.ocell[r][h] != cptr->cells.pstate.cell[r][h])
1498
1499 /*
1500 * Offsets of current tile in hold area. The idea here is that we need to copy
1501 * enough of the surrounding tiles into the hold area to do all resolution.
1502 * For table-driven functions one edge row suffices; for payoff-driven
1503 * functions, two edge rows/columns are needed (because we need to compute the
1504 * payoffs of the inner edge cells).
1505 */
1506 #define HX 2
1507 #define HY 2
1508
1509 /* macros to grab a row or column out of a tile and put it in the hold area */
1510 #define GET_COL(tcell, tr, fcell, fr) { \
1511 tcell[HY+0][tr] = fcell[0][fr]; \
1512 tcell[HY+1][tr] = fcell[1][fr]; \
1513 tcell[HY+2][tr] = fcell[2][fr]; \
1514 tcell[HY+3][tr] = fcell[3][fr]; \
1515 tcell[HY+4][tr] = fcell[4][fr]; \
1516 tcell[HY+5][tr] = fcell[5][fr]; \
1517 tcell[HY+6][tr] = fcell[6][fr]; \
1518 tcell[HY+7][tr] = fcell[7][fr]; \
1519 }
1520 #define GET_ROW(tcell, tc, fcell, fr) { \
1521 tcell[tc][HX+0] = fcell[fr][0]; \
1522 tcell[tc][HX+1] = fcell[fr][1]; \
1523 tcell[tc][HX+2] = fcell[fr][2]; \
1524 tcell[tc][HX+3] = fcell[fr][3]; \
1525 tcell[tc][HX+4] = fcell[fr][4]; \
1526 tcell[tc][HX+5] = fcell[fr][5]; \
1527 tcell[tc][HX+6] = fcell[fr][6]; \
1528 tcell[tc][HX+7] = fcell[fr][7]; \
1529 }
1530
1531 /* fill the hold area from a tile */
1532 #define GET_INTERIOR(to, from) { \
1533 GET_COL(to, HX+0, from, 0); \
1534 GET_COL(to, HX+1, from, 1); \
1535 GET_COL(to, HX+2, from, 2); \
1536 GET_COL(to, HX+3, from, 3); \
1537 GET_COL(to, HX+4, from, 4); \
1538 GET_COL(to, HX+5, from, 5); \
1539 GET_COL(to, HX+6, from, 6); \
1540 GET_COL(to, HX+7, from, 7); \
1541 }
1542
compute_payoff(int me,int you)1543 static float compute_payoff(int me, int you) {
1544 /* compute payoff function for Prisoner's Dilemma simulations */
1545 if (you == 0 || me == 0)
1546 return 0;
1547 else
1548 return payoffs[me - 1][you - 1];
1549 }
1550
1551 static cell_t hold[HY + BOXSIZE + HY][HX + BOXSIZE + HX];
1552
get_corner(int dy,int dx,tile * cp,int sy,int sx)1553 static void get_corner(int dy, int dx, tile *cp, int sy, int sx) {
1554 /* fetch a tile corner into the hold area */
1555 hold[dy ][dx ] = cp->cells.pstate.ocell[sy ][sx ];
1556 hold[dy+1][dx ] = cp->cells.pstate.ocell[sy+1][sx ];
1557 hold[dy ][dx+1] = cp->cells.pstate.ocell[sy ][sx+1];
1558 hold[dy+1][dx+1] = cp->cells.pstate.ocell[sy+1][sx+1];
1559 }
1560
bad_state_handler8(tile * cptr,int yc,int xc,cell_t u,cell_t ur,cell_t r,cell_t dr,cell_t d,cell_t dl,cell_t l,cell_t ul,cell_t oldval)1561 static cell_t bad_state_handler8(tile *cptr, int yc, int xc, cell_t u,
1562 cell_t ur, cell_t r, cell_t dr, cell_t d, cell_t dl, cell_t l,
1563 cell_t ul, cell_t oldval) {
1564 cell_t newval;
1565 FILE *fp;
1566 drawbox(cptr->x + xc, cptr->y + yc, cptr->x + xc + 2, cptr->y + yc + 2,
1567 WHITE_EVER);
1568 state = STOP;
1569 newval = patch_transition8(oldval, u, ur, r, dr, d, dl, l, ul);
1570 drawcell(RXPOS(cptr->x + xc + 1), RYPOS(cptr->y + yc + 1), newval);
1571 erasebox(cptr->x + xc, cptr->y + yc, cptr->x + xc + 2, cptr->y + yc + 2);
1572 if (active_rules[0] && (fp = fopen(PATCH_LOG, "a"))) {
1573 fprintf(fp, "%c%c%c%c%c%c%c%c%c%c", itos(oldval), itos(u), itos(ur),
1574 itos(r), itos(dr), itos(d), itos(dl), itos(l), itos(ul),
1575 itos(newval));
1576 stamp("\t#", fp);
1577 fclose(fp);
1578 }
1579 return newval;
1580 }
1581
evolvep(pattern * context)1582 static void evolvep(pattern *context) { /* slower table-driven evolve for n-state spaces */
1583 register tile *cptr, *ncptr;
1584 int nzcount, live_total = 0;
1585 float payoff[HY + BOXSIZE + HY][HX + BOXSIZE + HX];
1586 /* first, save old state and extend active region as necessary */
1587 for (cptr = context->tiles; cptr; cptr = cptr->next) {
1588 if (cptr->dead) goto cpbox; /* dead cells don't grow */
1589 if (H_CHNG(0))
1590 maketile(context, cptr->x - BOXSIZE, cptr->y);
1591 if (H_CHNG(BOXSIZE - 1))
1592 maketile(context, cptr->x + BOXSIZE, cptr->y);
1593 if (V_CHNG(0))
1594 maketile(context, cptr->x, cptr->y - BOXSIZE);
1595 if (V_CHNG(BOXSIZE - 1))
1596 maketile(context, cptr->x, cptr->y + BOXSIZE);
1597 if (X_CHNG(0,0)) {
1598 maketile(context, cptr->x - BOXSIZE, cptr->y);
1599 maketile(context, cptr->x, cptr->y - BOXSIZE);
1600 maketile(context, cptr->x - BOXSIZE, cptr->y - BOXSIZE);
1601 }
1602 if (X_CHNG(BOXSIZE - 1,0)) {
1603 maketile(context, cptr->x - BOXSIZE, cptr->y);
1604 maketile(context, cptr->x, cptr->y + BOXSIZE);
1605 maketile(context, cptr->x - BOXSIZE, cptr->y + BOXSIZE);
1606 }
1607 if (X_CHNG(0,BOXSIZE - 1)) {
1608 maketile(context, cptr->x, cptr->y - BOXSIZE);
1609 maketile(context, cptr->x + BOXSIZE, cptr->y);
1610 maketile(context, cptr->x + BOXSIZE, cptr->y - BOXSIZE);
1611 }
1612 if (X_CHNG(BOXSIZE - 1,BOXSIZE - 1)) {
1613 maketile(context, cptr->x + BOXSIZE, cptr->y);
1614 maketile(context, cptr->x, cptr->y + BOXSIZE);
1615 maketile(context, cptr->x + BOXSIZE, cptr->y + BOXSIZE);
1616 }
1617 /* we may need to grab the diagonally-adjacent tiles too */
1618 cpbox:
1619 memcpy(&cptr->cells.pstate.ocell,
1620 &cptr->cells.pstate.cell,
1621 sizeof(cell_t[BOXSIZE][BOXSIZE]));
1622 }
1623 /* evolution in action */
1624 for (cptr = context->tiles; cptr; cptr = cptr->next) {
1625 register int i, j;
1626 memset(hold, '\0', sizeof(hold));
1627 GET_INTERIOR(hold, cptr->cells.pstate.ocell);
1628 /* drawbox(cptr->x, cptr->y,
1629 cptr->x + BOXSIZE - 1, cptr->y + BOXSIZE - 1, WHITE_EVER);
1630 */
1631 /* fill in left edge cells if needed */
1632 if (ncptr = fetchtile(context, cptr->x - BOXSIZE, cptr->y)) {
1633 GET_COL(hold, 1, ncptr->cells.pstate.ocell, BOXSIZE - 1);
1634 GET_COL(hold, 0, ncptr->cells.pstate.ocell, BOXSIZE - 2);
1635 }
1636 /* fill in right edge cells if needed */
1637 if (ncptr = fetchtile(context, cptr->x + BOXSIZE, cptr->y)) {
1638 GET_COL(hold, BOXSIZE + 2, ncptr->cells.pstate.ocell, 0);
1639 GET_COL(hold, BOXSIZE + 3, ncptr->cells.pstate.ocell, 1);
1640 }
1641 /* fill in top edge cells if needed */
1642 if (ncptr = fetchtile(context, cptr->x, cptr->y - BOXSIZE)) {
1643 GET_ROW(hold, 1, ncptr->cells.pstate.ocell, BOXSIZE - 1);
1644 GET_ROW(hold, 0, ncptr->cells.pstate.ocell, BOXSIZE - 2);
1645 }
1646 /* fill in bottom edge cells if needed */
1647 if (ncptr = fetchtile(context, cptr->x, cptr->y + BOXSIZE)) {
1648 GET_ROW(hold, BOXSIZE + 2, ncptr->cells.pstate.ocell, 0);
1649 GET_ROW(hold, BOXSIZE + 3, ncptr->cells.pstate.ocell, 1);
1650 }
1651 if (ncptr = fetchtile(context, cptr->x - BOXSIZE, cptr->y - BOXSIZE))
1652 get_corner(0, 0, ncptr, BOXSIZE - 2, BOXSIZE - 2);
1653 if (ncptr = fetchtile(context, cptr->x + BOXSIZE, cptr->y - BOXSIZE))
1654 get_corner(0, BOXSIZE + 2, ncptr, BOXSIZE - 2, 0);
1655 if (ncptr = fetchtile(context, cptr->x + BOXSIZE, cptr->y + BOXSIZE))
1656 get_corner(BOXSIZE + 2, BOXSIZE + 2, ncptr, 0, 0);
1657 if (ncptr = fetchtile(context, cptr->x - BOXSIZE, cptr->y + BOXSIZE))
1658 get_corner(BOXSIZE + 2, 0, ncptr, 0, BOXSIZE - 2);
1659 if (ev_mode == TAB8_DRIVEN)
1660 goto NOPAYOFF;
1661 /* flatten away the transition pseudo-states */
1662 for (i = 0; i <= BOXSIZE + 3; i++)
1663 for (j = 0; j <= BOXSIZE + 3; j++)
1664 if (hold[i][j] > 2)
1665 hold[i][j] = 5 - hold[i][j];
1666 for (i = 1; i <= BOXSIZE + 2; i++)
1667 for (j = 1; j <= BOXSIZE + 2; j++) {
1668 int ostate = hold[i][j];
1669 payoff[i][j] = compute_payoff(ostate, hold[i - 1][j - 1]);
1670 payoff[i][j] += compute_payoff(ostate, hold[i - 1][j]);
1671 payoff[i][j] += compute_payoff(ostate, hold[i - 1][j + 1]);
1672 payoff[i][j] += compute_payoff(ostate, hold[i][j - 1]);
1673 payoff[i][j] += compute_payoff(ostate, hold[i][j + 1]);
1674 payoff[i][j] += compute_payoff(ostate, hold[i + 1][j - 1]);
1675 payoff[i][j] += compute_payoff(ostate, hold[i + 1][j]);
1676 payoff[i][j] += compute_payoff(ostate, hold[i + 1][j + 1]);
1677 payoff[i][j] += compute_payoff(ostate, ostate); /*a self-bargain?*/
1678 }
1679 NOPAYOFF:
1680 /* apply the transition function */
1681 nzcount = 0;
1682 for (i = HY; i < BOXSIZE + HY; i++)
1683 for (j = HX; j < BOXSIZE + HX; j++) {
1684 register int newval;
1685 static offsets neighbors[] =
1686 {
1687 {-1, -1}, {-1, 0}, {-1, 1},
1688 { 0, -1}, { 0, 0}, { 0, 1},
1689 { 1, -1}, { 1, 0}, { 1, 1}
1690 };
1691 float highest, maxpayoff[MAXSTATES];
1692 unsigned int k;
1693 /* compute the maximum payoff of each strategy */
1694 if (ev_mode == TAB8_DRIVEN) {
1695 newval = btrans[hold[i][j]][hold[i - 1][j]][hold[i - 1][j + 1]]
1696 [hold[i][j + 1]][hold[i + 1][j + 1]][hold[i + 1][j]]
1697 [hold[i + 1][j - 1]][hold[i][j - 1]][hold[i - 1][j - 1]];
1698 if (newval == BADSTATE)
1699 if (passive < 0)
1700 make_transition8(0, newval = hold[i][j], hold[i - 1][j],
1701 hold[i - 1][j + 1], hold[i][j + 1], hold[i + 1][j + 1],
1702 hold[i + 1][j], hold[i + 1][j - 1], hold[i][j - 1],
1703 hold[i - 1][j - 1], newval);
1704 else
1705 newval = bad_state_handler8(cptr, i - HY, j - HX, hold[i - 1][j],
1706 hold[i - 1][j + 1], hold[i][j + 1], hold[i + 1][j + 1],
1707 hold[i + 1][j], hold[i + 1][j - 1], hold[i][j - 1],
1708 hold[i - 1][j - 1], hold[i][j]);
1709 goto CONT;
1710 }
1711 memset(maxpayoff, '\0', sizeof(maxpayoff));
1712 for (k = 0; k < sizeof(neighbors)/sizeof(offsets); k++) {
1713 float np = payoff[i + neighbors[k].yi][j + neighbors[k].xi];
1714 newval = hold[i + neighbors[k].yi][j + neighbors[k].xi];
1715 if (np > maxpayoff[newval])
1716 maxpayoff[newval] = np;
1717 }
1718 /*
1719 * Pick the strategy with the highest payoff.
1720 * Break ties towards lowest-numbered strategy.
1721 */
1722 if (newval = hold[i][j]) {
1723 highest = 0;
1724 for (k = 0; k < maxstates; k++)
1725 if (maxpayoff[k] > highest)
1726 highest = maxpayoff[newval = k];
1727 }
1728 /* this creates the transition pseudo-states */
1729 if (highest > payoff[i][j] && newval != hold[i][j])
1730 newval = hold[i][j] + 2;
1731 CONT:
1732 if (newval != cptr->cells.pstate.cell[i - HY][j - HX]) {
1733 context->chgcount++;
1734 /* OK, assign the new cell state */
1735 cptr->cells.pstate.cell[i - HY][j - HX] = newval;
1736 }
1737 if (newval) {
1738 if (dispboxes)
1739 context->cellcount[newval]++;
1740 nzcount++;
1741 }
1742 }
1743 if (nzcount == 0)
1744 cptr->dead++;
1745 else
1746 {
1747 if (truehistory && context == &active) add2history(cptr);
1748 cptr->dead = 0;
1749 if (oscillators) osc_values(context, cptr);
1750 live_total++;
1751 }
1752 }
1753 fix_plain(ncptr);
1754 if (context->chgcount == 0 || live_total == 0)
1755 state = STOP;
1756 }
1757
bad_state_handler(tile * cptr,int yc,int xc,cell_t u,cell_t r,cell_t d,cell_t l,cell_t oldval)1758 static cell_t bad_state_handler(tile *cptr, int yc, int xc, cell_t u, cell_t r, cell_t d, cell_t l, cell_t oldval) {
1759 cell_t newval;
1760 FILE *fp;
1761 drawbox(cptr->x + xc, cptr->y + yc, cptr->x + xc + 2, cptr->y + yc + 2,
1762 WHITE_EVER);
1763 state = STOP;
1764 newval = patch_transition(oldval, u, r, d, l);
1765 drawcell(RXPOS(cptr->x + xc + 1), RYPOS(cptr->y + yc + 1), newval);
1766 erasebox(cptr->x + xc, cptr->y + yc, cptr->x + xc + 2, cptr->y + yc + 2);
1767 if (active_rules[0] && (fp = fopen(PATCH_LOG, "a"))) {
1768 fprintf(fp, "%c%c%c%c%c%c", itos(oldval),
1769 itos(u), itos(r), itos(d), itos(l), itos(newval));
1770 stamp("\t#", fp);
1771 fclose(fp);
1772 }
1773 return newval;
1774 }
1775
1776 #define new_state(yc, xc, u, r, d, l) {\
1777 newval = ztrans[oldval = ocell[yc][xc]][u][r][d][l];\
1778 if (newval == BADSTATE)\
1779 if (passive < 0)\
1780 make_transition(0, newval = oldval, u, r, d, l, oldval);\
1781 else\
1782 newval = bad_state_handler(cptr, yc, xc, u, r, d, l, oldval);\
1783 if (newval != oldval) {\
1784 context->chgcount++;\
1785 chgcount = 1;\
1786 cptr->cells.nstate.cell[yc][xc] = newval;\
1787 }\
1788 if (newval) {\
1789 if (dispboxes)\
1790 context->cellcount[newval]++;\
1791 nzcount = 1;\
1792 }}
1793
evolven(pattern * context)1794 static void evolven(pattern *context) {
1795 register u32bits t1, t2;
1796 int live_total = 0;
1797 register tile *cptr;
1798 tile *cptrup, *cptrdn, *cptrlf, *cptrrt;
1799 static cell_t ocell[BOXSIZE][BOXSIZE];
1800 for (cptr = context->tiles; cptr; cptr = cptr->next) {
1801 cptr->nochgcp = cptr->nochg;
1802 cptr->nochg = 0;
1803 if (cptr->dead) continue;
1804 cptrup = cptr->up;
1805 cptrdn = cptr->dn;
1806 cptrlf = cptr->lf;
1807 cptrrt = cptr->rt;
1808 if ((t1 = cptr->cells.nstate.live[0][0]) || cptr->cells.nstate.live[0][1]) {
1809 if (cptrup == NULL) {
1810 cptrup = maketile(context, cptr->x, cptr->y - BOXSIZE);
1811 cptrup->dn = cptr;
1812 }
1813 cptrup->cells.nstate.l[2] = t1;
1814 cptrup->cells.nstate.l[3] = cptr->cells.nstate.live[0][1];
1815 }
1816 if ((t1 = cptr->cells.nstate.live[7][0]) || cptr->cells.nstate.live[7][1]) {
1817 if (cptrdn == NULL) {
1818 cptrdn = maketile(context, cptr->x, cptr->y + BOXSIZE);
1819 cptrdn->up = cptr;
1820 }
1821 cptrdn->cells.nstate.l[0] = t1;
1822 cptrdn->cells.nstate.l[1] = cptr->cells.nstate.live[7][1];
1823 }
1824 if ((t1 = cptr->cells.nstate.cell[0][0]) || cptr->cells.nstate.cell[1][0]
1825 || cptr->cells.nstate.cell[2][0] || cptr->cells.nstate.cell[3][0]
1826 || cptr->cells.nstate.cell[4][0] || cptr->cells.nstate.cell[5][0]
1827 || cptr->cells.nstate.cell[6][0] || cptr->cells.nstate.cell[7][0]) {
1828 if (cptrlf == NULL) {
1829 cptrlf = maketile(context, cptr->x - BOXSIZE, cptr->y);
1830 cptrlf->rt = cptr;
1831 }
1832 cptrlf->cells.nstate.c[3][0] = t1;
1833 cptrlf->cells.nstate.c[3][1] = cptr->cells.nstate.cell[1][0];
1834 cptrlf->cells.nstate.c[3][2] = cptr->cells.nstate.cell[2][0];
1835 cptrlf->cells.nstate.c[3][3] = cptr->cells.nstate.cell[3][0];
1836 cptrlf->cells.nstate.c[3][4] = cptr->cells.nstate.cell[4][0];
1837 cptrlf->cells.nstate.c[3][5] = cptr->cells.nstate.cell[5][0];
1838 cptrlf->cells.nstate.c[3][6] = cptr->cells.nstate.cell[6][0];
1839 cptrlf->cells.nstate.c[3][7] = cptr->cells.nstate.cell[7][0];
1840 }
1841 if ((t1 = cptr->cells.nstate.cell[0][7]) || cptr->cells.nstate.cell[1][7]
1842 || cptr->cells.nstate.cell[2][7] || cptr->cells.nstate.cell[3][7]
1843 || cptr->cells.nstate.cell[4][7] || cptr->cells.nstate.cell[5][7]
1844 || cptr->cells.nstate.cell[6][7] || cptr->cells.nstate.cell[7][7]) {
1845 if (cptrrt == NULL) {
1846 cptrrt = maketile(context, cptr->x + BOXSIZE, cptr->y);
1847 cptrrt->lf = cptr;
1848 }
1849 cptrrt->cells.nstate.c[2][0] = t1;
1850 cptrrt->cells.nstate.c[2][1] = cptr->cells.nstate.cell[1][7];
1851 cptrrt->cells.nstate.c[2][2] = cptr->cells.nstate.cell[2][7];
1852 cptrrt->cells.nstate.c[2][3] = cptr->cells.nstate.cell[3][7];
1853 cptrrt->cells.nstate.c[2][4] = cptr->cells.nstate.cell[4][7];
1854 cptrrt->cells.nstate.c[2][5] = cptr->cells.nstate.cell[5][7];
1855 cptrrt->cells.nstate.c[2][6] = cptr->cells.nstate.cell[6][7];
1856 cptrrt->cells.nstate.c[2][7] = cptr->cells.nstate.cell[7][7];
1857 }
1858 cptr->up = cptrup;
1859 cptr->dn = cptrdn;
1860 cptr->lf = cptrlf;
1861 cptr->rt = cptrrt;
1862 }
1863 /*
1864 * Perform actual evolution.
1865 */
1866 fix_plain(cptrup);
1867 for (cptr = context->tiles; cptr; cptr = cptr->next) {
1868 register int newval, nzcount = 0, chgcount = 0, oldval;
1869 if (cptr->nochgcp == 5) {
1870 if (dispboxes)
1871 for (t2 = 0; t2 < BOXSIZE; ++t2)
1872 for (t1 = 0; t1 < BOXSIZE; ++t1) {
1873 if (newval = cptr->cells.nstate.cell[t2][t1]) {
1874 context->cellcount[newval]++;
1875 nzcount = 1;
1876 }
1877 }
1878 else
1879 nzcount = cptr->cells.nstate.live[0][0] || cptr->cells.nstate.live[0][1]
1880 || cptr->cells.nstate.live[1][0] || cptr->cells.nstate.live[1][1]
1881 || cptr->cells.nstate.live[2][0] || cptr->cells.nstate.live[2][1]
1882 || cptr->cells.nstate.live[3][0] || cptr->cells.nstate.live[3][1]
1883 || cptr->cells.nstate.live[4][0] || cptr->cells.nstate.live[4][1]
1884 || cptr->cells.nstate.live[5][0] || cptr->cells.nstate.live[5][1]
1885 || cptr->cells.nstate.live[6][0] || cptr->cells.nstate.live[6][1]
1886 || cptr->cells.nstate.live[7][0] || cptr->cells.nstate.live[7][1];
1887 goto calc_nochg;
1888 }
1889 memcpy(ocell, cptr->cells.nstate.cell, sizeof(cell_t[BOXSIZE][BOXSIZE]));
1890 new_state(0, 0, cptr->cells.nstate.c[0][0], ocell[0][1], ocell[1][0], cptr->cells.nstate.c[2][0]);//ul
1891 new_state(0, 7, cptr->cells.nstate.c[0][7], cptr->cells.nstate.c[3][0], ocell[1][7], ocell[0][6]);//ur
1892 new_state(7, 0, ocell[6][0], ocell[7][1], cptr->cells.nstate.c[1][0], cptr->cells.nstate.c[2][7]);//ll
1893 new_state(7, 7, ocell[6][7], cptr->cells.nstate.c[3][7], cptr->cells.nstate.c[1][7], ocell[7][6]);//lr
1894 for (t2 = 1; t2 <= 6; ++t2) {
1895 new_state(0, t2, cptr->cells.nstate.c[0][t2], ocell[0][t2 + 1], ocell[1][t2], ocell[0][t2 - 1]);//u
1896 new_state(7, t2, ocell[6][t2], ocell[7][t2 + 1], cptr->cells.nstate.c[1][t2], ocell[7][t2 - 1]);//d
1897 new_state(t2, 0, ocell[t2 - 1][0], ocell[t2][1], ocell[t2 + 1][0], cptr->cells.nstate.c[2][t2]);//l
1898 new_state(t2, 7, ocell[t2 - 1][7], cptr->cells.nstate.c[3][t2], ocell[t2 + 1][7], ocell[t2][6]);//r
1899 }
1900 for (t2 = 1; t2 <= 6; ++t2)
1901 for (t1 = 1; t1 <= 6; ++t1)
1902 new_state(t2, t1, ocell[t2 - 1][t1], ocell[t2][t1 + 1], ocell[t2 + 1][t1], ocell[t2][t1 - 1]);
1903 for (t2 = 0; t2 < 8; ++t2)
1904 cptr->cells.nstate.l[t2] = 0;
1905 /*
1906 * Box-aging and statistics gathering.
1907 */
1908 if (chgcount == 0) {
1909 calc_nochg:
1910 cptr->nochg++;
1911 if (cptr->lf || (cptr->lf = fetchtile(context, cptr->x - BOXSIZE, cptr->y)))
1912 cptr->lf->nochg++;
1913 else
1914 cptr->nochg++;
1915 if (cptr->rt || (cptr->rt = fetchtile(context, cptr->x + BOXSIZE, cptr->y)))
1916 cptr->rt->nochg++;
1917 else
1918 cptr->nochg++;
1919 if (cptr->up || (cptr->up = fetchtile(context, cptr->x, cptr->y - BOXSIZE)))
1920 cptr->up->nochg++;
1921 else
1922 cptr->nochg++;
1923 if (cptr->dn || (cptr->dn = fetchtile(context, cptr->x, cptr->y + BOXSIZE)))
1924 cptr->dn->nochg++;
1925 else
1926 cptr->nochg++;
1927 }
1928 else
1929 if (truehistory && context == &active) add2history(cptr);
1930 if (nzcount == 0)
1931 cptr->dead++;
1932 else
1933 {
1934 cptr->dead = 0;
1935 live_total++;
1936 if (oscillators) osc_values(context, cptr);
1937 }
1938 }
1939 if (live_total == 0 || context->chgcount == 0)
1940 state = STOP;
1941 }
1942
1943 /*
1944 * Parsing machinery for the transition-rule compiler begins here.
1945 *
1946 * !!!*** Nifty hack alert **** Nifty hack alert **** Nifty hack alert ****!!!
1947 *
1948 * An implementation problem with the state-quintuple format is that we need
1949 * to apply the `code-generator' function to all glob patterns implied by an
1950 * RE of the form
1951 *
1952 * <ss><ss><ss><ss><ss>
1953 *
1954 * where <ss> can be a digit or a digit set bracketed by [, ]; but there
1955 * could be up to MAXSTATES to the 5th power of these, which is too many to
1956 * generate into a scratch array or file and then crunch through.
1957 *
1958 * Read on, and be enlightened...
1959 * Eric S. Raymond
1960 * esr@snark.thyrsus.com
1961 */
1962 #define E_NOCLOSE "Missing ] character"
1963 #define E_BADCHAR "Invalid character"
1964 #define E_WRONGNUM "Wrong number of states"
1965
parse_recurse(char * buf,int ecount)1966 static char *parse_recurse(char *buf, int ecount) {
1967 static cell_t sofar[8 + 2];
1968 int nhsize = 6;
1969 if (ev_mode == TAB8_DRIVEN)
1970 nhsize = 10;
1971 while (buf[0] == ' ' || buf[0] == '\t')
1972 buf++;
1973 if (ecount > nhsize)
1974 return E_WRONGNUM;
1975 else if (is_state(buf[0])) {
1976 /*
1977 * Sequential cons of next state onto the tip of the branch
1978 * passed on.
1979 */
1980 sofar[ecount] = stoi(*buf);
1981 return parse_recurse(buf + 1, ecount + 1);
1982 }
1983 else if (buf[0] == '[') {
1984 char *ep = strchr(buf, ']');
1985 if (ep == 0)
1986 return E_NOCLOSE;
1987 /*
1988 * Wild-carding time. We iterate through the set; for each member,
1989 * we start a recurse from just past the *end* of the set.
1990 */
1991 while (is_state(*++buf)) {
1992 char *err;
1993 sofar[ecount] = stoi(*buf);
1994 if ((err = parse_recurse(ep + 1, ecount + 1)) == E_NOCLOSE
1995 || err == E_BADCHAR || err == E_WRONGNUM)
1996 return err;
1997 }
1998 return 0;
1999 }
2000 else if (buf[0] == ']')
2001 return 0;
2002 else if (buf[0] != '\n' && buf[0] != '\0' && buf[0] != '\r')
2003 return E_BADCHAR;
2004 else if (ecount < nhsize)
2005 return E_WRONGNUM;
2006 else
2007 {
2008 if (ev_mode != TAB8_DRIVEN)
2009 make_transition(0, sofar[0], sofar[1], sofar[2], sofar[3], sofar[4],
2010 sofar[5]);
2011 else
2012 make_transition8(0, sofar[0], sofar[1], sofar[2], sofar[3], sofar[4],
2013 sofar[5], sofar[6], sofar[7], sofar[8], sofar[9]);
2014 return 0;
2015 }
2016 }
2017
2018 /*
2019 * Here is the actual transition function implementation. Note that this
2020 * will eat up obscene amounts of memory for large maxstates values;
2021 * 32K for 3, 1M for 4, 32M for 5 and so on. However, it has the merit of
2022 * being simple and very fast.
2023 */
2024
make_transition(int force,int s,int a,int b,int c,int d,int t)2025 void make_transition(int force, int s, int a, int b, int c, int d, int t) {
2026 /* add a transition to the search tree */
2027 int oldval = ztrans[s][a][b][c][d];
2028 /* enforce rotational symmetry */
2029 if (oldval == BADSTATE || passive >= 0 || force) {
2030 ztrans[s][a][b][c][d] = t;
2031 if (!nosymm) {
2032 ztrans[s][b][c][d][a]
2033 = ztrans[s][c][d][a][b]
2034 = ztrans[s][d][a][b][c] = t;
2035 if (rotate4reflect)
2036 ztrans[s][d][c][b][a]
2037 = ztrans[s][c][b][a][d]
2038 = ztrans[s][b][a][d][c]
2039 = ztrans[s][a][d][c][b] = t;
2040 }
2041 }
2042 }
2043
make_transition8(int force,int s,int a,int b,int c,int d,int e,int f,int g,int h,int t)2044 void make_transition8(int force, int s, int a, int b, int c, int d, int e, int f, int g, int h, int t) {
2045 int oldval = btrans[s][a][b][c][d][e][f][g][h];
2046 /* enforce rotational symmetry */
2047 if (oldval == BADSTATE || passive >= 0 || force) {
2048 btrans[s][a][b][c][d][e][f][g][h] = t;
2049 if (!nosymm) {
2050 btrans[s][c][d][e][f][g][h][a][b]
2051 = btrans[s][e][f][g][h][a][b][c][d]
2052 = btrans[s][g][h][a][b][c][d][e][f] = t;
2053 if (rotate4reflect)
2054 btrans[s][a][h][g][f][e][d][c][b]
2055 = btrans[s][g][f][e][d][c][b][a][h]
2056 = btrans[s][e][d][c][b][a][h][g][f]
2057 = btrans[s][c][b][a][h][g][f][e][d] = t;
2058 else
2059 btrans[s][b][c][d][e][f][g][h][a]
2060 = btrans[s][d][e][f][g][h][a][b][c]
2061 = btrans[s][f][g][h][a][b][c][d][e]
2062 = btrans[s][h][a][b][c][d][e][f][g] = t;
2063 }
2064 }
2065 }
2066
parse_rule(char * buf)2067 char *parse_rule(char *buf) { /* parse a transition rule */
2068 char *err = parse_recurse(buf, 0);
2069 if (err == E_NOCLOSE
2070 || err == E_WRONGNUM || err == E_BADCHAR)
2071 return err;
2072 else
2073 return 0;
2074 }
2075
readrules(const char * file)2076 char *readrules(const char *file) {
2077 /* read a transition-rule set out of a file */
2078 static char buf[1024], buf2[80];
2079 FILE *fp;
2080 unsigned n, s, c, r, line = 0, new_ev_mode = TABLE_DRIVEN;
2081 register unsigned i, j, k, l, m;
2082 if ((fp = fopen(file, "r")) == 0)
2083 return (char*)SYSERR;
2084 passive = -1;
2085 if (palettemod) DefaultPalette();
2086 palettemod = historymode = nosymm = rotate4reflect = 0;
2087 while (fgets(buf, sizeof(buf), fp)) {
2088 char *cp, *errmsg;
2089 line++;
2090 if (cp = strchr(buf, '#')) {
2091 *cp = '\n';
2092 *++cp = '\0';
2093 }
2094 if (*buf == '\n' || *buf == '\0')
2095 continue;
2096 else if (!strncmp(buf, "nosymm", 6))
2097 nosymm = 1;
2098 else if (!strncmp(buf, "rotate4reflect", 14))
2099 rotate4reflect = 1;
2100 else if (!strncasecmp(buf, "Moore", 5))
2101 new_ev_mode = TAB8_DRIVEN;
2102 else if (!strncmp(buf, "debug", 5));
2103 else if (!strncasecmp(buf, "states ", 7)) {
2104 unsigned long memreq;
2105 if ((n = atoi(buf + 7)) > NMAX)
2106 return "Too many states";
2107 alloc_states(new_ev_mode, n);
2108 memreq = n*n*n*n*n;
2109 if (ev_mode == TAB8_DRIVEN) {
2110 memreq *= n*n*n*n;
2111 if (n > 12) return "Moore neiborhood supports only up to 12 states";
2112 }
2113 if (dm_given < memreq) {
2114 dm_given = 0;
2115 free(trans);
2116 if ((trans = malloc(memreq)) == 0)
2117 return "No enough free RAM for so many states";
2118 dm_given = memreq;
2119 }
2120 memset(trans, BADSTATE, memreq);
2121 }
2122 else if (!strncmp(buf, "passive ", 8)) {
2123 if ((passive = atoi(buf + 8)) >= maxstates)
2124 return "Too many states for passive";
2125 for (i = 0; i <= passive; i++)
2126 for (j = 0; j <= passive; j++)
2127 for (k = 0; k <= passive; k++)
2128 for (l = 0; l <= passive; l++)
2129 for (m = 0; m <= passive; m++)
2130 if (ev_mode != TAB8_DRIVEN)
2131 make_transition(0, i, j, k, l, m, i);
2132 else {
2133 int j1, k1, l1, m1;
2134 for (j1 = 0; j1 <= passive; j1++)
2135 for (k1 = 0; k1 <= passive; k1++)
2136 for (l1 = 0; l1 <= passive; l1++)
2137 for (m1 = 0; m1 <= passive; m1++)
2138 make_transition8(0, i, j, k, l, m, j1, k1, l1, m1, i);
2139 }
2140 }
2141 else if (sscanf(buf, "%u(%u*%u)%u", &s, &n, &c, &r) == 4 && ev_mode == TABLE_DRIVEN) {
2142 if (c == 0) {
2143 for (i = 0; i < maxstates; i++)
2144 if (i != n)
2145 for (j = 0; j < maxstates; j++)
2146 if (j != n)
2147 for (k = 0; k < maxstates; k++)
2148 if (k != n)
2149 for (l = 0; l < maxstates; l++)
2150 if (l != n)
2151 make_transition(0, s, i, j, k, l, r);
2152 }
2153 else if (c == 1) {
2154 for (i = 0; i < maxstates; i++)
2155 if (i != n)
2156 for (j = 0; j < maxstates; j++)
2157 if (j != n)
2158 for (k = 0; k < maxstates; k++)
2159 if (k != n)
2160 make_transition(0, s, n, i, j, k, r);
2161 }
2162 else if (c == 2) {
2163 for (i = 0; i < maxstates; i++)
2164 if (i != n)
2165 for (j = 0; j < maxstates; j++)
2166 if (j != n) {
2167 make_transition(0, s, n, n, i, j, r);
2168 make_transition(0, s, n, i, n, j, r);
2169 }
2170 }
2171 else /* (c == 3) */
2172 {
2173 for (i = 0; i < maxstates; i++)
2174 if (i != n)
2175 make_transition(0, s, n, n, n, i, r);
2176 }
2177 }
2178 else if (errmsg = parse_recurse(buf, 0)) {
2179 sprintf(buf2, "%s, line %d", errmsg, line);
2180 fclose(fp);
2181 return buf2;
2182 }
2183 }
2184 fclose(fp);
2185 return 0;
2186 }
2187
2188 /* now, pull it all together */
2189
generate(pattern * context)2190 void generate(pattern *context) {
2191 register tile *cptr, *nextptr;
2192 static unsigned t, tc1 = 3, tc2 = 4000000;
2193 static struct timeval prev, cur;
2194 memset(context->cellcount, 0, maxstates*sizeof(cellcount_t));
2195 context->chgcount = 0;
2196 if (oscillators) context->osc1 = context->osc2 = context->osc3 = context->osc4 = context->osc5 = 0;
2197 if (ev_mode == VALENCE_DRIVEN)
2198 if (born & 1)
2199 evolve2b0(context);
2200 else
2201 evolve2(context);
2202 else if (ev_mode == GEN_DRIVEN)
2203 if (born & 1)
2204 evolve3b0(context);
2205 else
2206 evolve3(context);
2207 else if (ev_mode == TABLE_DRIVEN)
2208 evolven(context);
2209 else
2210 evolvep(context);
2211
2212 /* clean up tiles that have gone blank */
2213 for (cptr = context->tiles; cptr; cptr = nextptr) {
2214 nextptr = cptr->next;
2215 if (cptr->dead > DEADTIME)
2216 killtile(context, cptr);
2217 }
2218 if ((++context->generations&tc1) == 0 && context == &active) {
2219 gettimeofday(&cur, 0);
2220 t = (cur.tv_sec - prev.tv_sec)*1000000 + cur.tv_usec - prev.tv_usec;
2221 if (t == 0)
2222 tc2 += 4000000;
2223 else {
2224 if ((speed = tc2/t) < 20)
2225 speed += (tc2%t >= t/2);
2226 prev = cur;
2227 tc2 = 4000000;
2228 }
2229 }
2230 if (oscillators && context == &active)
2231 if (active.chgcount == oscillator_check.chgcount && active.osc1 == oscillator_check.osc1
2232 && active.osc2 == oscillator_check.osc2 && active.osc3 == oscillator_check.osc3
2233 && active.osc4 == oscillator_check.osc4 && active.osc5 == oscillator_check.osc5)
2234 if ((!memcmp(oscillator_check.cellcount + 1, active.cellcount + 1, maxstates - 1))
2235 && comparepatterns(&active, &oscillator_check)) {
2236 state = STOP;
2237 redraw_lifew();
2238 sprintf(inpbuf, "Period-%d oscillator is found", active.generations - oscillator_check.generations);
2239 announce_and_wait(GREEN_EVER);
2240 oscillators = 0;
2241 dispboxes = save_dispboxes;
2242 dispchanges = save_dispchanges;
2243 announce_and_delay("Oscillator check mode is off");
2244 }
2245 if (runcounter && --runcounter == 0) {
2246 state = STOP;
2247 strcpy(inpbuf, "Time up.");
2248 announce_and_wait(GREEN_EVER);
2249 displaystats();
2250 }
2251 }
2252