1 | /* -*- Mode: C; tab-width: 4 -*- */ |
---|
2 | /* loop --- Chris Langton's self-producing loops */ |
---|
3 | |
---|
4 | #if 0 |
---|
5 | static const char sccsid[] = "@(#)loop.c 5.01 2000/03/15 xlockmore"; |
---|
6 | #endif |
---|
7 | |
---|
8 | /*- |
---|
9 | * Copyright (c) 1996 by David Bagley. |
---|
10 | * |
---|
11 | * Permission to use, copy, modify, and distribute this software and its |
---|
12 | * documentation for any purpose and without fee is hereby granted, |
---|
13 | * provided that the above copyright notice appear in all copies and that |
---|
14 | * both that copyright notice and this permission notice appear in |
---|
15 | * supporting documentation. |
---|
16 | * |
---|
17 | * This file is provided AS IS with no warranties of any kind. The author |
---|
18 | * shall have no liability with respect to the infringement of copyrights, |
---|
19 | * trade secrets or any patents by this file or any part thereof. In no |
---|
20 | * event will the author be liable for any lost revenue or profits or |
---|
21 | * other special, indirect and consequential damages. |
---|
22 | * |
---|
23 | * Revision History: |
---|
24 | * 15-Mar-2001: Added some flaws, random blue wall spots, to liven it up. |
---|
25 | * This mod seems to expose a bug where hexagons are erased |
---|
26 | * for no apparent reason. |
---|
27 | * 01-Nov-2000: Allocation checks |
---|
28 | * 16-Jun-2000: Fully coded the hexagonal rules. (Rules that end up in |
---|
29 | * state zero were not bothered with since a calloc was used |
---|
30 | * to set non-explicit rules to zero. This allows the |
---|
31 | * compile-time option RAND_RULES to work here (at least to |
---|
32 | * generation 540).) |
---|
33 | * Also added compile-time option DELAYDEBUGLOOP for debugging |
---|
34 | * life form. This also turns off the random initial direction |
---|
35 | * of the loop. Set DELAYDEBUGLOOP to be 10 and use with |
---|
36 | * something like this: |
---|
37 | * xlock -mode loop -neighbors 6 -size 5 -delay 1 -count 540 -nolock |
---|
38 | * 18-Oct-1998: Started creating a hexagon version. |
---|
39 | * It proved not that difficult because I used Langton's Loop |
---|
40 | * as a guide, hexagons have more neighbors so there is more |
---|
41 | * freedom to program, and the loop will has six sides to |
---|
42 | * store its genes (data). |
---|
43 | * (Soon after this a triangular version with neighbors = 6 |
---|
44 | * was attempted but was unsuccessful). |
---|
45 | * 10-May-1997: Compatible with xscreensaver |
---|
46 | * 15-Nov-1995: Coded from Chris Langton's Self-Reproduction in Cellular |
---|
47 | * Automata Physica 10D 135-144 1984, also used wire.c as a |
---|
48 | * guide. |
---|
49 | */ |
---|
50 | |
---|
51 | /*- |
---|
52 | Grid Number of Neighbors |
---|
53 | ---- ------------------ |
---|
54 | Square 4 |
---|
55 | Hexagon 6 (currently in development) |
---|
56 | */ |
---|
57 | |
---|
58 | /*- |
---|
59 | * From Steven Levy's Artificial Life |
---|
60 | * Chris Langton's cellular automata "loops" reproduce in the spirit of life. |
---|
61 | * Beginning from a single organism, the loops from a colony. As the loops |
---|
62 | * on the outer fringes reproduce, the inner loops -- blocked by their |
---|
63 | * daughters -- can no longer produce offspring. These dead progenitors |
---|
64 | * provide a base for future generations' expansion, much like the formation |
---|
65 | * of a coral reef. This self-organizing behavior emerges spontaneously, |
---|
66 | * from the bottom up -- a key characteristic of artificial life. |
---|
67 | */ |
---|
68 | |
---|
69 | /*- |
---|
70 | Don't Panic -- When the artificial life tries to leave its petri |
---|
71 | dish (ie. the screen) it will (usually) die... |
---|
72 | The loops are short of "real" life because a general purpose Turing |
---|
73 | machine is not contained in the loop. This is a simplification of |
---|
74 | von Neumann and Codd's self-producing Turing machine. |
---|
75 | The data spinning around could be viewed as both its DNA and its internal |
---|
76 | clock. The program can be initalized to have the loop spin both ways... |
---|
77 | but only one way around will work for a given rule. An open question (at |
---|
78 | least to me): Is handedness a requirement for (artificial) life? Here |
---|
79 | there is handedness at both the initial condition and the transition rule. |
---|
80 | */ |
---|
81 | |
---|
82 | #ifdef STANDALONE |
---|
83 | #define MODE_loop |
---|
84 | #define PROGCLASS "loop" |
---|
85 | #define HACK_INIT init_loop |
---|
86 | #define HACK_DRAW draw_loop |
---|
87 | #define loop_opts xlockmore_opts |
---|
88 | #define DEFAULTS "*delay: 100000 \n" \ |
---|
89 | "*count: -5 \n" \ |
---|
90 | "*cycles: 1600 \n" \ |
---|
91 | "*size: -12 \n" \ |
---|
92 | "*ncolors: 15 \n" \ |
---|
93 | "*neighbors: 0 \n" |
---|
94 | #define UNIFORM_COLORS |
---|
95 | #include "xlockmore.h" /* in xscreensaver distribution */ |
---|
96 | #else /* STANDALONE */ |
---|
97 | #include "xlock.h" /* in xlockmore distribution */ |
---|
98 | #endif /* STANDALONE */ |
---|
99 | #include "automata.h" |
---|
100 | |
---|
101 | #ifdef MODE_loop |
---|
102 | |
---|
103 | /*- |
---|
104 | * neighbors of 0 randomizes between 4 and 6. |
---|
105 | */ |
---|
106 | #define DEF_NEIGHBORS "0" /* choose random value */ |
---|
107 | |
---|
108 | static int neighbors; |
---|
109 | |
---|
110 | static XrmOptionDescRec opts[] = |
---|
111 | { |
---|
112 | {(char *) "-neighbors", (char *) ".loop.neighbors", XrmoptionSepArg, (caddr_t) NULL} |
---|
113 | }; |
---|
114 | |
---|
115 | static argtype vars[] = |
---|
116 | { |
---|
117 | {(caddr_t *) & neighbors, (char *) "neighbors", (char *) "Neighbors", (char *) DEF_NEIGHBORS, t_Int} |
---|
118 | }; |
---|
119 | |
---|
120 | static OptionStruct desc[] = |
---|
121 | { |
---|
122 | {(char *) "-neighbors num", (char *) "squares 4 or hexagons 6"} |
---|
123 | }; |
---|
124 | |
---|
125 | ModeSpecOpt loop_opts = |
---|
126 | {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc}; |
---|
127 | |
---|
128 | |
---|
129 | #ifdef USE_MODULES |
---|
130 | ModStruct loop_description = |
---|
131 | {"loop", "init_loop", "draw_loop", "release_loop", |
---|
132 | "refresh_loop", "init_loop", (char *) NULL, &loop_opts, |
---|
133 | 100000, 5, 1600, -12, 64, 1.0, "", |
---|
134 | "Shows Langton's self-producing loops", 0, NULL}; |
---|
135 | |
---|
136 | #endif |
---|
137 | |
---|
138 | #define LOOPBITS(n,w,h)\ |
---|
139 | if ((lp->pixmaps[lp->init_bits]=\ |
---|
140 | XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\ |
---|
141 | free_loop(display,lp); return;} else {lp->init_bits++;} |
---|
142 | |
---|
143 | static int local_neighbors = 0; |
---|
144 | |
---|
145 | #if 0 |
---|
146 | /* Used to fast forward to troubled generations, mainly used for debugging. |
---|
147 | -delay 1 -count 170 -neighbors 6 # divisions starts |
---|
148 | 540 first cell collision |
---|
149 | 1111 mutant being born from 2 parents |
---|
150 | 1156 mutant born |
---|
151 | */ |
---|
152 | #define DELAYDEBUGLOOP 10 |
---|
153 | #endif |
---|
154 | |
---|
155 | #define COLORS 8 |
---|
156 | #define REALCOLORS (COLORS-2) |
---|
157 | #define MINLOOPS 1 |
---|
158 | #define REDRAWSTEP 2000 /* How many cells to draw per cycle */ |
---|
159 | #define ADAM_SIZE 8 /* MIN 5 */ |
---|
160 | #if 1 |
---|
161 | #define ADAM_LOOPX (ADAM_SIZE+2) |
---|
162 | #define ADAM_LOOPY (ADAM_SIZE+2) |
---|
163 | #else |
---|
164 | #define ADAM_LOOPX 16 |
---|
165 | #define ADAM_LOOPY 10 |
---|
166 | #endif |
---|
167 | #define MINGRIDSIZE (3*ADAM_LOOPX) |
---|
168 | #if 0 |
---|
169 | /* TRIA stuff was an attempt to make a triangular lifeform on a |
---|
170 | hexagonal grid but I got bored. You may need an additional 7th |
---|
171 | state for a coherent step by step process of cell separation and |
---|
172 | initial stem development. |
---|
173 | */ |
---|
174 | #define TRIA 1 |
---|
175 | #endif |
---|
176 | #ifdef TRIA |
---|
177 | #define HEX_ADAM_SIZE 3 /* MIN 3 */ |
---|
178 | #else |
---|
179 | #define HEX_ADAM_SIZE 5 /* MIN 3 */ |
---|
180 | #endif |
---|
181 | #if 1 |
---|
182 | #define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1) |
---|
183 | #define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1) |
---|
184 | #else |
---|
185 | #define HEX_ADAM_LOOPX 3 |
---|
186 | #define HEX_ADAM_LOOPY 7 |
---|
187 | #endif |
---|
188 | #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX) |
---|
189 | #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6))) |
---|
190 | #define NEIGHBORKINDS 2 |
---|
191 | #define ANGLES 360 |
---|
192 | #define MAXNEIGHBORS 6 |
---|
193 | |
---|
194 | /* Singly linked list */ |
---|
195 | typedef struct _CellList { |
---|
196 | XPoint pt; |
---|
197 | struct _CellList *next; |
---|
198 | } CellList; |
---|
199 | |
---|
200 | typedef struct { |
---|
201 | int init_bits; |
---|
202 | int generation; |
---|
203 | int xs, ys; |
---|
204 | int xb, yb; |
---|
205 | int nrows, ncols; |
---|
206 | int bx, by, bnrows, bncols; |
---|
207 | int mincol, minrow, maxcol, maxrow; |
---|
208 | int width, height; |
---|
209 | int redrawing, redrawpos; |
---|
210 | Bool dead, clockwise; |
---|
211 | unsigned char *newcells, *oldcells; |
---|
212 | int ncells[COLORS]; |
---|
213 | CellList *cellList[COLORS]; |
---|
214 | unsigned long colors[COLORS]; |
---|
215 | GC stippledGC; |
---|
216 | Pixmap pixmaps[COLORS]; |
---|
217 | union { |
---|
218 | XPoint hexagon[6]; |
---|
219 | } shape; |
---|
220 | } loopstruct; |
---|
221 | |
---|
222 | static loopstruct *loops = (loopstruct *) NULL; |
---|
223 | |
---|
224 | #define TRANSITION(TT,V) V=TT&7;TT>>=3 |
---|
225 | #define FINALTRANSITION(TT,V) V=TT&7 |
---|
226 | #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)]) |
---|
227 | #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)]) |
---|
228 | |
---|
229 | #if 0 |
---|
230 | /* Instead of setting "unused" state rules to zero it randomizes them. |
---|
231 | These rules take over when something unexpected happens... like when a |
---|
232 | cell hits a wall (the end of the screen). |
---|
233 | */ |
---|
234 | #define RAND_RULES |
---|
235 | #endif |
---|
236 | |
---|
237 | #ifdef RAND_RULES |
---|
238 | #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\ |
---|
239 | (TABLE(R,T,L,B)|=((I)<<((C)*3))) |
---|
240 | #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\ |
---|
241 | (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3))) |
---|
242 | #else |
---|
243 | #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)|=((I)<<((C)*3))) |
---|
244 | #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3))) |
---|
245 | #endif |
---|
246 | #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7) |
---|
247 | #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7) |
---|
248 | |
---|
249 | static unsigned int *table = (unsigned int *) NULL; |
---|
250 | /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */ |
---|
251 | /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */ |
---|
252 | |
---|
253 | static char plots[NEIGHBORKINDS] = |
---|
254 | { |
---|
255 | 4, 6 /* Neighborhoods */ |
---|
256 | }; |
---|
257 | |
---|
258 | static unsigned int transition_table[] = |
---|
259 | { /* Octal CBLTR->I */ |
---|
260 | /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */ |
---|
261 | 0000000, 0025271, 0113221, 0202422, 0301021, |
---|
262 | 0000012, 0100011, 0122244, 0202452, 0301220, |
---|
263 | 0000020, 0100061, 0122277, 0202520, 0302511, |
---|
264 | 0000030, 0100077, 0122434, 0202552, 0401120, |
---|
265 | 0000050, 0100111, 0122547, 0202622, 0401220, |
---|
266 | 0000063, 0100121, 0123244, 0202722, 0401250, |
---|
267 | 0000071, 0100211, 0123277, 0203122, 0402120, |
---|
268 | 0000112, 0100244, 0124255, 0203216, 0402221, |
---|
269 | 0000122, 0100277, 0124267, 0203226, 0402326, |
---|
270 | 0000132, 0100511, 0125275, 0203422, 0402520, |
---|
271 | 0000212, 0101011, 0200012, 0204222, 0403221, |
---|
272 | 0000220, 0101111, 0200022, 0205122, 0500022, |
---|
273 | 0000230, 0101244, 0200042, 0205212, 0500215, |
---|
274 | 0000262, 0101277, 0200071, 0205222, 0500225, |
---|
275 | 0000272, 0102026, 0200122, 0205521, 0500232, |
---|
276 | 0000320, 0102121, 0200152, 0205725, 0500272, |
---|
277 | 0000525, 0102211, 0200212, 0206222, 0500520, |
---|
278 | 0000622, 0102244, 0200222, 0206722, 0502022, |
---|
279 | 0000722, 0102263, 0200232, 0207122, 0502122, |
---|
280 | 0001022, 0102277, 0200242, 0207222, 0502152, |
---|
281 | 0001120, 0102327, 0200250, 0207422, 0502220, |
---|
282 | 0002020, 0102424, 0200262, 0207722, 0502244, |
---|
283 | 0002030, 0102626, 0200272, 0211222, 0502722, |
---|
284 | 0002050, 0102644, 0200326, 0211261, 0512122, |
---|
285 | 0002125, 0102677, 0200423, 0212222, 0512220, |
---|
286 | 0002220, 0102710, 0200517, 0212242, 0512422, |
---|
287 | 0002322, 0102727, 0200522, 0212262, 0512722, |
---|
288 | 0005222, 0105427, 0200575, 0212272, 0600011, |
---|
289 | 0012321, 0111121, 0200722, 0214222, 0600021, |
---|
290 | 0012421, 0111221, 0201022, 0215222, 0602120, |
---|
291 | 0012525, 0111244, 0201122, 0216222, 0612125, |
---|
292 | 0012621, 0111251, 0201222, 0217222, 0612131, |
---|
293 | 0012721, 0111261, 0201422, 0222272, 0612225, |
---|
294 | 0012751, 0111277, 0201722, 0222442, 0700077, |
---|
295 | 0014221, 0111522, 0202022, 0222462, 0701120, |
---|
296 | 0014321, 0112121, 0202032, 0222762, 0701220, |
---|
297 | 0014421, 0112221, 0202052, 0222772, 0701250, |
---|
298 | 0014721, 0112244, 0202073, 0300013, 0702120, |
---|
299 | 0016251, 0112251, 0202122, 0300022, 0702221, |
---|
300 | 0017221, 0112277, 0202152, 0300041, 0702251, |
---|
301 | 0017255, 0112321, 0202212, 0300076, 0702321, |
---|
302 | 0017521, 0112424, 0202222, 0300123, 0702525, |
---|
303 | 0017621, 0112621, 0202272, 0300421, 0702720, |
---|
304 | 0017721, 0112727, 0202321, 0300622 |
---|
305 | }; |
---|
306 | |
---|
307 | static unsigned int hex_transition_table[] = |
---|
308 | { /* Octal CBbltTR->I */ |
---|
309 | /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */ |
---|
310 | |
---|
311 | #ifdef TRIA |
---|
312 | 000000000, 000000020, 000000220, 000002220, 000022220, |
---|
313 | 011122121, 011121221, 011122221, 011221221, |
---|
314 | 011222221, 011112121, 011112221, |
---|
315 | 020021122, 020002122, 020211222, 021111222, |
---|
316 | 020221122, 020027122, 020020722, 020021022, |
---|
317 | 001127221, |
---|
318 | 011122727, 011227227, 010122121, 010222211, |
---|
319 | 021117222, 020112272, |
---|
320 | 070221220, |
---|
321 | 001227221, |
---|
322 | 010221121, 011721221, 011222277, |
---|
323 | 020111222, 020221172, |
---|
324 | 070211220, |
---|
325 | 001217221, |
---|
326 | 010212277, 010221221, |
---|
327 | 020122112, |
---|
328 | 070122220, |
---|
329 | 001722221, |
---|
330 | 010221271, |
---|
331 | 020002022, 021122172, |
---|
332 | 070121220, |
---|
333 | 011122277, 011172121, |
---|
334 | 010212177, 011212277, |
---|
335 | 070112220, |
---|
336 | 001772221, |
---|
337 | 021221772, |
---|
338 | 070121270, 070721220, |
---|
339 | 000112721, 000272211, |
---|
340 | 010022211, 012222277, |
---|
341 | 020072272, 020227122, 020217222, |
---|
342 | 010211121, |
---|
343 | 020002727, |
---|
344 | 070222220, |
---|
345 | 001727721, |
---|
346 | 020021072, 020070722, |
---|
347 | 070002072, 070007022, |
---|
348 | 001772721, |
---|
349 | 070002022, |
---|
350 | 000000070, 000000770, 000072220, 000000270, |
---|
351 | 020110222, 020220272, 020220722, |
---|
352 | 070007071, 070002072, 070007022, |
---|
353 | 000000012, 000000122, 000000212, 001277721, |
---|
354 | 020122072, 020202212, |
---|
355 | 010002121, |
---|
356 | 020001122, 020002112, |
---|
357 | 020021722, |
---|
358 | 020122022, 020027022, 020070122, 020020122, |
---|
359 | 010227027, |
---|
360 | 020101222, |
---|
361 | 010227227, 010227277, |
---|
362 | 021722172, |
---|
363 | 001727221, |
---|
364 | 010222277, |
---|
365 | 020702272, |
---|
366 | 070122020, |
---|
367 | 000172721, |
---|
368 | 010022277, 010202177, 010227127, |
---|
369 | |
---|
370 | 001214221, |
---|
371 | 010202244, |
---|
372 | 020024122, 020020422, |
---|
373 | 040122220, |
---|
374 | 001422221, |
---|
375 | 010221241, 010224224, |
---|
376 | 021122142, |
---|
377 | 040121220, |
---|
378 | 001124221, |
---|
379 | 010224274, |
---|
380 | 020112242, 021422172, |
---|
381 | 040221220, |
---|
382 | 001224221, 001427221, |
---|
383 | 010222244, |
---|
384 | 020227042, |
---|
385 | 040122020, |
---|
386 | 000142721, |
---|
387 | 010022244, 010202144, 010224124, |
---|
388 | 040112220, |
---|
389 | 001442221, |
---|
390 | 021221442, |
---|
391 | 040121240, 040421220, |
---|
392 | 000242211, 000112421, |
---|
393 | 020042242, 020214222, 020021422, 020220242, 020024022, |
---|
394 | 011224224, |
---|
395 | 020224122, |
---|
396 | 020220422, |
---|
397 | 012222244, |
---|
398 | 020002424, |
---|
399 | 040222220, |
---|
400 | 001244421, 000000420, 000000440, 000000240, 000000040, |
---|
401 | 020040121, 020021042, |
---|
402 | 040004022, 040004042, 040002042, |
---|
403 | 010021121, |
---|
404 | 020011122, 020002112, |
---|
405 | 001424421, |
---|
406 | 020040422, |
---|
407 | 001442421, |
---|
408 | 040002022, |
---|
409 | 001724221, |
---|
410 | 010227247, |
---|
411 | 020224072, 021417222, |
---|
412 | 000172421, |
---|
413 | 010021721, |
---|
414 | 020017022, |
---|
415 | 020120212, |
---|
416 | 020271727, |
---|
417 | 070207072, 070701220, |
---|
418 | 000001222, |
---|
419 | 020110122, |
---|
420 | 001277221, |
---|
421 | 001777721, |
---|
422 | 020021222, 020202272, 020120222, 020221722, |
---|
423 | 020027227, |
---|
424 | 070070222, |
---|
425 | 000007220, |
---|
426 | 020101272, 020272172, 020721422, 020721722, |
---|
427 | 020011222, 020202242, |
---|
428 | #if 0 |
---|
429 | {2,2,0,0,2,7,0}, |
---|
430 | {2,0,2,0,2,0,2}, |
---|
431 | {2,4,1,2,2,1,2}, |
---|
432 | {2,1,2,1,2,1,2}, |
---|
433 | {2,0,2,2,1,1,2}, |
---|
434 | {2,7,1,1,1,1,2}, |
---|
435 | {0,2,2,2,2,2,2}, |
---|
436 | {2,2,0,0,7,7,0}, |
---|
437 | {2,1,2,0,2,0,7}, |
---|
438 | {2,0,1,2,2,1,2}, |
---|
439 | {2,4,2,1,2,1,2}, |
---|
440 | {2,1,2,2,1,1,2}, |
---|
441 | {2,0,7,1,1,1,2}, |
---|
442 | {0,2,2,2,2,2,2}, |
---|
443 | #endif |
---|
444 | #else |
---|
445 | 000000000, 000000020, 000000220, 000002220, |
---|
446 | 011212121, 011212221, 011221221, 011222221, |
---|
447 | 020002122, 020021122, 020211122, |
---|
448 | |
---|
449 | 010221221, 010222121, |
---|
450 | 020002022, 020021022, 020020122, 020112022, |
---|
451 | |
---|
452 | 010202121, |
---|
453 | 020102022, 020202112, |
---|
454 | |
---|
455 | 000000012, 000000122, 000000212, |
---|
456 | 010002121, |
---|
457 | 020001122, 020002112, 020011122, |
---|
458 | |
---|
459 | |
---|
460 | 001227221, 001272221, 001272721, |
---|
461 | 012212277, 011222727, 011212727, |
---|
462 | 020021722, 020027122, 020020722, 020027022, |
---|
463 | 020211722, 020202172, 020120272, |
---|
464 | 020271122, 020202172, 020207122, 020217122, |
---|
465 | 020120272, 020210722, 020270722, |
---|
466 | 070212220, 070221220, 070212120, |
---|
467 | |
---|
468 | |
---|
469 | 012222277, |
---|
470 | 020002727, |
---|
471 | 070222220, |
---|
472 | |
---|
473 | 001277721, 000000070, 000000270, 000000720, 000000770, |
---|
474 | 020070122, 020021072, |
---|
475 | 070002072, 070007022, 070007071, |
---|
476 | |
---|
477 | 020070722, |
---|
478 | 070002022, |
---|
479 | |
---|
480 | 010227227, 010222727, 010202727, |
---|
481 | 020172022, 020202712, |
---|
482 | |
---|
483 | 001224221, 001242221, 001242421, |
---|
484 | 012212244, 011222424, 011212424, |
---|
485 | 020021422, 020024122, 020020422, 020024022, |
---|
486 | 020211422, 020202142, 020120242, |
---|
487 | 020241122, 020202142, 020204122, 020214122, |
---|
488 | 020120242, 020210422, 020240422, |
---|
489 | 040212220, 040221220, 040212120, |
---|
490 | |
---|
491 | |
---|
492 | 012222244, |
---|
493 | 020002424, |
---|
494 | 040222220, |
---|
495 | |
---|
496 | 001244421, 000000040, 000000240, 000000420, 000000440, |
---|
497 | 020040122, 020021042, |
---|
498 | 040002042, |
---|
499 | 040004021, 040004042, |
---|
500 | |
---|
501 | 020040422, |
---|
502 | 040002022, |
---|
503 | |
---|
504 | 010224224, 010222424, 010202424, |
---|
505 | 020142022, 020202412, |
---|
506 | 020011722, 020112072, 020172072, 020142072, |
---|
507 | |
---|
508 | |
---|
509 | |
---|
510 | 000210225, 000022015, 000022522, |
---|
511 | 011225521, |
---|
512 | 020120525, 020020152, 020005122, 020214255, 020021152, |
---|
513 | 020255242, |
---|
514 | 050215222, 050225121, |
---|
515 | |
---|
516 | 000225220, 001254222, |
---|
517 | 010221250, 011221251, 011225221, |
---|
518 | 020025122, 020152152, 020211252, 020214522, 020511125, |
---|
519 | 050212241, 05221120, |
---|
520 | 040521225, |
---|
521 | |
---|
522 | 000000250, 000000520, 000150220, 000220520, 000222210, |
---|
523 | 001224251, |
---|
524 | 010022152, 010251221, 010522121, 011212151, 011221251, |
---|
525 | 011215221, |
---|
526 | 020000220, 020002152, 020020220, 020022152, |
---|
527 | 020021422, 020022152, 020022522, 020025425, 020050422, |
---|
528 | 020051022, 020051122, 020211122, 020211222, 020215222, |
---|
529 | 020245122, |
---|
530 | 050021125, 050021025, 050011125, 051242221, |
---|
531 | 041225220, |
---|
532 | |
---|
533 | 000220250, 000220520, 001227521, 001275221, |
---|
534 | 011257227, 011522727, |
---|
535 | 020002052, 020002752, 020021052, 020057125, |
---|
536 | 050020722, 050027125, |
---|
537 | 070215220, |
---|
538 | |
---|
539 | 070212255, |
---|
540 | 071225220, |
---|
541 | 020275122, |
---|
542 | 051272521, |
---|
543 | 020055725, |
---|
544 | 020021552, |
---|
545 | 012252277, |
---|
546 | 050002521, |
---|
547 | 020005725, |
---|
548 | |
---|
549 | 050011022, |
---|
550 | 000000155, |
---|
551 | 020050722, |
---|
552 | 001227250, |
---|
553 | 010512727, |
---|
554 | 010002151, |
---|
555 | 020027112, |
---|
556 | 001227251, |
---|
557 | 012227257, |
---|
558 | 050002125, |
---|
559 | 020517122, |
---|
560 | 050002025, |
---|
561 | 020050102, |
---|
562 | 050002725, |
---|
563 | 020570722, |
---|
564 | 001252721, |
---|
565 | 020007051, |
---|
566 | 020102052, |
---|
567 | 020271072, |
---|
568 | 050001122, |
---|
569 | 010002151, |
---|
570 | 011227257, |
---|
571 | 020051722, |
---|
572 | 020057022, |
---|
573 | 020050122, |
---|
574 | |
---|
575 | |
---|
576 | 020051422, |
---|
577 | 011224254, |
---|
578 | 012224254, |
---|
579 | |
---|
580 | 020054022, |
---|
581 | 050002425, |
---|
582 | 040252220, |
---|
583 | 020002454, |
---|
584 | |
---|
585 | |
---|
586 | 000000540, |
---|
587 | 001254425, |
---|
588 | 050004024, |
---|
589 | 040004051, |
---|
590 | |
---|
591 | 000000142, |
---|
592 | 040001522, |
---|
593 | 010002547, |
---|
594 | 020045122, |
---|
595 | 051221240, |
---|
596 | 020002512, |
---|
597 | 020021522, |
---|
598 | |
---|
599 | |
---|
600 | 020020022, |
---|
601 | 021125522, |
---|
602 | 020521122, |
---|
603 | 020025022, |
---|
604 | 020025522, |
---|
605 | 020020522, |
---|
606 | |
---|
607 | 020202222, |
---|
608 | 020212222, |
---|
609 | 021212222, |
---|
610 | 021222722, |
---|
611 | 021222422, |
---|
612 | 020002222, |
---|
613 | 020021222, |
---|
614 | 020022122, |
---|
615 | 020212122, |
---|
616 | 020027222, |
---|
617 | 020024222, |
---|
618 | 020212722, |
---|
619 | 020212422, |
---|
620 | 020202122, |
---|
621 | 001222221, |
---|
622 | 020002522, |
---|
623 | |
---|
624 | 020017125, |
---|
625 | 010022722, |
---|
626 | 020212052, |
---|
627 | |
---|
628 | 020205052, |
---|
629 | 070221250, |
---|
630 | |
---|
631 | 000000050, 000005220, 000002270, 070252220, |
---|
632 | 000000450, 000007220, |
---|
633 | 000220220, 000202220, 000022020, 000020220, |
---|
634 | |
---|
635 | 000222040, |
---|
636 | 000220440, |
---|
637 | 000022040, |
---|
638 | 000040220, |
---|
639 | |
---|
640 | 000252220, |
---|
641 | 050221120, 010221520, |
---|
642 | 002222220, |
---|
643 | |
---|
644 | 000070220, 000220720, |
---|
645 | 000020520, 000070250, 000222070, 000027020, |
---|
646 | 000022070, 000202270, 000024020, 000220420, |
---|
647 | 000220270, 000220240, 000072020, 000042020, |
---|
648 | 000002020, 000002070, 000020270, 000020250, |
---|
649 | 000270270, 000007020, 000040270, |
---|
650 | |
---|
651 | /* Collision starts (gen 540), not sure to have rules to save it |
---|
652 | or depend on calloc to intialize remaining rules to 0 so that |
---|
653 | the mutant will be born |
---|
654 | */ |
---|
655 | 000050220, |
---|
656 | #endif |
---|
657 | }; |
---|
658 | |
---|
659 | |
---|
660 | /*- |
---|
661 | Neighborhoods are read as follows (rotations are not listed): |
---|
662 | T |
---|
663 | L C R ==> I |
---|
664 | B |
---|
665 | |
---|
666 | t T |
---|
667 | l C R ==> I |
---|
668 | b B |
---|
669 | */ |
---|
670 | |
---|
671 | static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] = |
---|
672 | { |
---|
673 | /* 10x10 */ |
---|
674 | {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}, |
---|
675 | {2, 4, 0, 1, 4, 0, 1, 1, 1, 2}, |
---|
676 | {2, 1, 2, 2, 2, 2, 2, 2, 1, 2}, |
---|
677 | {2, 0, 2, 0, 0, 0, 0, 2, 1, 2}, |
---|
678 | {2, 7, 2, 0, 0, 0, 0, 2, 7, 2}, |
---|
679 | {2, 1, 2, 0, 0, 0, 0, 2, 0, 2}, |
---|
680 | {2, 0, 2, 0, 0, 0, 0, 2, 1, 2}, |
---|
681 | {2, 7, 2, 2, 2, 2, 2, 2, 7, 2}, |
---|
682 | {2, 1, 0, 6, 1, 0, 7, 1, 0, 2}, |
---|
683 | {0, 2, 2, 2, 2, 2, 2, 2, 2, 0} |
---|
684 | }; |
---|
685 | |
---|
686 | static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] = |
---|
687 | { |
---|
688 | #if 0 |
---|
689 | /* Experimental TRIA5:7x7 */ |
---|
690 | {2,2,0,0,0,0,0}, |
---|
691 | {2,1,2,0,2,2,0}, |
---|
692 | {2,0,4,2,2,0,2}, |
---|
693 | {2,7,2,0,2,0,2}, |
---|
694 | {2,1,2,2,1,1,2}, |
---|
695 | {2,0,7,1,0,7,2}, |
---|
696 | {0,2,2,2,2,2,2}, |
---|
697 | /* Stem cells, only "5" will fully reproduce itself */ |
---|
698 | /* 3:12x7 */ |
---|
699 | {2,2,2,2,0,0,0,0,0,0,0,0}, |
---|
700 | {2,1,1,1,2,0,0,0,0,0,0,0}, |
---|
701 | {2,1,2,2,1,2,2,2,2,2,2,0}, |
---|
702 | {2,1,2,0,2,7,1,1,1,1,1,2}, |
---|
703 | {0,2,1,2,2,0,2,2,2,2,2,2}, |
---|
704 | {0,0,2,0,4,1,2,0,0,0,0,0}, |
---|
705 | {0,0,0,2,2,2,2,0,0,0,0,0} |
---|
706 | /* 4:14x9 */ |
---|
707 | {2,2,2,2,2,0,0,0,0,0,0,0,0,0}, |
---|
708 | {2,1,1,1,1,2,0,0,0,0,0,0,0,0}, |
---|
709 | {2,1,2,2,2,1,2,0,0,0,0,0,0,0}, |
---|
710 | {2,1,2,0,0,2,1,2,2,2,2,2,2,0}, |
---|
711 | {2,1,2,0,0,0,2,7,1,1,1,1,1,2}, |
---|
712 | {0,2,1,2,0,0,2,0,2,2,2,2,2,2}, |
---|
713 | {0,0,2,0,2,2,2,1,2,0,0,0,0,0}, |
---|
714 | {0,0,0,2,4,1,0,7,2,0,0,0,0,0}, |
---|
715 | {0,0,0,0,2,2,2,2,2,0,0,0,0,0} |
---|
716 | /* 5:16x11 */ |
---|
717 | {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0}, |
---|
718 | {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0}, |
---|
719 | {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0}, |
---|
720 | {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0}, |
---|
721 | {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0}, |
---|
722 | {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2}, |
---|
723 | {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2}, |
---|
724 | {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0}, |
---|
725 | {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0}, |
---|
726 | {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0}, |
---|
727 | {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0} |
---|
728 | /* test:3x7 (0,4) is blank ... very strange. |
---|
729 | init_adam seems ok something after that I guess */ |
---|
730 | {2,2,0}, |
---|
731 | {2,0,2}, |
---|
732 | {0,2,2}, |
---|
733 | {0,0,0}, |
---|
734 | {2,2,0}, |
---|
735 | {2,1,2}, |
---|
736 | {0,2,2}, |
---|
737 | #else /* this might be better for hexagons, spacewise efficient... */ |
---|
738 | #ifdef TRIA |
---|
739 | /* Experimental TRIA5:7x7 */ |
---|
740 | {2,2,0,0,2,2,0}, |
---|
741 | {2,4,2,0,2,7,2}, |
---|
742 | {2,1,0,2,2,0,2}, |
---|
743 | {2,0,2,1,2,1,2}, |
---|
744 | {2,7,2,2,7,7,2}, |
---|
745 | {2,1,0,7,1,0,2}, |
---|
746 | {0,2,2,2,2,2,2}, |
---|
747 | #else |
---|
748 | /* 5:11x11 */ |
---|
749 | {2,2,2,2,2,2,0,0,0,0,0}, |
---|
750 | {2,1,1,7,0,1,2,0,0,0,0}, |
---|
751 | {2,1,2,2,2,2,7,2,0,0,0}, |
---|
752 | {2,1,2,0,0,0,2,0,2,0,0}, |
---|
753 | {2,1,2,0,0,0,0,2,1,2,0}, |
---|
754 | {2,1,2,0,0,0,0,0,2,7,2}, |
---|
755 | {0,2,1,2,0,0,0,0,2,0,2}, |
---|
756 | {0,0,2,1,2,0,0,0,2,1,2}, |
---|
757 | {0,0,0,2,1,2,2,2,2,4,2}, |
---|
758 | {0,0,0,0,2,1,1,1,1,5,2}, |
---|
759 | {0,0,0,0,0,2,2,2,2,2,2} |
---|
760 | #endif |
---|
761 | #endif |
---|
762 | }; |
---|
763 | |
---|
764 | static void |
---|
765 | position_of_neighbor(int dir, int *pcol, int *prow) |
---|
766 | { |
---|
767 | int col = *pcol, row = *prow; |
---|
768 | |
---|
769 | /* NO WRAPING */ |
---|
770 | |
---|
771 | if (local_neighbors == 6) { |
---|
772 | switch (dir) { |
---|
773 | case 0: |
---|
774 | col++; |
---|
775 | break; |
---|
776 | case 60: |
---|
777 | col += (row & 1); |
---|
778 | row--; |
---|
779 | break; |
---|
780 | case 120: |
---|
781 | col -= !(row & 1); |
---|
782 | row--; |
---|
783 | break; |
---|
784 | case 180: |
---|
785 | col--; |
---|
786 | break; |
---|
787 | case 240: |
---|
788 | col -= !(row & 1); |
---|
789 | row++; |
---|
790 | break; |
---|
791 | case 300: |
---|
792 | col += (row & 1); |
---|
793 | row++; |
---|
794 | break; |
---|
795 | default: |
---|
796 | (void) fprintf(stderr, "wrong direction %d\n", dir); |
---|
797 | } |
---|
798 | } else { |
---|
799 | switch (dir) { |
---|
800 | case 0: |
---|
801 | col++; |
---|
802 | break; |
---|
803 | case 90: |
---|
804 | row--; |
---|
805 | break; |
---|
806 | case 180: |
---|
807 | col--; |
---|
808 | break; |
---|
809 | case 270: |
---|
810 | row++; |
---|
811 | break; |
---|
812 | default: |
---|
813 | (void) fprintf(stderr, "wrong direction %d\n", dir); |
---|
814 | } |
---|
815 | } |
---|
816 | *pcol = col; |
---|
817 | *prow = row; |
---|
818 | } |
---|
819 | |
---|
820 | static Bool |
---|
821 | withinBounds(loopstruct * lp, int col, int row) |
---|
822 | { |
---|
823 | return (row >= 1 && row < lp->bnrows - 1 && |
---|
824 | col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2))); |
---|
825 | } |
---|
826 | |
---|
827 | static void |
---|
828 | fillcell(ModeInfo * mi, GC gc, int col, int row) |
---|
829 | { |
---|
830 | loopstruct *lp = &loops[MI_SCREEN(mi)]; |
---|
831 | |
---|
832 | if (local_neighbors == 6) { |
---|
833 | int ccol = 2 * col + !(row & 1), crow = 2 * row; |
---|
834 | |
---|
835 | lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs; |
---|
836 | lp->shape.hexagon[0].y = lp->yb + crow * lp->ys; |
---|
837 | if (lp->xs == 1 && lp->ys == 1) |
---|
838 | XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc, |
---|
839 | lp->shape.hexagon[0].x, lp->shape.hexagon[0].y); |
---|
840 | else |
---|
841 | XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc, |
---|
842 | lp->shape.hexagon, 6, Convex, CoordModePrevious); |
---|
843 | } else { |
---|
844 | XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc, |
---|
845 | lp->xb + lp->xs * col, lp->yb + lp->ys * row, |
---|
846 | lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3)); |
---|
847 | } |
---|
848 | } |
---|
849 | |
---|
850 | static void |
---|
851 | drawcell(ModeInfo * mi, int col, int row, int state) |
---|
852 | { |
---|
853 | loopstruct *lp = &loops[MI_SCREEN(mi)]; |
---|
854 | XGCValues gcv; |
---|
855 | GC gc; |
---|
856 | |
---|
857 | if (MI_NPIXELS(mi) >= COLORS) { |
---|
858 | gc = MI_GC(mi); |
---|
859 | XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]); |
---|
860 | } else { |
---|
861 | gcv.stipple = lp->pixmaps[state]; |
---|
862 | gcv.foreground = MI_WHITE_PIXEL(mi); |
---|
863 | gcv.background = MI_BLACK_PIXEL(mi); |
---|
864 | XChangeGC(MI_DISPLAY(mi), lp->stippledGC, |
---|
865 | GCStipple | GCForeground | GCBackground, &gcv); |
---|
866 | gc = lp->stippledGC; |
---|
867 | } |
---|
868 | fillcell(mi, gc, col, row); |
---|
869 | } |
---|
870 | |
---|
871 | #ifdef DEBUG |
---|
872 | static void |
---|
873 | print_state(ModeInfo * mi, int state) |
---|
874 | { |
---|
875 | loopstruct *lp = &loops[MI_SCREEN(mi)]; |
---|
876 | CellList *locallist = lp->cellList[state]; |
---|
877 | int i = 0; |
---|
878 | |
---|
879 | (void) printf("state %d\n", state); |
---|
880 | while (locallist) { |
---|
881 | (void) printf("%d x %d, y %d\n", i, |
---|
882 | locallist->pt.x, locallist->pt.y); |
---|
883 | locallist = locallist->next; |
---|
884 | i++; |
---|
885 | } |
---|
886 | } |
---|
887 | |
---|
888 | #endif |
---|
889 | |
---|
890 | static void |
---|
891 | free_state(loopstruct * lp, int state) |
---|
892 | { |
---|
893 | CellList *current; |
---|
894 | |
---|
895 | while (lp->cellList[state]) { |
---|
896 | current = lp->cellList[state]; |
---|
897 | lp->cellList[state] = lp->cellList[state]->next; |
---|
898 | (void) free((void *) current); |
---|
899 | } |
---|
900 | lp->ncells[state] = 0; |
---|
901 | } |
---|
902 | |
---|
903 | static void |
---|
904 | free_list(loopstruct * lp) |
---|
905 | { |
---|
906 | int state; |
---|
907 | |
---|
908 | for (state = 0; state < COLORS; state++) |
---|
909 | free_state(lp, state); |
---|
910 | } |
---|
911 | |
---|
912 | static void |
---|
913 | free_loop(Display *display, loopstruct * lp) |
---|
914 | { |
---|
915 | int shade; |
---|
916 | |
---|
917 | for (shade = 0; shade < lp->init_bits; shade++) |
---|
918 | if (lp->pixmaps[shade] != None) { |
---|
919 | XFreePixmap(display, lp->pixmaps[shade]); |
---|
920 | lp->pixmaps[shade] = None; |
---|
921 | } |
---|
922 | if (lp->stippledGC != None) { |
---|
923 | XFreeGC(display, lp->stippledGC); |
---|
924 | lp->stippledGC = None; |
---|
925 | } |
---|
926 | if (lp->oldcells != NULL) { |
---|
927 | (void) free((void *) lp->oldcells); |
---|
928 | lp->oldcells = (unsigned char *) NULL; |
---|
929 | } |
---|
930 | if (lp->newcells != NULL) { |
---|
931 | (void) free((void *) lp->newcells); |
---|
932 | lp->newcells = (unsigned char *) NULL; |
---|
933 | } |
---|
934 | free_list(lp); |
---|
935 | } |
---|
936 | |
---|
937 | static Bool |
---|
938 | addtolist(ModeInfo * mi, int col, int row, unsigned char state) |
---|
939 | { |
---|
940 | loopstruct *lp = &loops[MI_SCREEN(mi)]; |
---|
941 | CellList *current = lp->cellList[state]; |
---|
942 | |
---|
943 | if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) == |
---|
944 | NULL) { |
---|
945 | lp->cellList[state] = current; |
---|
946 | free_loop(MI_DISPLAY(mi), lp); |
---|
947 | return False; |
---|
948 | } |
---|
949 | lp->cellList[state]->pt.x = col; |
---|
950 | lp->cellList[state]->pt.y = row; |
---|
951 | lp->cellList[state]->next = current; |
---|
952 | lp->ncells[state]++; |
---|
953 | return True; |
---|
954 | } |
---|
955 | |
---|
956 | static Bool |
---|
957 | draw_state(ModeInfo * mi, int state) |
---|
958 | { |
---|
959 | loopstruct *lp = &loops[MI_SCREEN(mi)]; |
---|
960 | Display *display = MI_DISPLAY(mi); |
---|
961 | GC gc; |
---|
962 | XGCValues gcv; |
---|
963 | CellList *current = lp->cellList[state]; |
---|
964 | |
---|
965 | if (MI_NPIXELS(mi) >= COLORS) { |
---|
966 | gc = MI_GC(mi); |
---|
967 | XSetForeground(display, gc, lp->colors[state]); |
---|
968 | } else { |
---|
969 | gcv.stipple = lp->pixmaps[state]; |
---|
970 | gcv.foreground = MI_WHITE_PIXEL(mi); |
---|
971 | gcv.background = MI_BLACK_PIXEL(mi); |
---|
972 | XChangeGC(display, lp->stippledGC, |
---|
973 | GCStipple | GCForeground | GCBackground, &gcv); |
---|
974 | gc = lp->stippledGC; |
---|
975 | } |
---|
976 | |
---|
977 | if (local_neighbors == 6) { /* Draw right away, slow */ |
---|
978 | while (current) { |
---|
979 | int col, row, ccol, crow; |
---|
980 | |
---|
981 | col = current->pt.x; |
---|
982 | row = current->pt.y; |
---|
983 | ccol = 2 * col + !(row & 1), crow = 2 * row; |
---|
984 | lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs; |
---|
985 | lp->shape.hexagon[0].y = lp->yb + crow * lp->ys; |
---|
986 | if (lp->xs == 1 && lp->ys == 1) |
---|
987 | XDrawPoint(display, MI_WINDOW(mi), gc, |
---|
988 | lp->shape.hexagon[0].x, lp->shape.hexagon[0].y); |
---|
989 | else |
---|
990 | XFillPolygon(display, MI_WINDOW(mi), gc, |
---|
991 | lp->shape.hexagon, 6, Convex, CoordModePrevious); |
---|
992 | current = current->next; |
---|
993 | } |
---|
994 | } else { |
---|
995 | /* Take advantage of XFillRectangles */ |
---|
996 | XRectangle *rects; |
---|
997 | int nrects = 0; |
---|
998 | |
---|
999 | /* Create Rectangle list from part of the cellList */ |
---|
1000 | if ((rects = (XRectangle *) malloc(lp->ncells[state] * |
---|
1001 | sizeof (XRectangle))) == NULL) { |
---|
1002 | return False; |
---|
1003 | } |
---|
1004 | |
---|
1005 | while (current) { |
---|
1006 | rects[nrects].x = lp->xb + current->pt.x * lp->xs; |
---|
1007 | rects[nrects].y = lp->yb + current->pt.y * lp->ys; |
---|
1008 | rects[nrects].width = lp->xs - (lp->xs > 3); |
---|
1009 | rects[nrects].height = lp->ys - (lp->ys > 3); |
---|
1010 | current = current->next; |
---|
1011 | nrects++; |
---|
1012 | } |
---|
1013 | /* Finally get to draw */ |
---|
1014 | XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects); |
---|
1015 | /* Free up rects list and the appropriate part of the cellList */ |
---|
1016 | (void) free((void *) rects); |
---|
1017 | } |
---|
1018 | free_state(lp, state); |
---|
1019 | XFlush(display); |
---|
1020 | return True; |
---|
1021 | } |
---|
1022 | |
---|
1023 | static Bool |
---|
1024 | init_table(void) |
---|
1025 | { |
---|
1026 | if (table == NULL) { |
---|
1027 | int mult = 1; |
---|
1028 | unsigned int tt, c, n[MAXNEIGHBORS], i; |
---|
1029 | int j, k; |
---|
1030 | int size_transition_table = sizeof (transition_table) / |
---|
1031 | sizeof (unsigned int); |
---|
1032 | int size_hex_transition_table = sizeof (hex_transition_table) / |
---|
1033 | sizeof (unsigned int); |
---|
1034 | |
---|
1035 | for (j = 0; j < local_neighbors; j++) |
---|
1036 | mult *= 8; |
---|
1037 | |
---|
1038 | if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) { |
---|
1039 | return False; |
---|
1040 | } |
---|
1041 | |
---|
1042 | |
---|
1043 | #ifdef RAND_RULES |
---|
1044 | /* Here I was interested to see what happens when it hits a wall.... |
---|
1045 | Rules not normally used take over... takes too much time though */ |
---|
1046 | /* Each state = 3 bits */ |
---|
1047 | if (MAXRAND < 16777216.0) { |
---|
1048 | for (j = 0; j < mult; j++) { |
---|
1049 | table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096)); |
---|
1050 | } |
---|
1051 | } else { |
---|
1052 | for (j = 0; j < mult; j++) { |
---|
1053 | table[j] = (unsigned int) (NRAND(16777216)); |
---|
1054 | } |
---|
1055 | } |
---|
1056 | #endif |
---|
1057 | if (local_neighbors == 6) { |
---|
1058 | for (j = 0; j < size_hex_transition_table; j++) { |
---|
1059 | tt = hex_transition_table[j]; |
---|
1060 | TRANSITION(tt, i); |
---|
1061 | for (k = 0; k < local_neighbors; k++) { |
---|
1062 | TRANSITION(tt, n[k]); |
---|
1063 | } |
---|
1064 | FINALTRANSITION(tt, c); |
---|
1065 | HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i); |
---|
1066 | HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i); |
---|
1067 | HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i); |
---|
1068 | HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i); |
---|
1069 | HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i); |
---|
1070 | HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i); |
---|
1071 | } |
---|
1072 | } else { |
---|
1073 | for (j = 0; j < size_transition_table; j++) { |
---|
1074 | tt = transition_table[j]; |
---|
1075 | TRANSITION(tt, i); |
---|
1076 | for (k = 0; k < local_neighbors; k++) { |
---|
1077 | TRANSITION(tt, n[k]); |
---|
1078 | } |
---|
1079 | FINALTRANSITION(tt, c); |
---|
1080 | TABLE_IN(c, n[0], n[1], n[2], n[3], i); |
---|
1081 | TABLE_IN(c, n[1], n[2], n[3], n[0], i); |
---|
1082 | TABLE_IN(c, n[2], n[3], n[0], n[1], i); |
---|
1083 | TABLE_IN(c, n[3], n[0], n[1], n[2], i); |
---|
1084 | } |
---|
1085 | } |
---|
1086 | } |
---|
1087 | return True; |
---|
1088 | } |
---|
1089 | |
---|
1090 | static void |
---|
1091 | init_flaw(ModeInfo * mi) |
---|
1092 | { |
---|
1093 | loopstruct *lp = &loops[MI_SCREEN(mi)]; |
---|
1094 | int a, b; |
---|
1095 | |
---|
1096 | #define BLUE 2 |
---|
1097 | if (lp->bncols <= 3 || lp->bnrows <= 3) |
---|
1098 | return; |
---|
1099 | a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ? |
---|
1100 | HEX_MINGRIDSIZE : MINGRIDSIZE)); |
---|
1101 | a = NRAND(a) + (lp->bncols - a) / 2; |
---|
1102 | b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ? |
---|
1103 | HEX_MINGRIDSIZE : MINGRIDSIZE)); |
---|
1104 | b = NRAND(b) + (lp->bnrows - b) / 2; |
---|
1105 | if (lp->mincol > a) |
---|
1106 | lp->mincol = a; |
---|
1107 | if (lp->minrow > b) |
---|
1108 | lp->minrow = b; |
---|
1109 | if (lp->maxcol < a + 2) |
---|
1110 | lp->maxcol = a + 2; |
---|
1111 | if (lp->maxrow < b + 2) |
---|
1112 | lp->maxrow = b + 2; |
---|
1113 | |
---|
1114 | if (local_neighbors == 6) { |
---|
1115 | lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE; |
---|
1116 | lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE; |
---|
1117 | lp->newcells[(b + 1) * lp->bncols + a] = BLUE; |
---|
1118 | lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE; |
---|
1119 | lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE; |
---|
1120 | lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE; |
---|
1121 | } else { |
---|
1122 | int orient = NRAND(4); |
---|
1123 | lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE; |
---|
1124 | if (orient == 0 || orient == 1) { |
---|
1125 | lp->newcells[lp->bncols * b + a + 1] = BLUE; |
---|
1126 | } |
---|
1127 | if (orient == 1 || orient == 2) { |
---|
1128 | lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE; |
---|
1129 | } |
---|
1130 | if (orient == 2 || orient == 3) { |
---|
1131 | lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE; |
---|
1132 | } |
---|
1133 | if (orient == 3 || orient == 0) { |
---|
1134 | lp->newcells[lp->bncols * (b + 1) + a] = BLUE; |
---|
1135 | } |
---|
1136 | } |
---|
1137 | } |
---|
1138 | |
---|
1139 | static void |
---|
1140 | init_adam(ModeInfo * mi) |
---|
1141 | { |
---|
1142 | loopstruct *lp = &loops[MI_SCREEN(mi)]; |
---|
1143 | XPoint start, dirx, diry; |
---|
1144 | int i, j, dir; |
---|
1145 | |
---|
1146 | #ifdef DELAYDEBUGLOOP |
---|
1147 | lp->clockwise = 0; |
---|
1148 | if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */ |
---|
1149 | #endif |
---|
1150 | lp->clockwise = (Bool) (LRAND() & 1); |
---|
1151 | #ifdef DELAYDEBUGLOOP |
---|
1152 | dir = 0; |
---|
1153 | if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */ |
---|
1154 | #endif |
---|
1155 | dir = NRAND(local_neighbors); |
---|
1156 | if (local_neighbors == 6) { |
---|
1157 | int k; |
---|
1158 | |
---|
1159 | switch (dir) { |
---|
1160 | case 0: |
---|
1161 | start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2; |
---|
1162 | start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2; |
---|
1163 | if (lp->mincol > start.x - 2) |
---|
1164 | lp->mincol = start.x - 2; |
---|
1165 | if (lp->minrow > start.y - 1) |
---|
1166 | lp->minrow = start.y - 1; |
---|
1167 | if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1) |
---|
1168 | lp->maxcol = start.x + HEX_ADAM_LOOPX + 1; |
---|
1169 | if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) |
---|
1170 | lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; |
---|
1171 | for (j = 0; j < HEX_ADAM_LOOPY; j++) { |
---|
1172 | for (i = 0; i < HEX_ADAM_LOOPX; i++) { |
---|
1173 | k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2); |
---|
1174 | lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] = |
---|
1175 | (lp->clockwise) ? |
---|
1176 | hex_self_reproducing_loop[i][j] : |
---|
1177 | hex_self_reproducing_loop[j][i]; |
---|
1178 | } |
---|
1179 | } |
---|
1180 | break; |
---|
1181 | case 1: |
---|
1182 | start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2; |
---|
1183 | start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2; |
---|
1184 | if (lp->mincol > start.x - 1) |
---|
1185 | lp->mincol = start.x - 1; |
---|
1186 | if (lp->minrow > start.y - HEX_ADAM_LOOPX) |
---|
1187 | lp->minrow = start.y - HEX_ADAM_LOOPX; |
---|
1188 | if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1) |
---|
1189 | lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1; |
---|
1190 | if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) |
---|
1191 | lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; |
---|
1192 | for (j = 0; j < HEX_ADAM_LOOPY; j++) { |
---|
1193 | for (i = 0; i < HEX_ADAM_LOOPX; i++) { |
---|
1194 | k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2) |
---|
1195 | ? -(i + j + 1) / 2 : -(i + j) / 2); |
---|
1196 | lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] = |
---|
1197 | (lp->clockwise) ? |
---|
1198 | hex_self_reproducing_loop[i][j] : |
---|
1199 | hex_self_reproducing_loop[j][i]; |
---|
1200 | } |
---|
1201 | } |
---|
1202 | break; |
---|
1203 | case 2: |
---|
1204 | start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2; |
---|
1205 | start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2; |
---|
1206 | if (lp->mincol > start.x - 2) |
---|
1207 | lp->mincol = start.x - 2; |
---|
1208 | if (lp->minrow > start.y - 1) |
---|
1209 | lp->minrow = start.y - 1; |
---|
1210 | if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1) |
---|
1211 | lp->maxcol = start.x + HEX_ADAM_LOOPX + 1; |
---|
1212 | if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) |
---|
1213 | lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; |
---|
1214 | for (j = 0; j < HEX_ADAM_LOOPX; j++) { |
---|
1215 | for (i = 0; i < HEX_ADAM_LOOPY; i++) { |
---|
1216 | k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2); |
---|
1217 | lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] = |
---|
1218 | (lp->clockwise) ? |
---|
1219 | hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] : |
---|
1220 | hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1]; |
---|
1221 | } |
---|
1222 | } |
---|
1223 | break; |
---|
1224 | case 3: |
---|
1225 | start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2; |
---|
1226 | start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2; |
---|
1227 | if (lp->mincol > start.x - 1) |
---|
1228 | lp->mincol = start.x - 1; |
---|
1229 | if (lp->minrow > start.y - 1) |
---|
1230 | lp->minrow = start.y - 1; |
---|
1231 | if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1) |
---|
1232 | lp->maxcol = start.x + HEX_ADAM_LOOPX + 1; |
---|
1233 | if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) |
---|
1234 | lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; |
---|
1235 | for (j = 0; j < HEX_ADAM_LOOPY; j++) { |
---|
1236 | for (i = 0; i < HEX_ADAM_LOOPX; i++) { |
---|
1237 | k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2); |
---|
1238 | lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] = |
---|
1239 | (lp->clockwise) ? |
---|
1240 | hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] : |
---|
1241 | hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1]; |
---|
1242 | } |
---|
1243 | } |
---|
1244 | break; |
---|
1245 | case 4: |
---|
1246 | start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2; |
---|
1247 | start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2; |
---|
1248 | if (lp->mincol > start.x - 1) |
---|
1249 | lp->mincol = start.x - 1; |
---|
1250 | if (lp->minrow > start.y - HEX_ADAM_LOOPX) |
---|
1251 | lp->minrow = start.y - HEX_ADAM_LOOPX; |
---|
1252 | if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1) |
---|
1253 | lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1; |
---|
1254 | if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1) |
---|
1255 | lp->maxrow = start.y + HEX_ADAM_LOOPY + 1; |
---|
1256 | for (j = 0; j < HEX_ADAM_LOOPY; j++) { |
---|
1257 | for (i = 0; i < HEX_ADAM_LOOPX; i++) { |
---|
1258 | k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2) |
---|
1259 | ? -(i + j + 1) / 2 : -(i + j) / 2); |
---|
1260 | lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] = |
---|
1261 | (lp->clockwise) ? |
---|
1262 | hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] : |
---|
1263 | hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1]; |
---|
1264 | } |
---|
1265 | } |
---|
1266 | break; |
---|
1267 | case 5: |
---|
1268 | start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2; |
---|
1269 | start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2; |
---|
1270 | if (lp->mincol > start.x - 2) |
---|
1271 | lp->mincol = start.x - 2; |
---|
1272 | if (lp->minrow > start.y - 1) |
---|
1273 | lp->minrow = start.y - 1; |
---|
1274 | if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1) |
---|
1275 | lp->maxcol = start.x + HEX_ADAM_LOOPY + 1; |
---|
1276 | if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1) |
---|
1277 | lp->maxrow = start.y + HEX_ADAM_LOOPX + 1; |
---|
1278 | for (j = 0; j < HEX_ADAM_LOOPX; j++) { |
---|
1279 | for (i = 0; i < HEX_ADAM_LOOPY; i++) { |
---|
1280 | k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2); |
---|
1281 | lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] = |
---|
1282 | (lp->clockwise) ? |
---|
1283 | hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] : |
---|
1284 | hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j]; |
---|
1285 | } |
---|
1286 | } |
---|
1287 | break; |
---|
1288 | } |
---|
1289 | #if DEBUGTEST |
---|
1290 | /* (void) printf ("s %d s %d \n", start.x, start.y); */ |
---|
1291 | (void) printf ("%d %d %d %d %d\n", |
---|
1292 | start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx, |
---|
1293 | start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]); |
---|
1294 | /* Draw right away */ |
---|
1295 | drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx, |
---|
1296 | start.y + j - lp->by, |
---|
1297 | hex_self_reproducing_loop[j][i]); |
---|
1298 | #endif |
---|
1299 | } else { |
---|
1300 | switch (dir) { |
---|
1301 | case 0: |
---|
1302 | start.x = (lp->bncols - ADAM_LOOPX) / 2; |
---|
1303 | start.y = (lp->bnrows - ADAM_LOOPY) / 2; |
---|
1304 | dirx.x = 1, dirx.y = 0; |
---|
1305 | diry.x = 0, diry.y = 1; |
---|
1306 | if (lp->mincol > start.x) |
---|
1307 | lp->mincol = start.x; |
---|
1308 | if (lp->minrow > start.y) |
---|
1309 | lp->minrow = start.y; |
---|
1310 | if (lp->maxcol < start.x + ADAM_LOOPX) |
---|
1311 | lp->maxcol = start.x + ADAM_LOOPX; |
---|
1312 | if (lp->maxrow < start.y + ADAM_LOOPY) |
---|
1313 | lp->maxrow = start.y + ADAM_LOOPY; |
---|
1314 | break; |
---|
1315 | case 1: |
---|
1316 | start.x = (lp->bncols + ADAM_LOOPY) / 2; |
---|
1317 | start.y = (lp->bnrows - ADAM_LOOPX) / 2; |
---|
1318 | dirx.x = 0, dirx.y = 1; |
---|
1319 | diry.x = -1, diry.y = 0; |
---|
1320 | if (lp->mincol > start.x - ADAM_LOOPY) |
---|
1321 | lp->mincol = start.x - ADAM_LOOPY; |
---|
1322 | if (lp->minrow > start.y) |
---|
1323 | lp->minrow = start.y; |
---|
1324 | if (lp->maxcol < start.x) |
---|
1325 | lp->maxcol = start.x; |
---|
1326 | if (lp->maxrow < start.y + ADAM_LOOPX) |
---|
1327 | lp->maxrow = start.y + ADAM_LOOPX; |
---|
1328 | break; |
---|
1329 | case 2: |
---|
1330 | start.x = (lp->bncols + ADAM_LOOPX) / 2; |
---|
1331 | start.y = (lp->bnrows + ADAM_LOOPY) / 2; |
---|
1332 | dirx.x = -1, dirx.y = 0; |
---|
1333 | diry.x = 0, diry.y = -1; |
---|
1334 | if (lp->mincol > start.x - ADAM_LOOPX) |
---|
1335 | lp->mincol = start.x - ADAM_LOOPX; |
---|
1336 | if (lp->minrow > start.y - ADAM_LOOPY) |
---|
1337 | lp->minrow = start.y - ADAM_LOOPY; |
---|
1338 | if (lp->maxcol < start.x) |
---|
1339 | lp->maxcol = start.x; |
---|
1340 | if (lp->maxrow < start.y) |
---|
1341 | lp->maxrow = start.y; |
---|
1342 | break; |
---|
1343 | case 3: |
---|
1344 | start.x = (lp->bncols - ADAM_LOOPY) / 2; |
---|
1345 | start.y = (lp->bnrows + ADAM_LOOPX) / 2; |
---|
1346 | dirx.x = 0, dirx.y = -1; |
---|
1347 | diry.x = 1, diry.y = 0; |
---|
1348 | if (lp->mincol > start.x) |
---|
1349 | lp->mincol = start.x; |
---|
1350 | if (lp->minrow > start.y - ADAM_LOOPX) |
---|
1351 | lp->minrow = start.y - ADAM_LOOPX; |
---|
1352 | if (lp->maxcol < start.x + ADAM_LOOPX) |
---|
1353 | lp->maxcol = start.x + ADAM_LOOPX; |
---|
1354 | if (lp->maxrow < start.y) |
---|
1355 | lp->maxrow = start.y; |
---|
1356 | break; |
---|
1357 | } |
---|
1358 | for (j = 0; j < ADAM_LOOPY; j++) |
---|
1359 | for (i = 0; i < ADAM_LOOPX; i++) |
---|
1360 | lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) + |
---|
1361 | start.x + dirx.x * i + diry.x * j] = |
---|
1362 | (lp->clockwise) ? |
---|
1363 | self_reproducing_loop[j][ADAM_LOOPX - i - 1] : |
---|
1364 | self_reproducing_loop[j][i]; |
---|
1365 | #if DEBUG |
---|
1366 | /* Draw right away */ |
---|
1367 | drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx, |
---|
1368 | start.y + dirx.y * i + diry.y * j - lp->by, |
---|
1369 | (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]); |
---|
1370 | #endif |
---|
1371 | } |
---|
1372 | } |
---|
1373 | |
---|
1374 | |
---|
1375 | static void |
---|
1376 | do_gen(loopstruct * lp) |
---|
1377 | { |
---|
1378 | int i, j, k; |
---|
1379 | unsigned char *z; |
---|
1380 | unsigned int n[MAXNEIGHBORS]; |
---|
1381 | unsigned int c; |
---|
1382 | |
---|
1383 | #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols))) |
---|
1384 | |
---|
1385 | for (j = lp->minrow; j <= lp->maxrow; j++) { |
---|
1386 | for (i = lp->mincol; i <= lp->maxcol; i++) { |
---|
1387 | z = lp->newcells + i + j * lp->bncols; |
---|
1388 | c = LOC(i, j); |
---|
1389 | for (k = 0; k < local_neighbors; k++) { |
---|
1390 | int newi = i, newj = j; |
---|
1391 | |
---|
1392 | position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj); |
---|
1393 | n[k] = 0; |
---|
1394 | if (withinBounds(lp, newi, newj)) { |
---|
1395 | n[k] = LOC(newi, newj); |
---|
1396 | } |
---|
1397 | } |
---|
1398 | if (local_neighbors == 6) { |
---|
1399 | *z = (lp->clockwise) ? |
---|
1400 | HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) : |
---|
1401 | HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]); |
---|
1402 | } else { |
---|
1403 | *z = (lp->clockwise) ? |
---|
1404 | TABLE_OUT(c, n[3], n[2], n[1], n[0]) : |
---|
1405 | TABLE_OUT(c, n[0], n[1], n[2], n[3]); |
---|
1406 | } |
---|
1407 | } |
---|
1408 | } |
---|
1409 | } |
---|
1410 | |
---|
1411 | void |
---|
1412 | release_loop(ModeInfo * mi) |
---|
1413 | { |
---|
1414 | if (loops != NULL) { |
---|
1415 | int screen; |
---|
1416 | |
---|
1417 | for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) |
---|
1418 | free_loop(MI_DISPLAY(mi), &loops[screen]); |
---|
1419 | (void) free((void *) loops); |
---|
1420 | loops = (loopstruct *) NULL; |
---|
1421 | } |
---|
1422 | if (table != NULL) { |
---|
1423 | (void) free((void *) table); |
---|
1424 | table = (unsigned int *) NULL; |
---|
1425 | } |
---|
1426 | } |
---|
1427 | |
---|
1428 | void |
---|
1429 | init_loop(ModeInfo * mi) |
---|
1430 | { |
---|
1431 | Display *display = MI_DISPLAY(mi); |
---|
1432 | Window window = MI_WINDOW(mi); |
---|
1433 | int i, size = MI_SIZE(mi); |
---|
1434 | loopstruct *lp; |
---|
1435 | XGCValues gcv; |
---|
1436 | |
---|
1437 | if (loops == NULL) { |
---|
1438 | if ((loops = (loopstruct *) calloc(MI_NUM_SCREENS(mi), |
---|
1439 | sizeof (loopstruct))) == NULL) |
---|
1440 | return; |
---|
1441 | } |
---|
1442 | lp = &loops[MI_SCREEN(mi)]; |
---|
1443 | |
---|
1444 | lp->redrawing = 0; |
---|
1445 | |
---|
1446 | if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) { |
---|
1447 | if (lp->stippledGC == None) { |
---|
1448 | gcv.fill_style = FillOpaqueStippled; |
---|
1449 | if ((lp->stippledGC = XCreateGC(display, window, |
---|
1450 | GCFillStyle, &gcv)) == None) { |
---|
1451 | free_loop(display, lp); |
---|
1452 | return; |
---|
1453 | } |
---|
1454 | } |
---|
1455 | LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE); |
---|
1456 | LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE); |
---|
1457 | LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE); |
---|
1458 | LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE); |
---|
1459 | LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE); |
---|
1460 | LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE); |
---|
1461 | LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE); |
---|
1462 | LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE); |
---|
1463 | } |
---|
1464 | if (MI_NPIXELS(mi) >= COLORS) { |
---|
1465 | /* Maybe these colors should be randomized */ |
---|
1466 | lp->colors[0] = MI_BLACK_PIXEL(mi); |
---|
1467 | lp->colors[1] = MI_PIXEL(mi, 0); /* RED */ |
---|
1468 | lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */ |
---|
1469 | lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */ |
---|
1470 | lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */ |
---|
1471 | lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */ |
---|
1472 | lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */ |
---|
1473 | lp->colors[7] = MI_WHITE_PIXEL(mi); |
---|
1474 | } |
---|
1475 | free_list(lp); |
---|
1476 | lp->generation = 0; |
---|
1477 | lp->width = MI_WIDTH(mi); |
---|
1478 | lp->height = MI_HEIGHT(mi); |
---|
1479 | |
---|
1480 | if (!local_neighbors) { |
---|
1481 | for (i = 0; i < NEIGHBORKINDS; i++) { |
---|
1482 | if (neighbors == plots[i]) { |
---|
1483 | local_neighbors = neighbors; |
---|
1484 | break; |
---|
1485 | } |
---|
1486 | if (i == NEIGHBORKINDS - 1) { |
---|
1487 | #if 1 |
---|
1488 | local_neighbors = plots[NRAND(NEIGHBORKINDS)]; |
---|
1489 | #else |
---|
1490 | local_neighbors = 4; |
---|
1491 | #endif |
---|
1492 | break; |
---|
1493 | } |
---|
1494 | } |
---|
1495 | } |
---|
1496 | |
---|
1497 | |
---|
1498 | if (local_neighbors == 6) { |
---|
1499 | int nccols, ncrows; |
---|
1500 | |
---|
1501 | if (lp->width < 8) |
---|
1502 | lp->width = 8; |
---|
1503 | if (lp->height < 8) |
---|
1504 | lp->height = 8; |
---|
1505 | if (size < -MINSIZE) { |
---|
1506 | lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) / |
---|
1507 | HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; |
---|
1508 | } else if (size < MINSIZE) { |
---|
1509 | if (!size) |
---|
1510 | lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE); |
---|
1511 | else |
---|
1512 | lp->ys = MINSIZE; |
---|
1513 | } else |
---|
1514 | lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / |
---|
1515 | HEX_MINGRIDSIZE)); |
---|
1516 | lp->xs = lp->ys; |
---|
1517 | nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE); |
---|
1518 | ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE); |
---|
1519 | lp->ncols = nccols / 2; |
---|
1520 | lp->nrows = ncrows / 2; |
---|
1521 | lp->nrows -= !(lp->nrows & 1); /* Must be odd */ |
---|
1522 | lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs; |
---|
1523 | lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys; |
---|
1524 | for (i = 0; i < 6; i++) { |
---|
1525 | lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x; |
---|
1526 | lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3; |
---|
1527 | } |
---|
1528 | } else { |
---|
1529 | if (size < -MINSIZE) |
---|
1530 | lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) / |
---|
1531 | MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE; |
---|
1532 | else if (size < MINSIZE) { |
---|
1533 | if (!size) |
---|
1534 | lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE); |
---|
1535 | else |
---|
1536 | lp->ys = MINSIZE; |
---|
1537 | } else |
---|
1538 | lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / |
---|
1539 | MINGRIDSIZE)); |
---|
1540 | lp->xs = lp->ys; |
---|
1541 | lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1); |
---|
1542 | lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1); |
---|
1543 | lp->xb = (lp->width - lp->xs * lp->ncols) / 2; |
---|
1544 | lp->yb = (lp->height - lp->ys * lp->nrows) / 2; |
---|
1545 | } |
---|
1546 | lp->bx = 1; |
---|
1547 | lp->by = 1; |
---|
1548 | lp->bncols = lp->ncols + 2 * lp->bx; |
---|
1549 | lp->bnrows = lp->nrows + 2 * lp->by; |
---|
1550 | |
---|
1551 | MI_CLEARWINDOW(mi); |
---|
1552 | |
---|
1553 | if (lp->oldcells != NULL) { |
---|
1554 | (void) free((void *) lp->oldcells); |
---|
1555 | lp->oldcells = (unsigned char *) NULL; |
---|
1556 | } |
---|
1557 | if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows, |
---|
1558 | sizeof (unsigned char))) == NULL) { |
---|
1559 | free_loop(display, lp); |
---|
1560 | return; |
---|
1561 | } |
---|
1562 | if (lp->newcells != NULL) { |
---|
1563 | (void) free((void *) lp->newcells); |
---|
1564 | lp->newcells = (unsigned char *) NULL; |
---|
1565 | } |
---|
1566 | if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows, |
---|
1567 | sizeof (unsigned char))) == NULL) { |
---|
1568 | free_loop(display, lp); |
---|
1569 | return; |
---|
1570 | } |
---|
1571 | if (!init_table()) { |
---|
1572 | release_loop(mi); |
---|
1573 | return; |
---|
1574 | } |
---|
1575 | lp->mincol = lp->bncols - 1; |
---|
1576 | lp->minrow = lp->bnrows - 1; |
---|
1577 | lp->maxcol = 0; |
---|
1578 | lp->maxrow = 0; |
---|
1579 | #ifndef DELAYDEBUGLOOP |
---|
1580 | { |
---|
1581 | int flaws = MI_COUNT(mi); |
---|
1582 | |
---|
1583 | if (flaws < 0) |
---|
1584 | flaws = NRAND(-MI_COUNT(mi) + 1); |
---|
1585 | for (i = 0; i < flaws; i++) { |
---|
1586 | init_flaw(mi); |
---|
1587 | } |
---|
1588 | /* actual flaws might be less since the adam loop done next */ |
---|
1589 | } |
---|
1590 | #endif |
---|
1591 | init_adam(mi); |
---|
1592 | } |
---|
1593 | |
---|
1594 | void |
---|
1595 | draw_loop(ModeInfo * mi) |
---|
1596 | { |
---|
1597 | int offset, i, j; |
---|
1598 | unsigned char *z, *znew; |
---|
1599 | loopstruct *lp; |
---|
1600 | |
---|
1601 | if (loops == NULL) |
---|
1602 | return; |
---|
1603 | lp = &loops[MI_SCREEN(mi)]; |
---|
1604 | if (lp->newcells == NULL) |
---|
1605 | return; |
---|
1606 | |
---|
1607 | MI_IS_DRAWN(mi) = True; |
---|
1608 | lp->dead = True; |
---|
1609 | #ifdef DELAYDEBUGLOOP |
---|
1610 | if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) { |
---|
1611 | (void) sleep(DELAYDEBUGLOOP); |
---|
1612 | } |
---|
1613 | #endif |
---|
1614 | |
---|
1615 | for (j = lp->minrow; j <= lp->maxrow; j++) { |
---|
1616 | for (i = lp->mincol; i <= lp->maxcol; i++) { |
---|
1617 | offset = j * lp->bncols + i; |
---|
1618 | z = lp->oldcells + offset; |
---|
1619 | znew = lp->newcells + offset; |
---|
1620 | if (*z != *znew) { |
---|
1621 | lp->dead = False; |
---|
1622 | *z = *znew; |
---|
1623 | if (!addtolist(mi, i - lp->bx, j - lp->by, *znew)) |
---|
1624 | return; |
---|
1625 | if (i == lp->mincol && i > lp->bx) |
---|
1626 | lp->mincol--; |
---|
1627 | if (j == lp->minrow && j > lp->by) |
---|
1628 | lp->minrow--; |
---|
1629 | if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx) |
---|
1630 | lp->maxcol++; |
---|
1631 | if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by) |
---|
1632 | lp->maxrow++; |
---|
1633 | } |
---|
1634 | } |
---|
1635 | } |
---|
1636 | for (i = 0; i < COLORS; i++) |
---|
1637 | if (!draw_state(mi, i)) { |
---|
1638 | free_loop(MI_DISPLAY(mi), lp); |
---|
1639 | return; |
---|
1640 | } |
---|
1641 | if (++lp->generation > MI_CYCLES(mi) || lp->dead) { |
---|
1642 | init_loop(mi); |
---|
1643 | return; |
---|
1644 | } else |
---|
1645 | do_gen(lp); |
---|
1646 | |
---|
1647 | if (lp->redrawing) { |
---|
1648 | for (i = 0; i < REDRAWSTEP; i++) { |
---|
1649 | if ((*(lp->oldcells + lp->redrawpos))) { |
---|
1650 | drawcell(mi, lp->redrawpos % lp->bncols - lp->bx, |
---|
1651 | lp->redrawpos / lp->bncols - lp->by, |
---|
1652 | *(lp->oldcells + lp->redrawpos)); |
---|
1653 | } |
---|
1654 | if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) { |
---|
1655 | lp->redrawing = 0; |
---|
1656 | break; |
---|
1657 | } |
---|
1658 | } |
---|
1659 | } |
---|
1660 | } |
---|
1661 | |
---|
1662 | void |
---|
1663 | refresh_loop(ModeInfo * mi) |
---|
1664 | { |
---|
1665 | loopstruct *lp; |
---|
1666 | |
---|
1667 | if (loops == NULL) |
---|
1668 | return; |
---|
1669 | lp = &loops[MI_SCREEN(mi)]; |
---|
1670 | |
---|
1671 | MI_CLEARWINDOW(mi); |
---|
1672 | lp->redrawing = 1; |
---|
1673 | lp->redrawpos = lp->by * lp->ncols + lp->bx; |
---|
1674 | } |
---|
1675 | |
---|
1676 | #endif /* MODE_loop */ |
---|