1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* loop --- Chris Langton's self-producing loops */
5 static const char sccsid[] = "@(#)loop.c 5.01 2000/03/15 xlockmore";
9 * Copyright (c) 1996 by David Bagley.
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.
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.
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
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
52 Grid Number of Neighbors
53 ---- ------------------
55 Hexagon 6 (currently in development)
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.
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.
88 # define DEFAULTS "*delay: 100000 \n" \
93 # define UNIFORM_COLORS
94 # define reshape_loop 0
95 # define loop_handle_event 0
96 # include "xlockmore.h" /* in xscreensaver distribution */
97 #else /* STANDALONE */
98 # include "xlock.h" /* in xlockmore distribution */
99 #endif /* STANDALONE */
100 #include "automata.h"
105 * neighbors of 0 randomizes between 4 and 6.
107 #define DEF_NEIGHBORS "0" /* choose random value */
109 static int neighbors;
111 static XrmOptionDescRec opts[] =
113 {"-neighbors", ".loop.neighbors", XrmoptionSepArg, 0}
116 static argtype vars[] =
118 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
121 static OptionStruct desc[] =
123 {"-neighbors num", "squares 4 or hexagons 6"}
126 ENTRYPOINT ModeSpecOpt loop_opts =
127 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
131 ModStruct loop_description =
132 {"loop", "init_loop", "draw_loop", "release_loop",
133 "refresh_loop", "init_loop", (char *) NULL, &loop_opts,
134 100000, 5, 1600, -12, 64, 1.0, "",
135 "Shows Langton's self-producing loops", 0, NULL};
139 #define LOOPBITS(n,w,h)\
140 if ((lp->pixmaps[lp->init_bits]=\
141 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
142 free_loop(display,lp); return;} else {lp->init_bits++;}
144 static int local_neighbors = 0;
147 /* Used to fast forward to troubled generations, mainly used for debugging.
148 -delay 1 -count 170 -neighbors 6 # divisions starts
149 540 first cell collision
150 1111 mutant being born from 2 parents
153 #define DELAYDEBUGLOOP 10
157 #define REALCOLORS (COLORS-2)
159 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
160 #define ADAM_SIZE 8 /* MIN 5 */
162 #define ADAM_LOOPX (ADAM_SIZE+2)
163 #define ADAM_LOOPY (ADAM_SIZE+2)
165 #define ADAM_LOOPX 16
166 #define ADAM_LOOPY 10
168 #define MINGRIDSIZE (3*ADAM_LOOPX)
170 /* TRIA stuff was an attempt to make a triangular lifeform on a
171 hexagonal grid but I got bored. You may need an additional 7th
172 state for a coherent step by step process of cell separation and
173 initial stem development.
178 #define HEX_ADAM_SIZE 3 /* MIN 3 */
180 #define HEX_ADAM_SIZE 5 /* MIN 3 */
183 #define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
184 #define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
186 #define HEX_ADAM_LOOPX 3
187 #define HEX_ADAM_LOOPY 7
189 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
190 #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6)))
191 #define NEIGHBORKINDS 2
193 #define MAXNEIGHBORS 6
195 /* Singly linked list */
196 typedef struct _CellList {
198 struct _CellList *next;
207 int bx, by, bnrows, bncols;
208 int mincol, minrow, maxcol, maxrow;
210 int redrawing, redrawpos;
211 Bool dead, clockwise;
212 unsigned char *newcells, *oldcells;
214 CellList *cellList[COLORS];
215 unsigned long colors[COLORS];
217 Pixmap pixmaps[COLORS];
223 static loopstruct *loops = (loopstruct *) NULL;
225 #define TRANSITION(TT,V) V=TT&7;TT>>=3
226 #define FINALTRANSITION(TT,V) V=TT&7
227 #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)])
228 #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)])
231 /* Instead of setting "unused" state rules to zero it randomizes them.
232 These rules take over when something unexpected happens... like when a
233 cell hits a wall (the end of the screen).
239 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\
240 (TABLE(R,T,L,B)|=((I)<<((C)*3)))
241 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\
242 (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
244 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)|=((I)<<((C)*3)))
245 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
247 #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7)
248 #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7)
250 static unsigned int *table = (unsigned int *) NULL;
251 /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */
252 /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */
254 static char plots[NEIGHBORKINDS] =
256 4, 6 /* Neighborhoods */
259 static unsigned int transition_table[] =
260 { /* Octal CBLTR->I */
261 /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */
262 0000000, 0025271, 0113221, 0202422, 0301021,
263 0000012, 0100011, 0122244, 0202452, 0301220,
264 0000020, 0100061, 0122277, 0202520, 0302511,
265 0000030, 0100077, 0122434, 0202552, 0401120,
266 0000050, 0100111, 0122547, 0202622, 0401220,
267 0000063, 0100121, 0123244, 0202722, 0401250,
268 0000071, 0100211, 0123277, 0203122, 0402120,
269 0000112, 0100244, 0124255, 0203216, 0402221,
270 0000122, 0100277, 0124267, 0203226, 0402326,
271 0000132, 0100511, 0125275, 0203422, 0402520,
272 0000212, 0101011, 0200012, 0204222, 0403221,
273 0000220, 0101111, 0200022, 0205122, 0500022,
274 0000230, 0101244, 0200042, 0205212, 0500215,
275 0000262, 0101277, 0200071, 0205222, 0500225,
276 0000272, 0102026, 0200122, 0205521, 0500232,
277 0000320, 0102121, 0200152, 0205725, 0500272,
278 0000525, 0102211, 0200212, 0206222, 0500520,
279 0000622, 0102244, 0200222, 0206722, 0502022,
280 0000722, 0102263, 0200232, 0207122, 0502122,
281 0001022, 0102277, 0200242, 0207222, 0502152,
282 0001120, 0102327, 0200250, 0207422, 0502220,
283 0002020, 0102424, 0200262, 0207722, 0502244,
284 0002030, 0102626, 0200272, 0211222, 0502722,
285 0002050, 0102644, 0200326, 0211261, 0512122,
286 0002125, 0102677, 0200423, 0212222, 0512220,
287 0002220, 0102710, 0200517, 0212242, 0512422,
288 0002322, 0102727, 0200522, 0212262, 0512722,
289 0005222, 0105427, 0200575, 0212272, 0600011,
290 0012321, 0111121, 0200722, 0214222, 0600021,
291 0012421, 0111221, 0201022, 0215222, 0602120,
292 0012525, 0111244, 0201122, 0216222, 0612125,
293 0012621, 0111251, 0201222, 0217222, 0612131,
294 0012721, 0111261, 0201422, 0222272, 0612225,
295 0012751, 0111277, 0201722, 0222442, 0700077,
296 0014221, 0111522, 0202022, 0222462, 0701120,
297 0014321, 0112121, 0202032, 0222762, 0701220,
298 0014421, 0112221, 0202052, 0222772, 0701250,
299 0014721, 0112244, 0202073, 0300013, 0702120,
300 0016251, 0112251, 0202122, 0300022, 0702221,
301 0017221, 0112277, 0202152, 0300041, 0702251,
302 0017255, 0112321, 0202212, 0300076, 0702321,
303 0017521, 0112424, 0202222, 0300123, 0702525,
304 0017621, 0112621, 0202272, 0300421, 0702720,
305 0017721, 0112727, 0202321, 0300622
308 static unsigned int hex_transition_table[] =
309 { /* Octal CBbltTR->I */
310 /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */
313 000000000, 000000020, 000000220, 000002220, 000022220,
314 011122121, 011121221, 011122221, 011221221,
315 011222221, 011112121, 011112221,
316 020021122, 020002122, 020211222, 021111222,
317 020221122, 020027122, 020020722, 020021022,
319 011122727, 011227227, 010122121, 010222211,
320 021117222, 020112272,
323 010221121, 011721221, 011222277,
324 020111222, 020221172,
327 010212277, 010221221,
332 020002022, 021122172,
334 011122277, 011172121,
335 010212177, 011212277,
339 070121270, 070721220,
340 000112721, 000272211,
341 010022211, 012222277,
342 020072272, 020227122, 020217222,
347 020021072, 020070722,
348 070002072, 070007022,
351 000000070, 000000770, 000072220, 000000270,
352 020110222, 020220272, 020220722,
353 070007071, 070002072, 070007022,
354 000000012, 000000122, 000000212, 001277721,
355 020122072, 020202212,
357 020001122, 020002112,
359 020122022, 020027022, 020070122, 020020122,
362 010227227, 010227277,
369 010022277, 010202177, 010227127,
373 020024122, 020020422,
376 010221241, 010224224,
381 020112242, 021422172,
383 001224221, 001427221,
388 010022244, 010202144, 010224124,
392 040121240, 040421220,
393 000242211, 000112421,
394 020042242, 020214222, 020021422, 020220242, 020024022,
401 001244421, 000000420, 000000440, 000000240, 000000040,
402 020040121, 020021042,
403 040004022, 040004042, 040002042,
405 020011122, 020002112,
412 020224072, 021417222,
418 070207072, 070701220,
423 020021222, 020202272, 020120222, 020221722,
427 020101272, 020272172, 020721422, 020721722,
428 020011222, 020202242,
446 000000000, 000000020, 000000220, 000002220,
447 011212121, 011212221, 011221221, 011222221,
448 020002122, 020021122, 020211122,
450 010221221, 010222121,
451 020002022, 020021022, 020020122, 020112022,
454 020102022, 020202112,
456 000000012, 000000122, 000000212,
458 020001122, 020002112, 020011122,
461 001227221, 001272221, 001272721,
462 012212277, 011222727, 011212727,
463 020021722, 020027122, 020020722, 020027022,
464 020211722, 020202172, 020120272,
465 020271122, 020202172, 020207122, 020217122,
466 020120272, 020210722, 020270722,
467 070212220, 070221220, 070212120,
474 001277721, 000000070, 000000270, 000000720, 000000770,
475 020070122, 020021072,
476 070002072, 070007022, 070007071,
481 010227227, 010222727, 010202727,
482 020172022, 020202712,
484 001224221, 001242221, 001242421,
485 012212244, 011222424, 011212424,
486 020021422, 020024122, 020020422, 020024022,
487 020211422, 020202142, 020120242,
488 020241122, 020202142, 020204122, 020214122,
489 020120242, 020210422, 020240422,
490 040212220, 040221220, 040212120,
497 001244421, 000000040, 000000240, 000000420, 000000440,
498 020040122, 020021042,
500 040004021, 040004042,
505 010224224, 010222424, 010202424,
506 020142022, 020202412,
507 020011722, 020112072, 020172072, 020142072,
511 000210225, 000022015, 000022522,
513 020120525, 020020152, 020005122, 020214255, 020021152,
515 050215222, 050225121,
517 000225220, 001254222,
518 010221250, 011221251, 011225221,
519 020025122, 020152152, 020211252, 020214522, 020511125,
523 000000250, 000000520, 000150220, 000220520, 000222210,
525 010022152, 010251221, 010522121, 011212151, 011221251,
527 020000220, 020002152, 020020220, 020022152,
528 020021422, 020022152, 020022522, 020025425, 020050422,
529 020051022, 020051122, 020211122, 020211222, 020215222,
531 050021125, 050021025, 050011125, 051242221,
534 000220250, 000220520, 001227521, 001275221,
535 011257227, 011522727,
536 020002052, 020002752, 020021052, 020057125,
537 050020722, 050027125,
632 000000050, 000005220, 000002270, 070252220,
633 000000450, 000007220,
634 000220220, 000202220, 000022020, 000020220,
642 050221120, 010221520,
645 000070220, 000220720,
646 000020520, 000070250, 000222070, 000027020,
647 000022070, 000202270, 000024020, 000220420,
648 000220270, 000220240, 000072020, 000042020,
649 000002020, 000002070, 000020270, 000020250,
650 000270270, 000007020, 000040270,
652 /* Collision starts (gen 540), not sure to have rules to save it
653 or depend on calloc to intialize remaining rules to 0 so that
654 the mutant will be born
662 Neighborhoods are read as follows (rotations are not listed):
672 static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] =
675 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0},
676 {2, 4, 0, 1, 4, 0, 1, 1, 1, 2},
677 {2, 1, 2, 2, 2, 2, 2, 2, 1, 2},
678 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
679 {2, 7, 2, 0, 0, 0, 0, 2, 7, 2},
680 {2, 1, 2, 0, 0, 0, 0, 2, 0, 2},
681 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
682 {2, 7, 2, 2, 2, 2, 2, 2, 7, 2},
683 {2, 1, 0, 6, 1, 0, 7, 1, 0, 2},
684 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}
687 static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] =
690 /* Experimental TRIA5:7x7 */
698 /* Stem cells, only "5" will fully reproduce itself */
700 {2,2,2,2,0,0,0,0,0,0,0,0},
701 {2,1,1,1,2,0,0,0,0,0,0,0},
702 {2,1,2,2,1,2,2,2,2,2,2,0},
703 {2,1,2,0,2,7,1,1,1,1,1,2},
704 {0,2,1,2,2,0,2,2,2,2,2,2},
705 {0,0,2,0,4,1,2,0,0,0,0,0},
706 {0,0,0,2,2,2,2,0,0,0,0,0}
708 {2,2,2,2,2,0,0,0,0,0,0,0,0,0},
709 {2,1,1,1,1,2,0,0,0,0,0,0,0,0},
710 {2,1,2,2,2,1,2,0,0,0,0,0,0,0},
711 {2,1,2,0,0,2,1,2,2,2,2,2,2,0},
712 {2,1,2,0,0,0,2,7,1,1,1,1,1,2},
713 {0,2,1,2,0,0,2,0,2,2,2,2,2,2},
714 {0,0,2,0,2,2,2,1,2,0,0,0,0,0},
715 {0,0,0,2,4,1,0,7,2,0,0,0,0,0},
716 {0,0,0,0,2,2,2,2,2,0,0,0,0,0}
718 {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0},
719 {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0},
720 {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0},
721 {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0},
722 {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0},
723 {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2},
724 {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2},
725 {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0},
726 {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0},
727 {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0},
728 {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0}
729 /* test:3x7 (0,4) is blank ... very strange.
730 init_adam seems ok something after that I guess */
738 #else /* this might be better for hexagons, spacewise efficient... */
740 /* Experimental TRIA5:7x7 */
750 {2,2,2,2,2,2,0,0,0,0,0},
751 {2,1,1,7,0,1,2,0,0,0,0},
752 {2,1,2,2,2,2,7,2,0,0,0},
753 {2,1,2,0,0,0,2,0,2,0,0},
754 {2,1,2,0,0,0,0,2,1,2,0},
755 {2,1,2,0,0,0,0,0,2,7,2},
756 {0,2,1,2,0,0,0,0,2,0,2},
757 {0,0,2,1,2,0,0,0,2,1,2},
758 {0,0,0,2,1,2,2,2,2,4,2},
759 {0,0,0,0,2,1,1,1,1,5,2},
760 {0,0,0,0,0,2,2,2,2,2,2}
766 position_of_neighbor(int dir, int *pcol, int *prow)
768 int col = *pcol, row = *prow;
772 if (local_neighbors == 6) {
797 (void) fprintf(stderr, "wrong direction %d\n", dir);
814 (void) fprintf(stderr, "wrong direction %d\n", dir);
822 withinBounds(loopstruct * lp, int col, int row)
824 return (row >= 1 && row < lp->bnrows - 1 &&
825 col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2)));
829 fillcell(ModeInfo * mi, GC gc, int col, int row)
831 loopstruct *lp = &loops[MI_SCREEN(mi)];
833 if (local_neighbors == 6) {
834 int ccol = 2 * col + !(row & 1), crow = 2 * row;
836 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
837 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
838 if (lp->xs == 1 && lp->ys == 1)
839 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
840 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
842 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
843 lp->shape.hexagon, 6, Convex, CoordModePrevious);
845 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
846 lp->xb + lp->xs * col, lp->yb + lp->ys * row,
847 lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3));
852 drawcell(ModeInfo * mi, int col, int row, int state)
854 loopstruct *lp = &loops[MI_SCREEN(mi)];
858 if (MI_NPIXELS(mi) >= COLORS) {
860 XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]);
863 gcv.stipple = lp->pixmaps[state];
864 #endif /* DO_STIPPLE */
865 gcv.foreground = MI_WHITE_PIXEL(mi);
866 gcv.background = MI_BLACK_PIXEL(mi);
867 XChangeGC(MI_DISPLAY(mi), lp->stippledGC,
870 #endif /* DO_STIPPLE */
871 GCForeground | GCBackground, &gcv);
874 fillcell(mi, gc, col, row);
879 print_state(ModeInfo * mi, int state)
881 loopstruct *lp = &loops[MI_SCREEN(mi)];
882 CellList *locallist = lp->cellList[state];
885 (void) printf("state %d\n", state);
887 (void) printf("%d x %d, y %d\n", i,
888 locallist->pt.x, locallist->pt.y);
889 locallist = locallist->next;
897 free_state(loopstruct * lp, int state)
901 while (lp->cellList[state]) {
902 current = lp->cellList[state];
903 lp->cellList[state] = lp->cellList[state]->next;
904 (void) free((void *) current);
906 lp->ncells[state] = 0;
910 free_list(loopstruct * lp)
914 for (state = 0; state < COLORS; state++)
915 free_state(lp, state);
919 free_loop(Display *display, loopstruct * lp)
923 for (shade = 0; shade < lp->init_bits; shade++)
924 if (lp->pixmaps[shade] != None) {
925 XFreePixmap(display, lp->pixmaps[shade]);
926 lp->pixmaps[shade] = None;
928 if (lp->stippledGC != None) {
929 XFreeGC(display, lp->stippledGC);
930 lp->stippledGC = None;
932 if (lp->oldcells != NULL) {
933 (void) free((void *) lp->oldcells);
934 lp->oldcells = (unsigned char *) NULL;
936 if (lp->newcells != NULL) {
937 (void) free((void *) lp->newcells);
938 lp->newcells = (unsigned char *) NULL;
944 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
946 loopstruct *lp = &loops[MI_SCREEN(mi)];
947 CellList *current = lp->cellList[state];
949 if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
951 lp->cellList[state] = current;
952 free_loop(MI_DISPLAY(mi), lp);
955 lp->cellList[state]->pt.x = col;
956 lp->cellList[state]->pt.y = row;
957 lp->cellList[state]->next = current;
963 draw_state(ModeInfo * mi, int state)
965 loopstruct *lp = &loops[MI_SCREEN(mi)];
966 Display *display = MI_DISPLAY(mi);
969 CellList *current = lp->cellList[state];
971 if (MI_NPIXELS(mi) >= COLORS) {
973 XSetForeground(display, gc, lp->colors[state]);
976 gcv.stipple = lp->pixmaps[state];
977 #endif /* DO_STIPPLE */
978 gcv.foreground = MI_WHITE_PIXEL(mi);
979 gcv.background = MI_BLACK_PIXEL(mi);
980 XChangeGC(display, lp->stippledGC,
983 #endif /* DO_STIPPLE */
984 GCForeground | GCBackground, &gcv);
988 if (local_neighbors == 6) { /* Draw right away, slow */
990 int col, row, ccol, crow;
994 ccol = 2 * col + !(row & 1), crow = 2 * row;
995 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
996 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
997 if (lp->xs == 1 && lp->ys == 1)
998 XDrawPoint(display, MI_WINDOW(mi), gc,
999 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
1001 XFillPolygon(display, MI_WINDOW(mi), gc,
1002 lp->shape.hexagon, 6, Convex, CoordModePrevious);
1003 current = current->next;
1006 /* Take advantage of XFillRectangles */
1010 /* Create Rectangle list from part of the cellList */
1011 if ((rects = (XRectangle *) malloc(lp->ncells[state] *
1012 sizeof (XRectangle))) == NULL) {
1017 rects[nrects].x = lp->xb + current->pt.x * lp->xs;
1018 rects[nrects].y = lp->yb + current->pt.y * lp->ys;
1019 rects[nrects].width = lp->xs - (lp->xs > 3);
1020 rects[nrects].height = lp->ys - (lp->ys > 3);
1021 current = current->next;
1024 /* Finally get to draw */
1025 XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
1026 /* Free up rects list and the appropriate part of the cellList */
1027 (void) free((void *) rects);
1029 free_state(lp, state);
1036 if (table == NULL) {
1038 unsigned int tt, c, n[MAXNEIGHBORS], i;
1040 int size_transition_table = sizeof (transition_table) /
1041 sizeof (unsigned int);
1042 int size_hex_transition_table = sizeof (hex_transition_table) /
1043 sizeof (unsigned int);
1045 for (j = 0; j < local_neighbors; j++)
1048 if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
1054 /* Here I was interested to see what happens when it hits a wall....
1055 Rules not normally used take over... takes too much time though */
1056 /* Each state = 3 bits */
1057 if (MAXRAND < 16777216.0) {
1058 for (j = 0; j < mult; j++) {
1059 table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
1062 for (j = 0; j < mult; j++) {
1063 table[j] = (unsigned int) (NRAND(16777216));
1067 if (local_neighbors == 6) {
1068 for (j = 0; j < size_hex_transition_table; j++) {
1069 tt = hex_transition_table[j];
1071 for (k = 0; k < local_neighbors; k++) {
1072 TRANSITION(tt, n[k]);
1074 FINALTRANSITION(tt, c);
1075 HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
1076 HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
1077 HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
1078 HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i);
1079 HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i);
1080 HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i);
1083 for (j = 0; j < size_transition_table; j++) {
1084 tt = transition_table[j];
1086 for (k = 0; k < local_neighbors; k++) {
1087 TRANSITION(tt, n[k]);
1089 FINALTRANSITION(tt, c);
1090 TABLE_IN(c, n[0], n[1], n[2], n[3], i);
1091 TABLE_IN(c, n[1], n[2], n[3], n[0], i);
1092 TABLE_IN(c, n[2], n[3], n[0], n[1], i);
1093 TABLE_IN(c, n[3], n[0], n[1], n[2], i);
1101 init_flaw(ModeInfo * mi)
1103 loopstruct *lp = &loops[MI_SCREEN(mi)];
1107 if (lp->bncols <= 3 || lp->bnrows <= 3)
1109 a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
1110 HEX_MINGRIDSIZE : MINGRIDSIZE));
1111 a = NRAND(a) + (lp->bncols - a) / 2;
1112 b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
1113 HEX_MINGRIDSIZE : MINGRIDSIZE));
1114 b = NRAND(b) + (lp->bnrows - b) / 2;
1119 if (lp->maxcol < a + 2)
1121 if (lp->maxrow < b + 2)
1124 if (local_neighbors == 6) {
1125 lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
1126 lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1127 lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
1128 lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
1129 lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
1130 lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1132 int orient = NRAND(4);
1133 lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
1134 if (orient == 0 || orient == 1) {
1135 lp->newcells[lp->bncols * b + a + 1] = BLUE;
1137 if (orient == 1 || orient == 2) {
1138 lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
1140 if (orient == 2 || orient == 3) {
1141 lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
1143 if (orient == 3 || orient == 0) {
1144 lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
1150 init_adam(ModeInfo * mi)
1152 loopstruct *lp = &loops[MI_SCREEN(mi)];
1153 XPoint start = { 0, 0 }, dirx = { 0, 0 }, diry = { 0, 0 };
1156 #ifdef DELAYDEBUGLOOP
1158 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1160 lp->clockwise = (Bool) (LRAND() & 1);
1161 #ifdef DELAYDEBUGLOOP
1163 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1165 dir = NRAND(local_neighbors);
1166 if (local_neighbors == 6) {
1171 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1172 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1173 if (lp->mincol > start.x - 2)
1174 lp->mincol = start.x - 2;
1175 if (lp->minrow > start.y - 1)
1176 lp->minrow = start.y - 1;
1177 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1178 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1179 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1180 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1181 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1182 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1183 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1184 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1186 hex_self_reproducing_loop[i][j] :
1187 hex_self_reproducing_loop[j][i];
1192 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1193 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1194 if (lp->mincol > start.x - 1)
1195 lp->mincol = start.x - 1;
1196 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1197 lp->minrow = start.y - HEX_ADAM_LOOPX;
1198 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1199 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1200 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1201 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1202 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1203 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1204 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1205 ? -(i + j + 1) / 2 : -(i + j) / 2);
1206 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1208 hex_self_reproducing_loop[i][j] :
1209 hex_self_reproducing_loop[j][i];
1214 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1215 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1216 if (lp->mincol > start.x - 2)
1217 lp->mincol = start.x - 2;
1218 if (lp->minrow > start.y - 1)
1219 lp->minrow = start.y - 1;
1220 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1221 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1222 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1223 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1224 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1225 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1226 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1227 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1229 hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
1230 hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
1235 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1236 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1237 if (lp->mincol > start.x - 1)
1238 lp->mincol = start.x - 1;
1239 if (lp->minrow > start.y - 1)
1240 lp->minrow = start.y - 1;
1241 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1242 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1243 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1244 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1245 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1246 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1247 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1248 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1250 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1251 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1256 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1257 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1258 if (lp->mincol > start.x - 1)
1259 lp->mincol = start.x - 1;
1260 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1261 lp->minrow = start.y - HEX_ADAM_LOOPX;
1262 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1263 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1264 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1265 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1266 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1267 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1268 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1269 ? -(i + j + 1) / 2 : -(i + j) / 2);
1270 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1272 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1273 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1278 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1279 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1280 if (lp->mincol > start.x - 2)
1281 lp->mincol = start.x - 2;
1282 if (lp->minrow > start.y - 1)
1283 lp->minrow = start.y - 1;
1284 if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
1285 lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
1286 if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
1287 lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
1288 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1289 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1290 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1291 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1293 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
1294 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
1300 /* (void) printf ("s %d s %d \n", start.x, start.y); */
1301 (void) printf ("%d %d %d %d %d\n",
1302 start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1303 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
1304 /* Draw right away */
1305 drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1306 start.y + j - lp->by,
1307 hex_self_reproducing_loop[j][i]);
1312 start.x = (lp->bncols - ADAM_LOOPX) / 2;
1313 start.y = (lp->bnrows - ADAM_LOOPY) / 2;
1314 dirx.x = 1, dirx.y = 0;
1315 diry.x = 0, diry.y = 1;
1316 if (lp->mincol > start.x)
1317 lp->mincol = start.x;
1318 if (lp->minrow > start.y)
1319 lp->minrow = start.y;
1320 if (lp->maxcol < start.x + ADAM_LOOPX)
1321 lp->maxcol = start.x + ADAM_LOOPX;
1322 if (lp->maxrow < start.y + ADAM_LOOPY)
1323 lp->maxrow = start.y + ADAM_LOOPY;
1326 start.x = (lp->bncols + ADAM_LOOPY) / 2;
1327 start.y = (lp->bnrows - ADAM_LOOPX) / 2;
1328 dirx.x = 0, dirx.y = 1;
1329 diry.x = -1, diry.y = 0;
1330 if (lp->mincol > start.x - ADAM_LOOPY)
1331 lp->mincol = start.x - ADAM_LOOPY;
1332 if (lp->minrow > start.y)
1333 lp->minrow = start.y;
1334 if (lp->maxcol < start.x)
1335 lp->maxcol = start.x;
1336 if (lp->maxrow < start.y + ADAM_LOOPX)
1337 lp->maxrow = start.y + ADAM_LOOPX;
1340 start.x = (lp->bncols + ADAM_LOOPX) / 2;
1341 start.y = (lp->bnrows + ADAM_LOOPY) / 2;
1342 dirx.x = -1, dirx.y = 0;
1343 diry.x = 0, diry.y = -1;
1344 if (lp->mincol > start.x - ADAM_LOOPX)
1345 lp->mincol = start.x - ADAM_LOOPX;
1346 if (lp->minrow > start.y - ADAM_LOOPY)
1347 lp->minrow = start.y - ADAM_LOOPY;
1348 if (lp->maxcol < start.x)
1349 lp->maxcol = start.x;
1350 if (lp->maxrow < start.y)
1351 lp->maxrow = start.y;
1354 start.x = (lp->bncols - ADAM_LOOPY) / 2;
1355 start.y = (lp->bnrows + ADAM_LOOPX) / 2;
1356 dirx.x = 0, dirx.y = -1;
1357 diry.x = 1, diry.y = 0;
1358 if (lp->mincol > start.x)
1359 lp->mincol = start.x;
1360 if (lp->minrow > start.y - ADAM_LOOPX)
1361 lp->minrow = start.y - ADAM_LOOPX;
1362 if (lp->maxcol < start.x + ADAM_LOOPX)
1363 lp->maxcol = start.x + ADAM_LOOPX;
1364 if (lp->maxrow < start.y)
1365 lp->maxrow = start.y;
1368 for (j = 0; j < ADAM_LOOPY; j++)
1369 for (i = 0; i < ADAM_LOOPX; i++)
1370 lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
1371 start.x + dirx.x * i + diry.x * j] =
1373 self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
1374 self_reproducing_loop[j][i];
1376 /* Draw right away */
1377 drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
1378 start.y + dirx.y * i + diry.y * j - lp->by,
1379 (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
1386 do_gen(loopstruct * lp)
1390 unsigned int n[MAXNEIGHBORS];
1393 #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols)))
1395 for (j = lp->minrow; j <= lp->maxrow; j++) {
1396 for (i = lp->mincol; i <= lp->maxcol; i++) {
1397 z = lp->newcells + i + j * lp->bncols;
1399 for (k = 0; k < local_neighbors; k++) {
1400 int newi = i, newj = j;
1402 position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj);
1404 if (withinBounds(lp, newi, newj)) {
1405 n[k] = LOC(newi, newj);
1408 if (local_neighbors == 6) {
1409 *z = (lp->clockwise) ?
1410 HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
1411 HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
1413 *z = (lp->clockwise) ?
1414 TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
1415 TABLE_OUT(c, n[0], n[1], n[2], n[3]);
1422 release_loop (ModeInfo * mi)
1424 if (loops != NULL) {
1427 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1428 free_loop(MI_DISPLAY(mi), &loops[screen]);
1429 (void) free((void *) loops);
1430 loops = (loopstruct *) NULL;
1432 if (table != NULL) {
1433 (void) free((void *) table);
1434 table = (unsigned int *) NULL;
1438 static void *stop_warning_about_triangleUnit_already;
1442 init_loop (ModeInfo * mi)
1444 Display *display = MI_DISPLAY(mi);
1445 int i, size = MI_SIZE(mi);
1448 stop_warning_about_triangleUnit_already = (void *) &triangleUnit;
1450 if (loops == NULL) {
1451 if ((loops = (loopstruct *) calloc(MI_NUM_SCREENS(mi),
1452 sizeof (loopstruct))) == NULL)
1455 lp = &loops[MI_SCREEN(mi)];
1460 if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
1461 Window window = MI_WINDOW(mi);
1463 if (lp->stippledGC == None) {
1464 gcv.fill_style = FillOpaqueStippled;
1465 if ((lp->stippledGC = XCreateGC(display, window,
1466 GCFillStyle, &gcv)) == None) {
1467 free_loop(display, lp);
1471 LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE);
1472 LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE);
1473 LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE);
1474 LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE);
1475 LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE);
1476 LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
1477 LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
1478 LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
1480 #endif /* DO_STIPPLE */
1481 if (MI_NPIXELS(mi) >= COLORS) {
1482 /* Maybe these colors should be randomized */
1483 lp->colors[0] = MI_BLACK_PIXEL(mi);
1484 lp->colors[1] = MI_PIXEL(mi, 0); /* RED */
1485 lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */
1486 lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */
1487 lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */
1488 lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */
1489 lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */
1490 lp->colors[7] = MI_WHITE_PIXEL(mi);
1494 lp->width = MI_WIDTH(mi);
1495 lp->height = MI_HEIGHT(mi);
1497 if (!local_neighbors) {
1498 for (i = 0; i < NEIGHBORKINDS; i++) {
1499 if (neighbors == plots[i]) {
1500 local_neighbors = neighbors;
1503 if (i == NEIGHBORKINDS - 1) {
1505 local_neighbors = plots[NRAND(NEIGHBORKINDS)];
1507 local_neighbors = 4;
1515 if (local_neighbors == 6) {
1522 if (size < -MINSIZE) {
1523 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1524 HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1525 } else if (size < MINSIZE) {
1527 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE);
1531 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1534 nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
1535 ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
1536 lp->ncols = nccols / 2;
1537 lp->nrows = ncrows / 2;
1538 lp->nrows -= !(lp->nrows & 1); /* Must be odd */
1539 lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
1540 lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
1541 for (i = 0; i < 6; i++) {
1542 lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x;
1543 lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
1546 if (size < -MINSIZE)
1547 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1548 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1549 else if (size < MINSIZE) {
1551 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE);
1555 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1558 lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1);
1559 lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1);
1560 lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
1561 lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
1565 lp->bncols = lp->ncols + 2 * lp->bx;
1566 lp->bnrows = lp->nrows + 2 * lp->by;
1570 if (lp->oldcells != NULL) {
1571 (void) free((void *) lp->oldcells);
1572 lp->oldcells = (unsigned char *) NULL;
1574 if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1575 sizeof (unsigned char))) == NULL) {
1576 free_loop(display, lp);
1579 if (lp->newcells != NULL) {
1580 (void) free((void *) lp->newcells);
1581 lp->newcells = (unsigned char *) NULL;
1583 if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1584 sizeof (unsigned char))) == NULL) {
1585 free_loop(display, lp);
1588 if (!init_table()) {
1592 lp->mincol = lp->bncols - 1;
1593 lp->minrow = lp->bnrows - 1;
1596 #ifndef DELAYDEBUGLOOP
1598 int flaws = MI_COUNT(mi);
1601 flaws = NRAND(-MI_COUNT(mi) + 1);
1602 for (i = 0; i < flaws; i++) {
1605 /* actual flaws might be less since the adam loop done next */
1612 draw_loop (ModeInfo * mi)
1615 unsigned char *z, *znew;
1620 lp = &loops[MI_SCREEN(mi)];
1621 if (lp->newcells == NULL)
1624 MI_IS_DRAWN(mi) = True;
1626 #ifdef DELAYDEBUGLOOP
1627 if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
1628 (void) sleep(DELAYDEBUGLOOP);
1632 for (j = lp->minrow; j <= lp->maxrow; j++) {
1633 for (i = lp->mincol; i <= lp->maxcol; i++) {
1634 offset = j * lp->bncols + i;
1635 z = lp->oldcells + offset;
1636 znew = lp->newcells + offset;
1640 if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
1642 if (i == lp->mincol && i > lp->bx)
1644 if (j == lp->minrow && j > lp->by)
1646 if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx)
1648 if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by)
1653 for (i = 0; i < COLORS; i++)
1654 if (!draw_state(mi, i)) {
1655 free_loop(MI_DISPLAY(mi), lp);
1658 if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
1664 if (lp->redrawing) {
1665 for (i = 0; i < REDRAWSTEP; i++) {
1666 if ((*(lp->oldcells + lp->redrawpos))) {
1667 drawcell(mi, lp->redrawpos % lp->bncols - lp->bx,
1668 lp->redrawpos / lp->bncols - lp->by,
1669 *(lp->oldcells + lp->redrawpos));
1671 if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) {
1680 refresh_loop (ModeInfo * mi)
1686 lp = &loops[MI_SCREEN(mi)];
1690 lp->redrawpos = lp->by * lp->ncols + lp->bx;
1693 XSCREENSAVER_MODULE ("Loop", loop)
1695 #endif /* MODE_loop */