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" \
97 # define reshape_loop 0
98 # define loop_handle_event 0
99 # define UNIFORM_COLORS
100 # include "xlockmore.h" /* in xscreensaver distribution */
101 #else /* STANDALONE */
102 # include "xlock.h" /* in xlockmore distribution */
103 #endif /* STANDALONE */
104 #include "automata.h"
109 * neighbors of 0 randomizes between 4 and 6.
111 #define DEF_NEIGHBORS "0" /* choose random value */
113 static int neighbors;
115 static XrmOptionDescRec opts[] =
117 {"-neighbors", ".loop.neighbors", XrmoptionSepArg, 0}
120 static argtype vars[] =
122 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
125 static OptionStruct desc[] =
127 {"-neighbors num", "squares 4 or hexagons 6"}
130 ENTRYPOINT ModeSpecOpt loop_opts =
131 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
135 ModStruct loop_description =
136 {"loop", "init_loop", "draw_loop", "release_loop",
137 "refresh_loop", "init_loop", "free_loop", &loop_opts,
138 100000, 5, 1600, -12, 64, 1.0, "",
139 "Shows Langton's self-producing loops", 0, NULL};
143 #define LOOPBITS(n,w,h)\
144 if ((lp->pixmaps[lp->init_bits]=\
145 XCreatePixmapFromBitmapData(MI_DISPLAY(mi),window,(char *)n,w,h,1,0,1))==None){\
146 free_loop(mi); return;} else {lp->init_bits++;}
148 static int local_neighbors = 0;
151 /* Used to fast forward to troubled generations, mainly used for debugging.
152 -delay 1 -count 170 -neighbors 6 # divisions starts
153 540 first cell collision
154 1111 mutant being born from 2 parents
157 #define DELAYDEBUGLOOP 10
161 #define REALCOLORS (COLORS-2)
163 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
164 #define ADAM_SIZE 8 /* MIN 5 */
166 #define ADAM_LOOPX (ADAM_SIZE+2)
167 #define ADAM_LOOPY (ADAM_SIZE+2)
169 #define ADAM_LOOPX 16
170 #define ADAM_LOOPY 10
172 #define MINGRIDSIZE (3*ADAM_LOOPX)
174 /* TRIA stuff was an attempt to make a triangular lifeform on a
175 hexagonal grid but I got bored. You may need an additional 7th
176 state for a coherent step by step process of cell separation and
177 initial stem development.
182 #define HEX_ADAM_SIZE 3 /* MIN 3 */
184 #define HEX_ADAM_SIZE 5 /* MIN 3 */
187 #define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
188 #define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
190 #define HEX_ADAM_LOOPX 3
191 #define HEX_ADAM_LOOPY 7
193 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
194 /* #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6))) */
196 #define NEIGHBORKINDS 2
198 #define MAXNEIGHBORS 6
200 /* Singly linked list */
201 typedef struct _CellList {
203 struct _CellList *next;
212 int bx, by, bnrows, bncols;
213 int mincol, minrow, maxcol, maxrow;
215 int redrawing, redrawpos;
216 Bool dead, clockwise;
217 unsigned char *newcells, *oldcells;
219 CellList *cellList[COLORS];
220 unsigned long colors[COLORS];
222 Pixmap pixmaps[COLORS];
228 static loopstruct *loops = (loopstruct *) NULL;
230 #define TRANSITION(TT,V) V=TT&7;TT>>=3
231 #define FINALTRANSITION(TT,V) V=TT&7
232 #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)])
233 #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)])
236 /* Instead of setting "unused" state rules to zero it randomizes them.
237 These rules take over when something unexpected happens... like when a
238 cell hits a wall (the end of the screen).
244 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\
245 (TABLE(R,T,L,B)|=((I)<<((C)*3)))
246 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\
247 (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
249 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)|=((I)<<((C)*3)))
250 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
252 #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7)
253 #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7)
255 static unsigned int *table = (unsigned int *) NULL;
256 /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */
257 /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */
259 static char plots[NEIGHBORKINDS] =
261 4, 6 /* Neighborhoods */
264 static unsigned int transition_table[] =
265 { /* Octal CBLTR->I */
266 /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */
267 0000000, 0025271, 0113221, 0202422, 0301021,
268 0000012, 0100011, 0122244, 0202452, 0301220,
269 0000020, 0100061, 0122277, 0202520, 0302511,
270 0000030, 0100077, 0122434, 0202552, 0401120,
271 0000050, 0100111, 0122547, 0202622, 0401220,
272 0000063, 0100121, 0123244, 0202722, 0401250,
273 0000071, 0100211, 0123277, 0203122, 0402120,
274 0000112, 0100244, 0124255, 0203216, 0402221,
275 0000122, 0100277, 0124267, 0203226, 0402326,
276 0000132, 0100511, 0125275, 0203422, 0402520,
277 0000212, 0101011, 0200012, 0204222, 0403221,
278 0000220, 0101111, 0200022, 0205122, 0500022,
279 0000230, 0101244, 0200042, 0205212, 0500215,
280 0000262, 0101277, 0200071, 0205222, 0500225,
281 0000272, 0102026, 0200122, 0205521, 0500232,
282 0000320, 0102121, 0200152, 0205725, 0500272,
283 0000525, 0102211, 0200212, 0206222, 0500520,
284 0000622, 0102244, 0200222, 0206722, 0502022,
285 0000722, 0102263, 0200232, 0207122, 0502122,
286 0001022, 0102277, 0200242, 0207222, 0502152,
287 0001120, 0102327, 0200250, 0207422, 0502220,
288 0002020, 0102424, 0200262, 0207722, 0502244,
289 0002030, 0102626, 0200272, 0211222, 0502722,
290 0002050, 0102644, 0200326, 0211261, 0512122,
291 0002125, 0102677, 0200423, 0212222, 0512220,
292 0002220, 0102710, 0200517, 0212242, 0512422,
293 0002322, 0102727, 0200522, 0212262, 0512722,
294 0005222, 0105427, 0200575, 0212272, 0600011,
295 0012321, 0111121, 0200722, 0214222, 0600021,
296 0012421, 0111221, 0201022, 0215222, 0602120,
297 0012525, 0111244, 0201122, 0216222, 0612125,
298 0012621, 0111251, 0201222, 0217222, 0612131,
299 0012721, 0111261, 0201422, 0222272, 0612225,
300 0012751, 0111277, 0201722, 0222442, 0700077,
301 0014221, 0111522, 0202022, 0222462, 0701120,
302 0014321, 0112121, 0202032, 0222762, 0701220,
303 0014421, 0112221, 0202052, 0222772, 0701250,
304 0014721, 0112244, 0202073, 0300013, 0702120,
305 0016251, 0112251, 0202122, 0300022, 0702221,
306 0017221, 0112277, 0202152, 0300041, 0702251,
307 0017255, 0112321, 0202212, 0300076, 0702321,
308 0017521, 0112424, 0202222, 0300123, 0702525,
309 0017621, 0112621, 0202272, 0300421, 0702720,
310 0017721, 0112727, 0202321, 0300622
313 static unsigned int hex_transition_table[] =
314 { /* Octal CBbltTR->I */
315 /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */
318 000000000, 000000020, 000000220, 000002220, 000022220,
319 011122121, 011121221, 011122221, 011221221,
320 011222221, 011112121, 011112221,
321 020021122, 020002122, 020211222, 021111222,
322 020221122, 020027122, 020020722, 020021022,
324 011122727, 011227227, 010122121, 010222211,
325 021117222, 020112272,
328 010221121, 011721221, 011222277,
329 020111222, 020221172,
332 010212277, 010221221,
337 020002022, 021122172,
339 011122277, 011172121,
340 010212177, 011212277,
344 070121270, 070721220,
345 000112721, 000272211,
346 010022211, 012222277,
347 020072272, 020227122, 020217222,
352 020021072, 020070722,
353 070002072, 070007022,
356 000000070, 000000770, 000072220, 000000270,
357 020110222, 020220272, 020220722,
358 070007071, 070002072, 070007022,
359 000000012, 000000122, 000000212, 001277721,
360 020122072, 020202212,
362 020001122, 020002112,
364 020122022, 020027022, 020070122, 020020122,
367 010227227, 010227277,
374 010022277, 010202177, 010227127,
378 020024122, 020020422,
381 010221241, 010224224,
386 020112242, 021422172,
388 001224221, 001427221,
393 010022244, 010202144, 010224124,
397 040121240, 040421220,
398 000242211, 000112421,
399 020042242, 020214222, 020021422, 020220242, 020024022,
406 001244421, 000000420, 000000440, 000000240, 000000040,
407 020040121, 020021042,
408 040004022, 040004042, 040002042,
410 020011122, 020002112,
417 020224072, 021417222,
423 070207072, 070701220,
428 020021222, 020202272, 020120222, 020221722,
432 020101272, 020272172, 020721422, 020721722,
433 020011222, 020202242,
451 000000000, 000000020, 000000220, 000002220,
452 011212121, 011212221, 011221221, 011222221,
453 020002122, 020021122, 020211122,
455 010221221, 010222121,
456 020002022, 020021022, 020020122, 020112022,
459 020102022, 020202112,
461 000000012, 000000122, 000000212,
463 020001122, 020002112, 020011122,
466 001227221, 001272221, 001272721,
467 012212277, 011222727, 011212727,
468 020021722, 020027122, 020020722, 020027022,
469 020211722, 020202172, 020120272,
470 020271122, 020202172, 020207122, 020217122,
471 020120272, 020210722, 020270722,
472 070212220, 070221220, 070212120,
479 001277721, 000000070, 000000270, 000000720, 000000770,
480 020070122, 020021072,
481 070002072, 070007022, 070007071,
486 010227227, 010222727, 010202727,
487 020172022, 020202712,
489 001224221, 001242221, 001242421,
490 012212244, 011222424, 011212424,
491 020021422, 020024122, 020020422, 020024022,
492 020211422, 020202142, 020120242,
493 020241122, 020202142, 020204122, 020214122,
494 020120242, 020210422, 020240422,
495 040212220, 040221220, 040212120,
502 001244421, 000000040, 000000240, 000000420, 000000440,
503 020040122, 020021042,
505 040004021, 040004042,
510 010224224, 010222424, 010202424,
511 020142022, 020202412,
512 020011722, 020112072, 020172072, 020142072,
516 000210225, 000022015, 000022522,
518 020120525, 020020152, 020005122, 020214255, 020021152,
520 050215222, 050225121,
522 000225220, 001254222,
523 010221250, 011221251, 011225221,
524 020025122, 020152152, 020211252, 020214522, 020511125,
528 000000250, 000000520, 000150220, 000220520, 000222210,
530 010022152, 010251221, 010522121, 011212151, 011221251,
532 020000220, 020002152, 020020220, 020022152,
533 020021422, 020022152, 020022522, 020025425, 020050422,
534 020051022, 020051122, 020211122, 020211222, 020215222,
536 050021125, 050021025, 050011125, 051242221,
539 000220250, 000220520, 001227521, 001275221,
540 011257227, 011522727,
541 020002052, 020002752, 020021052, 020057125,
542 050020722, 050027125,
637 000000050, 000005220, 000002270, 070252220,
638 000000450, 000007220,
639 000220220, 000202220, 000022020, 000020220,
647 050221120, 010221520,
650 000070220, 000220720,
651 000020520, 000070250, 000222070, 000027020,
652 000022070, 000202270, 000024020, 000220420,
653 000220270, 000220240, 000072020, 000042020,
654 000002020, 000002070, 000020270, 000020250,
655 000270270, 000007020, 000040270,
657 /* Collision starts (gen 540), not sure to have rules to save it
658 or depend on calloc to intialize remaining rules to 0 so that
659 the mutant will be born
667 Neighborhoods are read as follows (rotations are not listed):
677 static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] =
680 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0},
681 {2, 4, 0, 1, 4, 0, 1, 1, 1, 2},
682 {2, 1, 2, 2, 2, 2, 2, 2, 1, 2},
683 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
684 {2, 7, 2, 0, 0, 0, 0, 2, 7, 2},
685 {2, 1, 2, 0, 0, 0, 0, 2, 0, 2},
686 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
687 {2, 7, 2, 2, 2, 2, 2, 2, 7, 2},
688 {2, 1, 0, 6, 1, 0, 7, 1, 0, 2},
689 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}
692 static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] =
695 /* Experimental TRIA5:7x7 */
703 /* Stem cells, only "5" will fully reproduce itself */
705 {2,2,2,2,0,0,0,0,0,0,0,0},
706 {2,1,1,1,2,0,0,0,0,0,0,0},
707 {2,1,2,2,1,2,2,2,2,2,2,0},
708 {2,1,2,0,2,7,1,1,1,1,1,2},
709 {0,2,1,2,2,0,2,2,2,2,2,2},
710 {0,0,2,0,4,1,2,0,0,0,0,0},
711 {0,0,0,2,2,2,2,0,0,0,0,0}
713 {2,2,2,2,2,0,0,0,0,0,0,0,0,0},
714 {2,1,1,1,1,2,0,0,0,0,0,0,0,0},
715 {2,1,2,2,2,1,2,0,0,0,0,0,0,0},
716 {2,1,2,0,0,2,1,2,2,2,2,2,2,0},
717 {2,1,2,0,0,0,2,7,1,1,1,1,1,2},
718 {0,2,1,2,0,0,2,0,2,2,2,2,2,2},
719 {0,0,2,0,2,2,2,1,2,0,0,0,0,0},
720 {0,0,0,2,4,1,0,7,2,0,0,0,0,0},
721 {0,0,0,0,2,2,2,2,2,0,0,0,0,0}
723 {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0},
724 {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0},
725 {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0},
726 {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0},
727 {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0},
728 {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2},
729 {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2},
730 {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0},
731 {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0},
732 {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0},
733 {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0}
734 /* test:3x7 (0,4) is blank ... very strange.
735 init_adam seems ok something after that I guess */
743 #else /* this might be better for hexagons, spacewise efficient... */
745 /* Experimental TRIA5:7x7 */
755 {2,2,2,2,2,2,0,0,0,0,0},
756 {2,1,1,7,0,1,2,0,0,0,0},
757 {2,1,2,2,2,2,7,2,0,0,0},
758 {2,1,2,0,0,0,2,0,2,0,0},
759 {2,1,2,0,0,0,0,2,1,2,0},
760 {2,1,2,0,0,0,0,0,2,7,2},
761 {0,2,1,2,0,0,0,0,2,0,2},
762 {0,0,2,1,2,0,0,0,2,1,2},
763 {0,0,0,2,1,2,2,2,2,4,2},
764 {0,0,0,0,2,1,1,1,1,5,2},
765 {0,0,0,0,0,2,2,2,2,2,2}
771 position_of_neighbor(int dir, int *pcol, int *prow)
773 int col = *pcol, row = *prow;
777 if (local_neighbors == 6) {
802 (void) fprintf(stderr, "wrong direction %d\n", dir);
819 (void) fprintf(stderr, "wrong direction %d\n", dir);
827 withinBounds(loopstruct * lp, int col, int row)
829 return (row >= 1 && row < lp->bnrows - 1 &&
830 col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2)));
834 fillcell(ModeInfo * mi, GC gc, int col, int row)
836 loopstruct *lp = &loops[MI_SCREEN(mi)];
838 if (local_neighbors == 6) {
839 int ccol = 2 * col + !(row & 1), crow = 2 * row;
841 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
842 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
843 if (lp->xs == 1 && lp->ys == 1)
844 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
845 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
847 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
848 lp->shape.hexagon, 6, Convex, CoordModePrevious);
850 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
851 lp->xb + lp->xs * col, lp->yb + lp->ys * row,
852 lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3));
857 drawcell(ModeInfo * mi, int col, int row, int state)
859 loopstruct *lp = &loops[MI_SCREEN(mi)];
863 if (MI_NPIXELS(mi) >= COLORS) {
865 XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]);
868 gcv.stipple = lp->pixmaps[state];
869 #endif /* DO_STIPPLE */
870 gcv.foreground = MI_WHITE_PIXEL(mi);
871 gcv.background = MI_BLACK_PIXEL(mi);
872 XChangeGC(MI_DISPLAY(mi), lp->stippledGC,
875 #endif /* DO_STIPPLE */
876 GCForeground | GCBackground, &gcv);
879 fillcell(mi, gc, col, row);
884 print_state(ModeInfo * mi, int state)
886 loopstruct *lp = &loops[MI_SCREEN(mi)];
887 CellList *locallist = lp->cellList[state];
890 (void) printf("state %d\n", state);
892 (void) printf("%d x %d, y %d\n", i,
893 locallist->pt.x, locallist->pt.y);
894 locallist = locallist->next;
902 free_state(loopstruct * lp, int state)
906 while (lp->cellList[state]) {
907 current = lp->cellList[state];
908 lp->cellList[state] = lp->cellList[state]->next;
909 (void) free((void *) current);
911 lp->ncells[state] = 0;
915 free_list(loopstruct * lp)
919 for (state = 0; state < COLORS; state++)
920 free_state(lp, state);
924 free_loop(ModeInfo * mi)
926 Display *display = MI_DISPLAY(mi);
927 loopstruct *lp = &loops[MI_SCREEN(mi)];
930 for (shade = 0; shade < lp->init_bits; shade++)
931 if (lp->pixmaps[shade] != None) {
932 XFreePixmap(display, lp->pixmaps[shade]);
933 lp->pixmaps[shade] = None;
935 if (lp->stippledGC != None) {
936 XFreeGC(display, lp->stippledGC);
937 lp->stippledGC = None;
939 if (lp->oldcells != NULL) {
940 (void) free((void *) lp->oldcells);
941 lp->oldcells = (unsigned char *) NULL;
943 if (lp->newcells != NULL) {
944 (void) free((void *) lp->newcells);
945 lp->newcells = (unsigned char *) NULL;
951 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
953 loopstruct *lp = &loops[MI_SCREEN(mi)];
954 CellList *current = lp->cellList[state];
956 if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
958 lp->cellList[state] = current;
962 lp->cellList[state]->pt.x = col;
963 lp->cellList[state]->pt.y = row;
964 lp->cellList[state]->next = current;
970 draw_state(ModeInfo * mi, int state)
972 loopstruct *lp = &loops[MI_SCREEN(mi)];
973 Display *display = MI_DISPLAY(mi);
976 CellList *current = lp->cellList[state];
978 if (MI_NPIXELS(mi) >= COLORS) {
980 XSetForeground(display, gc, lp->colors[state]);
983 gcv.stipple = lp->pixmaps[state];
984 #endif /* DO_STIPPLE */
985 gcv.foreground = MI_WHITE_PIXEL(mi);
986 gcv.background = MI_BLACK_PIXEL(mi);
987 XChangeGC(display, lp->stippledGC,
990 #endif /* DO_STIPPLE */
991 GCForeground | GCBackground, &gcv);
995 if (local_neighbors == 6) { /* Draw right away, slow */
997 int col, row, ccol, crow;
1000 row = current->pt.y;
1001 ccol = 2 * col + !(row & 1), crow = 2 * row;
1002 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
1003 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
1004 if (lp->xs == 1 && lp->ys == 1)
1005 XDrawPoint(display, MI_WINDOW(mi), gc,
1006 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
1008 XFillPolygon(display, MI_WINDOW(mi), gc,
1009 lp->shape.hexagon, 6, Convex, CoordModePrevious);
1010 current = current->next;
1013 /* Take advantage of XFillRectangles */
1017 /* Create Rectangle list from part of the cellList */
1018 if ((rects = (XRectangle *) malloc(lp->ncells[state] *
1019 sizeof (XRectangle))) == NULL) {
1024 rects[nrects].x = lp->xb + current->pt.x * lp->xs;
1025 rects[nrects].y = lp->yb + current->pt.y * lp->ys;
1026 rects[nrects].width = lp->xs - (lp->xs > 3);
1027 rects[nrects].height = lp->ys - (lp->ys > 3);
1028 current = current->next;
1031 /* Finally get to draw */
1032 XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
1033 /* Free up rects list and the appropriate part of the cellList */
1034 (void) free((void *) rects);
1036 free_state(lp, state);
1043 if (table == NULL) {
1045 unsigned int tt, c, n[MAXNEIGHBORS], i;
1047 int size_transition_table = sizeof (transition_table) /
1048 sizeof (unsigned int);
1049 int size_hex_transition_table = sizeof (hex_transition_table) /
1050 sizeof (unsigned int);
1052 for (j = 0; j < local_neighbors; j++)
1055 if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
1061 /* Here I was interested to see what happens when it hits a wall....
1062 Rules not normally used take over... takes too much time though */
1063 /* Each state = 3 bits */
1064 if (MAXRAND < 16777216.0) {
1065 for (j = 0; j < mult; j++) {
1066 table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
1069 for (j = 0; j < mult; j++) {
1070 table[j] = (unsigned int) (NRAND(16777216));
1074 if (local_neighbors == 6) {
1075 for (j = 0; j < size_hex_transition_table; j++) {
1076 tt = hex_transition_table[j];
1078 for (k = 0; k < local_neighbors; k++) {
1079 TRANSITION(tt, n[k]);
1081 FINALTRANSITION(tt, c);
1082 HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
1083 HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
1084 HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
1085 HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i);
1086 HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i);
1087 HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i);
1090 for (j = 0; j < size_transition_table; j++) {
1091 tt = transition_table[j];
1093 for (k = 0; k < local_neighbors; k++) {
1094 TRANSITION(tt, n[k]);
1096 FINALTRANSITION(tt, c);
1097 TABLE_IN(c, n[0], n[1], n[2], n[3], i);
1098 TABLE_IN(c, n[1], n[2], n[3], n[0], i);
1099 TABLE_IN(c, n[2], n[3], n[0], n[1], i);
1100 TABLE_IN(c, n[3], n[0], n[1], n[2], i);
1108 init_flaw(ModeInfo * mi)
1110 loopstruct *lp = &loops[MI_SCREEN(mi)];
1114 if (lp->bncols <= 3 || lp->bnrows <= 3)
1116 a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
1117 HEX_MINGRIDSIZE : MINGRIDSIZE));
1118 a = NRAND(a) + (lp->bncols - a) / 2;
1119 b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
1120 HEX_MINGRIDSIZE : MINGRIDSIZE));
1121 b = NRAND(b) + (lp->bnrows - b) / 2;
1126 if (lp->maxcol < a + 2)
1128 if (lp->maxrow < b + 2)
1131 if (local_neighbors == 6) {
1132 lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
1133 lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1134 lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
1135 lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
1136 lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
1137 lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1139 int orient = NRAND(4);
1140 lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
1141 if (orient == 0 || orient == 1) {
1142 lp->newcells[lp->bncols * b + a + 1] = BLUE;
1144 if (orient == 1 || orient == 2) {
1145 lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
1147 if (orient == 2 || orient == 3) {
1148 lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
1150 if (orient == 3 || orient == 0) {
1151 lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
1157 init_adam(ModeInfo * mi)
1159 loopstruct *lp = &loops[MI_SCREEN(mi)];
1160 XPoint start = { 0, 0 }, dirx = { 0, 0 }, diry = { 0, 0 };
1163 #ifdef DELAYDEBUGLOOP
1165 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1167 lp->clockwise = (Bool) (LRAND() & 1);
1168 #ifdef DELAYDEBUGLOOP
1170 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1172 dir = NRAND(local_neighbors);
1173 if (local_neighbors == 6) {
1178 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1179 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1180 if (lp->mincol > start.x - 2)
1181 lp->mincol = start.x - 2;
1182 if (lp->minrow > start.y - 1)
1183 lp->minrow = start.y - 1;
1184 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1185 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1186 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1187 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1188 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1189 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1190 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1191 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1193 hex_self_reproducing_loop[i][j] :
1194 hex_self_reproducing_loop[j][i];
1199 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1200 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1201 if (lp->mincol > start.x - 1)
1202 lp->mincol = start.x - 1;
1203 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1204 lp->minrow = start.y - HEX_ADAM_LOOPX;
1205 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1206 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1207 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1208 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1209 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1210 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1211 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1212 ? -(i + j + 1) / 2 : -(i + j) / 2);
1213 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1215 hex_self_reproducing_loop[i][j] :
1216 hex_self_reproducing_loop[j][i];
1221 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1222 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1223 if (lp->mincol > start.x - 2)
1224 lp->mincol = start.x - 2;
1225 if (lp->minrow > start.y - 1)
1226 lp->minrow = start.y - 1;
1227 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1228 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1229 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1230 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1231 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1232 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1233 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1234 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1236 hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
1237 hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
1242 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1243 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1244 if (lp->mincol > start.x - 1)
1245 lp->mincol = start.x - 1;
1246 if (lp->minrow > start.y - 1)
1247 lp->minrow = start.y - 1;
1248 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1249 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1250 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1251 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1252 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1253 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1254 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1255 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1257 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1258 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1263 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1264 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1265 if (lp->mincol > start.x - 1)
1266 lp->mincol = start.x - 1;
1267 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1268 lp->minrow = start.y - HEX_ADAM_LOOPX;
1269 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1270 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1271 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1272 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1273 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1274 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1275 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1276 ? -(i + j + 1) / 2 : -(i + j) / 2);
1277 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1279 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1280 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1285 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1286 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1287 if (lp->mincol > start.x - 2)
1288 lp->mincol = start.x - 2;
1289 if (lp->minrow > start.y - 1)
1290 lp->minrow = start.y - 1;
1291 if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
1292 lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
1293 if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
1294 lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
1295 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1296 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1297 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1298 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1300 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
1301 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
1307 /* (void) printf ("s %d s %d \n", start.x, start.y); */
1308 (void) printf ("%d %d %d %d %d\n",
1309 start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1310 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
1311 /* Draw right away */
1312 drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1313 start.y + j - lp->by,
1314 hex_self_reproducing_loop[j][i]);
1319 start.x = (lp->bncols - ADAM_LOOPX) / 2;
1320 start.y = (lp->bnrows - ADAM_LOOPY) / 2;
1321 dirx.x = 1, dirx.y = 0;
1322 diry.x = 0, diry.y = 1;
1323 if (lp->mincol > start.x)
1324 lp->mincol = start.x;
1325 if (lp->minrow > start.y)
1326 lp->minrow = start.y;
1327 if (lp->maxcol < start.x + ADAM_LOOPX)
1328 lp->maxcol = start.x + ADAM_LOOPX;
1329 if (lp->maxrow < start.y + ADAM_LOOPY)
1330 lp->maxrow = start.y + ADAM_LOOPY;
1333 start.x = (lp->bncols + ADAM_LOOPY) / 2;
1334 start.y = (lp->bnrows - ADAM_LOOPX) / 2;
1335 dirx.x = 0, dirx.y = 1;
1336 diry.x = -1, diry.y = 0;
1337 if (lp->mincol > start.x - ADAM_LOOPY)
1338 lp->mincol = start.x - ADAM_LOOPY;
1339 if (lp->minrow > start.y)
1340 lp->minrow = start.y;
1341 if (lp->maxcol < start.x)
1342 lp->maxcol = start.x;
1343 if (lp->maxrow < start.y + ADAM_LOOPX)
1344 lp->maxrow = start.y + ADAM_LOOPX;
1347 start.x = (lp->bncols + ADAM_LOOPX) / 2;
1348 start.y = (lp->bnrows + ADAM_LOOPY) / 2;
1349 dirx.x = -1, dirx.y = 0;
1350 diry.x = 0, diry.y = -1;
1351 if (lp->mincol > start.x - ADAM_LOOPX)
1352 lp->mincol = start.x - ADAM_LOOPX;
1353 if (lp->minrow > start.y - ADAM_LOOPY)
1354 lp->minrow = start.y - ADAM_LOOPY;
1355 if (lp->maxcol < start.x)
1356 lp->maxcol = start.x;
1357 if (lp->maxrow < start.y)
1358 lp->maxrow = start.y;
1361 start.x = (lp->bncols - ADAM_LOOPY) / 2;
1362 start.y = (lp->bnrows + ADAM_LOOPX) / 2;
1363 dirx.x = 0, dirx.y = -1;
1364 diry.x = 1, diry.y = 0;
1365 if (lp->mincol > start.x)
1366 lp->mincol = start.x;
1367 if (lp->minrow > start.y - ADAM_LOOPX)
1368 lp->minrow = start.y - ADAM_LOOPX;
1369 if (lp->maxcol < start.x + ADAM_LOOPX)
1370 lp->maxcol = start.x + ADAM_LOOPX;
1371 if (lp->maxrow < start.y)
1372 lp->maxrow = start.y;
1375 for (j = 0; j < ADAM_LOOPY; j++)
1376 for (i = 0; i < ADAM_LOOPX; i++)
1377 lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
1378 start.x + dirx.x * i + diry.x * j] =
1380 self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
1381 self_reproducing_loop[j][i];
1383 /* Draw right away */
1384 drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
1385 start.y + dirx.y * i + diry.y * j - lp->by,
1386 (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
1393 do_gen(loopstruct * lp)
1397 unsigned int n[MAXNEIGHBORS];
1400 #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols)))
1402 for (j = lp->minrow; j <= lp->maxrow; j++) {
1403 for (i = lp->mincol; i <= lp->maxcol; i++) {
1404 z = lp->newcells + i + j * lp->bncols;
1406 for (k = 0; k < local_neighbors; k++) {
1407 int newi = i, newj = j;
1409 position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj);
1411 if (withinBounds(lp, newi, newj)) {
1412 n[k] = LOC(newi, newj);
1415 if (local_neighbors == 6) {
1416 *z = (lp->clockwise) ?
1417 HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
1418 HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
1420 *z = (lp->clockwise) ?
1421 TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
1422 TABLE_OUT(c, n[0], n[1], n[2], n[3]);
1429 release_loop (ModeInfo * mi)
1431 if (table != NULL) {
1432 (void) free((void *) table);
1433 table = (unsigned int *) NULL;
1437 static void *stop_warning_about_triangleUnit_already;
1441 init_loop (ModeInfo * mi)
1443 int i, size = MI_SIZE(mi);
1446 stop_warning_about_triangleUnit_already = (void *) &triangleUnit;
1448 MI_INIT (mi, loops);
1449 lp = &loops[MI_SCREEN(mi)];
1453 if (MI_WIDTH(mi) < 100 || MI_HEIGHT(mi) < 100) /* tiny window */
1454 size = MIN(MI_WIDTH(mi), MI_HEIGHT(mi));
1457 if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
1458 Window window = MI_WINDOW(mi);
1460 if (lp->stippledGC == None) {
1461 gcv.fill_style = FillOpaqueStippled;
1462 if ((lp->stippledGC = XCreateGC(MI_DISPLAY(mi), window,
1463 GCFillStyle, &gcv)) == None) {
1468 LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE);
1469 LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE);
1470 LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE);
1471 LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE);
1472 LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE);
1473 LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
1474 LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
1475 LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
1477 #endif /* DO_STIPPLE */
1478 if (MI_NPIXELS(mi) >= COLORS) {
1479 /* Maybe these colors should be randomized */
1480 lp->colors[0] = MI_BLACK_PIXEL(mi);
1481 lp->colors[1] = MI_PIXEL(mi, 0); /* RED */
1482 lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */
1483 lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */
1484 lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */
1485 lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */
1486 lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */
1487 lp->colors[7] = MI_WHITE_PIXEL(mi);
1491 lp->width = MI_WIDTH(mi);
1492 lp->height = MI_HEIGHT(mi);
1494 if (!local_neighbors) {
1495 for (i = 0; i < NEIGHBORKINDS; i++) {
1496 if (neighbors == plots[i]) {
1497 local_neighbors = neighbors;
1500 if (i == NEIGHBORKINDS - 1) {
1502 local_neighbors = plots[NRAND(NEIGHBORKINDS)];
1504 local_neighbors = 4;
1512 if (local_neighbors == 6) {
1519 if (size < -MINSIZE) {
1520 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1521 HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1522 } else if (size < MINSIZE) {
1524 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE);
1528 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1531 nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
1532 ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
1533 lp->ncols = nccols / 2;
1534 lp->nrows = ncrows / 2;
1535 lp->nrows -= !(lp->nrows & 1); /* Must be odd */
1536 lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
1537 lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
1538 for (i = 0; i < 6; i++) {
1539 lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x;
1540 lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
1543 if (size < -MINSIZE)
1544 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1545 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1546 else if (size < MINSIZE) {
1548 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE);
1552 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1555 lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1);
1556 lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1);
1557 lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
1558 lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
1562 lp->bncols = lp->ncols + 2 * lp->bx;
1563 lp->bnrows = lp->nrows + 2 * lp->by;
1567 if (lp->oldcells != NULL) {
1568 (void) free((void *) lp->oldcells);
1569 lp->oldcells = (unsigned char *) NULL;
1571 if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1572 sizeof (unsigned char))) == NULL) {
1576 if (lp->newcells != NULL) {
1577 (void) free((void *) lp->newcells);
1578 lp->newcells = (unsigned char *) NULL;
1580 if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1581 sizeof (unsigned char))) == NULL) {
1585 if (!init_table()) {
1589 lp->mincol = lp->bncols - 1;
1590 lp->minrow = lp->bnrows - 1;
1593 #ifndef DELAYDEBUGLOOP
1595 int flaws = MI_COUNT(mi);
1598 flaws = NRAND(-MI_COUNT(mi) + 1);
1599 for (i = 0; i < flaws; i++) {
1602 /* actual flaws might be less since the adam loop done next */
1609 draw_loop (ModeInfo * mi)
1612 unsigned char *z, *znew;
1617 lp = &loops[MI_SCREEN(mi)];
1618 if (lp->newcells == NULL)
1621 MI_IS_DRAWN(mi) = True;
1623 #ifdef DELAYDEBUGLOOP
1624 if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
1625 (void) sleep(DELAYDEBUGLOOP);
1629 for (j = lp->minrow; j <= lp->maxrow; j++) {
1630 for (i = lp->mincol; i <= lp->maxcol; i++) {
1631 offset = j * lp->bncols + i;
1632 z = lp->oldcells + offset;
1633 znew = lp->newcells + offset;
1637 if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
1639 if (i == lp->mincol && i > lp->bx)
1641 if (j == lp->minrow && j > lp->by)
1643 if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx)
1645 if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by)
1650 for (i = 0; i < COLORS; i++)
1651 if (!draw_state(mi, i)) {
1655 if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
1661 if (lp->redrawing) {
1662 for (i = 0; i < REDRAWSTEP; i++) {
1663 if ((*(lp->oldcells + lp->redrawpos))) {
1664 drawcell(mi, lp->redrawpos % lp->bncols - lp->bx,
1665 lp->redrawpos / lp->bncols - lp->by,
1666 *(lp->oldcells + lp->redrawpos));
1668 if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) {
1678 refresh_loop (ModeInfo * mi)
1684 lp = &loops[MI_SCREEN(mi)];
1688 lp->redrawpos = lp->by * lp->ncols + lp->bx;
1692 XSCREENSAVER_MODULE ("Loop", loop)
1694 #endif /* MODE_loop */