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 UNIFORM_COLORS
97 # include "xlockmore.h" /* in xscreensaver distribution */
98 #else /* STANDALONE */
99 # include "xlock.h" /* in xlockmore distribution */
100 #endif /* STANDALONE */
101 #include "automata.h"
106 * neighbors of 0 randomizes between 4 and 6.
108 #define DEF_NEIGHBORS "0" /* choose random value */
110 static int neighbors;
112 static XrmOptionDescRec opts[] =
114 {"-neighbors", ".loop.neighbors", XrmoptionSepArg, 0}
117 static argtype vars[] =
119 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
122 static OptionStruct desc[] =
124 {"-neighbors num", "squares 4 or hexagons 6"}
127 ENTRYPOINT ModeSpecOpt loop_opts =
128 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
132 ModStruct loop_description =
133 {"loop", "init_loop", "draw_loop", "release_loop",
134 "refresh_loop", "init_loop", (char *) NULL, &loop_opts,
135 100000, 5, 1600, -12, 64, 1.0, "",
136 "Shows Langton's self-producing loops", 0, NULL};
140 #define LOOPBITS(n,w,h)\
141 if ((lp->pixmaps[lp->init_bits]=\
142 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
143 free_loop(display,lp); return;} else {lp->init_bits++;}
145 static int local_neighbors = 0;
148 /* Used to fast forward to troubled generations, mainly used for debugging.
149 -delay 1 -count 170 -neighbors 6 # divisions starts
150 540 first cell collision
151 1111 mutant being born from 2 parents
154 #define DELAYDEBUGLOOP 10
158 #define REALCOLORS (COLORS-2)
160 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
161 #define ADAM_SIZE 8 /* MIN 5 */
163 #define ADAM_LOOPX (ADAM_SIZE+2)
164 #define ADAM_LOOPY (ADAM_SIZE+2)
166 #define ADAM_LOOPX 16
167 #define ADAM_LOOPY 10
169 #define MINGRIDSIZE (3*ADAM_LOOPX)
171 /* TRIA stuff was an attempt to make a triangular lifeform on a
172 hexagonal grid but I got bored. You may need an additional 7th
173 state for a coherent step by step process of cell separation and
174 initial stem development.
179 #define HEX_ADAM_SIZE 3 /* MIN 3 */
181 #define HEX_ADAM_SIZE 5 /* MIN 3 */
184 #define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
185 #define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
187 #define HEX_ADAM_LOOPX 3
188 #define HEX_ADAM_LOOPY 7
190 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
191 #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6)))
192 #define NEIGHBORKINDS 2
194 #define MAXNEIGHBORS 6
196 /* Singly linked list */
197 typedef struct _CellList {
199 struct _CellList *next;
208 int bx, by, bnrows, bncols;
209 int mincol, minrow, maxcol, maxrow;
211 int redrawing, redrawpos;
212 Bool dead, clockwise;
213 unsigned char *newcells, *oldcells;
215 CellList *cellList[COLORS];
216 unsigned long colors[COLORS];
218 Pixmap pixmaps[COLORS];
224 static loopstruct *loops = (loopstruct *) NULL;
226 #define TRANSITION(TT,V) V=TT&7;TT>>=3
227 #define FINALTRANSITION(TT,V) V=TT&7
228 #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)])
229 #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)])
232 /* Instead of setting "unused" state rules to zero it randomizes them.
233 These rules take over when something unexpected happens... like when a
234 cell hits a wall (the end of the screen).
240 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\
241 (TABLE(R,T,L,B)|=((I)<<((C)*3)))
242 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\
243 (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
245 #define TABLE_IN(C,R,T,L,B,I) (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)|=((I)<<((C)*3)))
248 #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7)
249 #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7)
251 static unsigned int *table = (unsigned int *) NULL;
252 /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */
253 /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */
255 static char plots[NEIGHBORKINDS] =
257 4, 6 /* Neighborhoods */
260 static unsigned int transition_table[] =
261 { /* Octal CBLTR->I */
262 /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */
263 0000000, 0025271, 0113221, 0202422, 0301021,
264 0000012, 0100011, 0122244, 0202452, 0301220,
265 0000020, 0100061, 0122277, 0202520, 0302511,
266 0000030, 0100077, 0122434, 0202552, 0401120,
267 0000050, 0100111, 0122547, 0202622, 0401220,
268 0000063, 0100121, 0123244, 0202722, 0401250,
269 0000071, 0100211, 0123277, 0203122, 0402120,
270 0000112, 0100244, 0124255, 0203216, 0402221,
271 0000122, 0100277, 0124267, 0203226, 0402326,
272 0000132, 0100511, 0125275, 0203422, 0402520,
273 0000212, 0101011, 0200012, 0204222, 0403221,
274 0000220, 0101111, 0200022, 0205122, 0500022,
275 0000230, 0101244, 0200042, 0205212, 0500215,
276 0000262, 0101277, 0200071, 0205222, 0500225,
277 0000272, 0102026, 0200122, 0205521, 0500232,
278 0000320, 0102121, 0200152, 0205725, 0500272,
279 0000525, 0102211, 0200212, 0206222, 0500520,
280 0000622, 0102244, 0200222, 0206722, 0502022,
281 0000722, 0102263, 0200232, 0207122, 0502122,
282 0001022, 0102277, 0200242, 0207222, 0502152,
283 0001120, 0102327, 0200250, 0207422, 0502220,
284 0002020, 0102424, 0200262, 0207722, 0502244,
285 0002030, 0102626, 0200272, 0211222, 0502722,
286 0002050, 0102644, 0200326, 0211261, 0512122,
287 0002125, 0102677, 0200423, 0212222, 0512220,
288 0002220, 0102710, 0200517, 0212242, 0512422,
289 0002322, 0102727, 0200522, 0212262, 0512722,
290 0005222, 0105427, 0200575, 0212272, 0600011,
291 0012321, 0111121, 0200722, 0214222, 0600021,
292 0012421, 0111221, 0201022, 0215222, 0602120,
293 0012525, 0111244, 0201122, 0216222, 0612125,
294 0012621, 0111251, 0201222, 0217222, 0612131,
295 0012721, 0111261, 0201422, 0222272, 0612225,
296 0012751, 0111277, 0201722, 0222442, 0700077,
297 0014221, 0111522, 0202022, 0222462, 0701120,
298 0014321, 0112121, 0202032, 0222762, 0701220,
299 0014421, 0112221, 0202052, 0222772, 0701250,
300 0014721, 0112244, 0202073, 0300013, 0702120,
301 0016251, 0112251, 0202122, 0300022, 0702221,
302 0017221, 0112277, 0202152, 0300041, 0702251,
303 0017255, 0112321, 0202212, 0300076, 0702321,
304 0017521, 0112424, 0202222, 0300123, 0702525,
305 0017621, 0112621, 0202272, 0300421, 0702720,
306 0017721, 0112727, 0202321, 0300622
309 static unsigned int hex_transition_table[] =
310 { /* Octal CBbltTR->I */
311 /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */
314 000000000, 000000020, 000000220, 000002220, 000022220,
315 011122121, 011121221, 011122221, 011221221,
316 011222221, 011112121, 011112221,
317 020021122, 020002122, 020211222, 021111222,
318 020221122, 020027122, 020020722, 020021022,
320 011122727, 011227227, 010122121, 010222211,
321 021117222, 020112272,
324 010221121, 011721221, 011222277,
325 020111222, 020221172,
328 010212277, 010221221,
333 020002022, 021122172,
335 011122277, 011172121,
336 010212177, 011212277,
340 070121270, 070721220,
341 000112721, 000272211,
342 010022211, 012222277,
343 020072272, 020227122, 020217222,
348 020021072, 020070722,
349 070002072, 070007022,
352 000000070, 000000770, 000072220, 000000270,
353 020110222, 020220272, 020220722,
354 070007071, 070002072, 070007022,
355 000000012, 000000122, 000000212, 001277721,
356 020122072, 020202212,
358 020001122, 020002112,
360 020122022, 020027022, 020070122, 020020122,
363 010227227, 010227277,
370 010022277, 010202177, 010227127,
374 020024122, 020020422,
377 010221241, 010224224,
382 020112242, 021422172,
384 001224221, 001427221,
389 010022244, 010202144, 010224124,
393 040121240, 040421220,
394 000242211, 000112421,
395 020042242, 020214222, 020021422, 020220242, 020024022,
402 001244421, 000000420, 000000440, 000000240, 000000040,
403 020040121, 020021042,
404 040004022, 040004042, 040002042,
406 020011122, 020002112,
413 020224072, 021417222,
419 070207072, 070701220,
424 020021222, 020202272, 020120222, 020221722,
428 020101272, 020272172, 020721422, 020721722,
429 020011222, 020202242,
447 000000000, 000000020, 000000220, 000002220,
448 011212121, 011212221, 011221221, 011222221,
449 020002122, 020021122, 020211122,
451 010221221, 010222121,
452 020002022, 020021022, 020020122, 020112022,
455 020102022, 020202112,
457 000000012, 000000122, 000000212,
459 020001122, 020002112, 020011122,
462 001227221, 001272221, 001272721,
463 012212277, 011222727, 011212727,
464 020021722, 020027122, 020020722, 020027022,
465 020211722, 020202172, 020120272,
466 020271122, 020202172, 020207122, 020217122,
467 020120272, 020210722, 020270722,
468 070212220, 070221220, 070212120,
475 001277721, 000000070, 000000270, 000000720, 000000770,
476 020070122, 020021072,
477 070002072, 070007022, 070007071,
482 010227227, 010222727, 010202727,
483 020172022, 020202712,
485 001224221, 001242221, 001242421,
486 012212244, 011222424, 011212424,
487 020021422, 020024122, 020020422, 020024022,
488 020211422, 020202142, 020120242,
489 020241122, 020202142, 020204122, 020214122,
490 020120242, 020210422, 020240422,
491 040212220, 040221220, 040212120,
498 001244421, 000000040, 000000240, 000000420, 000000440,
499 020040122, 020021042,
501 040004021, 040004042,
506 010224224, 010222424, 010202424,
507 020142022, 020202412,
508 020011722, 020112072, 020172072, 020142072,
512 000210225, 000022015, 000022522,
514 020120525, 020020152, 020005122, 020214255, 020021152,
516 050215222, 050225121,
518 000225220, 001254222,
519 010221250, 011221251, 011225221,
520 020025122, 020152152, 020211252, 020214522, 020511125,
524 000000250, 000000520, 000150220, 000220520, 000222210,
526 010022152, 010251221, 010522121, 011212151, 011221251,
528 020000220, 020002152, 020020220, 020022152,
529 020021422, 020022152, 020022522, 020025425, 020050422,
530 020051022, 020051122, 020211122, 020211222, 020215222,
532 050021125, 050021025, 050011125, 051242221,
535 000220250, 000220520, 001227521, 001275221,
536 011257227, 011522727,
537 020002052, 020002752, 020021052, 020057125,
538 050020722, 050027125,
633 000000050, 000005220, 000002270, 070252220,
634 000000450, 000007220,
635 000220220, 000202220, 000022020, 000020220,
643 050221120, 010221520,
646 000070220, 000220720,
647 000020520, 000070250, 000222070, 000027020,
648 000022070, 000202270, 000024020, 000220420,
649 000220270, 000220240, 000072020, 000042020,
650 000002020, 000002070, 000020270, 000020250,
651 000270270, 000007020, 000040270,
653 /* Collision starts (gen 540), not sure to have rules to save it
654 or depend on calloc to intialize remaining rules to 0 so that
655 the mutant will be born
663 Neighborhoods are read as follows (rotations are not listed):
673 static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] =
676 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0},
677 {2, 4, 0, 1, 4, 0, 1, 1, 1, 2},
678 {2, 1, 2, 2, 2, 2, 2, 2, 1, 2},
679 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
680 {2, 7, 2, 0, 0, 0, 0, 2, 7, 2},
681 {2, 1, 2, 0, 0, 0, 0, 2, 0, 2},
682 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
683 {2, 7, 2, 2, 2, 2, 2, 2, 7, 2},
684 {2, 1, 0, 6, 1, 0, 7, 1, 0, 2},
685 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}
688 static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] =
691 /* Experimental TRIA5:7x7 */
699 /* Stem cells, only "5" will fully reproduce itself */
701 {2,2,2,2,0,0,0,0,0,0,0,0},
702 {2,1,1,1,2,0,0,0,0,0,0,0},
703 {2,1,2,2,1,2,2,2,2,2,2,0},
704 {2,1,2,0,2,7,1,1,1,1,1,2},
705 {0,2,1,2,2,0,2,2,2,2,2,2},
706 {0,0,2,0,4,1,2,0,0,0,0,0},
707 {0,0,0,2,2,2,2,0,0,0,0,0}
709 {2,2,2,2,2,0,0,0,0,0,0,0,0,0},
710 {2,1,1,1,1,2,0,0,0,0,0,0,0,0},
711 {2,1,2,2,2,1,2,0,0,0,0,0,0,0},
712 {2,1,2,0,0,2,1,2,2,2,2,2,2,0},
713 {2,1,2,0,0,0,2,7,1,1,1,1,1,2},
714 {0,2,1,2,0,0,2,0,2,2,2,2,2,2},
715 {0,0,2,0,2,2,2,1,2,0,0,0,0,0},
716 {0,0,0,2,4,1,0,7,2,0,0,0,0,0},
717 {0,0,0,0,2,2,2,2,2,0,0,0,0,0}
719 {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0},
720 {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0},
721 {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0},
722 {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0},
723 {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0},
724 {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2},
725 {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2},
726 {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0},
727 {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0},
728 {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0},
729 {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0}
730 /* test:3x7 (0,4) is blank ... very strange.
731 init_adam seems ok something after that I guess */
739 #else /* this might be better for hexagons, spacewise efficient... */
741 /* Experimental TRIA5:7x7 */
751 {2,2,2,2,2,2,0,0,0,0,0},
752 {2,1,1,7,0,1,2,0,0,0,0},
753 {2,1,2,2,2,2,7,2,0,0,0},
754 {2,1,2,0,0,0,2,0,2,0,0},
755 {2,1,2,0,0,0,0,2,1,2,0},
756 {2,1,2,0,0,0,0,0,2,7,2},
757 {0,2,1,2,0,0,0,0,2,0,2},
758 {0,0,2,1,2,0,0,0,2,1,2},
759 {0,0,0,2,1,2,2,2,2,4,2},
760 {0,0,0,0,2,1,1,1,1,5,2},
761 {0,0,0,0,0,2,2,2,2,2,2}
767 position_of_neighbor(int dir, int *pcol, int *prow)
769 int col = *pcol, row = *prow;
773 if (local_neighbors == 6) {
798 (void) fprintf(stderr, "wrong direction %d\n", dir);
815 (void) fprintf(stderr, "wrong direction %d\n", dir);
823 withinBounds(loopstruct * lp, int col, int row)
825 return (row >= 1 && row < lp->bnrows - 1 &&
826 col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2)));
830 fillcell(ModeInfo * mi, GC gc, int col, int row)
832 loopstruct *lp = &loops[MI_SCREEN(mi)];
834 if (local_neighbors == 6) {
835 int ccol = 2 * col + !(row & 1), crow = 2 * row;
837 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
838 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
839 if (lp->xs == 1 && lp->ys == 1)
840 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
841 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
843 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
844 lp->shape.hexagon, 6, Convex, CoordModePrevious);
846 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
847 lp->xb + lp->xs * col, lp->yb + lp->ys * row,
848 lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3));
853 drawcell(ModeInfo * mi, int col, int row, int state)
855 loopstruct *lp = &loops[MI_SCREEN(mi)];
859 if (MI_NPIXELS(mi) >= COLORS) {
861 XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]);
864 gcv.stipple = lp->pixmaps[state];
865 #endif /* DO_STIPPLE */
866 gcv.foreground = MI_WHITE_PIXEL(mi);
867 gcv.background = MI_BLACK_PIXEL(mi);
868 XChangeGC(MI_DISPLAY(mi), lp->stippledGC,
871 #endif /* DO_STIPPLE */
872 GCForeground | GCBackground, &gcv);
875 fillcell(mi, gc, col, row);
880 print_state(ModeInfo * mi, int state)
882 loopstruct *lp = &loops[MI_SCREEN(mi)];
883 CellList *locallist = lp->cellList[state];
886 (void) printf("state %d\n", state);
888 (void) printf("%d x %d, y %d\n", i,
889 locallist->pt.x, locallist->pt.y);
890 locallist = locallist->next;
898 free_state(loopstruct * lp, int state)
902 while (lp->cellList[state]) {
903 current = lp->cellList[state];
904 lp->cellList[state] = lp->cellList[state]->next;
905 (void) free((void *) current);
907 lp->ncells[state] = 0;
911 free_list(loopstruct * lp)
915 for (state = 0; state < COLORS; state++)
916 free_state(lp, state);
920 free_loop(Display *display, loopstruct * lp)
924 for (shade = 0; shade < lp->init_bits; shade++)
925 if (lp->pixmaps[shade] != None) {
926 XFreePixmap(display, lp->pixmaps[shade]);
927 lp->pixmaps[shade] = None;
929 if (lp->stippledGC != None) {
930 XFreeGC(display, lp->stippledGC);
931 lp->stippledGC = None;
933 if (lp->oldcells != NULL) {
934 (void) free((void *) lp->oldcells);
935 lp->oldcells = (unsigned char *) NULL;
937 if (lp->newcells != NULL) {
938 (void) free((void *) lp->newcells);
939 lp->newcells = (unsigned char *) NULL;
945 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
947 loopstruct *lp = &loops[MI_SCREEN(mi)];
948 CellList *current = lp->cellList[state];
950 if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
952 lp->cellList[state] = current;
953 free_loop(MI_DISPLAY(mi), lp);
956 lp->cellList[state]->pt.x = col;
957 lp->cellList[state]->pt.y = row;
958 lp->cellList[state]->next = current;
964 draw_state(ModeInfo * mi, int state)
966 loopstruct *lp = &loops[MI_SCREEN(mi)];
967 Display *display = MI_DISPLAY(mi);
970 CellList *current = lp->cellList[state];
972 if (MI_NPIXELS(mi) >= COLORS) {
974 XSetForeground(display, gc, lp->colors[state]);
977 gcv.stipple = lp->pixmaps[state];
978 #endif /* DO_STIPPLE */
979 gcv.foreground = MI_WHITE_PIXEL(mi);
980 gcv.background = MI_BLACK_PIXEL(mi);
981 XChangeGC(display, lp->stippledGC,
984 #endif /* DO_STIPPLE */
985 GCForeground | GCBackground, &gcv);
989 if (local_neighbors == 6) { /* Draw right away, slow */
991 int col, row, ccol, crow;
995 ccol = 2 * col + !(row & 1), crow = 2 * row;
996 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
997 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
998 if (lp->xs == 1 && lp->ys == 1)
999 XDrawPoint(display, MI_WINDOW(mi), gc,
1000 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
1002 XFillPolygon(display, MI_WINDOW(mi), gc,
1003 lp->shape.hexagon, 6, Convex, CoordModePrevious);
1004 current = current->next;
1007 /* Take advantage of XFillRectangles */
1011 /* Create Rectangle list from part of the cellList */
1012 if ((rects = (XRectangle *) malloc(lp->ncells[state] *
1013 sizeof (XRectangle))) == NULL) {
1018 rects[nrects].x = lp->xb + current->pt.x * lp->xs;
1019 rects[nrects].y = lp->yb + current->pt.y * lp->ys;
1020 rects[nrects].width = lp->xs - (lp->xs > 3);
1021 rects[nrects].height = lp->ys - (lp->ys > 3);
1022 current = current->next;
1025 /* Finally get to draw */
1026 XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
1027 /* Free up rects list and the appropriate part of the cellList */
1028 (void) free((void *) rects);
1030 free_state(lp, state);
1037 if (table == NULL) {
1039 unsigned int tt, c, n[MAXNEIGHBORS], i;
1041 int size_transition_table = sizeof (transition_table) /
1042 sizeof (unsigned int);
1043 int size_hex_transition_table = sizeof (hex_transition_table) /
1044 sizeof (unsigned int);
1046 for (j = 0; j < local_neighbors; j++)
1049 if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
1055 /* Here I was interested to see what happens when it hits a wall....
1056 Rules not normally used take over... takes too much time though */
1057 /* Each state = 3 bits */
1058 if (MAXRAND < 16777216.0) {
1059 for (j = 0; j < mult; j++) {
1060 table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
1063 for (j = 0; j < mult; j++) {
1064 table[j] = (unsigned int) (NRAND(16777216));
1068 if (local_neighbors == 6) {
1069 for (j = 0; j < size_hex_transition_table; j++) {
1070 tt = hex_transition_table[j];
1072 for (k = 0; k < local_neighbors; k++) {
1073 TRANSITION(tt, n[k]);
1075 FINALTRANSITION(tt, c);
1076 HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
1077 HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
1078 HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
1079 HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i);
1080 HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i);
1081 HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i);
1084 for (j = 0; j < size_transition_table; j++) {
1085 tt = transition_table[j];
1087 for (k = 0; k < local_neighbors; k++) {
1088 TRANSITION(tt, n[k]);
1090 FINALTRANSITION(tt, c);
1091 TABLE_IN(c, n[0], n[1], n[2], n[3], i);
1092 TABLE_IN(c, n[1], n[2], n[3], n[0], i);
1093 TABLE_IN(c, n[2], n[3], n[0], n[1], i);
1094 TABLE_IN(c, n[3], n[0], n[1], n[2], i);
1102 init_flaw(ModeInfo * mi)
1104 loopstruct *lp = &loops[MI_SCREEN(mi)];
1108 if (lp->bncols <= 3 || lp->bnrows <= 3)
1110 a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
1111 HEX_MINGRIDSIZE : MINGRIDSIZE));
1112 a = NRAND(a) + (lp->bncols - a) / 2;
1113 b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
1114 HEX_MINGRIDSIZE : MINGRIDSIZE));
1115 b = NRAND(b) + (lp->bnrows - b) / 2;
1120 if (lp->maxcol < a + 2)
1122 if (lp->maxrow < b + 2)
1125 if (local_neighbors == 6) {
1126 lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
1127 lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1128 lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
1129 lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
1130 lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
1131 lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1133 int orient = NRAND(4);
1134 lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
1135 if (orient == 0 || orient == 1) {
1136 lp->newcells[lp->bncols * b + a + 1] = BLUE;
1138 if (orient == 1 || orient == 2) {
1139 lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
1141 if (orient == 2 || orient == 3) {
1142 lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
1144 if (orient == 3 || orient == 0) {
1145 lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
1151 init_adam(ModeInfo * mi)
1153 loopstruct *lp = &loops[MI_SCREEN(mi)];
1154 XPoint start = { 0, 0 }, dirx = { 0, 0 }, diry = { 0, 0 };
1157 #ifdef DELAYDEBUGLOOP
1159 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1161 lp->clockwise = (Bool) (LRAND() & 1);
1162 #ifdef DELAYDEBUGLOOP
1164 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1166 dir = NRAND(local_neighbors);
1167 if (local_neighbors == 6) {
1172 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1173 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1174 if (lp->mincol > start.x - 2)
1175 lp->mincol = start.x - 2;
1176 if (lp->minrow > start.y - 1)
1177 lp->minrow = start.y - 1;
1178 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1179 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1180 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1181 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1182 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1183 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1184 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1185 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1187 hex_self_reproducing_loop[i][j] :
1188 hex_self_reproducing_loop[j][i];
1193 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1194 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1195 if (lp->mincol > start.x - 1)
1196 lp->mincol = start.x - 1;
1197 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1198 lp->minrow = start.y - HEX_ADAM_LOOPX;
1199 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1200 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1201 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1202 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1203 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1204 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1205 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1206 ? -(i + j + 1) / 2 : -(i + j) / 2);
1207 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1209 hex_self_reproducing_loop[i][j] :
1210 hex_self_reproducing_loop[j][i];
1215 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1216 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1217 if (lp->mincol > start.x - 2)
1218 lp->mincol = start.x - 2;
1219 if (lp->minrow > start.y - 1)
1220 lp->minrow = start.y - 1;
1221 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1222 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1223 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1224 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1225 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1226 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1227 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1228 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1230 hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
1231 hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
1236 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1237 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1238 if (lp->mincol > start.x - 1)
1239 lp->mincol = start.x - 1;
1240 if (lp->minrow > start.y - 1)
1241 lp->minrow = start.y - 1;
1242 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1243 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1244 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1245 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1246 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1247 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1248 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1249 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1251 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1252 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1257 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1258 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1259 if (lp->mincol > start.x - 1)
1260 lp->mincol = start.x - 1;
1261 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1262 lp->minrow = start.y - HEX_ADAM_LOOPX;
1263 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1264 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1265 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1266 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1267 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1268 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1269 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1270 ? -(i + j + 1) / 2 : -(i + j) / 2);
1271 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1273 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1274 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1279 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1280 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1281 if (lp->mincol > start.x - 2)
1282 lp->mincol = start.x - 2;
1283 if (lp->minrow > start.y - 1)
1284 lp->minrow = start.y - 1;
1285 if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
1286 lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
1287 if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
1288 lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
1289 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1290 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1291 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1292 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1294 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
1295 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
1301 /* (void) printf ("s %d s %d \n", start.x, start.y); */
1302 (void) printf ("%d %d %d %d %d\n",
1303 start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1304 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
1305 /* Draw right away */
1306 drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1307 start.y + j - lp->by,
1308 hex_self_reproducing_loop[j][i]);
1313 start.x = (lp->bncols - ADAM_LOOPX) / 2;
1314 start.y = (lp->bnrows - ADAM_LOOPY) / 2;
1315 dirx.x = 1, dirx.y = 0;
1316 diry.x = 0, diry.y = 1;
1317 if (lp->mincol > start.x)
1318 lp->mincol = start.x;
1319 if (lp->minrow > start.y)
1320 lp->minrow = start.y;
1321 if (lp->maxcol < start.x + ADAM_LOOPX)
1322 lp->maxcol = start.x + ADAM_LOOPX;
1323 if (lp->maxrow < start.y + ADAM_LOOPY)
1324 lp->maxrow = start.y + ADAM_LOOPY;
1327 start.x = (lp->bncols + ADAM_LOOPY) / 2;
1328 start.y = (lp->bnrows - ADAM_LOOPX) / 2;
1329 dirx.x = 0, dirx.y = 1;
1330 diry.x = -1, diry.y = 0;
1331 if (lp->mincol > start.x - ADAM_LOOPY)
1332 lp->mincol = start.x - ADAM_LOOPY;
1333 if (lp->minrow > start.y)
1334 lp->minrow = start.y;
1335 if (lp->maxcol < start.x)
1336 lp->maxcol = start.x;
1337 if (lp->maxrow < start.y + ADAM_LOOPX)
1338 lp->maxrow = start.y + ADAM_LOOPX;
1341 start.x = (lp->bncols + ADAM_LOOPX) / 2;
1342 start.y = (lp->bnrows + ADAM_LOOPY) / 2;
1343 dirx.x = -1, dirx.y = 0;
1344 diry.x = 0, diry.y = -1;
1345 if (lp->mincol > start.x - ADAM_LOOPX)
1346 lp->mincol = start.x - ADAM_LOOPX;
1347 if (lp->minrow > start.y - ADAM_LOOPY)
1348 lp->minrow = start.y - ADAM_LOOPY;
1349 if (lp->maxcol < start.x)
1350 lp->maxcol = start.x;
1351 if (lp->maxrow < start.y)
1352 lp->maxrow = start.y;
1355 start.x = (lp->bncols - ADAM_LOOPY) / 2;
1356 start.y = (lp->bnrows + ADAM_LOOPX) / 2;
1357 dirx.x = 0, dirx.y = -1;
1358 diry.x = 1, diry.y = 0;
1359 if (lp->mincol > start.x)
1360 lp->mincol = start.x;
1361 if (lp->minrow > start.y - ADAM_LOOPX)
1362 lp->minrow = start.y - ADAM_LOOPX;
1363 if (lp->maxcol < start.x + ADAM_LOOPX)
1364 lp->maxcol = start.x + ADAM_LOOPX;
1365 if (lp->maxrow < start.y)
1366 lp->maxrow = start.y;
1369 for (j = 0; j < ADAM_LOOPY; j++)
1370 for (i = 0; i < ADAM_LOOPX; i++)
1371 lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
1372 start.x + dirx.x * i + diry.x * j] =
1374 self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
1375 self_reproducing_loop[j][i];
1377 /* Draw right away */
1378 drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
1379 start.y + dirx.y * i + diry.y * j - lp->by,
1380 (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
1387 do_gen(loopstruct * lp)
1391 unsigned int n[MAXNEIGHBORS];
1394 #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols)))
1396 for (j = lp->minrow; j <= lp->maxrow; j++) {
1397 for (i = lp->mincol; i <= lp->maxcol; i++) {
1398 z = lp->newcells + i + j * lp->bncols;
1400 for (k = 0; k < local_neighbors; k++) {
1401 int newi = i, newj = j;
1403 position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj);
1405 if (withinBounds(lp, newi, newj)) {
1406 n[k] = LOC(newi, newj);
1409 if (local_neighbors == 6) {
1410 *z = (lp->clockwise) ?
1411 HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
1412 HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
1414 *z = (lp->clockwise) ?
1415 TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
1416 TABLE_OUT(c, n[0], n[1], n[2], n[3]);
1423 release_loop (ModeInfo * mi)
1425 if (loops != NULL) {
1428 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1429 free_loop(MI_DISPLAY(mi), &loops[screen]);
1430 (void) free((void *) loops);
1431 loops = (loopstruct *) NULL;
1433 if (table != NULL) {
1434 (void) free((void *) table);
1435 table = (unsigned int *) NULL;
1439 static void *stop_warning_about_triangleUnit_already;
1443 init_loop (ModeInfo * mi)
1445 Display *display = MI_DISPLAY(mi);
1446 int i, size = MI_SIZE(mi);
1449 stop_warning_about_triangleUnit_already = (void *) &triangleUnit;
1451 if (loops == NULL) {
1452 if ((loops = (loopstruct *) calloc(MI_NUM_SCREENS(mi),
1453 sizeof (loopstruct))) == NULL)
1456 lp = &loops[MI_SCREEN(mi)];
1461 if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
1462 Window window = MI_WINDOW(mi);
1464 if (lp->stippledGC == None) {
1465 gcv.fill_style = FillOpaqueStippled;
1466 if ((lp->stippledGC = XCreateGC(display, window,
1467 GCFillStyle, &gcv)) == None) {
1468 free_loop(display, lp);
1472 LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE);
1473 LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE);
1474 LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE);
1475 LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE);
1476 LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE);
1477 LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
1478 LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
1479 LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
1481 #endif /* DO_STIPPLE */
1482 if (MI_NPIXELS(mi) >= COLORS) {
1483 /* Maybe these colors should be randomized */
1484 lp->colors[0] = MI_BLACK_PIXEL(mi);
1485 lp->colors[1] = MI_PIXEL(mi, 0); /* RED */
1486 lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */
1487 lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */
1488 lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */
1489 lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */
1490 lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */
1491 lp->colors[7] = MI_WHITE_PIXEL(mi);
1495 lp->width = MI_WIDTH(mi);
1496 lp->height = MI_HEIGHT(mi);
1498 if (!local_neighbors) {
1499 for (i = 0; i < NEIGHBORKINDS; i++) {
1500 if (neighbors == plots[i]) {
1501 local_neighbors = neighbors;
1504 if (i == NEIGHBORKINDS - 1) {
1506 local_neighbors = plots[NRAND(NEIGHBORKINDS)];
1508 local_neighbors = 4;
1516 if (local_neighbors == 6) {
1523 if (size < -MINSIZE) {
1524 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1525 HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1526 } else if (size < MINSIZE) {
1528 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE);
1532 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1535 nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
1536 ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
1537 lp->ncols = nccols / 2;
1538 lp->nrows = ncrows / 2;
1539 lp->nrows -= !(lp->nrows & 1); /* Must be odd */
1540 lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
1541 lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
1542 for (i = 0; i < 6; i++) {
1543 lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x;
1544 lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
1547 if (size < -MINSIZE)
1548 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1549 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1550 else if (size < MINSIZE) {
1552 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE);
1556 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1559 lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1);
1560 lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1);
1561 lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
1562 lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
1566 lp->bncols = lp->ncols + 2 * lp->bx;
1567 lp->bnrows = lp->nrows + 2 * lp->by;
1571 if (lp->oldcells != NULL) {
1572 (void) free((void *) lp->oldcells);
1573 lp->oldcells = (unsigned char *) NULL;
1575 if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1576 sizeof (unsigned char))) == NULL) {
1577 free_loop(display, lp);
1580 if (lp->newcells != NULL) {
1581 (void) free((void *) lp->newcells);
1582 lp->newcells = (unsigned char *) NULL;
1584 if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1585 sizeof (unsigned char))) == NULL) {
1586 free_loop(display, lp);
1589 if (!init_table()) {
1593 lp->mincol = lp->bncols - 1;
1594 lp->minrow = lp->bnrows - 1;
1597 #ifndef DELAYDEBUGLOOP
1599 int flaws = MI_COUNT(mi);
1602 flaws = NRAND(-MI_COUNT(mi) + 1);
1603 for (i = 0; i < flaws; i++) {
1606 /* actual flaws might be less since the adam loop done next */
1613 draw_loop (ModeInfo * mi)
1616 unsigned char *z, *znew;
1621 lp = &loops[MI_SCREEN(mi)];
1622 if (lp->newcells == NULL)
1625 MI_IS_DRAWN(mi) = True;
1627 #ifdef DELAYDEBUGLOOP
1628 if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
1629 (void) sleep(DELAYDEBUGLOOP);
1633 for (j = lp->minrow; j <= lp->maxrow; j++) {
1634 for (i = lp->mincol; i <= lp->maxcol; i++) {
1635 offset = j * lp->bncols + i;
1636 z = lp->oldcells + offset;
1637 znew = lp->newcells + offset;
1641 if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
1643 if (i == lp->mincol && i > lp->bx)
1645 if (j == lp->minrow && j > lp->by)
1647 if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx)
1649 if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by)
1654 for (i = 0; i < COLORS; i++)
1655 if (!draw_state(mi, i)) {
1656 free_loop(MI_DISPLAY(mi), lp);
1659 if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
1665 if (lp->redrawing) {
1666 for (i = 0; i < REDRAWSTEP; i++) {
1667 if ((*(lp->oldcells + lp->redrawpos))) {
1668 drawcell(mi, lp->redrawpos % lp->bncols - lp->bx,
1669 lp->redrawpos / lp->bncols - lp->by,
1670 *(lp->oldcells + lp->redrawpos));
1672 if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) {
1681 reshape_loop(ModeInfo * mi, int width, int height)
1683 XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
1688 refresh_loop (ModeInfo * mi)
1694 lp = &loops[MI_SCREEN(mi)];
1698 lp->redrawpos = lp->by * lp->ncols + lp->bx;
1702 loop_handle_event (ModeInfo *mi, XEvent *event)
1704 if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
1706 reshape_loop (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1712 XSCREENSAVER_MODULE ("Loop", loop)
1714 #endif /* MODE_loop */