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