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(MI_DISPLAY(mi),window,(char *)n,w,h,1,0,1))==None){\
143 free_loop(mi); 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(ModeInfo * mi)
922 Display *display = MI_DISPLAY(mi);
923 loopstruct *lp = &loops[MI_SCREEN(mi)];
926 for (shade = 0; shade < lp->init_bits; shade++)
927 if (lp->pixmaps[shade] != None) {
928 XFreePixmap(display, lp->pixmaps[shade]);
929 lp->pixmaps[shade] = None;
931 if (lp->stippledGC != None) {
932 XFreeGC(display, lp->stippledGC);
933 lp->stippledGC = None;
935 if (lp->oldcells != NULL) {
936 (void) free((void *) lp->oldcells);
937 lp->oldcells = (unsigned char *) NULL;
939 if (lp->newcells != NULL) {
940 (void) free((void *) lp->newcells);
941 lp->newcells = (unsigned char *) NULL;
947 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
949 loopstruct *lp = &loops[MI_SCREEN(mi)];
950 CellList *current = lp->cellList[state];
952 if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
954 lp->cellList[state] = current;
958 lp->cellList[state]->pt.x = col;
959 lp->cellList[state]->pt.y = row;
960 lp->cellList[state]->next = current;
966 draw_state(ModeInfo * mi, int state)
968 loopstruct *lp = &loops[MI_SCREEN(mi)];
969 Display *display = MI_DISPLAY(mi);
972 CellList *current = lp->cellList[state];
974 if (MI_NPIXELS(mi) >= COLORS) {
976 XSetForeground(display, gc, lp->colors[state]);
979 gcv.stipple = lp->pixmaps[state];
980 #endif /* DO_STIPPLE */
981 gcv.foreground = MI_WHITE_PIXEL(mi);
982 gcv.background = MI_BLACK_PIXEL(mi);
983 XChangeGC(display, lp->stippledGC,
986 #endif /* DO_STIPPLE */
987 GCForeground | GCBackground, &gcv);
991 if (local_neighbors == 6) { /* Draw right away, slow */
993 int col, row, ccol, crow;
997 ccol = 2 * col + !(row & 1), crow = 2 * row;
998 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
999 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
1000 if (lp->xs == 1 && lp->ys == 1)
1001 XDrawPoint(display, MI_WINDOW(mi), gc,
1002 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
1004 XFillPolygon(display, MI_WINDOW(mi), gc,
1005 lp->shape.hexagon, 6, Convex, CoordModePrevious);
1006 current = current->next;
1009 /* Take advantage of XFillRectangles */
1013 /* Create Rectangle list from part of the cellList */
1014 if ((rects = (XRectangle *) malloc(lp->ncells[state] *
1015 sizeof (XRectangle))) == NULL) {
1020 rects[nrects].x = lp->xb + current->pt.x * lp->xs;
1021 rects[nrects].y = lp->yb + current->pt.y * lp->ys;
1022 rects[nrects].width = lp->xs - (lp->xs > 3);
1023 rects[nrects].height = lp->ys - (lp->ys > 3);
1024 current = current->next;
1027 /* Finally get to draw */
1028 XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
1029 /* Free up rects list and the appropriate part of the cellList */
1030 (void) free((void *) rects);
1032 free_state(lp, state);
1039 if (table == NULL) {
1041 unsigned int tt, c, n[MAXNEIGHBORS], i;
1043 int size_transition_table = sizeof (transition_table) /
1044 sizeof (unsigned int);
1045 int size_hex_transition_table = sizeof (hex_transition_table) /
1046 sizeof (unsigned int);
1048 for (j = 0; j < local_neighbors; j++)
1051 if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
1057 /* Here I was interested to see what happens when it hits a wall....
1058 Rules not normally used take over... takes too much time though */
1059 /* Each state = 3 bits */
1060 if (MAXRAND < 16777216.0) {
1061 for (j = 0; j < mult; j++) {
1062 table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
1065 for (j = 0; j < mult; j++) {
1066 table[j] = (unsigned int) (NRAND(16777216));
1070 if (local_neighbors == 6) {
1071 for (j = 0; j < size_hex_transition_table; j++) {
1072 tt = hex_transition_table[j];
1074 for (k = 0; k < local_neighbors; k++) {
1075 TRANSITION(tt, n[k]);
1077 FINALTRANSITION(tt, c);
1078 HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
1079 HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
1080 HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
1081 HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i);
1082 HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i);
1083 HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i);
1086 for (j = 0; j < size_transition_table; j++) {
1087 tt = transition_table[j];
1089 for (k = 0; k < local_neighbors; k++) {
1090 TRANSITION(tt, n[k]);
1092 FINALTRANSITION(tt, c);
1093 TABLE_IN(c, n[0], n[1], n[2], n[3], i);
1094 TABLE_IN(c, n[1], n[2], n[3], n[0], i);
1095 TABLE_IN(c, n[2], n[3], n[0], n[1], i);
1096 TABLE_IN(c, n[3], n[0], n[1], n[2], i);
1104 init_flaw(ModeInfo * mi)
1106 loopstruct *lp = &loops[MI_SCREEN(mi)];
1110 if (lp->bncols <= 3 || lp->bnrows <= 3)
1112 a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
1113 HEX_MINGRIDSIZE : MINGRIDSIZE));
1114 a = NRAND(a) + (lp->bncols - a) / 2;
1115 b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
1116 HEX_MINGRIDSIZE : MINGRIDSIZE));
1117 b = NRAND(b) + (lp->bnrows - b) / 2;
1122 if (lp->maxcol < a + 2)
1124 if (lp->maxrow < b + 2)
1127 if (local_neighbors == 6) {
1128 lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
1129 lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1130 lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
1131 lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
1132 lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
1133 lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1135 int orient = NRAND(4);
1136 lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
1137 if (orient == 0 || orient == 1) {
1138 lp->newcells[lp->bncols * b + a + 1] = BLUE;
1140 if (orient == 1 || orient == 2) {
1141 lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
1143 if (orient == 2 || orient == 3) {
1144 lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
1146 if (orient == 3 || orient == 0) {
1147 lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
1153 init_adam(ModeInfo * mi)
1155 loopstruct *lp = &loops[MI_SCREEN(mi)];
1156 XPoint start = { 0, 0 }, dirx = { 0, 0 }, diry = { 0, 0 };
1159 #ifdef DELAYDEBUGLOOP
1161 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1163 lp->clockwise = (Bool) (LRAND() & 1);
1164 #ifdef DELAYDEBUGLOOP
1166 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1168 dir = NRAND(local_neighbors);
1169 if (local_neighbors == 6) {
1174 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1175 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1176 if (lp->mincol > start.x - 2)
1177 lp->mincol = start.x - 2;
1178 if (lp->minrow > start.y - 1)
1179 lp->minrow = start.y - 1;
1180 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1181 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1182 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1183 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1184 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1185 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1186 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1187 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1189 hex_self_reproducing_loop[i][j] :
1190 hex_self_reproducing_loop[j][i];
1195 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1196 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1197 if (lp->mincol > start.x - 1)
1198 lp->mincol = start.x - 1;
1199 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1200 lp->minrow = start.y - HEX_ADAM_LOOPX;
1201 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1202 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1203 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1204 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1205 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1206 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1207 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1208 ? -(i + j + 1) / 2 : -(i + j) / 2);
1209 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1211 hex_self_reproducing_loop[i][j] :
1212 hex_self_reproducing_loop[j][i];
1217 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1218 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1219 if (lp->mincol > start.x - 2)
1220 lp->mincol = start.x - 2;
1221 if (lp->minrow > start.y - 1)
1222 lp->minrow = start.y - 1;
1223 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1224 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1225 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1226 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1227 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1228 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1229 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1230 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1232 hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
1233 hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
1238 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1239 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1240 if (lp->mincol > start.x - 1)
1241 lp->mincol = start.x - 1;
1242 if (lp->minrow > start.y - 1)
1243 lp->minrow = start.y - 1;
1244 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1245 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1246 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1247 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1248 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1249 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1250 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1251 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1253 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1254 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1259 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1260 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1261 if (lp->mincol > start.x - 1)
1262 lp->mincol = start.x - 1;
1263 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1264 lp->minrow = start.y - HEX_ADAM_LOOPX;
1265 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1266 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1267 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1268 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1269 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1270 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1271 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1272 ? -(i + j + 1) / 2 : -(i + j) / 2);
1273 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1275 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1276 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1281 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1282 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1283 if (lp->mincol > start.x - 2)
1284 lp->mincol = start.x - 2;
1285 if (lp->minrow > start.y - 1)
1286 lp->minrow = start.y - 1;
1287 if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
1288 lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
1289 if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
1290 lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
1291 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1292 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1293 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1294 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1296 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
1297 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
1303 /* (void) printf ("s %d s %d \n", start.x, start.y); */
1304 (void) printf ("%d %d %d %d %d\n",
1305 start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1306 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
1307 /* Draw right away */
1308 drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1309 start.y + j - lp->by,
1310 hex_self_reproducing_loop[j][i]);
1315 start.x = (lp->bncols - ADAM_LOOPX) / 2;
1316 start.y = (lp->bnrows - ADAM_LOOPY) / 2;
1317 dirx.x = 1, dirx.y = 0;
1318 diry.x = 0, diry.y = 1;
1319 if (lp->mincol > start.x)
1320 lp->mincol = start.x;
1321 if (lp->minrow > start.y)
1322 lp->minrow = start.y;
1323 if (lp->maxcol < start.x + ADAM_LOOPX)
1324 lp->maxcol = start.x + ADAM_LOOPX;
1325 if (lp->maxrow < start.y + ADAM_LOOPY)
1326 lp->maxrow = start.y + ADAM_LOOPY;
1329 start.x = (lp->bncols + ADAM_LOOPY) / 2;
1330 start.y = (lp->bnrows - ADAM_LOOPX) / 2;
1331 dirx.x = 0, dirx.y = 1;
1332 diry.x = -1, diry.y = 0;
1333 if (lp->mincol > start.x - ADAM_LOOPY)
1334 lp->mincol = start.x - ADAM_LOOPY;
1335 if (lp->minrow > start.y)
1336 lp->minrow = start.y;
1337 if (lp->maxcol < start.x)
1338 lp->maxcol = start.x;
1339 if (lp->maxrow < start.y + ADAM_LOOPX)
1340 lp->maxrow = start.y + ADAM_LOOPX;
1343 start.x = (lp->bncols + ADAM_LOOPX) / 2;
1344 start.y = (lp->bnrows + ADAM_LOOPY) / 2;
1345 dirx.x = -1, dirx.y = 0;
1346 diry.x = 0, diry.y = -1;
1347 if (lp->mincol > start.x - ADAM_LOOPX)
1348 lp->mincol = start.x - ADAM_LOOPX;
1349 if (lp->minrow > start.y - ADAM_LOOPY)
1350 lp->minrow = start.y - ADAM_LOOPY;
1351 if (lp->maxcol < start.x)
1352 lp->maxcol = start.x;
1353 if (lp->maxrow < start.y)
1354 lp->maxrow = start.y;
1357 start.x = (lp->bncols - ADAM_LOOPY) / 2;
1358 start.y = (lp->bnrows + ADAM_LOOPX) / 2;
1359 dirx.x = 0, dirx.y = -1;
1360 diry.x = 1, diry.y = 0;
1361 if (lp->mincol > start.x)
1362 lp->mincol = start.x;
1363 if (lp->minrow > start.y - ADAM_LOOPX)
1364 lp->minrow = start.y - ADAM_LOOPX;
1365 if (lp->maxcol < start.x + ADAM_LOOPX)
1366 lp->maxcol = start.x + ADAM_LOOPX;
1367 if (lp->maxrow < start.y)
1368 lp->maxrow = start.y;
1371 for (j = 0; j < ADAM_LOOPY; j++)
1372 for (i = 0; i < ADAM_LOOPX; i++)
1373 lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
1374 start.x + dirx.x * i + diry.x * j] =
1376 self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
1377 self_reproducing_loop[j][i];
1379 /* Draw right away */
1380 drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
1381 start.y + dirx.y * i + diry.y * j - lp->by,
1382 (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
1389 do_gen(loopstruct * lp)
1393 unsigned int n[MAXNEIGHBORS];
1396 #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols)))
1398 for (j = lp->minrow; j <= lp->maxrow; j++) {
1399 for (i = lp->mincol; i <= lp->maxcol; i++) {
1400 z = lp->newcells + i + j * lp->bncols;
1402 for (k = 0; k < local_neighbors; k++) {
1403 int newi = i, newj = j;
1405 position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj);
1407 if (withinBounds(lp, newi, newj)) {
1408 n[k] = LOC(newi, newj);
1411 if (local_neighbors == 6) {
1412 *z = (lp->clockwise) ?
1413 HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
1414 HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
1416 *z = (lp->clockwise) ?
1417 TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
1418 TABLE_OUT(c, n[0], n[1], n[2], n[3]);
1425 release_loop (ModeInfo * mi)
1427 if (table != NULL) {
1428 (void) free((void *) table);
1429 table = (unsigned int *) NULL;
1433 static void *stop_warning_about_triangleUnit_already;
1437 init_loop (ModeInfo * mi)
1439 int i, size = MI_SIZE(mi);
1442 stop_warning_about_triangleUnit_already = (void *) &triangleUnit;
1444 MI_INIT (mi, loops, free_loop);
1445 lp = &loops[MI_SCREEN(mi)];
1450 if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
1451 Window window = MI_WINDOW(mi);
1453 if (lp->stippledGC == None) {
1454 gcv.fill_style = FillOpaqueStippled;
1455 if ((lp->stippledGC = XCreateGC(MI_DISPLAY(mi), window,
1456 GCFillStyle, &gcv)) == None) {
1461 LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE);
1462 LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE);
1463 LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE);
1464 LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE);
1465 LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE);
1466 LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
1467 LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
1468 LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
1470 #endif /* DO_STIPPLE */
1471 if (MI_NPIXELS(mi) >= COLORS) {
1472 /* Maybe these colors should be randomized */
1473 lp->colors[0] = MI_BLACK_PIXEL(mi);
1474 lp->colors[1] = MI_PIXEL(mi, 0); /* RED */
1475 lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */
1476 lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */
1477 lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */
1478 lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */
1479 lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */
1480 lp->colors[7] = MI_WHITE_PIXEL(mi);
1484 lp->width = MI_WIDTH(mi);
1485 lp->height = MI_HEIGHT(mi);
1487 if (!local_neighbors) {
1488 for (i = 0; i < NEIGHBORKINDS; i++) {
1489 if (neighbors == plots[i]) {
1490 local_neighbors = neighbors;
1493 if (i == NEIGHBORKINDS - 1) {
1495 local_neighbors = plots[NRAND(NEIGHBORKINDS)];
1497 local_neighbors = 4;
1505 if (local_neighbors == 6) {
1512 if (size < -MINSIZE) {
1513 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1514 HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1515 } else if (size < MINSIZE) {
1517 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE);
1521 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1524 nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
1525 ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
1526 lp->ncols = nccols / 2;
1527 lp->nrows = ncrows / 2;
1528 lp->nrows -= !(lp->nrows & 1); /* Must be odd */
1529 lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
1530 lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
1531 for (i = 0; i < 6; i++) {
1532 lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x;
1533 lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
1536 if (size < -MINSIZE)
1537 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1538 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1539 else if (size < MINSIZE) {
1541 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE);
1545 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1548 lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1);
1549 lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1);
1550 lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
1551 lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
1555 lp->bncols = lp->ncols + 2 * lp->bx;
1556 lp->bnrows = lp->nrows + 2 * lp->by;
1560 if (lp->oldcells != NULL) {
1561 (void) free((void *) lp->oldcells);
1562 lp->oldcells = (unsigned char *) NULL;
1564 if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1565 sizeof (unsigned char))) == NULL) {
1569 if (lp->newcells != NULL) {
1570 (void) free((void *) lp->newcells);
1571 lp->newcells = (unsigned char *) NULL;
1573 if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1574 sizeof (unsigned char))) == NULL) {
1578 if (!init_table()) {
1582 lp->mincol = lp->bncols - 1;
1583 lp->minrow = lp->bnrows - 1;
1586 #ifndef DELAYDEBUGLOOP
1588 int flaws = MI_COUNT(mi);
1591 flaws = NRAND(-MI_COUNT(mi) + 1);
1592 for (i = 0; i < flaws; i++) {
1595 /* actual flaws might be less since the adam loop done next */
1602 draw_loop (ModeInfo * mi)
1605 unsigned char *z, *znew;
1610 lp = &loops[MI_SCREEN(mi)];
1611 if (lp->newcells == NULL)
1614 MI_IS_DRAWN(mi) = True;
1616 #ifdef DELAYDEBUGLOOP
1617 if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
1618 (void) sleep(DELAYDEBUGLOOP);
1622 for (j = lp->minrow; j <= lp->maxrow; j++) {
1623 for (i = lp->mincol; i <= lp->maxcol; i++) {
1624 offset = j * lp->bncols + i;
1625 z = lp->oldcells + offset;
1626 znew = lp->newcells + offset;
1630 if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
1632 if (i == lp->mincol && i > lp->bx)
1634 if (j == lp->minrow && j > lp->by)
1636 if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx)
1638 if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by)
1643 for (i = 0; i < COLORS; i++)
1644 if (!draw_state(mi, i)) {
1648 if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
1654 if (lp->redrawing) {
1655 for (i = 0; i < REDRAWSTEP; i++) {
1656 if ((*(lp->oldcells + lp->redrawpos))) {
1657 drawcell(mi, lp->redrawpos % lp->bncols - lp->bx,
1658 lp->redrawpos / lp->bncols - lp->by,
1659 *(lp->oldcells + lp->redrawpos));
1661 if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) {
1670 reshape_loop(ModeInfo * mi, int width, int height)
1672 XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
1677 refresh_loop (ModeInfo * mi)
1683 lp = &loops[MI_SCREEN(mi)];
1687 lp->redrawpos = lp->by * lp->ncols + lp->bx;
1691 loop_handle_event (ModeInfo *mi, XEvent *event)
1693 if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
1695 reshape_loop (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
1701 XSCREENSAVER_MODULE ("Loop", loop)
1703 #endif /* MODE_loop */