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" \
95 # define UNIFORM_COLORS
96 # define reshape_loop 0
97 # define loop_handle_event 0
98 # include "xlockmore.h" /* in xscreensaver distribution */
99 #else /* STANDALONE */
100 # include "xlock.h" /* in xlockmore distribution */
101 #endif /* STANDALONE */
102 #include "automata.h"
107 * neighbors of 0 randomizes between 4 and 6.
109 #define DEF_NEIGHBORS "0" /* choose random value */
111 static int neighbors;
113 static XrmOptionDescRec opts[] =
115 {"-neighbors", ".loop.neighbors", XrmoptionSepArg, 0}
118 static argtype vars[] =
120 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
123 static OptionStruct desc[] =
125 {"-neighbors num", "squares 4 or hexagons 6"}
128 ENTRYPOINT ModeSpecOpt loop_opts =
129 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
133 ModStruct loop_description =
134 {"loop", "init_loop", "draw_loop", "release_loop",
135 "refresh_loop", "init_loop", (char *) NULL, &loop_opts,
136 100000, 5, 1600, -12, 64, 1.0, "",
137 "Shows Langton's self-producing loops", 0, NULL};
141 #define LOOPBITS(n,w,h)\
142 if ((lp->pixmaps[lp->init_bits]=\
143 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
144 free_loop(display,lp); return;} else {lp->init_bits++;}
146 static int local_neighbors = 0;
149 /* Used to fast forward to troubled generations, mainly used for debugging.
150 -delay 1 -count 170 -neighbors 6 # divisions starts
151 540 first cell collision
152 1111 mutant being born from 2 parents
155 #define DELAYDEBUGLOOP 10
159 #define REALCOLORS (COLORS-2)
161 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
162 #define ADAM_SIZE 8 /* MIN 5 */
164 #define ADAM_LOOPX (ADAM_SIZE+2)
165 #define ADAM_LOOPY (ADAM_SIZE+2)
167 #define ADAM_LOOPX 16
168 #define ADAM_LOOPY 10
170 #define MINGRIDSIZE (3*ADAM_LOOPX)
172 /* TRIA stuff was an attempt to make a triangular lifeform on a
173 hexagonal grid but I got bored. You may need an additional 7th
174 state for a coherent step by step process of cell separation and
175 initial stem development.
180 #define HEX_ADAM_SIZE 3 /* MIN 3 */
182 #define HEX_ADAM_SIZE 5 /* MIN 3 */
185 #define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
186 #define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
188 #define HEX_ADAM_LOOPX 3
189 #define HEX_ADAM_LOOPY 7
191 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
192 #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6)))
193 #define NEIGHBORKINDS 2
195 #define MAXNEIGHBORS 6
197 /* Singly linked list */
198 typedef struct _CellList {
200 struct _CellList *next;
209 int bx, by, bnrows, bncols;
210 int mincol, minrow, maxcol, maxrow;
212 int redrawing, redrawpos;
213 Bool dead, clockwise;
214 unsigned char *newcells, *oldcells;
216 CellList *cellList[COLORS];
217 unsigned long colors[COLORS];
219 Pixmap pixmaps[COLORS];
225 static loopstruct *loops = (loopstruct *) NULL;
227 #define TRANSITION(TT,V) V=TT&7;TT>>=3
228 #define FINALTRANSITION(TT,V) V=TT&7
229 #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)])
230 #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)])
233 /* Instead of setting "unused" state rules to zero it randomizes them.
234 These rules take over when something unexpected happens... like when a
235 cell hits a wall (the end of the screen).
241 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\
242 (TABLE(R,T,L,B)|=((I)<<((C)*3)))
243 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\
244 (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
246 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)|=((I)<<((C)*3)))
247 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
249 #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7)
250 #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7)
252 static unsigned int *table = (unsigned int *) NULL;
253 /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */
254 /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */
256 static char plots[NEIGHBORKINDS] =
258 4, 6 /* Neighborhoods */
261 static unsigned int transition_table[] =
262 { /* Octal CBLTR->I */
263 /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */
264 0000000, 0025271, 0113221, 0202422, 0301021,
265 0000012, 0100011, 0122244, 0202452, 0301220,
266 0000020, 0100061, 0122277, 0202520, 0302511,
267 0000030, 0100077, 0122434, 0202552, 0401120,
268 0000050, 0100111, 0122547, 0202622, 0401220,
269 0000063, 0100121, 0123244, 0202722, 0401250,
270 0000071, 0100211, 0123277, 0203122, 0402120,
271 0000112, 0100244, 0124255, 0203216, 0402221,
272 0000122, 0100277, 0124267, 0203226, 0402326,
273 0000132, 0100511, 0125275, 0203422, 0402520,
274 0000212, 0101011, 0200012, 0204222, 0403221,
275 0000220, 0101111, 0200022, 0205122, 0500022,
276 0000230, 0101244, 0200042, 0205212, 0500215,
277 0000262, 0101277, 0200071, 0205222, 0500225,
278 0000272, 0102026, 0200122, 0205521, 0500232,
279 0000320, 0102121, 0200152, 0205725, 0500272,
280 0000525, 0102211, 0200212, 0206222, 0500520,
281 0000622, 0102244, 0200222, 0206722, 0502022,
282 0000722, 0102263, 0200232, 0207122, 0502122,
283 0001022, 0102277, 0200242, 0207222, 0502152,
284 0001120, 0102327, 0200250, 0207422, 0502220,
285 0002020, 0102424, 0200262, 0207722, 0502244,
286 0002030, 0102626, 0200272, 0211222, 0502722,
287 0002050, 0102644, 0200326, 0211261, 0512122,
288 0002125, 0102677, 0200423, 0212222, 0512220,
289 0002220, 0102710, 0200517, 0212242, 0512422,
290 0002322, 0102727, 0200522, 0212262, 0512722,
291 0005222, 0105427, 0200575, 0212272, 0600011,
292 0012321, 0111121, 0200722, 0214222, 0600021,
293 0012421, 0111221, 0201022, 0215222, 0602120,
294 0012525, 0111244, 0201122, 0216222, 0612125,
295 0012621, 0111251, 0201222, 0217222, 0612131,
296 0012721, 0111261, 0201422, 0222272, 0612225,
297 0012751, 0111277, 0201722, 0222442, 0700077,
298 0014221, 0111522, 0202022, 0222462, 0701120,
299 0014321, 0112121, 0202032, 0222762, 0701220,
300 0014421, 0112221, 0202052, 0222772, 0701250,
301 0014721, 0112244, 0202073, 0300013, 0702120,
302 0016251, 0112251, 0202122, 0300022, 0702221,
303 0017221, 0112277, 0202152, 0300041, 0702251,
304 0017255, 0112321, 0202212, 0300076, 0702321,
305 0017521, 0112424, 0202222, 0300123, 0702525,
306 0017621, 0112621, 0202272, 0300421, 0702720,
307 0017721, 0112727, 0202321, 0300622
310 static unsigned int hex_transition_table[] =
311 { /* Octal CBbltTR->I */
312 /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */
315 000000000, 000000020, 000000220, 000002220, 000022220,
316 011122121, 011121221, 011122221, 011221221,
317 011222221, 011112121, 011112221,
318 020021122, 020002122, 020211222, 021111222,
319 020221122, 020027122, 020020722, 020021022,
321 011122727, 011227227, 010122121, 010222211,
322 021117222, 020112272,
325 010221121, 011721221, 011222277,
326 020111222, 020221172,
329 010212277, 010221221,
334 020002022, 021122172,
336 011122277, 011172121,
337 010212177, 011212277,
341 070121270, 070721220,
342 000112721, 000272211,
343 010022211, 012222277,
344 020072272, 020227122, 020217222,
349 020021072, 020070722,
350 070002072, 070007022,
353 000000070, 000000770, 000072220, 000000270,
354 020110222, 020220272, 020220722,
355 070007071, 070002072, 070007022,
356 000000012, 000000122, 000000212, 001277721,
357 020122072, 020202212,
359 020001122, 020002112,
361 020122022, 020027022, 020070122, 020020122,
364 010227227, 010227277,
371 010022277, 010202177, 010227127,
375 020024122, 020020422,
378 010221241, 010224224,
383 020112242, 021422172,
385 001224221, 001427221,
390 010022244, 010202144, 010224124,
394 040121240, 040421220,
395 000242211, 000112421,
396 020042242, 020214222, 020021422, 020220242, 020024022,
403 001244421, 000000420, 000000440, 000000240, 000000040,
404 020040121, 020021042,
405 040004022, 040004042, 040002042,
407 020011122, 020002112,
414 020224072, 021417222,
420 070207072, 070701220,
425 020021222, 020202272, 020120222, 020221722,
429 020101272, 020272172, 020721422, 020721722,
430 020011222, 020202242,
448 000000000, 000000020, 000000220, 000002220,
449 011212121, 011212221, 011221221, 011222221,
450 020002122, 020021122, 020211122,
452 010221221, 010222121,
453 020002022, 020021022, 020020122, 020112022,
456 020102022, 020202112,
458 000000012, 000000122, 000000212,
460 020001122, 020002112, 020011122,
463 001227221, 001272221, 001272721,
464 012212277, 011222727, 011212727,
465 020021722, 020027122, 020020722, 020027022,
466 020211722, 020202172, 020120272,
467 020271122, 020202172, 020207122, 020217122,
468 020120272, 020210722, 020270722,
469 070212220, 070221220, 070212120,
476 001277721, 000000070, 000000270, 000000720, 000000770,
477 020070122, 020021072,
478 070002072, 070007022, 070007071,
483 010227227, 010222727, 010202727,
484 020172022, 020202712,
486 001224221, 001242221, 001242421,
487 012212244, 011222424, 011212424,
488 020021422, 020024122, 020020422, 020024022,
489 020211422, 020202142, 020120242,
490 020241122, 020202142, 020204122, 020214122,
491 020120242, 020210422, 020240422,
492 040212220, 040221220, 040212120,
499 001244421, 000000040, 000000240, 000000420, 000000440,
500 020040122, 020021042,
502 040004021, 040004042,
507 010224224, 010222424, 010202424,
508 020142022, 020202412,
509 020011722, 020112072, 020172072, 020142072,
513 000210225, 000022015, 000022522,
515 020120525, 020020152, 020005122, 020214255, 020021152,
517 050215222, 050225121,
519 000225220, 001254222,
520 010221250, 011221251, 011225221,
521 020025122, 020152152, 020211252, 020214522, 020511125,
525 000000250, 000000520, 000150220, 000220520, 000222210,
527 010022152, 010251221, 010522121, 011212151, 011221251,
529 020000220, 020002152, 020020220, 020022152,
530 020021422, 020022152, 020022522, 020025425, 020050422,
531 020051022, 020051122, 020211122, 020211222, 020215222,
533 050021125, 050021025, 050011125, 051242221,
536 000220250, 000220520, 001227521, 001275221,
537 011257227, 011522727,
538 020002052, 020002752, 020021052, 020057125,
539 050020722, 050027125,
634 000000050, 000005220, 000002270, 070252220,
635 000000450, 000007220,
636 000220220, 000202220, 000022020, 000020220,
644 050221120, 010221520,
647 000070220, 000220720,
648 000020520, 000070250, 000222070, 000027020,
649 000022070, 000202270, 000024020, 000220420,
650 000220270, 000220240, 000072020, 000042020,
651 000002020, 000002070, 000020270, 000020250,
652 000270270, 000007020, 000040270,
654 /* Collision starts (gen 540), not sure to have rules to save it
655 or depend on calloc to intialize remaining rules to 0 so that
656 the mutant will be born
664 Neighborhoods are read as follows (rotations are not listed):
674 static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] =
677 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0},
678 {2, 4, 0, 1, 4, 0, 1, 1, 1, 2},
679 {2, 1, 2, 2, 2, 2, 2, 2, 1, 2},
680 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
681 {2, 7, 2, 0, 0, 0, 0, 2, 7, 2},
682 {2, 1, 2, 0, 0, 0, 0, 2, 0, 2},
683 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
684 {2, 7, 2, 2, 2, 2, 2, 2, 7, 2},
685 {2, 1, 0, 6, 1, 0, 7, 1, 0, 2},
686 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}
689 static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] =
692 /* Experimental TRIA5:7x7 */
700 /* Stem cells, only "5" will fully reproduce itself */
702 {2,2,2,2,0,0,0,0,0,0,0,0},
703 {2,1,1,1,2,0,0,0,0,0,0,0},
704 {2,1,2,2,1,2,2,2,2,2,2,0},
705 {2,1,2,0,2,7,1,1,1,1,1,2},
706 {0,2,1,2,2,0,2,2,2,2,2,2},
707 {0,0,2,0,4,1,2,0,0,0,0,0},
708 {0,0,0,2,2,2,2,0,0,0,0,0}
710 {2,2,2,2,2,0,0,0,0,0,0,0,0,0},
711 {2,1,1,1,1,2,0,0,0,0,0,0,0,0},
712 {2,1,2,2,2,1,2,0,0,0,0,0,0,0},
713 {2,1,2,0,0,2,1,2,2,2,2,2,2,0},
714 {2,1,2,0,0,0,2,7,1,1,1,1,1,2},
715 {0,2,1,2,0,0,2,0,2,2,2,2,2,2},
716 {0,0,2,0,2,2,2,1,2,0,0,0,0,0},
717 {0,0,0,2,4,1,0,7,2,0,0,0,0,0},
718 {0,0,0,0,2,2,2,2,2,0,0,0,0,0}
720 {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0},
721 {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0},
722 {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0},
723 {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0},
724 {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0},
725 {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2},
726 {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2},
727 {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0},
728 {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0},
729 {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0},
730 {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0}
731 /* test:3x7 (0,4) is blank ... very strange.
732 init_adam seems ok something after that I guess */
740 #else /* this might be better for hexagons, spacewise efficient... */
742 /* Experimental TRIA5:7x7 */
752 {2,2,2,2,2,2,0,0,0,0,0},
753 {2,1,1,7,0,1,2,0,0,0,0},
754 {2,1,2,2,2,2,7,2,0,0,0},
755 {2,1,2,0,0,0,2,0,2,0,0},
756 {2,1,2,0,0,0,0,2,1,2,0},
757 {2,1,2,0,0,0,0,0,2,7,2},
758 {0,2,1,2,0,0,0,0,2,0,2},
759 {0,0,2,1,2,0,0,0,2,1,2},
760 {0,0,0,2,1,2,2,2,2,4,2},
761 {0,0,0,0,2,1,1,1,1,5,2},
762 {0,0,0,0,0,2,2,2,2,2,2}
768 position_of_neighbor(int dir, int *pcol, int *prow)
770 int col = *pcol, row = *prow;
774 if (local_neighbors == 6) {
799 (void) fprintf(stderr, "wrong direction %d\n", dir);
816 (void) fprintf(stderr, "wrong direction %d\n", dir);
824 withinBounds(loopstruct * lp, int col, int row)
826 return (row >= 1 && row < lp->bnrows - 1 &&
827 col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2)));
831 fillcell(ModeInfo * mi, GC gc, int col, int row)
833 loopstruct *lp = &loops[MI_SCREEN(mi)];
835 if (local_neighbors == 6) {
836 int ccol = 2 * col + !(row & 1), crow = 2 * row;
838 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
839 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
840 if (lp->xs == 1 && lp->ys == 1)
841 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
842 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
844 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
845 lp->shape.hexagon, 6, Convex, CoordModePrevious);
847 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
848 lp->xb + lp->xs * col, lp->yb + lp->ys * row,
849 lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3));
854 drawcell(ModeInfo * mi, int col, int row, int state)
856 loopstruct *lp = &loops[MI_SCREEN(mi)];
860 if (MI_NPIXELS(mi) >= COLORS) {
862 XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]);
865 gcv.stipple = lp->pixmaps[state];
866 #endif /* DO_STIPPLE */
867 gcv.foreground = MI_WHITE_PIXEL(mi);
868 gcv.background = MI_BLACK_PIXEL(mi);
869 XChangeGC(MI_DISPLAY(mi), lp->stippledGC,
872 #endif /* DO_STIPPLE */
873 GCForeground | GCBackground, &gcv);
876 fillcell(mi, gc, col, row);
881 print_state(ModeInfo * mi, int state)
883 loopstruct *lp = &loops[MI_SCREEN(mi)];
884 CellList *locallist = lp->cellList[state];
887 (void) printf("state %d\n", state);
889 (void) printf("%d x %d, y %d\n", i,
890 locallist->pt.x, locallist->pt.y);
891 locallist = locallist->next;
899 free_state(loopstruct * lp, int state)
903 while (lp->cellList[state]) {
904 current = lp->cellList[state];
905 lp->cellList[state] = lp->cellList[state]->next;
906 (void) free((void *) current);
908 lp->ncells[state] = 0;
912 free_list(loopstruct * lp)
916 for (state = 0; state < COLORS; state++)
917 free_state(lp, state);
921 free_loop(Display *display, loopstruct * lp)
925 for (shade = 0; shade < lp->init_bits; shade++)
926 if (lp->pixmaps[shade] != None) {
927 XFreePixmap(display, lp->pixmaps[shade]);
928 lp->pixmaps[shade] = None;
930 if (lp->stippledGC != None) {
931 XFreeGC(display, lp->stippledGC);
932 lp->stippledGC = None;
934 if (lp->oldcells != NULL) {
935 (void) free((void *) lp->oldcells);
936 lp->oldcells = (unsigned char *) NULL;
938 if (lp->newcells != NULL) {
939 (void) free((void *) lp->newcells);
940 lp->newcells = (unsigned char *) NULL;
946 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
948 loopstruct *lp = &loops[MI_SCREEN(mi)];
949 CellList *current = lp->cellList[state];
951 if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
953 lp->cellList[state] = current;
954 free_loop(MI_DISPLAY(mi), lp);
957 lp->cellList[state]->pt.x = col;
958 lp->cellList[state]->pt.y = row;
959 lp->cellList[state]->next = current;
965 draw_state(ModeInfo * mi, int state)
967 loopstruct *lp = &loops[MI_SCREEN(mi)];
968 Display *display = MI_DISPLAY(mi);
971 CellList *current = lp->cellList[state];
973 if (MI_NPIXELS(mi) >= COLORS) {
975 XSetForeground(display, gc, lp->colors[state]);
978 gcv.stipple = lp->pixmaps[state];
979 #endif /* DO_STIPPLE */
980 gcv.foreground = MI_WHITE_PIXEL(mi);
981 gcv.background = MI_BLACK_PIXEL(mi);
982 XChangeGC(display, lp->stippledGC,
985 #endif /* DO_STIPPLE */
986 GCForeground | GCBackground, &gcv);
990 if (local_neighbors == 6) { /* Draw right away, slow */
992 int col, row, ccol, crow;
996 ccol = 2 * col + !(row & 1), crow = 2 * row;
997 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
998 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
999 if (lp->xs == 1 && lp->ys == 1)
1000 XDrawPoint(display, MI_WINDOW(mi), gc,
1001 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
1003 XFillPolygon(display, MI_WINDOW(mi), gc,
1004 lp->shape.hexagon, 6, Convex, CoordModePrevious);
1005 current = current->next;
1008 /* Take advantage of XFillRectangles */
1012 /* Create Rectangle list from part of the cellList */
1013 if ((rects = (XRectangle *) malloc(lp->ncells[state] *
1014 sizeof (XRectangle))) == NULL) {
1019 rects[nrects].x = lp->xb + current->pt.x * lp->xs;
1020 rects[nrects].y = lp->yb + current->pt.y * lp->ys;
1021 rects[nrects].width = lp->xs - (lp->xs > 3);
1022 rects[nrects].height = lp->ys - (lp->ys > 3);
1023 current = current->next;
1026 /* Finally get to draw */
1027 XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
1028 /* Free up rects list and the appropriate part of the cellList */
1029 (void) free((void *) rects);
1031 free_state(lp, state);
1038 if (table == NULL) {
1040 unsigned int tt, c, n[MAXNEIGHBORS], i;
1042 int size_transition_table = sizeof (transition_table) /
1043 sizeof (unsigned int);
1044 int size_hex_transition_table = sizeof (hex_transition_table) /
1045 sizeof (unsigned int);
1047 for (j = 0; j < local_neighbors; j++)
1050 if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
1056 /* Here I was interested to see what happens when it hits a wall....
1057 Rules not normally used take over... takes too much time though */
1058 /* Each state = 3 bits */
1059 if (MAXRAND < 16777216.0) {
1060 for (j = 0; j < mult; j++) {
1061 table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
1064 for (j = 0; j < mult; j++) {
1065 table[j] = (unsigned int) (NRAND(16777216));
1069 if (local_neighbors == 6) {
1070 for (j = 0; j < size_hex_transition_table; j++) {
1071 tt = hex_transition_table[j];
1073 for (k = 0; k < local_neighbors; k++) {
1074 TRANSITION(tt, n[k]);
1076 FINALTRANSITION(tt, c);
1077 HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
1078 HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
1079 HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
1080 HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i);
1081 HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i);
1082 HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i);
1085 for (j = 0; j < size_transition_table; j++) {
1086 tt = transition_table[j];
1088 for (k = 0; k < local_neighbors; k++) {
1089 TRANSITION(tt, n[k]);
1091 FINALTRANSITION(tt, c);
1092 TABLE_IN(c, n[0], n[1], n[2], n[3], i);
1093 TABLE_IN(c, n[1], n[2], n[3], n[0], i);
1094 TABLE_IN(c, n[2], n[3], n[0], n[1], i);
1095 TABLE_IN(c, n[3], n[0], n[1], n[2], i);
1103 init_flaw(ModeInfo * mi)
1105 loopstruct *lp = &loops[MI_SCREEN(mi)];
1109 if (lp->bncols <= 3 || lp->bnrows <= 3)
1111 a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
1112 HEX_MINGRIDSIZE : MINGRIDSIZE));
1113 a = NRAND(a) + (lp->bncols - a) / 2;
1114 b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
1115 HEX_MINGRIDSIZE : MINGRIDSIZE));
1116 b = NRAND(b) + (lp->bnrows - b) / 2;
1121 if (lp->maxcol < a + 2)
1123 if (lp->maxrow < b + 2)
1126 if (local_neighbors == 6) {
1127 lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
1128 lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1129 lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
1130 lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
1131 lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
1132 lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1134 int orient = NRAND(4);
1135 lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
1136 if (orient == 0 || orient == 1) {
1137 lp->newcells[lp->bncols * b + a + 1] = BLUE;
1139 if (orient == 1 || orient == 2) {
1140 lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
1142 if (orient == 2 || orient == 3) {
1143 lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
1145 if (orient == 3 || orient == 0) {
1146 lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
1152 init_adam(ModeInfo * mi)
1154 loopstruct *lp = &loops[MI_SCREEN(mi)];
1155 XPoint start = { 0, 0 }, dirx = { 0, 0 }, diry = { 0, 0 };
1158 #ifdef DELAYDEBUGLOOP
1160 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1162 lp->clockwise = (Bool) (LRAND() & 1);
1163 #ifdef DELAYDEBUGLOOP
1165 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1167 dir = NRAND(local_neighbors);
1168 if (local_neighbors == 6) {
1173 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1174 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1175 if (lp->mincol > start.x - 2)
1176 lp->mincol = start.x - 2;
1177 if (lp->minrow > start.y - 1)
1178 lp->minrow = start.y - 1;
1179 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1180 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1181 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1182 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1183 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1184 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1185 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1186 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1188 hex_self_reproducing_loop[i][j] :
1189 hex_self_reproducing_loop[j][i];
1194 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1195 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1196 if (lp->mincol > start.x - 1)
1197 lp->mincol = start.x - 1;
1198 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1199 lp->minrow = start.y - HEX_ADAM_LOOPX;
1200 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1201 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1202 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1203 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1204 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1205 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1206 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1207 ? -(i + j + 1) / 2 : -(i + j) / 2);
1208 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1210 hex_self_reproducing_loop[i][j] :
1211 hex_self_reproducing_loop[j][i];
1216 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1217 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1218 if (lp->mincol > start.x - 2)
1219 lp->mincol = start.x - 2;
1220 if (lp->minrow > start.y - 1)
1221 lp->minrow = start.y - 1;
1222 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1223 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1224 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1225 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1226 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1227 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1228 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1229 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1231 hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
1232 hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
1237 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1238 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1239 if (lp->mincol > start.x - 1)
1240 lp->mincol = start.x - 1;
1241 if (lp->minrow > start.y - 1)
1242 lp->minrow = start.y - 1;
1243 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1244 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1245 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1246 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1247 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1248 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1249 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1250 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1252 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1253 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1258 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1259 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1260 if (lp->mincol > start.x - 1)
1261 lp->mincol = start.x - 1;
1262 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1263 lp->minrow = start.y - HEX_ADAM_LOOPX;
1264 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1265 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1266 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1267 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1268 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1269 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1270 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1271 ? -(i + j + 1) / 2 : -(i + j) / 2);
1272 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1274 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1275 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1280 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1281 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1282 if (lp->mincol > start.x - 2)
1283 lp->mincol = start.x - 2;
1284 if (lp->minrow > start.y - 1)
1285 lp->minrow = start.y - 1;
1286 if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
1287 lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
1288 if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
1289 lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
1290 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1291 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1292 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1293 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1295 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
1296 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
1302 /* (void) printf ("s %d s %d \n", start.x, start.y); */
1303 (void) printf ("%d %d %d %d %d\n",
1304 start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1305 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
1306 /* Draw right away */
1307 drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1308 start.y + j - lp->by,
1309 hex_self_reproducing_loop[j][i]);
1314 start.x = (lp->bncols - ADAM_LOOPX) / 2;
1315 start.y = (lp->bnrows - ADAM_LOOPY) / 2;
1316 dirx.x = 1, dirx.y = 0;
1317 diry.x = 0, diry.y = 1;
1318 if (lp->mincol > start.x)
1319 lp->mincol = start.x;
1320 if (lp->minrow > start.y)
1321 lp->minrow = start.y;
1322 if (lp->maxcol < start.x + ADAM_LOOPX)
1323 lp->maxcol = start.x + ADAM_LOOPX;
1324 if (lp->maxrow < start.y + ADAM_LOOPY)
1325 lp->maxrow = start.y + ADAM_LOOPY;
1328 start.x = (lp->bncols + ADAM_LOOPY) / 2;
1329 start.y = (lp->bnrows - ADAM_LOOPX) / 2;
1330 dirx.x = 0, dirx.y = 1;
1331 diry.x = -1, diry.y = 0;
1332 if (lp->mincol > start.x - ADAM_LOOPY)
1333 lp->mincol = start.x - ADAM_LOOPY;
1334 if (lp->minrow > start.y)
1335 lp->minrow = start.y;
1336 if (lp->maxcol < start.x)
1337 lp->maxcol = start.x;
1338 if (lp->maxrow < start.y + ADAM_LOOPX)
1339 lp->maxrow = start.y + ADAM_LOOPX;
1342 start.x = (lp->bncols + ADAM_LOOPX) / 2;
1343 start.y = (lp->bnrows + ADAM_LOOPY) / 2;
1344 dirx.x = -1, dirx.y = 0;
1345 diry.x = 0, diry.y = -1;
1346 if (lp->mincol > start.x - ADAM_LOOPX)
1347 lp->mincol = start.x - ADAM_LOOPX;
1348 if (lp->minrow > start.y - ADAM_LOOPY)
1349 lp->minrow = start.y - ADAM_LOOPY;
1350 if (lp->maxcol < start.x)
1351 lp->maxcol = start.x;
1352 if (lp->maxrow < start.y)
1353 lp->maxrow = start.y;
1356 start.x = (lp->bncols - ADAM_LOOPY) / 2;
1357 start.y = (lp->bnrows + ADAM_LOOPX) / 2;
1358 dirx.x = 0, dirx.y = -1;
1359 diry.x = 1, diry.y = 0;
1360 if (lp->mincol > start.x)
1361 lp->mincol = start.x;
1362 if (lp->minrow > start.y - ADAM_LOOPX)
1363 lp->minrow = start.y - ADAM_LOOPX;
1364 if (lp->maxcol < start.x + ADAM_LOOPX)
1365 lp->maxcol = start.x + ADAM_LOOPX;
1366 if (lp->maxrow < start.y)
1367 lp->maxrow = start.y;
1370 for (j = 0; j < ADAM_LOOPY; j++)
1371 for (i = 0; i < ADAM_LOOPX; i++)
1372 lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
1373 start.x + dirx.x * i + diry.x * j] =
1375 self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
1376 self_reproducing_loop[j][i];
1378 /* Draw right away */
1379 drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
1380 start.y + dirx.y * i + diry.y * j - lp->by,
1381 (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
1388 do_gen(loopstruct * lp)
1392 unsigned int n[MAXNEIGHBORS];
1395 #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols)))
1397 for (j = lp->minrow; j <= lp->maxrow; j++) {
1398 for (i = lp->mincol; i <= lp->maxcol; i++) {
1399 z = lp->newcells + i + j * lp->bncols;
1401 for (k = 0; k < local_neighbors; k++) {
1402 int newi = i, newj = j;
1404 position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj);
1406 if (withinBounds(lp, newi, newj)) {
1407 n[k] = LOC(newi, newj);
1410 if (local_neighbors == 6) {
1411 *z = (lp->clockwise) ?
1412 HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
1413 HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
1415 *z = (lp->clockwise) ?
1416 TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
1417 TABLE_OUT(c, n[0], n[1], n[2], n[3]);
1424 release_loop (ModeInfo * mi)
1426 if (loops != NULL) {
1429 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1430 free_loop(MI_DISPLAY(mi), &loops[screen]);
1431 (void) free((void *) loops);
1432 loops = (loopstruct *) NULL;
1434 if (table != NULL) {
1435 (void) free((void *) table);
1436 table = (unsigned int *) NULL;
1440 static void *stop_warning_about_triangleUnit_already;
1444 init_loop (ModeInfo * mi)
1446 Display *display = MI_DISPLAY(mi);
1447 int i, size = MI_SIZE(mi);
1450 stop_warning_about_triangleUnit_already = (void *) &triangleUnit;
1452 if (loops == NULL) {
1453 if ((loops = (loopstruct *) calloc(MI_NUM_SCREENS(mi),
1454 sizeof (loopstruct))) == NULL)
1457 lp = &loops[MI_SCREEN(mi)];
1462 if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
1463 Window window = MI_WINDOW(mi);
1465 if (lp->stippledGC == None) {
1466 gcv.fill_style = FillOpaqueStippled;
1467 if ((lp->stippledGC = XCreateGC(display, window,
1468 GCFillStyle, &gcv)) == None) {
1469 free_loop(display, lp);
1473 LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE);
1474 LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE);
1475 LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE);
1476 LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE);
1477 LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE);
1478 LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
1479 LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
1480 LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
1482 #endif /* DO_STIPPLE */
1483 if (MI_NPIXELS(mi) >= COLORS) {
1484 /* Maybe these colors should be randomized */
1485 lp->colors[0] = MI_BLACK_PIXEL(mi);
1486 lp->colors[1] = MI_PIXEL(mi, 0); /* RED */
1487 lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */
1488 lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */
1489 lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */
1490 lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */
1491 lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */
1492 lp->colors[7] = MI_WHITE_PIXEL(mi);
1496 lp->width = MI_WIDTH(mi);
1497 lp->height = MI_HEIGHT(mi);
1499 if (!local_neighbors) {
1500 for (i = 0; i < NEIGHBORKINDS; i++) {
1501 if (neighbors == plots[i]) {
1502 local_neighbors = neighbors;
1505 if (i == NEIGHBORKINDS - 1) {
1507 local_neighbors = plots[NRAND(NEIGHBORKINDS)];
1509 local_neighbors = 4;
1517 if (local_neighbors == 6) {
1524 if (size < -MINSIZE) {
1525 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1526 HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1527 } else if (size < MINSIZE) {
1529 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE);
1533 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1536 nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
1537 ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
1538 lp->ncols = nccols / 2;
1539 lp->nrows = ncrows / 2;
1540 lp->nrows -= !(lp->nrows & 1); /* Must be odd */
1541 lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
1542 lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
1543 for (i = 0; i < 6; i++) {
1544 lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x;
1545 lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
1548 if (size < -MINSIZE)
1549 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1550 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1551 else if (size < MINSIZE) {
1553 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE);
1557 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1560 lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1);
1561 lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1);
1562 lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
1563 lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
1567 lp->bncols = lp->ncols + 2 * lp->bx;
1568 lp->bnrows = lp->nrows + 2 * lp->by;
1572 if (lp->oldcells != NULL) {
1573 (void) free((void *) lp->oldcells);
1574 lp->oldcells = (unsigned char *) NULL;
1576 if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1577 sizeof (unsigned char))) == NULL) {
1578 free_loop(display, lp);
1581 if (lp->newcells != NULL) {
1582 (void) free((void *) lp->newcells);
1583 lp->newcells = (unsigned char *) NULL;
1585 if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1586 sizeof (unsigned char))) == NULL) {
1587 free_loop(display, lp);
1590 if (!init_table()) {
1594 lp->mincol = lp->bncols - 1;
1595 lp->minrow = lp->bnrows - 1;
1598 #ifndef DELAYDEBUGLOOP
1600 int flaws = MI_COUNT(mi);
1603 flaws = NRAND(-MI_COUNT(mi) + 1);
1604 for (i = 0; i < flaws; i++) {
1607 /* actual flaws might be less since the adam loop done next */
1614 draw_loop (ModeInfo * mi)
1617 unsigned char *z, *znew;
1622 lp = &loops[MI_SCREEN(mi)];
1623 if (lp->newcells == NULL)
1626 MI_IS_DRAWN(mi) = True;
1628 #ifdef DELAYDEBUGLOOP
1629 if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
1630 (void) sleep(DELAYDEBUGLOOP);
1634 for (j = lp->minrow; j <= lp->maxrow; j++) {
1635 for (i = lp->mincol; i <= lp->maxcol; i++) {
1636 offset = j * lp->bncols + i;
1637 z = lp->oldcells + offset;
1638 znew = lp->newcells + offset;
1642 if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
1644 if (i == lp->mincol && i > lp->bx)
1646 if (j == lp->minrow && j > lp->by)
1648 if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx)
1650 if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by)
1655 for (i = 0; i < COLORS; i++)
1656 if (!draw_state(mi, i)) {
1657 free_loop(MI_DISPLAY(mi), lp);
1660 if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
1666 if (lp->redrawing) {
1667 for (i = 0; i < REDRAWSTEP; i++) {
1668 if ((*(lp->oldcells + lp->redrawpos))) {
1669 drawcell(mi, lp->redrawpos % lp->bncols - lp->bx,
1670 lp->redrawpos / lp->bncols - lp->by,
1671 *(lp->oldcells + lp->redrawpos));
1673 if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) {
1682 refresh_loop (ModeInfo * mi)
1688 lp = &loops[MI_SCREEN(mi)];
1692 lp->redrawpos = lp->by * lp->ncols + lp->bx;
1695 XSCREENSAVER_MODULE ("Loop", loop)
1697 #endif /* MODE_loop */