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.
84 #define PROGCLASS "loop"
85 #define HACK_INIT init_loop
86 #define HACK_DRAW draw_loop
87 #define loop_opts xlockmore_opts
88 #define DEFAULTS "*delay: 100000 \n" \
94 #define UNIFORM_COLORS
95 #include "xlockmore.h" /* in xscreensaver distribution */
96 #else /* STANDALONE */
97 #include "xlock.h" /* in xlockmore distribution */
98 #endif /* STANDALONE */
104 * neighbors of 0 randomizes between 4 and 6.
106 #define DEF_NEIGHBORS "0" /* choose random value */
108 static int neighbors;
110 static XrmOptionDescRec opts[] =
112 {"-neighbors", ".loop.neighbors", XrmoptionSepArg, 0}
115 static argtype vars[] =
117 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
120 static OptionStruct desc[] =
122 {"-neighbors num", "squares 4 or hexagons 6"}
125 ModeSpecOpt loop_opts =
126 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
130 ModStruct loop_description =
131 {"loop", "init_loop", "draw_loop", "release_loop",
132 "refresh_loop", "init_loop", (char *) NULL, &loop_opts,
133 100000, 5, 1600, -12, 64, 1.0, "",
134 "Shows Langton's self-producing loops", 0, NULL};
138 #define LOOPBITS(n,w,h)\
139 if ((lp->pixmaps[lp->init_bits]=\
140 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
141 free_loop(display,lp); return;} else {lp->init_bits++;}
143 static int local_neighbors = 0;
146 /* Used to fast forward to troubled generations, mainly used for debugging.
147 -delay 1 -count 170 -neighbors 6 # divisions starts
148 540 first cell collision
149 1111 mutant being born from 2 parents
152 #define DELAYDEBUGLOOP 10
156 #define REALCOLORS (COLORS-2)
158 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
159 #define ADAM_SIZE 8 /* MIN 5 */
161 #define ADAM_LOOPX (ADAM_SIZE+2)
162 #define ADAM_LOOPY (ADAM_SIZE+2)
164 #define ADAM_LOOPX 16
165 #define ADAM_LOOPY 10
167 #define MINGRIDSIZE (3*ADAM_LOOPX)
169 /* TRIA stuff was an attempt to make a triangular lifeform on a
170 hexagonal grid but I got bored. You may need an additional 7th
171 state for a coherent step by step process of cell separation and
172 initial stem development.
177 #define HEX_ADAM_SIZE 3 /* MIN 3 */
179 #define HEX_ADAM_SIZE 5 /* MIN 3 */
182 #define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
183 #define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
185 #define HEX_ADAM_LOOPX 3
186 #define HEX_ADAM_LOOPY 7
188 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
189 #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6)))
190 #define NEIGHBORKINDS 2
192 #define MAXNEIGHBORS 6
194 /* Singly linked list */
195 typedef struct _CellList {
197 struct _CellList *next;
206 int bx, by, bnrows, bncols;
207 int mincol, minrow, maxcol, maxrow;
209 int redrawing, redrawpos;
210 Bool dead, clockwise;
211 unsigned char *newcells, *oldcells;
213 CellList *cellList[COLORS];
214 unsigned long colors[COLORS];
216 Pixmap pixmaps[COLORS];
222 static loopstruct *loops = (loopstruct *) NULL;
224 #define TRANSITION(TT,V) V=TT&7;TT>>=3
225 #define FINALTRANSITION(TT,V) V=TT&7
226 #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)])
227 #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)])
230 /* Instead of setting "unused" state rules to zero it randomizes them.
231 These rules take over when something unexpected happens... like when a
232 cell hits a wall (the end of the screen).
238 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\
239 (TABLE(R,T,L,B)|=((I)<<((C)*3)))
240 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\
241 (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
243 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)|=((I)<<((C)*3)))
244 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
246 #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7)
247 #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7)
249 static unsigned int *table = (unsigned int *) NULL;
250 /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */
251 /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */
253 static char plots[NEIGHBORKINDS] =
255 4, 6 /* Neighborhoods */
258 static unsigned int transition_table[] =
259 { /* Octal CBLTR->I */
260 /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */
261 0000000, 0025271, 0113221, 0202422, 0301021,
262 0000012, 0100011, 0122244, 0202452, 0301220,
263 0000020, 0100061, 0122277, 0202520, 0302511,
264 0000030, 0100077, 0122434, 0202552, 0401120,
265 0000050, 0100111, 0122547, 0202622, 0401220,
266 0000063, 0100121, 0123244, 0202722, 0401250,
267 0000071, 0100211, 0123277, 0203122, 0402120,
268 0000112, 0100244, 0124255, 0203216, 0402221,
269 0000122, 0100277, 0124267, 0203226, 0402326,
270 0000132, 0100511, 0125275, 0203422, 0402520,
271 0000212, 0101011, 0200012, 0204222, 0403221,
272 0000220, 0101111, 0200022, 0205122, 0500022,
273 0000230, 0101244, 0200042, 0205212, 0500215,
274 0000262, 0101277, 0200071, 0205222, 0500225,
275 0000272, 0102026, 0200122, 0205521, 0500232,
276 0000320, 0102121, 0200152, 0205725, 0500272,
277 0000525, 0102211, 0200212, 0206222, 0500520,
278 0000622, 0102244, 0200222, 0206722, 0502022,
279 0000722, 0102263, 0200232, 0207122, 0502122,
280 0001022, 0102277, 0200242, 0207222, 0502152,
281 0001120, 0102327, 0200250, 0207422, 0502220,
282 0002020, 0102424, 0200262, 0207722, 0502244,
283 0002030, 0102626, 0200272, 0211222, 0502722,
284 0002050, 0102644, 0200326, 0211261, 0512122,
285 0002125, 0102677, 0200423, 0212222, 0512220,
286 0002220, 0102710, 0200517, 0212242, 0512422,
287 0002322, 0102727, 0200522, 0212262, 0512722,
288 0005222, 0105427, 0200575, 0212272, 0600011,
289 0012321, 0111121, 0200722, 0214222, 0600021,
290 0012421, 0111221, 0201022, 0215222, 0602120,
291 0012525, 0111244, 0201122, 0216222, 0612125,
292 0012621, 0111251, 0201222, 0217222, 0612131,
293 0012721, 0111261, 0201422, 0222272, 0612225,
294 0012751, 0111277, 0201722, 0222442, 0700077,
295 0014221, 0111522, 0202022, 0222462, 0701120,
296 0014321, 0112121, 0202032, 0222762, 0701220,
297 0014421, 0112221, 0202052, 0222772, 0701250,
298 0014721, 0112244, 0202073, 0300013, 0702120,
299 0016251, 0112251, 0202122, 0300022, 0702221,
300 0017221, 0112277, 0202152, 0300041, 0702251,
301 0017255, 0112321, 0202212, 0300076, 0702321,
302 0017521, 0112424, 0202222, 0300123, 0702525,
303 0017621, 0112621, 0202272, 0300421, 0702720,
304 0017721, 0112727, 0202321, 0300622
307 static unsigned int hex_transition_table[] =
308 { /* Octal CBbltTR->I */
309 /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */
312 000000000, 000000020, 000000220, 000002220, 000022220,
313 011122121, 011121221, 011122221, 011221221,
314 011222221, 011112121, 011112221,
315 020021122, 020002122, 020211222, 021111222,
316 020221122, 020027122, 020020722, 020021022,
318 011122727, 011227227, 010122121, 010222211,
319 021117222, 020112272,
322 010221121, 011721221, 011222277,
323 020111222, 020221172,
326 010212277, 010221221,
331 020002022, 021122172,
333 011122277, 011172121,
334 010212177, 011212277,
338 070121270, 070721220,
339 000112721, 000272211,
340 010022211, 012222277,
341 020072272, 020227122, 020217222,
346 020021072, 020070722,
347 070002072, 070007022,
350 000000070, 000000770, 000072220, 000000270,
351 020110222, 020220272, 020220722,
352 070007071, 070002072, 070007022,
353 000000012, 000000122, 000000212, 001277721,
354 020122072, 020202212,
356 020001122, 020002112,
358 020122022, 020027022, 020070122, 020020122,
361 010227227, 010227277,
368 010022277, 010202177, 010227127,
372 020024122, 020020422,
375 010221241, 010224224,
380 020112242, 021422172,
382 001224221, 001427221,
387 010022244, 010202144, 010224124,
391 040121240, 040421220,
392 000242211, 000112421,
393 020042242, 020214222, 020021422, 020220242, 020024022,
400 001244421, 000000420, 000000440, 000000240, 000000040,
401 020040121, 020021042,
402 040004022, 040004042, 040002042,
404 020011122, 020002112,
411 020224072, 021417222,
417 070207072, 070701220,
422 020021222, 020202272, 020120222, 020221722,
426 020101272, 020272172, 020721422, 020721722,
427 020011222, 020202242,
445 000000000, 000000020, 000000220, 000002220,
446 011212121, 011212221, 011221221, 011222221,
447 020002122, 020021122, 020211122,
449 010221221, 010222121,
450 020002022, 020021022, 020020122, 020112022,
453 020102022, 020202112,
455 000000012, 000000122, 000000212,
457 020001122, 020002112, 020011122,
460 001227221, 001272221, 001272721,
461 012212277, 011222727, 011212727,
462 020021722, 020027122, 020020722, 020027022,
463 020211722, 020202172, 020120272,
464 020271122, 020202172, 020207122, 020217122,
465 020120272, 020210722, 020270722,
466 070212220, 070221220, 070212120,
473 001277721, 000000070, 000000270, 000000720, 000000770,
474 020070122, 020021072,
475 070002072, 070007022, 070007071,
480 010227227, 010222727, 010202727,
481 020172022, 020202712,
483 001224221, 001242221, 001242421,
484 012212244, 011222424, 011212424,
485 020021422, 020024122, 020020422, 020024022,
486 020211422, 020202142, 020120242,
487 020241122, 020202142, 020204122, 020214122,
488 020120242, 020210422, 020240422,
489 040212220, 040221220, 040212120,
496 001244421, 000000040, 000000240, 000000420, 000000440,
497 020040122, 020021042,
499 040004021, 040004042,
504 010224224, 010222424, 010202424,
505 020142022, 020202412,
506 020011722, 020112072, 020172072, 020142072,
510 000210225, 000022015, 000022522,
512 020120525, 020020152, 020005122, 020214255, 020021152,
514 050215222, 050225121,
516 000225220, 001254222,
517 010221250, 011221251, 011225221,
518 020025122, 020152152, 020211252, 020214522, 020511125,
522 000000250, 000000520, 000150220, 000220520, 000222210,
524 010022152, 010251221, 010522121, 011212151, 011221251,
526 020000220, 020002152, 020020220, 020022152,
527 020021422, 020022152, 020022522, 020025425, 020050422,
528 020051022, 020051122, 020211122, 020211222, 020215222,
530 050021125, 050021025, 050011125, 051242221,
533 000220250, 000220520, 001227521, 001275221,
534 011257227, 011522727,
535 020002052, 020002752, 020021052, 020057125,
536 050020722, 050027125,
631 000000050, 000005220, 000002270, 070252220,
632 000000450, 000007220,
633 000220220, 000202220, 000022020, 000020220,
641 050221120, 010221520,
644 000070220, 000220720,
645 000020520, 000070250, 000222070, 000027020,
646 000022070, 000202270, 000024020, 000220420,
647 000220270, 000220240, 000072020, 000042020,
648 000002020, 000002070, 000020270, 000020250,
649 000270270, 000007020, 000040270,
651 /* Collision starts (gen 540), not sure to have rules to save it
652 or depend on calloc to intialize remaining rules to 0 so that
653 the mutant will be born
661 Neighborhoods are read as follows (rotations are not listed):
671 static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] =
674 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0},
675 {2, 4, 0, 1, 4, 0, 1, 1, 1, 2},
676 {2, 1, 2, 2, 2, 2, 2, 2, 1, 2},
677 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
678 {2, 7, 2, 0, 0, 0, 0, 2, 7, 2},
679 {2, 1, 2, 0, 0, 0, 0, 2, 0, 2},
680 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
681 {2, 7, 2, 2, 2, 2, 2, 2, 7, 2},
682 {2, 1, 0, 6, 1, 0, 7, 1, 0, 2},
683 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}
686 static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] =
689 /* Experimental TRIA5:7x7 */
697 /* Stem cells, only "5" will fully reproduce itself */
699 {2,2,2,2,0,0,0,0,0,0,0,0},
700 {2,1,1,1,2,0,0,0,0,0,0,0},
701 {2,1,2,2,1,2,2,2,2,2,2,0},
702 {2,1,2,0,2,7,1,1,1,1,1,2},
703 {0,2,1,2,2,0,2,2,2,2,2,2},
704 {0,0,2,0,4,1,2,0,0,0,0,0},
705 {0,0,0,2,2,2,2,0,0,0,0,0}
707 {2,2,2,2,2,0,0,0,0,0,0,0,0,0},
708 {2,1,1,1,1,2,0,0,0,0,0,0,0,0},
709 {2,1,2,2,2,1,2,0,0,0,0,0,0,0},
710 {2,1,2,0,0,2,1,2,2,2,2,2,2,0},
711 {2,1,2,0,0,0,2,7,1,1,1,1,1,2},
712 {0,2,1,2,0,0,2,0,2,2,2,2,2,2},
713 {0,0,2,0,2,2,2,1,2,0,0,0,0,0},
714 {0,0,0,2,4,1,0,7,2,0,0,0,0,0},
715 {0,0,0,0,2,2,2,2,2,0,0,0,0,0}
717 {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0},
718 {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0},
719 {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0},
720 {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0},
721 {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0},
722 {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2},
723 {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2},
724 {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0},
725 {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0},
726 {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0},
727 {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0}
728 /* test:3x7 (0,4) is blank ... very strange.
729 init_adam seems ok something after that I guess */
737 #else /* this might be better for hexagons, spacewise efficient... */
739 /* Experimental TRIA5:7x7 */
749 {2,2,2,2,2,2,0,0,0,0,0},
750 {2,1,1,7,0,1,2,0,0,0,0},
751 {2,1,2,2,2,2,7,2,0,0,0},
752 {2,1,2,0,0,0,2,0,2,0,0},
753 {2,1,2,0,0,0,0,2,1,2,0},
754 {2,1,2,0,0,0,0,0,2,7,2},
755 {0,2,1,2,0,0,0,0,2,0,2},
756 {0,0,2,1,2,0,0,0,2,1,2},
757 {0,0,0,2,1,2,2,2,2,4,2},
758 {0,0,0,0,2,1,1,1,1,5,2},
759 {0,0,0,0,0,2,2,2,2,2,2}
765 position_of_neighbor(int dir, int *pcol, int *prow)
767 int col = *pcol, row = *prow;
771 if (local_neighbors == 6) {
796 (void) fprintf(stderr, "wrong direction %d\n", dir);
813 (void) fprintf(stderr, "wrong direction %d\n", dir);
821 withinBounds(loopstruct * lp, int col, int row)
823 return (row >= 1 && row < lp->bnrows - 1 &&
824 col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2)));
828 fillcell(ModeInfo * mi, GC gc, int col, int row)
830 loopstruct *lp = &loops[MI_SCREEN(mi)];
832 if (local_neighbors == 6) {
833 int ccol = 2 * col + !(row & 1), crow = 2 * row;
835 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
836 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
837 if (lp->xs == 1 && lp->ys == 1)
838 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
839 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
841 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
842 lp->shape.hexagon, 6, Convex, CoordModePrevious);
844 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
845 lp->xb + lp->xs * col, lp->yb + lp->ys * row,
846 lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3));
851 drawcell(ModeInfo * mi, int col, int row, int state)
853 loopstruct *lp = &loops[MI_SCREEN(mi)];
857 if (MI_NPIXELS(mi) >= COLORS) {
859 XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]);
861 gcv.stipple = lp->pixmaps[state];
862 gcv.foreground = MI_WHITE_PIXEL(mi);
863 gcv.background = MI_BLACK_PIXEL(mi);
864 XChangeGC(MI_DISPLAY(mi), lp->stippledGC,
865 GCStipple | GCForeground | GCBackground, &gcv);
868 fillcell(mi, gc, col, row);
873 print_state(ModeInfo * mi, int state)
875 loopstruct *lp = &loops[MI_SCREEN(mi)];
876 CellList *locallist = lp->cellList[state];
879 (void) printf("state %d\n", state);
881 (void) printf("%d x %d, y %d\n", i,
882 locallist->pt.x, locallist->pt.y);
883 locallist = locallist->next;
891 free_state(loopstruct * lp, int state)
895 while (lp->cellList[state]) {
896 current = lp->cellList[state];
897 lp->cellList[state] = lp->cellList[state]->next;
898 (void) free((void *) current);
900 lp->ncells[state] = 0;
904 free_list(loopstruct * lp)
908 for (state = 0; state < COLORS; state++)
909 free_state(lp, state);
913 free_loop(Display *display, loopstruct * lp)
917 for (shade = 0; shade < lp->init_bits; shade++)
918 if (lp->pixmaps[shade] != None) {
919 XFreePixmap(display, lp->pixmaps[shade]);
920 lp->pixmaps[shade] = None;
922 if (lp->stippledGC != None) {
923 XFreeGC(display, lp->stippledGC);
924 lp->stippledGC = None;
926 if (lp->oldcells != NULL) {
927 (void) free((void *) lp->oldcells);
928 lp->oldcells = (unsigned char *) NULL;
930 if (lp->newcells != NULL) {
931 (void) free((void *) lp->newcells);
932 lp->newcells = (unsigned char *) NULL;
938 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
940 loopstruct *lp = &loops[MI_SCREEN(mi)];
941 CellList *current = lp->cellList[state];
943 if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
945 lp->cellList[state] = current;
946 free_loop(MI_DISPLAY(mi), lp);
949 lp->cellList[state]->pt.x = col;
950 lp->cellList[state]->pt.y = row;
951 lp->cellList[state]->next = current;
957 draw_state(ModeInfo * mi, int state)
959 loopstruct *lp = &loops[MI_SCREEN(mi)];
960 Display *display = MI_DISPLAY(mi);
963 CellList *current = lp->cellList[state];
965 if (MI_NPIXELS(mi) >= COLORS) {
967 XSetForeground(display, gc, lp->colors[state]);
969 gcv.stipple = lp->pixmaps[state];
970 gcv.foreground = MI_WHITE_PIXEL(mi);
971 gcv.background = MI_BLACK_PIXEL(mi);
972 XChangeGC(display, lp->stippledGC,
973 GCStipple | GCForeground | GCBackground, &gcv);
977 if (local_neighbors == 6) { /* Draw right away, slow */
979 int col, row, ccol, crow;
983 ccol = 2 * col + !(row & 1), crow = 2 * row;
984 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
985 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
986 if (lp->xs == 1 && lp->ys == 1)
987 XDrawPoint(display, MI_WINDOW(mi), gc,
988 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
990 XFillPolygon(display, MI_WINDOW(mi), gc,
991 lp->shape.hexagon, 6, Convex, CoordModePrevious);
992 current = current->next;
995 /* Take advantage of XFillRectangles */
999 /* Create Rectangle list from part of the cellList */
1000 if ((rects = (XRectangle *) malloc(lp->ncells[state] *
1001 sizeof (XRectangle))) == NULL) {
1006 rects[nrects].x = lp->xb + current->pt.x * lp->xs;
1007 rects[nrects].y = lp->yb + current->pt.y * lp->ys;
1008 rects[nrects].width = lp->xs - (lp->xs > 3);
1009 rects[nrects].height = lp->ys - (lp->ys > 3);
1010 current = current->next;
1013 /* Finally get to draw */
1014 XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
1015 /* Free up rects list and the appropriate part of the cellList */
1016 (void) free((void *) rects);
1018 free_state(lp, state);
1026 if (table == NULL) {
1028 unsigned int tt, c, n[MAXNEIGHBORS], i;
1030 int size_transition_table = sizeof (transition_table) /
1031 sizeof (unsigned int);
1032 int size_hex_transition_table = sizeof (hex_transition_table) /
1033 sizeof (unsigned int);
1035 for (j = 0; j < local_neighbors; j++)
1038 if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
1044 /* Here I was interested to see what happens when it hits a wall....
1045 Rules not normally used take over... takes too much time though */
1046 /* Each state = 3 bits */
1047 if (MAXRAND < 16777216.0) {
1048 for (j = 0; j < mult; j++) {
1049 table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
1052 for (j = 0; j < mult; j++) {
1053 table[j] = (unsigned int) (NRAND(16777216));
1057 if (local_neighbors == 6) {
1058 for (j = 0; j < size_hex_transition_table; j++) {
1059 tt = hex_transition_table[j];
1061 for (k = 0; k < local_neighbors; k++) {
1062 TRANSITION(tt, n[k]);
1064 FINALTRANSITION(tt, c);
1065 HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
1066 HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
1067 HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
1068 HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i);
1069 HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i);
1070 HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i);
1073 for (j = 0; j < size_transition_table; j++) {
1074 tt = transition_table[j];
1076 for (k = 0; k < local_neighbors; k++) {
1077 TRANSITION(tt, n[k]);
1079 FINALTRANSITION(tt, c);
1080 TABLE_IN(c, n[0], n[1], n[2], n[3], i);
1081 TABLE_IN(c, n[1], n[2], n[3], n[0], i);
1082 TABLE_IN(c, n[2], n[3], n[0], n[1], i);
1083 TABLE_IN(c, n[3], n[0], n[1], n[2], i);
1091 init_flaw(ModeInfo * mi)
1093 loopstruct *lp = &loops[MI_SCREEN(mi)];
1097 if (lp->bncols <= 3 || lp->bnrows <= 3)
1099 a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
1100 HEX_MINGRIDSIZE : MINGRIDSIZE));
1101 a = NRAND(a) + (lp->bncols - a) / 2;
1102 b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
1103 HEX_MINGRIDSIZE : MINGRIDSIZE));
1104 b = NRAND(b) + (lp->bnrows - b) / 2;
1109 if (lp->maxcol < a + 2)
1111 if (lp->maxrow < b + 2)
1114 if (local_neighbors == 6) {
1115 lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
1116 lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1117 lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
1118 lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
1119 lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
1120 lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1122 int orient = NRAND(4);
1123 lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
1124 if (orient == 0 || orient == 1) {
1125 lp->newcells[lp->bncols * b + a + 1] = BLUE;
1127 if (orient == 1 || orient == 2) {
1128 lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
1130 if (orient == 2 || orient == 3) {
1131 lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
1133 if (orient == 3 || orient == 0) {
1134 lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
1140 init_adam(ModeInfo * mi)
1142 loopstruct *lp = &loops[MI_SCREEN(mi)];
1143 XPoint start, dirx, diry;
1146 #ifdef DELAYDEBUGLOOP
1148 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1150 lp->clockwise = (Bool) (LRAND() & 1);
1151 #ifdef DELAYDEBUGLOOP
1153 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1155 dir = NRAND(local_neighbors);
1156 if (local_neighbors == 6) {
1161 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1162 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1163 if (lp->mincol > start.x - 2)
1164 lp->mincol = start.x - 2;
1165 if (lp->minrow > start.y - 1)
1166 lp->minrow = start.y - 1;
1167 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1168 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1169 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1170 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1171 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1172 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1173 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1174 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1176 hex_self_reproducing_loop[i][j] :
1177 hex_self_reproducing_loop[j][i];
1182 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1183 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1184 if (lp->mincol > start.x - 1)
1185 lp->mincol = start.x - 1;
1186 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1187 lp->minrow = start.y - HEX_ADAM_LOOPX;
1188 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1189 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1190 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1191 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1192 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1193 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1194 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1195 ? -(i + j + 1) / 2 : -(i + j) / 2);
1196 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1198 hex_self_reproducing_loop[i][j] :
1199 hex_self_reproducing_loop[j][i];
1204 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1205 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1206 if (lp->mincol > start.x - 2)
1207 lp->mincol = start.x - 2;
1208 if (lp->minrow > start.y - 1)
1209 lp->minrow = start.y - 1;
1210 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1211 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1212 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1213 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1214 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1215 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1216 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1217 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1219 hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
1220 hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
1225 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1226 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1227 if (lp->mincol > start.x - 1)
1228 lp->mincol = start.x - 1;
1229 if (lp->minrow > start.y - 1)
1230 lp->minrow = start.y - 1;
1231 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1232 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1233 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1234 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1235 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1236 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1237 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1238 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1240 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1241 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1246 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1247 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1248 if (lp->mincol > start.x - 1)
1249 lp->mincol = start.x - 1;
1250 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1251 lp->minrow = start.y - HEX_ADAM_LOOPX;
1252 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1253 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1254 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1255 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1256 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1257 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1258 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1259 ? -(i + j + 1) / 2 : -(i + j) / 2);
1260 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1262 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1263 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1268 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1269 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1270 if (lp->mincol > start.x - 2)
1271 lp->mincol = start.x - 2;
1272 if (lp->minrow > start.y - 1)
1273 lp->minrow = start.y - 1;
1274 if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
1275 lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
1276 if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
1277 lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
1278 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1279 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1280 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1281 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1283 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
1284 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
1290 /* (void) printf ("s %d s %d \n", start.x, start.y); */
1291 (void) printf ("%d %d %d %d %d\n",
1292 start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1293 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
1294 /* Draw right away */
1295 drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1296 start.y + j - lp->by,
1297 hex_self_reproducing_loop[j][i]);
1302 start.x = (lp->bncols - ADAM_LOOPX) / 2;
1303 start.y = (lp->bnrows - ADAM_LOOPY) / 2;
1304 dirx.x = 1, dirx.y = 0;
1305 diry.x = 0, diry.y = 1;
1306 if (lp->mincol > start.x)
1307 lp->mincol = start.x;
1308 if (lp->minrow > start.y)
1309 lp->minrow = start.y;
1310 if (lp->maxcol < start.x + ADAM_LOOPX)
1311 lp->maxcol = start.x + ADAM_LOOPX;
1312 if (lp->maxrow < start.y + ADAM_LOOPY)
1313 lp->maxrow = start.y + ADAM_LOOPY;
1316 start.x = (lp->bncols + ADAM_LOOPY) / 2;
1317 start.y = (lp->bnrows - ADAM_LOOPX) / 2;
1318 dirx.x = 0, dirx.y = 1;
1319 diry.x = -1, diry.y = 0;
1320 if (lp->mincol > start.x - ADAM_LOOPY)
1321 lp->mincol = start.x - ADAM_LOOPY;
1322 if (lp->minrow > start.y)
1323 lp->minrow = start.y;
1324 if (lp->maxcol < start.x)
1325 lp->maxcol = start.x;
1326 if (lp->maxrow < start.y + ADAM_LOOPX)
1327 lp->maxrow = start.y + ADAM_LOOPX;
1330 start.x = (lp->bncols + ADAM_LOOPX) / 2;
1331 start.y = (lp->bnrows + ADAM_LOOPY) / 2;
1332 dirx.x = -1, dirx.y = 0;
1333 diry.x = 0, diry.y = -1;
1334 if (lp->mincol > start.x - ADAM_LOOPX)
1335 lp->mincol = start.x - ADAM_LOOPX;
1336 if (lp->minrow > start.y - ADAM_LOOPY)
1337 lp->minrow = start.y - ADAM_LOOPY;
1338 if (lp->maxcol < start.x)
1339 lp->maxcol = start.x;
1340 if (lp->maxrow < start.y)
1341 lp->maxrow = start.y;
1344 start.x = (lp->bncols - ADAM_LOOPY) / 2;
1345 start.y = (lp->bnrows + ADAM_LOOPX) / 2;
1346 dirx.x = 0, dirx.y = -1;
1347 diry.x = 1, diry.y = 0;
1348 if (lp->mincol > start.x)
1349 lp->mincol = start.x;
1350 if (lp->minrow > start.y - ADAM_LOOPX)
1351 lp->minrow = start.y - ADAM_LOOPX;
1352 if (lp->maxcol < start.x + ADAM_LOOPX)
1353 lp->maxcol = start.x + ADAM_LOOPX;
1354 if (lp->maxrow < start.y)
1355 lp->maxrow = start.y;
1358 for (j = 0; j < ADAM_LOOPY; j++)
1359 for (i = 0; i < ADAM_LOOPX; i++)
1360 lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
1361 start.x + dirx.x * i + diry.x * j] =
1363 self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
1364 self_reproducing_loop[j][i];
1366 /* Draw right away */
1367 drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
1368 start.y + dirx.y * i + diry.y * j - lp->by,
1369 (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
1376 do_gen(loopstruct * lp)
1380 unsigned int n[MAXNEIGHBORS];
1383 #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols)))
1385 for (j = lp->minrow; j <= lp->maxrow; j++) {
1386 for (i = lp->mincol; i <= lp->maxcol; i++) {
1387 z = lp->newcells + i + j * lp->bncols;
1389 for (k = 0; k < local_neighbors; k++) {
1390 int newi = i, newj = j;
1392 position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj);
1394 if (withinBounds(lp, newi, newj)) {
1395 n[k] = LOC(newi, newj);
1398 if (local_neighbors == 6) {
1399 *z = (lp->clockwise) ?
1400 HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
1401 HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
1403 *z = (lp->clockwise) ?
1404 TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
1405 TABLE_OUT(c, n[0], n[1], n[2], n[3]);
1412 release_loop(ModeInfo * mi)
1414 if (loops != NULL) {
1417 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1418 free_loop(MI_DISPLAY(mi), &loops[screen]);
1419 (void) free((void *) loops);
1420 loops = (loopstruct *) NULL;
1422 if (table != NULL) {
1423 (void) free((void *) table);
1424 table = (unsigned int *) NULL;
1428 static void *stop_warning_about_triangleUnit_already;
1432 init_loop(ModeInfo * mi)
1434 Display *display = MI_DISPLAY(mi);
1435 Window window = MI_WINDOW(mi);
1436 int i, size = MI_SIZE(mi);
1440 stop_warning_about_triangleUnit_already = (void *) &triangleUnit;
1442 if (loops == NULL) {
1443 if ((loops = (loopstruct *) calloc(MI_NUM_SCREENS(mi),
1444 sizeof (loopstruct))) == NULL)
1447 lp = &loops[MI_SCREEN(mi)];
1451 if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
1452 if (lp->stippledGC == None) {
1453 gcv.fill_style = FillOpaqueStippled;
1454 if ((lp->stippledGC = XCreateGC(display, window,
1455 GCFillStyle, &gcv)) == None) {
1456 free_loop(display, lp);
1460 LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE);
1461 LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE);
1462 LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE);
1463 LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE);
1464 LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE);
1465 LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
1466 LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
1467 LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
1469 if (MI_NPIXELS(mi) >= COLORS) {
1470 /* Maybe these colors should be randomized */
1471 lp->colors[0] = MI_BLACK_PIXEL(mi);
1472 lp->colors[1] = MI_PIXEL(mi, 0); /* RED */
1473 lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */
1474 lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */
1475 lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */
1476 lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */
1477 lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */
1478 lp->colors[7] = MI_WHITE_PIXEL(mi);
1482 lp->width = MI_WIDTH(mi);
1483 lp->height = MI_HEIGHT(mi);
1485 if (!local_neighbors) {
1486 for (i = 0; i < NEIGHBORKINDS; i++) {
1487 if (neighbors == plots[i]) {
1488 local_neighbors = neighbors;
1491 if (i == NEIGHBORKINDS - 1) {
1493 local_neighbors = plots[NRAND(NEIGHBORKINDS)];
1495 local_neighbors = 4;
1503 if (local_neighbors == 6) {
1510 if (size < -MINSIZE) {
1511 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1512 HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1513 } else if (size < MINSIZE) {
1515 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE);
1519 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1522 nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
1523 ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
1524 lp->ncols = nccols / 2;
1525 lp->nrows = ncrows / 2;
1526 lp->nrows -= !(lp->nrows & 1); /* Must be odd */
1527 lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
1528 lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
1529 for (i = 0; i < 6; i++) {
1530 lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x;
1531 lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
1534 if (size < -MINSIZE)
1535 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1536 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1537 else if (size < MINSIZE) {
1539 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE);
1543 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1546 lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1);
1547 lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1);
1548 lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
1549 lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
1553 lp->bncols = lp->ncols + 2 * lp->bx;
1554 lp->bnrows = lp->nrows + 2 * lp->by;
1558 if (lp->oldcells != NULL) {
1559 (void) free((void *) lp->oldcells);
1560 lp->oldcells = (unsigned char *) NULL;
1562 if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1563 sizeof (unsigned char))) == NULL) {
1564 free_loop(display, lp);
1567 if (lp->newcells != NULL) {
1568 (void) free((void *) lp->newcells);
1569 lp->newcells = (unsigned char *) NULL;
1571 if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1572 sizeof (unsigned char))) == NULL) {
1573 free_loop(display, lp);
1576 if (!init_table()) {
1580 lp->mincol = lp->bncols - 1;
1581 lp->minrow = lp->bnrows - 1;
1584 #ifndef DELAYDEBUGLOOP
1586 int flaws = MI_COUNT(mi);
1589 flaws = NRAND(-MI_COUNT(mi) + 1);
1590 for (i = 0; i < flaws; i++) {
1593 /* actual flaws might be less since the adam loop done next */
1600 draw_loop(ModeInfo * mi)
1603 unsigned char *z, *znew;
1608 lp = &loops[MI_SCREEN(mi)];
1609 if (lp->newcells == NULL)
1612 MI_IS_DRAWN(mi) = True;
1614 #ifdef DELAYDEBUGLOOP
1615 if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
1616 (void) sleep(DELAYDEBUGLOOP);
1620 for (j = lp->minrow; j <= lp->maxrow; j++) {
1621 for (i = lp->mincol; i <= lp->maxcol; i++) {
1622 offset = j * lp->bncols + i;
1623 z = lp->oldcells + offset;
1624 znew = lp->newcells + offset;
1628 if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
1630 if (i == lp->mincol && i > lp->bx)
1632 if (j == lp->minrow && j > lp->by)
1634 if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx)
1636 if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by)
1641 for (i = 0; i < COLORS; i++)
1642 if (!draw_state(mi, i)) {
1643 free_loop(MI_DISPLAY(mi), lp);
1646 if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
1652 if (lp->redrawing) {
1653 for (i = 0; i < REDRAWSTEP; i++) {
1654 if ((*(lp->oldcells + lp->redrawpos))) {
1655 drawcell(mi, lp->redrawpos % lp->bncols - lp->bx,
1656 lp->redrawpos / lp->bncols - lp->by,
1657 *(lp->oldcells + lp->redrawpos));
1659 if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) {
1668 refresh_loop(ModeInfo * mi)
1674 lp = &loops[MI_SCREEN(mi)];
1678 lp->redrawpos = lp->by * lp->ncols + lp->bx;
1681 #endif /* MODE_loop */