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 "*fpsSolid: true \n" \
94 "*ignoreRotation: True \n" \
96 # define reshape_loop 0
97 # define loop_handle_event 0
98 # define UNIFORM_COLORS
99 # include "xlockmore.h" /* in xscreensaver distribution */
100 #else /* STANDALONE */
101 # include "xlock.h" /* in xlockmore distribution */
102 #endif /* STANDALONE */
103 #include "automata.h"
108 * neighbors of 0 randomizes between 4 and 6.
110 #define DEF_NEIGHBORS "0" /* choose random value */
112 static int neighbors;
114 static XrmOptionDescRec opts[] =
116 {"-neighbors", ".loop.neighbors", XrmoptionSepArg, 0}
119 static argtype vars[] =
121 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
124 static OptionStruct desc[] =
126 {"-neighbors num", "squares 4 or hexagons 6"}
129 ENTRYPOINT ModeSpecOpt loop_opts =
130 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
134 ModStruct loop_description =
135 {"loop", "init_loop", "draw_loop", "release_loop",
136 "refresh_loop", "init_loop", "free_loop", &loop_opts,
137 100000, 5, 1600, -12, 64, 1.0, "",
138 "Shows Langton's self-producing loops", 0, NULL};
142 #define LOOPBITS(n,w,h)\
143 if ((lp->pixmaps[lp->init_bits]=\
144 XCreatePixmapFromBitmapData(MI_DISPLAY(mi),window,(char *)n,w,h,1,0,1))==None){\
145 free_loop(mi); return;} else {lp->init_bits++;}
147 static int local_neighbors = 0;
150 /* Used to fast forward to troubled generations, mainly used for debugging.
151 -delay 1 -count 170 -neighbors 6 # divisions starts
152 540 first cell collision
153 1111 mutant being born from 2 parents
156 #define DELAYDEBUGLOOP 10
160 #define REALCOLORS (COLORS-2)
162 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
163 #define ADAM_SIZE 8 /* MIN 5 */
165 #define ADAM_LOOPX (ADAM_SIZE+2)
166 #define ADAM_LOOPY (ADAM_SIZE+2)
168 #define ADAM_LOOPX 16
169 #define ADAM_LOOPY 10
171 #define MINGRIDSIZE (3*ADAM_LOOPX)
173 /* TRIA stuff was an attempt to make a triangular lifeform on a
174 hexagonal grid but I got bored. You may need an additional 7th
175 state for a coherent step by step process of cell separation and
176 initial stem development.
181 #define HEX_ADAM_SIZE 3 /* MIN 3 */
183 #define HEX_ADAM_SIZE 5 /* MIN 3 */
186 #define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
187 #define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
189 #define HEX_ADAM_LOOPX 3
190 #define HEX_ADAM_LOOPY 7
192 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
193 /* #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6))) */
195 #define NEIGHBORKINDS 2
197 #define MAXNEIGHBORS 6
199 /* Singly linked list */
200 typedef struct _CellList {
202 struct _CellList *next;
211 int bx, by, bnrows, bncols;
212 int mincol, minrow, maxcol, maxrow;
214 int redrawing, redrawpos;
215 Bool dead, clockwise;
216 unsigned char *newcells, *oldcells;
218 CellList *cellList[COLORS];
219 unsigned long colors[COLORS];
221 Pixmap pixmaps[COLORS];
227 static loopstruct *loops = (loopstruct *) NULL;
229 #define TRANSITION(TT,V) V=TT&7;TT>>=3
230 #define FINALTRANSITION(TT,V) V=TT&7
231 #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)])
232 #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)])
235 /* Instead of setting "unused" state rules to zero it randomizes them.
236 These rules take over when something unexpected happens... like when a
237 cell hits a wall (the end of the screen).
243 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\
244 (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)&=~(7<<((C)*3)));\
246 (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
248 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)|=((I)<<((C)*3)))
249 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
251 #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7)
252 #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7)
254 static unsigned int *table = (unsigned int *) NULL;
255 /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */
256 /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */
258 static char plots[NEIGHBORKINDS] =
260 4, 6 /* Neighborhoods */
263 static unsigned int transition_table[] =
264 { /* Octal CBLTR->I */
265 /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */
266 0000000, 0025271, 0113221, 0202422, 0301021,
267 0000012, 0100011, 0122244, 0202452, 0301220,
268 0000020, 0100061, 0122277, 0202520, 0302511,
269 0000030, 0100077, 0122434, 0202552, 0401120,
270 0000050, 0100111, 0122547, 0202622, 0401220,
271 0000063, 0100121, 0123244, 0202722, 0401250,
272 0000071, 0100211, 0123277, 0203122, 0402120,
273 0000112, 0100244, 0124255, 0203216, 0402221,
274 0000122, 0100277, 0124267, 0203226, 0402326,
275 0000132, 0100511, 0125275, 0203422, 0402520,
276 0000212, 0101011, 0200012, 0204222, 0403221,
277 0000220, 0101111, 0200022, 0205122, 0500022,
278 0000230, 0101244, 0200042, 0205212, 0500215,
279 0000262, 0101277, 0200071, 0205222, 0500225,
280 0000272, 0102026, 0200122, 0205521, 0500232,
281 0000320, 0102121, 0200152, 0205725, 0500272,
282 0000525, 0102211, 0200212, 0206222, 0500520,
283 0000622, 0102244, 0200222, 0206722, 0502022,
284 0000722, 0102263, 0200232, 0207122, 0502122,
285 0001022, 0102277, 0200242, 0207222, 0502152,
286 0001120, 0102327, 0200250, 0207422, 0502220,
287 0002020, 0102424, 0200262, 0207722, 0502244,
288 0002030, 0102626, 0200272, 0211222, 0502722,
289 0002050, 0102644, 0200326, 0211261, 0512122,
290 0002125, 0102677, 0200423, 0212222, 0512220,
291 0002220, 0102710, 0200517, 0212242, 0512422,
292 0002322, 0102727, 0200522, 0212262, 0512722,
293 0005222, 0105427, 0200575, 0212272, 0600011,
294 0012321, 0111121, 0200722, 0214222, 0600021,
295 0012421, 0111221, 0201022, 0215222, 0602120,
296 0012525, 0111244, 0201122, 0216222, 0612125,
297 0012621, 0111251, 0201222, 0217222, 0612131,
298 0012721, 0111261, 0201422, 0222272, 0612225,
299 0012751, 0111277, 0201722, 0222442, 0700077,
300 0014221, 0111522, 0202022, 0222462, 0701120,
301 0014321, 0112121, 0202032, 0222762, 0701220,
302 0014421, 0112221, 0202052, 0222772, 0701250,
303 0014721, 0112244, 0202073, 0300013, 0702120,
304 0016251, 0112251, 0202122, 0300022, 0702221,
305 0017221, 0112277, 0202152, 0300041, 0702251,
306 0017255, 0112321, 0202212, 0300076, 0702321,
307 0017521, 0112424, 0202222, 0300123, 0702525,
308 0017621, 0112621, 0202272, 0300421, 0702720,
309 0017721, 0112727, 0202321, 0300622
312 static unsigned int hex_transition_table[] =
313 { /* Octal CBbltTR->I */
314 /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */
317 000000000, 000000020, 000000220, 000002220, 000022220,
318 011122121, 011121221, 011122221, 011221221,
319 011222221, 011112121, 011112221,
320 020021122, 020002122, 020211222, 021111222,
321 020221122, 020027122, 020020722, 020021022,
323 011122727, 011227227, 010122121, 010222211,
324 021117222, 020112272,
327 010221121, 011721221, 011222277,
328 020111222, 020221172,
331 010212277, 010221221,
336 020002022, 021122172,
338 011122277, 011172121,
339 010212177, 011212277,
343 070121270, 070721220,
344 000112721, 000272211,
345 010022211, 012222277,
346 020072272, 020227122, 020217222,
351 020021072, 020070722,
352 070002072, 070007022,
355 000000070, 000000770, 000072220, 000000270,
356 020110222, 020220272, 020220722,
357 070007071, 070002072, 070007022,
358 000000012, 000000122, 000000212, 001277721,
359 020122072, 020202212,
361 020001122, 020002112,
363 020122022, 020027022, 020070122, 020020122,
366 010227227, 010227277,
373 010022277, 010202177, 010227127,
377 020024122, 020020422,
380 010221241, 010224224,
385 020112242, 021422172,
387 001224221, 001427221,
392 010022244, 010202144, 010224124,
396 040121240, 040421220,
397 000242211, 000112421,
398 020042242, 020214222, 020021422, 020220242, 020024022,
405 001244421, 000000420, 000000440, 000000240, 000000040,
406 020040121, 020021042,
407 040004022, 040004042, 040002042,
409 020011122, 020002112,
416 020224072, 021417222,
422 070207072, 070701220,
427 020021222, 020202272, 020120222, 020221722,
431 020101272, 020272172, 020721422, 020721722,
432 020011222, 020202242,
450 000000000, 000000020, 000000220, 000002220,
451 011212121, 011212221, 011221221, 011222221,
452 020002122, 020021122, 020211122,
454 010221221, 010222121,
455 020002022, 020021022, 020020122, 020112022,
458 020102022, 020202112,
460 000000012, 000000122, 000000212,
462 020001122, 020002112, 020011122,
465 001227221, 001272221, 001272721,
466 012212277, 011222727, 011212727,
467 020021722, 020027122, 020020722, 020027022,
468 020211722, 020202172, 020120272,
469 020271122, 020202172, 020207122, 020217122,
470 020120272, 020210722, 020270722,
471 070212220, 070221220, 070212120,
478 001277721, 000000070, 000000270, 000000720, 000000770,
479 020070122, 020021072,
480 070002072, 070007022, 070007071,
485 010227227, 010222727, 010202727,
486 020172022, 020202712,
488 001224221, 001242221, 001242421,
489 012212244, 011222424, 011212424,
490 020021422, 020024122, 020020422, 020024022,
491 020211422, 020202142, 020120242,
492 020241122, 020202142, 020204122, 020214122,
493 020120242, 020210422, 020240422,
494 040212220, 040221220, 040212120,
501 001244421, 000000040, 000000240, 000000420, 000000440,
502 020040122, 020021042,
504 040004021, 040004042,
509 010224224, 010222424, 010202424,
510 020142022, 020202412,
511 020011722, 020112072, 020172072, 020142072,
515 000210225, 000022015, 000022522,
517 020120525, 020020152, 020005122, 020214255, 020021152,
519 050215222, 050225121,
521 000225220, 001254222,
522 010221250, 011221251, 011225221,
523 020025122, 020152152, 020211252, 020214522, 020511125,
527 000000250, 000000520, 000150220, 000220520, 000222210,
529 010022152, 010251221, 010522121, 011212151, 011221251,
531 020000220, 020002152, 020020220, 020022152,
532 020021422, 020022152, 020022522, 020025425, 020050422,
533 020051022, 020051122, 020211122, 020211222, 020215222,
535 050021125, 050021025, 050011125, 051242221,
538 000220250, 000220520, 001227521, 001275221,
539 011257227, 011522727,
540 020002052, 020002752, 020021052, 020057125,
541 050020722, 050027125,
636 000000050, 000005220, 000002270, 070252220,
637 000000450, 000007220,
638 000220220, 000202220, 000022020, 000020220,
646 050221120, 010221520,
649 000070220, 000220720,
650 000020520, 000070250, 000222070, 000027020,
651 000022070, 000202270, 000024020, 000220420,
652 000220270, 000220240, 000072020, 000042020,
653 000002020, 000002070, 000020270, 000020250,
654 000270270, 000007020, 000040270,
656 /* Collision starts (gen 540), not sure to have rules to save it
657 or depend on calloc to intialize remaining rules to 0 so that
658 the mutant will be born
666 Neighborhoods are read as follows (rotations are not listed):
676 static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] =
679 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0},
680 {2, 4, 0, 1, 4, 0, 1, 1, 1, 2},
681 {2, 1, 2, 2, 2, 2, 2, 2, 1, 2},
682 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
683 {2, 7, 2, 0, 0, 0, 0, 2, 7, 2},
684 {2, 1, 2, 0, 0, 0, 0, 2, 0, 2},
685 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
686 {2, 7, 2, 2, 2, 2, 2, 2, 7, 2},
687 {2, 1, 0, 6, 1, 0, 7, 1, 0, 2},
688 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}
691 static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] =
694 /* Experimental TRIA5:7x7 */
702 /* Stem cells, only "5" will fully reproduce itself */
704 {2,2,2,2,0,0,0,0,0,0,0,0},
705 {2,1,1,1,2,0,0,0,0,0,0,0},
706 {2,1,2,2,1,2,2,2,2,2,2,0},
707 {2,1,2,0,2,7,1,1,1,1,1,2},
708 {0,2,1,2,2,0,2,2,2,2,2,2},
709 {0,0,2,0,4,1,2,0,0,0,0,0},
710 {0,0,0,2,2,2,2,0,0,0,0,0}
712 {2,2,2,2,2,0,0,0,0,0,0,0,0,0},
713 {2,1,1,1,1,2,0,0,0,0,0,0,0,0},
714 {2,1,2,2,2,1,2,0,0,0,0,0,0,0},
715 {2,1,2,0,0,2,1,2,2,2,2,2,2,0},
716 {2,1,2,0,0,0,2,7,1,1,1,1,1,2},
717 {0,2,1,2,0,0,2,0,2,2,2,2,2,2},
718 {0,0,2,0,2,2,2,1,2,0,0,0,0,0},
719 {0,0,0,2,4,1,0,7,2,0,0,0,0,0},
720 {0,0,0,0,2,2,2,2,2,0,0,0,0,0}
722 {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0},
723 {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0},
724 {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0},
725 {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0},
726 {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0},
727 {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2},
728 {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2},
729 {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0},
730 {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0},
731 {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0},
732 {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0}
733 /* test:3x7 (0,4) is blank ... very strange.
734 init_adam seems ok something after that I guess */
742 #else /* this might be better for hexagons, spacewise efficient... */
744 /* Experimental TRIA5:7x7 */
754 {2,2,2,2,2,2,0,0,0,0,0},
755 {2,1,1,7,0,1,2,0,0,0,0},
756 {2,1,2,2,2,2,7,2,0,0,0},
757 {2,1,2,0,0,0,2,0,2,0,0},
758 {2,1,2,0,0,0,0,2,1,2,0},
759 {2,1,2,0,0,0,0,0,2,7,2},
760 {0,2,1,2,0,0,0,0,2,0,2},
761 {0,0,2,1,2,0,0,0,2,1,2},
762 {0,0,0,2,1,2,2,2,2,4,2},
763 {0,0,0,0,2,1,1,1,1,5,2},
764 {0,0,0,0,0,2,2,2,2,2,2}
770 position_of_neighbor(int dir, int *pcol, int *prow)
772 int col = *pcol, row = *prow;
776 if (local_neighbors == 6) {
801 (void) fprintf(stderr, "wrong direction %d\n", dir);
818 (void) fprintf(stderr, "wrong direction %d\n", dir);
826 withinBounds(loopstruct * lp, int col, int row)
828 return (row >= 1 && row < lp->bnrows - 1 &&
829 col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2)));
833 fillcell(ModeInfo * mi, GC gc, int col, int row)
835 loopstruct *lp = &loops[MI_SCREEN(mi)];
837 if (local_neighbors == 6) {
838 int ccol = 2 * col + !(row & 1), crow = 2 * row;
840 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
841 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
842 if (lp->xs == 1 && lp->ys == 1)
843 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
844 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
846 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
847 lp->shape.hexagon, 6, Convex, CoordModePrevious);
849 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
850 lp->xb + lp->xs * col, lp->yb + lp->ys * row,
851 lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3));
856 drawcell(ModeInfo * mi, int col, int row, int state)
858 loopstruct *lp = &loops[MI_SCREEN(mi)];
862 if (MI_NPIXELS(mi) >= COLORS) {
864 XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]);
867 gcv.stipple = lp->pixmaps[state];
868 #endif /* DO_STIPPLE */
869 gcv.foreground = MI_WHITE_PIXEL(mi);
870 gcv.background = MI_BLACK_PIXEL(mi);
871 XChangeGC(MI_DISPLAY(mi), lp->stippledGC,
874 #endif /* DO_STIPPLE */
875 GCForeground | GCBackground, &gcv);
878 fillcell(mi, gc, col, row);
883 print_state(ModeInfo * mi, int state)
885 loopstruct *lp = &loops[MI_SCREEN(mi)];
886 CellList *locallist = lp->cellList[state];
889 (void) printf("state %d\n", state);
891 (void) printf("%d x %d, y %d\n", i,
892 locallist->pt.x, locallist->pt.y);
893 locallist = locallist->next;
901 free_state(loopstruct * lp, int state)
905 while (lp->cellList[state]) {
906 current = lp->cellList[state];
907 lp->cellList[state] = lp->cellList[state]->next;
908 (void) free((void *) current);
910 lp->ncells[state] = 0;
914 free_list(loopstruct * lp)
918 for (state = 0; state < COLORS; state++)
919 free_state(lp, state);
923 free_loop(ModeInfo * mi)
925 Display *display = MI_DISPLAY(mi);
926 loopstruct *lp = &loops[MI_SCREEN(mi)];
929 for (shade = 0; shade < lp->init_bits; shade++)
930 if (lp->pixmaps[shade] != None) {
931 XFreePixmap(display, lp->pixmaps[shade]);
932 lp->pixmaps[shade] = None;
934 if (lp->stippledGC != None) {
935 XFreeGC(display, lp->stippledGC);
936 lp->stippledGC = None;
938 if (lp->oldcells != NULL) {
939 (void) free((void *) lp->oldcells);
940 lp->oldcells = (unsigned char *) NULL;
942 if (lp->newcells != NULL) {
943 (void) free((void *) lp->newcells);
944 lp->newcells = (unsigned char *) NULL;
950 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
952 loopstruct *lp = &loops[MI_SCREEN(mi)];
953 CellList *current = lp->cellList[state];
955 if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
957 lp->cellList[state] = current;
961 lp->cellList[state]->pt.x = col;
962 lp->cellList[state]->pt.y = row;
963 lp->cellList[state]->next = current;
969 draw_state(ModeInfo * mi, int state)
971 loopstruct *lp = &loops[MI_SCREEN(mi)];
972 Display *display = MI_DISPLAY(mi);
975 CellList *current = lp->cellList[state];
977 if (MI_NPIXELS(mi) >= COLORS) {
979 XSetForeground(display, gc, lp->colors[state]);
982 gcv.stipple = lp->pixmaps[state];
983 #endif /* DO_STIPPLE */
984 gcv.foreground = MI_WHITE_PIXEL(mi);
985 gcv.background = MI_BLACK_PIXEL(mi);
986 XChangeGC(display, lp->stippledGC,
989 #endif /* DO_STIPPLE */
990 GCForeground | GCBackground, &gcv);
994 if (local_neighbors == 6) { /* Draw right away, slow */
996 int col, row, ccol, crow;
1000 ccol = 2 * col + !(row & 1), crow = 2 * row;
1001 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
1002 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
1003 if (lp->xs == 1 && lp->ys == 1)
1004 XDrawPoint(display, MI_WINDOW(mi), gc,
1005 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
1007 XFillPolygon(display, MI_WINDOW(mi), gc,
1008 lp->shape.hexagon, 6, Convex, CoordModePrevious);
1009 current = current->next;
1012 /* Take advantage of XFillRectangles */
1016 /* Create Rectangle list from part of the cellList */
1017 if ((rects = (XRectangle *) malloc(lp->ncells[state] *
1018 sizeof (XRectangle))) == NULL) {
1023 rects[nrects].x = lp->xb + current->pt.x * lp->xs;
1024 rects[nrects].y = lp->yb + current->pt.y * lp->ys;
1025 rects[nrects].width = lp->xs - (lp->xs > 3);
1026 rects[nrects].height = lp->ys - (lp->ys > 3);
1027 current = current->next;
1030 /* Finally get to draw */
1031 XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
1032 /* Free up rects list and the appropriate part of the cellList */
1033 (void) free((void *) rects);
1035 free_state(lp, state);
1042 if (table == NULL) {
1044 unsigned int tt, c, n[MAXNEIGHBORS], i;
1046 int size_transition_table = sizeof (transition_table) /
1047 sizeof (unsigned int);
1048 int size_hex_transition_table = sizeof (hex_transition_table) /
1049 sizeof (unsigned int);
1051 for (j = 0; j < local_neighbors; j++)
1054 if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
1060 /* Here I was interested to see what happens when it hits a wall....
1061 Rules not normally used take over... takes too much time though */
1062 /* Each state = 3 bits */
1063 if (MAXRAND < 16777216.0) {
1064 for (j = 0; j < mult; j++) {
1065 table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
1068 for (j = 0; j < mult; j++) {
1069 table[j] = (unsigned int) (NRAND(16777216));
1073 if (local_neighbors == 6) {
1074 for (j = 0; j < size_hex_transition_table; j++) {
1075 tt = hex_transition_table[j];
1077 for (k = 0; k < local_neighbors; k++) {
1078 TRANSITION(tt, n[k]);
1080 FINALTRANSITION(tt, c);
1081 HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
1082 HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
1083 HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
1084 HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i);
1085 HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i);
1086 HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i);
1089 for (j = 0; j < size_transition_table; j++) {
1090 tt = transition_table[j];
1092 for (k = 0; k < local_neighbors; k++) {
1093 TRANSITION(tt, n[k]);
1095 FINALTRANSITION(tt, c);
1096 TABLE_IN(c, n[0], n[1], n[2], n[3], i);
1097 TABLE_IN(c, n[1], n[2], n[3], n[0], i);
1098 TABLE_IN(c, n[2], n[3], n[0], n[1], i);
1099 TABLE_IN(c, n[3], n[0], n[1], n[2], i);
1107 init_flaw(ModeInfo * mi)
1109 loopstruct *lp = &loops[MI_SCREEN(mi)];
1113 if (lp->bncols <= 3 || lp->bnrows <= 3)
1115 a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
1116 HEX_MINGRIDSIZE : MINGRIDSIZE));
1117 a = NRAND(a) + (lp->bncols - a) / 2;
1118 b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
1119 HEX_MINGRIDSIZE : MINGRIDSIZE));
1120 b = NRAND(b) + (lp->bnrows - b) / 2;
1125 if (lp->maxcol < a + 2)
1127 if (lp->maxrow < b + 2)
1130 if (local_neighbors == 6) {
1131 lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
1132 lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1133 lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
1134 lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
1135 lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
1136 lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1138 int orient = NRAND(4);
1139 lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
1140 if (orient == 0 || orient == 1) {
1141 lp->newcells[lp->bncols * b + a + 1] = BLUE;
1143 if (orient == 1 || orient == 2) {
1144 lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
1146 if (orient == 2 || orient == 3) {
1147 lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
1149 if (orient == 3 || orient == 0) {
1150 lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
1156 init_adam(ModeInfo * mi)
1158 loopstruct *lp = &loops[MI_SCREEN(mi)];
1159 XPoint start = { 0, 0 }, dirx = { 0, 0 }, diry = { 0, 0 };
1162 #ifdef DELAYDEBUGLOOP
1164 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1166 lp->clockwise = (Bool) (LRAND() & 1);
1167 #ifdef DELAYDEBUGLOOP
1169 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1171 dir = NRAND(local_neighbors);
1172 if (local_neighbors == 6) {
1177 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1178 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1179 if (lp->mincol > start.x - 2)
1180 lp->mincol = start.x - 2;
1181 if (lp->minrow > start.y - 1)
1182 lp->minrow = start.y - 1;
1183 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1184 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1185 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1186 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1187 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1188 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1189 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1190 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1192 hex_self_reproducing_loop[i][j] :
1193 hex_self_reproducing_loop[j][i];
1198 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1199 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1200 if (lp->mincol > start.x - 1)
1201 lp->mincol = start.x - 1;
1202 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1203 lp->minrow = start.y - HEX_ADAM_LOOPX;
1204 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1205 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1206 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1207 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1208 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1209 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1210 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1211 ? -(i + j + 1) / 2 : -(i + j) / 2);
1212 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1214 hex_self_reproducing_loop[i][j] :
1215 hex_self_reproducing_loop[j][i];
1220 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1221 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1222 if (lp->mincol > start.x - 2)
1223 lp->mincol = start.x - 2;
1224 if (lp->minrow > start.y - 1)
1225 lp->minrow = start.y - 1;
1226 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1227 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1228 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1229 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1230 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1231 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1232 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1233 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1235 hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
1236 hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
1241 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1242 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1243 if (lp->mincol > start.x - 1)
1244 lp->mincol = start.x - 1;
1245 if (lp->minrow > start.y - 1)
1246 lp->minrow = start.y - 1;
1247 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1248 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1249 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1250 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1251 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1252 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1253 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1254 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1256 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1257 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1262 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1263 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1264 if (lp->mincol > start.x - 1)
1265 lp->mincol = start.x - 1;
1266 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1267 lp->minrow = start.y - HEX_ADAM_LOOPX;
1268 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1269 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1270 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1271 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1272 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1273 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1274 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1275 ? -(i + j + 1) / 2 : -(i + j) / 2);
1276 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1278 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1279 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1284 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1285 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1286 if (lp->mincol > start.x - 2)
1287 lp->mincol = start.x - 2;
1288 if (lp->minrow > start.y - 1)
1289 lp->minrow = start.y - 1;
1290 if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
1291 lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
1292 if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
1293 lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
1294 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1295 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1296 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1297 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1299 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
1300 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
1306 /* (void) printf ("s %d s %d \n", start.x, start.y); */
1307 (void) printf ("%d %d %d %d %d\n",
1308 start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1309 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
1310 /* Draw right away */
1311 drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1312 start.y + j - lp->by,
1313 hex_self_reproducing_loop[j][i]);
1318 start.x = (lp->bncols - ADAM_LOOPX) / 2;
1319 start.y = (lp->bnrows - ADAM_LOOPY) / 2;
1320 dirx.x = 1, dirx.y = 0;
1321 diry.x = 0, diry.y = 1;
1322 if (lp->mincol > start.x)
1323 lp->mincol = start.x;
1324 if (lp->minrow > start.y)
1325 lp->minrow = start.y;
1326 if (lp->maxcol < start.x + ADAM_LOOPX)
1327 lp->maxcol = start.x + ADAM_LOOPX;
1328 if (lp->maxrow < start.y + ADAM_LOOPY)
1329 lp->maxrow = start.y + ADAM_LOOPY;
1332 start.x = (lp->bncols + ADAM_LOOPY) / 2;
1333 start.y = (lp->bnrows - ADAM_LOOPX) / 2;
1334 dirx.x = 0, dirx.y = 1;
1335 diry.x = -1, diry.y = 0;
1336 if (lp->mincol > start.x - ADAM_LOOPY)
1337 lp->mincol = start.x - ADAM_LOOPY;
1338 if (lp->minrow > start.y)
1339 lp->minrow = start.y;
1340 if (lp->maxcol < start.x)
1341 lp->maxcol = start.x;
1342 if (lp->maxrow < start.y + ADAM_LOOPX)
1343 lp->maxrow = start.y + ADAM_LOOPX;
1346 start.x = (lp->bncols + ADAM_LOOPX) / 2;
1347 start.y = (lp->bnrows + ADAM_LOOPY) / 2;
1348 dirx.x = -1, dirx.y = 0;
1349 diry.x = 0, diry.y = -1;
1350 if (lp->mincol > start.x - ADAM_LOOPX)
1351 lp->mincol = start.x - ADAM_LOOPX;
1352 if (lp->minrow > start.y - ADAM_LOOPY)
1353 lp->minrow = start.y - ADAM_LOOPY;
1354 if (lp->maxcol < start.x)
1355 lp->maxcol = start.x;
1356 if (lp->maxrow < start.y)
1357 lp->maxrow = start.y;
1360 start.x = (lp->bncols - ADAM_LOOPY) / 2;
1361 start.y = (lp->bnrows + ADAM_LOOPX) / 2;
1362 dirx.x = 0, dirx.y = -1;
1363 diry.x = 1, diry.y = 0;
1364 if (lp->mincol > start.x)
1365 lp->mincol = start.x;
1366 if (lp->minrow > start.y - ADAM_LOOPX)
1367 lp->minrow = start.y - ADAM_LOOPX;
1368 if (lp->maxcol < start.x + ADAM_LOOPX)
1369 lp->maxcol = start.x + ADAM_LOOPX;
1370 if (lp->maxrow < start.y)
1371 lp->maxrow = start.y;
1374 for (j = 0; j < ADAM_LOOPY; j++)
1375 for (i = 0; i < ADAM_LOOPX; i++)
1376 lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
1377 start.x + dirx.x * i + diry.x * j] =
1379 self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
1380 self_reproducing_loop[j][i];
1382 /* Draw right away */
1383 drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
1384 start.y + dirx.y * i + diry.y * j - lp->by,
1385 (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
1392 do_gen(loopstruct * lp)
1396 unsigned int n[MAXNEIGHBORS];
1399 #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols)))
1401 for (j = lp->minrow; j <= lp->maxrow; j++) {
1402 for (i = lp->mincol; i <= lp->maxcol; i++) {
1403 z = lp->newcells + i + j * lp->bncols;
1405 for (k = 0; k < local_neighbors; k++) {
1406 int newi = i, newj = j;
1408 position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj);
1410 if (withinBounds(lp, newi, newj)) {
1411 n[k] = LOC(newi, newj);
1414 if (local_neighbors == 6) {
1415 *z = (lp->clockwise) ?
1416 HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
1417 HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
1419 *z = (lp->clockwise) ?
1420 TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
1421 TABLE_OUT(c, n[0], n[1], n[2], n[3]);
1428 release_loop (ModeInfo * mi)
1430 if (table != NULL) {
1431 (void) free((void *) table);
1432 table = (unsigned int *) NULL;
1436 static void *stop_warning_about_triangleUnit_already;
1440 init_loop (ModeInfo * mi)
1442 int i, size = MI_SIZE(mi);
1445 stop_warning_about_triangleUnit_already = (void *) &triangleUnit;
1447 MI_INIT (mi, loops);
1448 lp = &loops[MI_SCREEN(mi)];
1452 if (MI_WIDTH(mi) < 100 || MI_HEIGHT(mi) < 100) /* tiny window */
1453 size = MIN(MI_WIDTH(mi), MI_HEIGHT(mi));
1456 if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
1457 Window window = MI_WINDOW(mi);
1459 if (lp->stippledGC == None) {
1460 gcv.fill_style = FillOpaqueStippled;
1461 if ((lp->stippledGC = XCreateGC(MI_DISPLAY(mi), window,
1462 GCFillStyle, &gcv)) == None) {
1467 LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE);
1468 LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE);
1469 LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE);
1470 LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE);
1471 LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE);
1472 LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
1473 LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
1474 LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
1476 #endif /* DO_STIPPLE */
1477 if (MI_NPIXELS(mi) >= COLORS) {
1478 /* Maybe these colors should be randomized */
1479 lp->colors[0] = MI_BLACK_PIXEL(mi);
1480 lp->colors[1] = MI_PIXEL(mi, 0); /* RED */
1481 lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */
1482 lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */
1483 lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */
1484 lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */
1485 lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */
1486 lp->colors[7] = MI_WHITE_PIXEL(mi);
1490 lp->width = MI_WIDTH(mi);
1491 lp->height = MI_HEIGHT(mi);
1493 if (!local_neighbors) {
1494 for (i = 0; i < NEIGHBORKINDS; i++) {
1495 if (neighbors == plots[i]) {
1496 local_neighbors = neighbors;
1499 if (i == NEIGHBORKINDS - 1) {
1501 local_neighbors = plots[NRAND(NEIGHBORKINDS)];
1503 local_neighbors = 4;
1511 if (local_neighbors == 6) {
1518 if (size < -MINSIZE) {
1519 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1520 HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1521 } else if (size < MINSIZE) {
1523 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE);
1527 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1530 nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
1531 ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
1532 lp->ncols = nccols / 2;
1533 lp->nrows = ncrows / 2;
1534 lp->nrows -= !(lp->nrows & 1); /* Must be odd */
1535 lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
1536 lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
1537 for (i = 0; i < 6; i++) {
1538 lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x;
1539 lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
1542 if (size < -MINSIZE)
1543 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1544 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1545 else if (size < MINSIZE) {
1547 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE);
1551 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1554 lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1);
1555 lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1);
1556 lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
1557 lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
1561 lp->bncols = lp->ncols + 2 * lp->bx;
1562 lp->bnrows = lp->nrows + 2 * lp->by;
1566 if (lp->oldcells != NULL) {
1567 (void) free((void *) lp->oldcells);
1568 lp->oldcells = (unsigned char *) NULL;
1570 if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1571 sizeof (unsigned char))) == NULL) {
1575 if (lp->newcells != NULL) {
1576 (void) free((void *) lp->newcells);
1577 lp->newcells = (unsigned char *) NULL;
1579 if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1580 sizeof (unsigned char))) == NULL) {
1584 if (!init_table()) {
1588 lp->mincol = lp->bncols - 1;
1589 lp->minrow = lp->bnrows - 1;
1592 #ifndef DELAYDEBUGLOOP
1594 int flaws = MI_COUNT(mi);
1597 flaws = NRAND(-MI_COUNT(mi) + 1);
1598 for (i = 0; i < flaws; i++) {
1601 /* actual flaws might be less since the adam loop done next */
1608 draw_loop (ModeInfo * mi)
1611 unsigned char *z, *znew;
1616 lp = &loops[MI_SCREEN(mi)];
1617 if (lp->newcells == NULL)
1620 MI_IS_DRAWN(mi) = True;
1622 #ifdef DELAYDEBUGLOOP
1623 if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
1624 (void) sleep(DELAYDEBUGLOOP);
1628 for (j = lp->minrow; j <= lp->maxrow; j++) {
1629 for (i = lp->mincol; i <= lp->maxcol; i++) {
1630 offset = j * lp->bncols + i;
1631 z = lp->oldcells + offset;
1632 znew = lp->newcells + offset;
1636 if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
1638 if (i == lp->mincol && i > lp->bx)
1640 if (j == lp->minrow && j > lp->by)
1642 if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx)
1644 if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by)
1649 for (i = 0; i < COLORS; i++)
1650 if (!draw_state(mi, i)) {
1654 if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
1660 if (lp->redrawing) {
1661 for (i = 0; i < REDRAWSTEP; i++) {
1662 if ((*(lp->oldcells + lp->redrawpos))) {
1663 drawcell(mi, lp->redrawpos % lp->bncols - lp->bx,
1664 lp->redrawpos / lp->bncols - lp->by,
1665 *(lp->oldcells + lp->redrawpos));
1667 if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) {
1677 refresh_loop (ModeInfo * mi)
1683 lp = &loops[MI_SCREEN(mi)];
1687 lp->redrawpos = lp->by * lp->ncols + lp->bx;
1691 XSCREENSAVER_MODULE ("Loop", loop)
1693 #endif /* MODE_loop */