1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* loop --- Chris Langton's self-producing loops */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)loop.c 5.01 2000/03/15 xlockmore";
10 * Copyright (c) 1996 by David Bagley.
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
18 * This file is provided AS IS with no warranties of any kind. The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof. In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
25 * 15-Mar-2001: Added some flaws, random blue wall spots, to liven it up.
26 * This mod seems to expose a bug where hexagons are erased
27 * for no apparent reason.
28 * 01-Nov-2000: Allocation checks
29 * 16-Jun-2000: Fully coded the hexagonal rules. (Rules that end up in
30 * state zero were not bothered with since a calloc was used
31 * to set non-explicit rules to zero. This allows the
32 * compile-time option RAND_RULES to work here (at least to
34 * Also added compile-time option DELAYDEBUGLOOP for debugging
35 * life form. This also turns off the random initial direction
36 * of the loop. Set DELAYDEBUGLOOP to be 10 and use with
37 * something like this:
38 * xlock -mode loop -neighbors 6 -size 5 -delay 1 -count 540 -nolock
39 * 18-Oct-1998: Started creating a hexagon version.
40 * It proved not that difficult because I used Langton's Loop
41 * as a guide, hexagons have more neighbors so there is more
42 * freedom to program, and the loop will has six sides to
43 * store its genes (data).
44 * (Soon after this a triangular version with neighbors = 6
45 * was attempted but was unsuccessful).
46 * 10-May-1997: Compatible with xscreensaver
47 * 15-Nov-1995: Coded from Chris Langton's Self-Reproduction in Cellular
48 * Automata Physica 10D 135-144 1984, also used wire.c as a
53 Grid Number of Neighbors
54 ---- ------------------
56 Hexagon 6 (currently in development)
60 * From Steven Levy's Artificial Life
61 * Chris Langton's cellular automata "loops" reproduce in the spirit of life.
62 * Beginning from a single organism, the loops from a colony. As the loops
63 * on the outer fringes reproduce, the inner loops -- blocked by their
64 * daughters -- can no longer produce offspring. These dead progenitors
65 * provide a base for future generations' expansion, much like the formation
66 * of a coral reef. This self-organizing behavior emerges spontaneously,
67 * from the bottom up -- a key characteristic of artificial life.
71 Don't Panic -- When the artificial life tries to leave its petri
72 dish (ie. the screen) it will (usually) die...
73 The loops are short of "real" life because a general purpose Turing
74 machine is not contained in the loop. This is a simplification of
75 von Neumann and Codd's self-producing Turing machine.
76 The data spinning around could be viewed as both its DNA and its internal
77 clock. The program can be initalized to have the loop spin both ways...
78 but only one way around will work for a given rule. An open question (at
79 least to me): Is handedness a requirement for (artificial) life? Here
80 there is handedness at both the initial condition and the transition rule.
85 #define PROGCLASS "loop"
86 #define HACK_INIT init_loop
87 #define HACK_DRAW draw_loop
88 #define loop_opts xlockmore_opts
89 #define DEFAULTS "*delay: 100000 \n" \
95 #define UNIFORM_COLORS
96 #include "xlockmore.h" /* in xscreensaver distribution */
97 #else /* STANDALONE */
98 #include "xlock.h" /* in xlockmore distribution */
99 #endif /* STANDALONE */
100 #include "automata.h"
105 * neighbors of 0 randomizes between 4 and 6.
107 #define DEF_NEIGHBORS "0" /* choose random value */
109 static int neighbors;
111 static XrmOptionDescRec opts[] =
113 {(char *) "-neighbors", (char *) ".loop.neighbors", XrmoptionSepArg, (caddr_t) NULL}
116 static argtype vars[] =
118 {(caddr_t *) & neighbors, (char *) "neighbors", (char *) "Neighbors", (char *) DEF_NEIGHBORS, t_Int}
121 static OptionStruct desc[] =
123 {(char *) "-neighbors num", (char *) "squares 4 or hexagons 6"}
126 ModeSpecOpt loop_opts =
127 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
131 ModStruct loop_description =
132 {"loop", "init_loop", "draw_loop", "release_loop",
133 "refresh_loop", "init_loop", (char *) NULL, &loop_opts,
134 100000, 5, 1600, -12, 64, 1.0, "",
135 "Shows Langton's self-producing loops", 0, NULL};
139 #define LOOPBITS(n,w,h)\
140 if ((lp->pixmaps[lp->init_bits]=\
141 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
142 free_loop(display,lp); return;} else {lp->init_bits++;}
144 static int local_neighbors = 0;
147 /* Used to fast forward to troubled generations, mainly used for debugging.
148 -delay 1 -count 170 -neighbors 6 # divisions starts
149 540 first cell collision
150 1111 mutant being born from 2 parents
153 #define DELAYDEBUGLOOP 10
157 #define REALCOLORS (COLORS-2)
159 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
160 #define ADAM_SIZE 8 /* MIN 5 */
162 #define ADAM_LOOPX (ADAM_SIZE+2)
163 #define ADAM_LOOPY (ADAM_SIZE+2)
165 #define ADAM_LOOPX 16
166 #define ADAM_LOOPY 10
168 #define MINGRIDSIZE (3*ADAM_LOOPX)
170 /* TRIA stuff was an attempt to make a triangular lifeform on a
171 hexagonal grid but I got bored. You may need an additional 7th
172 state for a coherent step by step process of cell separation and
173 initial stem development.
178 #define HEX_ADAM_SIZE 3 /* MIN 3 */
180 #define HEX_ADAM_SIZE 5 /* MIN 3 */
183 #define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
184 #define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
186 #define HEX_ADAM_LOOPX 3
187 #define HEX_ADAM_LOOPY 7
189 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
190 #define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6)))
191 #define NEIGHBORKINDS 2
193 #define MAXNEIGHBORS 6
195 /* Singly linked list */
196 typedef struct _CellList {
198 struct _CellList *next;
207 int bx, by, bnrows, bncols;
208 int mincol, minrow, maxcol, maxrow;
210 int redrawing, redrawpos;
211 Bool dead, clockwise;
212 unsigned char *newcells, *oldcells;
214 CellList *cellList[COLORS];
215 unsigned long colors[COLORS];
217 Pixmap pixmaps[COLORS];
223 static loopstruct *loops = (loopstruct *) NULL;
225 #define TRANSITION(TT,V) V=TT&7;TT>>=3
226 #define FINALTRANSITION(TT,V) V=TT&7
227 #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)])
228 #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)])
231 /* Instead of setting "unused" state rules to zero it randomizes them.
232 These rules take over when something unexpected happens... like when a
233 cell hits a wall (the end of the screen).
239 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\
240 (TABLE(R,T,L,B)|=((I)<<((C)*3)))
241 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\
242 (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
244 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)|=((I)<<((C)*3)))
245 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)|=((I)<<((C)*3)))
247 #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7)
248 #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7)
250 static unsigned int *table = (unsigned int *) NULL;
251 /* square: 8*8*8*8 = 2^12 = 2^3^4 = 4096 */
252 /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */
254 static char plots[NEIGHBORKINDS] =
256 4, 6 /* Neighborhoods */
259 static unsigned int transition_table[] =
260 { /* Octal CBLTR->I */
261 /* CBLTRI CBLTRI CBLTRI CBLTRI CBLTRI */
262 0000000, 0025271, 0113221, 0202422, 0301021,
263 0000012, 0100011, 0122244, 0202452, 0301220,
264 0000020, 0100061, 0122277, 0202520, 0302511,
265 0000030, 0100077, 0122434, 0202552, 0401120,
266 0000050, 0100111, 0122547, 0202622, 0401220,
267 0000063, 0100121, 0123244, 0202722, 0401250,
268 0000071, 0100211, 0123277, 0203122, 0402120,
269 0000112, 0100244, 0124255, 0203216, 0402221,
270 0000122, 0100277, 0124267, 0203226, 0402326,
271 0000132, 0100511, 0125275, 0203422, 0402520,
272 0000212, 0101011, 0200012, 0204222, 0403221,
273 0000220, 0101111, 0200022, 0205122, 0500022,
274 0000230, 0101244, 0200042, 0205212, 0500215,
275 0000262, 0101277, 0200071, 0205222, 0500225,
276 0000272, 0102026, 0200122, 0205521, 0500232,
277 0000320, 0102121, 0200152, 0205725, 0500272,
278 0000525, 0102211, 0200212, 0206222, 0500520,
279 0000622, 0102244, 0200222, 0206722, 0502022,
280 0000722, 0102263, 0200232, 0207122, 0502122,
281 0001022, 0102277, 0200242, 0207222, 0502152,
282 0001120, 0102327, 0200250, 0207422, 0502220,
283 0002020, 0102424, 0200262, 0207722, 0502244,
284 0002030, 0102626, 0200272, 0211222, 0502722,
285 0002050, 0102644, 0200326, 0211261, 0512122,
286 0002125, 0102677, 0200423, 0212222, 0512220,
287 0002220, 0102710, 0200517, 0212242, 0512422,
288 0002322, 0102727, 0200522, 0212262, 0512722,
289 0005222, 0105427, 0200575, 0212272, 0600011,
290 0012321, 0111121, 0200722, 0214222, 0600021,
291 0012421, 0111221, 0201022, 0215222, 0602120,
292 0012525, 0111244, 0201122, 0216222, 0612125,
293 0012621, 0111251, 0201222, 0217222, 0612131,
294 0012721, 0111261, 0201422, 0222272, 0612225,
295 0012751, 0111277, 0201722, 0222442, 0700077,
296 0014221, 0111522, 0202022, 0222462, 0701120,
297 0014321, 0112121, 0202032, 0222762, 0701220,
298 0014421, 0112221, 0202052, 0222772, 0701250,
299 0014721, 0112244, 0202073, 0300013, 0702120,
300 0016251, 0112251, 0202122, 0300022, 0702221,
301 0017221, 0112277, 0202152, 0300041, 0702251,
302 0017255, 0112321, 0202212, 0300076, 0702321,
303 0017521, 0112424, 0202222, 0300123, 0702525,
304 0017621, 0112621, 0202272, 0300421, 0702720,
305 0017721, 0112727, 0202321, 0300622
308 static unsigned int hex_transition_table[] =
309 { /* Octal CBbltTR->I */
310 /* CBbltTRI CBbltTRI CBbltTRI CBbltTRI CBbltTRI */
313 000000000, 000000020, 000000220, 000002220, 000022220,
314 011122121, 011121221, 011122221, 011221221,
315 011222221, 011112121, 011112221,
316 020021122, 020002122, 020211222, 021111222,
317 020221122, 020027122, 020020722, 020021022,
319 011122727, 011227227, 010122121, 010222211,
320 021117222, 020112272,
323 010221121, 011721221, 011222277,
324 020111222, 020221172,
327 010212277, 010221221,
332 020002022, 021122172,
334 011122277, 011172121,
335 010212177, 011212277,
339 070121270, 070721220,
340 000112721, 000272211,
341 010022211, 012222277,
342 020072272, 020227122, 020217222,
347 020021072, 020070722,
348 070002072, 070007022,
351 000000070, 000000770, 000072220, 000000270,
352 020110222, 020220272, 020220722,
353 070007071, 070002072, 070007022,
354 000000012, 000000122, 000000212, 001277721,
355 020122072, 020202212,
357 020001122, 020002112,
359 020122022, 020027022, 020070122, 020020122,
362 010227227, 010227277,
369 010022277, 010202177, 010227127,
373 020024122, 020020422,
376 010221241, 010224224,
381 020112242, 021422172,
383 001224221, 001427221,
388 010022244, 010202144, 010224124,
392 040121240, 040421220,
393 000242211, 000112421,
394 020042242, 020214222, 020021422, 020220242, 020024022,
401 001244421, 000000420, 000000440, 000000240, 000000040,
402 020040121, 020021042,
403 040004022, 040004042, 040002042,
405 020011122, 020002112,
412 020224072, 021417222,
418 070207072, 070701220,
423 020021222, 020202272, 020120222, 020221722,
427 020101272, 020272172, 020721422, 020721722,
428 020011222, 020202242,
446 000000000, 000000020, 000000220, 000002220,
447 011212121, 011212221, 011221221, 011222221,
448 020002122, 020021122, 020211122,
450 010221221, 010222121,
451 020002022, 020021022, 020020122, 020112022,
454 020102022, 020202112,
456 000000012, 000000122, 000000212,
458 020001122, 020002112, 020011122,
461 001227221, 001272221, 001272721,
462 012212277, 011222727, 011212727,
463 020021722, 020027122, 020020722, 020027022,
464 020211722, 020202172, 020120272,
465 020271122, 020202172, 020207122, 020217122,
466 020120272, 020210722, 020270722,
467 070212220, 070221220, 070212120,
474 001277721, 000000070, 000000270, 000000720, 000000770,
475 020070122, 020021072,
476 070002072, 070007022, 070007071,
481 010227227, 010222727, 010202727,
482 020172022, 020202712,
484 001224221, 001242221, 001242421,
485 012212244, 011222424, 011212424,
486 020021422, 020024122, 020020422, 020024022,
487 020211422, 020202142, 020120242,
488 020241122, 020202142, 020204122, 020214122,
489 020120242, 020210422, 020240422,
490 040212220, 040221220, 040212120,
497 001244421, 000000040, 000000240, 000000420, 000000440,
498 020040122, 020021042,
500 040004021, 040004042,
505 010224224, 010222424, 010202424,
506 020142022, 020202412,
507 020011722, 020112072, 020172072, 020142072,
511 000210225, 000022015, 000022522,
513 020120525, 020020152, 020005122, 020214255, 020021152,
515 050215222, 050225121,
517 000225220, 001254222,
518 010221250, 011221251, 011225221,
519 020025122, 020152152, 020211252, 020214522, 020511125,
523 000000250, 000000520, 000150220, 000220520, 000222210,
525 010022152, 010251221, 010522121, 011212151, 011221251,
527 020000220, 020002152, 020020220, 020022152,
528 020021422, 020022152, 020022522, 020025425, 020050422,
529 020051022, 020051122, 020211122, 020211222, 020215222,
531 050021125, 050021025, 050011125, 051242221,
534 000220250, 000220520, 001227521, 001275221,
535 011257227, 011522727,
536 020002052, 020002752, 020021052, 020057125,
537 050020722, 050027125,
632 000000050, 000005220, 000002270, 070252220,
633 000000450, 000007220,
634 000220220, 000202220, 000022020, 000020220,
642 050221120, 010221520,
645 000070220, 000220720,
646 000020520, 000070250, 000222070, 000027020,
647 000022070, 000202270, 000024020, 000220420,
648 000220270, 000220240, 000072020, 000042020,
649 000002020, 000002070, 000020270, 000020250,
650 000270270, 000007020, 000040270,
652 /* Collision starts (gen 540), not sure to have rules to save it
653 or depend on calloc to intialize remaining rules to 0 so that
654 the mutant will be born
662 Neighborhoods are read as follows (rotations are not listed):
672 static unsigned char self_reproducing_loop[ADAM_LOOPY][ADAM_LOOPX] =
675 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0},
676 {2, 4, 0, 1, 4, 0, 1, 1, 1, 2},
677 {2, 1, 2, 2, 2, 2, 2, 2, 1, 2},
678 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
679 {2, 7, 2, 0, 0, 0, 0, 2, 7, 2},
680 {2, 1, 2, 0, 0, 0, 0, 2, 0, 2},
681 {2, 0, 2, 0, 0, 0, 0, 2, 1, 2},
682 {2, 7, 2, 2, 2, 2, 2, 2, 7, 2},
683 {2, 1, 0, 6, 1, 0, 7, 1, 0, 2},
684 {0, 2, 2, 2, 2, 2, 2, 2, 2, 0}
687 static unsigned char hex_self_reproducing_loop[HEX_ADAM_LOOPY][HEX_ADAM_LOOPX] =
690 /* Experimental TRIA5:7x7 */
698 /* Stem cells, only "5" will fully reproduce itself */
700 {2,2,2,2,0,0,0,0,0,0,0,0},
701 {2,1,1,1,2,0,0,0,0,0,0,0},
702 {2,1,2,2,1,2,2,2,2,2,2,0},
703 {2,1,2,0,2,7,1,1,1,1,1,2},
704 {0,2,1,2,2,0,2,2,2,2,2,2},
705 {0,0,2,0,4,1,2,0,0,0,0,0},
706 {0,0,0,2,2,2,2,0,0,0,0,0}
708 {2,2,2,2,2,0,0,0,0,0,0,0,0,0},
709 {2,1,1,1,1,2,0,0,0,0,0,0,0,0},
710 {2,1,2,2,2,1,2,0,0,0,0,0,0,0},
711 {2,1,2,0,0,2,1,2,2,2,2,2,2,0},
712 {2,1,2,0,0,0,2,7,1,1,1,1,1,2},
713 {0,2,1,2,0,0,2,0,2,2,2,2,2,2},
714 {0,0,2,0,2,2,2,1,2,0,0,0,0,0},
715 {0,0,0,2,4,1,0,7,2,0,0,0,0,0},
716 {0,0,0,0,2,2,2,2,2,0,0,0,0,0}
718 {2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0},
719 {2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0},
720 {2,1,2,2,2,2,1,2,0,0,0,0,0,0,0,0},
721 {2,1,2,0,0,0,2,1,2,0,0,0,0,0,0,0},
722 {2,1,2,0,0,0,0,2,1,2,2,2,2,2,2,0},
723 {2,1,2,0,0,0,0,0,2,7,1,1,1,1,1,2},
724 {0,2,1,2,0,0,0,0,2,0,2,2,2,2,2,2},
725 {0,0,2,0,2,0,0,0,2,1,2,0,0,0,0,0},
726 {0,0,0,2,4,2,2,2,2,7,2,0,0,0,0,0},
727 {0,0,0,0,2,1,0,7,1,0,2,0,0,0,0,0},
728 {0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0}
729 /* test:3x7 (0,4) is blank ... very strange.
730 init_adam seems ok something after that I guess */
738 #else /* this might be better for hexagons, spacewise efficient... */
740 /* Experimental TRIA5:7x7 */
750 {2,2,2,2,2,2,0,0,0,0,0},
751 {2,1,1,7,0,1,2,0,0,0,0},
752 {2,1,2,2,2,2,7,2,0,0,0},
753 {2,1,2,0,0,0,2,0,2,0,0},
754 {2,1,2,0,0,0,0,2,1,2,0},
755 {2,1,2,0,0,0,0,0,2,7,2},
756 {0,2,1,2,0,0,0,0,2,0,2},
757 {0,0,2,1,2,0,0,0,2,1,2},
758 {0,0,0,2,1,2,2,2,2,4,2},
759 {0,0,0,0,2,1,1,1,1,5,2},
760 {0,0,0,0,0,2,2,2,2,2,2}
766 position_of_neighbor(int dir, int *pcol, int *prow)
768 int col = *pcol, row = *prow;
772 if (local_neighbors == 6) {
797 (void) fprintf(stderr, "wrong direction %d\n", dir);
814 (void) fprintf(stderr, "wrong direction %d\n", dir);
822 withinBounds(loopstruct * lp, int col, int row)
824 return (row >= 1 && row < lp->bnrows - 1 &&
825 col >= 1 && col < lp->bncols - 1 - (local_neighbors == 6 && (row % 2)));
829 fillcell(ModeInfo * mi, GC gc, int col, int row)
831 loopstruct *lp = &loops[MI_SCREEN(mi)];
833 if (local_neighbors == 6) {
834 int ccol = 2 * col + !(row & 1), crow = 2 * row;
836 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
837 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
838 if (lp->xs == 1 && lp->ys == 1)
839 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
840 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
842 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
843 lp->shape.hexagon, 6, Convex, CoordModePrevious);
845 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
846 lp->xb + lp->xs * col, lp->yb + lp->ys * row,
847 lp->xs - (lp->xs > 3), lp->ys - (lp->ys > 3));
852 drawcell(ModeInfo * mi, int col, int row, int state)
854 loopstruct *lp = &loops[MI_SCREEN(mi)];
858 if (MI_NPIXELS(mi) >= COLORS) {
860 XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]);
862 gcv.stipple = lp->pixmaps[state];
863 gcv.foreground = MI_WHITE_PIXEL(mi);
864 gcv.background = MI_BLACK_PIXEL(mi);
865 XChangeGC(MI_DISPLAY(mi), lp->stippledGC,
866 GCStipple | GCForeground | GCBackground, &gcv);
869 fillcell(mi, gc, col, row);
874 print_state(ModeInfo * mi, int state)
876 loopstruct *lp = &loops[MI_SCREEN(mi)];
877 CellList *locallist = lp->cellList[state];
880 (void) printf("state %d\n", state);
882 (void) printf("%d x %d, y %d\n", i,
883 locallist->pt.x, locallist->pt.y);
884 locallist = locallist->next;
892 free_state(loopstruct * lp, int state)
896 while (lp->cellList[state]) {
897 current = lp->cellList[state];
898 lp->cellList[state] = lp->cellList[state]->next;
899 (void) free((void *) current);
901 lp->ncells[state] = 0;
905 free_list(loopstruct * lp)
909 for (state = 0; state < COLORS; state++)
910 free_state(lp, state);
914 free_loop(Display *display, loopstruct * lp)
918 for (shade = 0; shade < lp->init_bits; shade++)
919 if (lp->pixmaps[shade] != None) {
920 XFreePixmap(display, lp->pixmaps[shade]);
921 lp->pixmaps[shade] = None;
923 if (lp->stippledGC != None) {
924 XFreeGC(display, lp->stippledGC);
925 lp->stippledGC = None;
927 if (lp->oldcells != NULL) {
928 (void) free((void *) lp->oldcells);
929 lp->oldcells = (unsigned char *) NULL;
931 if (lp->newcells != NULL) {
932 (void) free((void *) lp->newcells);
933 lp->newcells = (unsigned char *) NULL;
939 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
941 loopstruct *lp = &loops[MI_SCREEN(mi)];
942 CellList *current = lp->cellList[state];
944 if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
946 lp->cellList[state] = current;
947 free_loop(MI_DISPLAY(mi), lp);
950 lp->cellList[state]->pt.x = col;
951 lp->cellList[state]->pt.y = row;
952 lp->cellList[state]->next = current;
958 draw_state(ModeInfo * mi, int state)
960 loopstruct *lp = &loops[MI_SCREEN(mi)];
961 Display *display = MI_DISPLAY(mi);
964 CellList *current = lp->cellList[state];
966 if (MI_NPIXELS(mi) >= COLORS) {
968 XSetForeground(display, gc, lp->colors[state]);
970 gcv.stipple = lp->pixmaps[state];
971 gcv.foreground = MI_WHITE_PIXEL(mi);
972 gcv.background = MI_BLACK_PIXEL(mi);
973 XChangeGC(display, lp->stippledGC,
974 GCStipple | GCForeground | GCBackground, &gcv);
978 if (local_neighbors == 6) { /* Draw right away, slow */
980 int col, row, ccol, crow;
984 ccol = 2 * col + !(row & 1), crow = 2 * row;
985 lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
986 lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
987 if (lp->xs == 1 && lp->ys == 1)
988 XDrawPoint(display, MI_WINDOW(mi), gc,
989 lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
991 XFillPolygon(display, MI_WINDOW(mi), gc,
992 lp->shape.hexagon, 6, Convex, CoordModePrevious);
993 current = current->next;
996 /* Take advantage of XFillRectangles */
1000 /* Create Rectangle list from part of the cellList */
1001 if ((rects = (XRectangle *) malloc(lp->ncells[state] *
1002 sizeof (XRectangle))) == NULL) {
1007 rects[nrects].x = lp->xb + current->pt.x * lp->xs;
1008 rects[nrects].y = lp->yb + current->pt.y * lp->ys;
1009 rects[nrects].width = lp->xs - (lp->xs > 3);
1010 rects[nrects].height = lp->ys - (lp->ys > 3);
1011 current = current->next;
1014 /* Finally get to draw */
1015 XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
1016 /* Free up rects list and the appropriate part of the cellList */
1017 (void) free((void *) rects);
1019 free_state(lp, state);
1027 if (table == NULL) {
1029 unsigned int tt, c, n[MAXNEIGHBORS], i;
1031 int size_transition_table = sizeof (transition_table) /
1032 sizeof (unsigned int);
1033 int size_hex_transition_table = sizeof (hex_transition_table) /
1034 sizeof (unsigned int);
1036 for (j = 0; j < local_neighbors; j++)
1039 if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
1045 /* Here I was interested to see what happens when it hits a wall....
1046 Rules not normally used take over... takes too much time though */
1047 /* Each state = 3 bits */
1048 if (MAXRAND < 16777216.0) {
1049 for (j = 0; j < mult; j++) {
1050 table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
1053 for (j = 0; j < mult; j++) {
1054 table[j] = (unsigned int) (NRAND(16777216));
1058 if (local_neighbors == 6) {
1059 for (j = 0; j < size_hex_transition_table; j++) {
1060 tt = hex_transition_table[j];
1062 for (k = 0; k < local_neighbors; k++) {
1063 TRANSITION(tt, n[k]);
1065 FINALTRANSITION(tt, c);
1066 HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
1067 HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
1068 HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
1069 HEX_TABLE_IN(c, n[3], n[4], n[5], n[0], n[1], n[2], i);
1070 HEX_TABLE_IN(c, n[4], n[5], n[0], n[1], n[2], n[3], i);
1071 HEX_TABLE_IN(c, n[5], n[0], n[1], n[2], n[3], n[4], i);
1074 for (j = 0; j < size_transition_table; j++) {
1075 tt = transition_table[j];
1077 for (k = 0; k < local_neighbors; k++) {
1078 TRANSITION(tt, n[k]);
1080 FINALTRANSITION(tt, c);
1081 TABLE_IN(c, n[0], n[1], n[2], n[3], i);
1082 TABLE_IN(c, n[1], n[2], n[3], n[0], i);
1083 TABLE_IN(c, n[2], n[3], n[0], n[1], i);
1084 TABLE_IN(c, n[3], n[0], n[1], n[2], i);
1092 init_flaw(ModeInfo * mi)
1094 loopstruct *lp = &loops[MI_SCREEN(mi)];
1098 if (lp->bncols <= 3 || lp->bnrows <= 3)
1100 a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
1101 HEX_MINGRIDSIZE : MINGRIDSIZE));
1102 a = NRAND(a) + (lp->bncols - a) / 2;
1103 b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
1104 HEX_MINGRIDSIZE : MINGRIDSIZE));
1105 b = NRAND(b) + (lp->bnrows - b) / 2;
1110 if (lp->maxcol < a + 2)
1112 if (lp->maxrow < b + 2)
1115 if (local_neighbors == 6) {
1116 lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
1117 lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1118 lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
1119 lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
1120 lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
1121 lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
1123 int orient = NRAND(4);
1124 lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
1125 if (orient == 0 || orient == 1) {
1126 lp->newcells[lp->bncols * b + a + 1] = BLUE;
1128 if (orient == 1 || orient == 2) {
1129 lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
1131 if (orient == 2 || orient == 3) {
1132 lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
1134 if (orient == 3 || orient == 0) {
1135 lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
1141 init_adam(ModeInfo * mi)
1143 loopstruct *lp = &loops[MI_SCREEN(mi)];
1144 XPoint start, dirx, diry;
1147 #ifdef DELAYDEBUGLOOP
1149 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1151 lp->clockwise = (Bool) (LRAND() & 1);
1152 #ifdef DELAYDEBUGLOOP
1154 if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
1156 dir = NRAND(local_neighbors);
1157 if (local_neighbors == 6) {
1162 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1163 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1164 if (lp->mincol > start.x - 2)
1165 lp->mincol = start.x - 2;
1166 if (lp->minrow > start.y - 1)
1167 lp->minrow = start.y - 1;
1168 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1169 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1170 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1171 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1172 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1173 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1174 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1175 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1177 hex_self_reproducing_loop[i][j] :
1178 hex_self_reproducing_loop[j][i];
1183 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1184 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1185 if (lp->mincol > start.x - 1)
1186 lp->mincol = start.x - 1;
1187 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1188 lp->minrow = start.y - HEX_ADAM_LOOPX;
1189 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1190 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1191 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1192 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1193 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1194 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1195 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1196 ? -(i + j + 1) / 2 : -(i + j) / 2);
1197 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1199 hex_self_reproducing_loop[i][j] :
1200 hex_self_reproducing_loop[j][i];
1205 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1206 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1207 if (lp->mincol > start.x - 2)
1208 lp->mincol = start.x - 2;
1209 if (lp->minrow > start.y - 1)
1210 lp->minrow = start.y - 1;
1211 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1212 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1213 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1214 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1215 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1216 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1217 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1218 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1220 hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
1221 hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
1226 start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
1227 start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
1228 if (lp->mincol > start.x - 1)
1229 lp->mincol = start.x - 1;
1230 if (lp->minrow > start.y - 1)
1231 lp->minrow = start.y - 1;
1232 if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
1233 lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
1234 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1235 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1236 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1237 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1238 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
1239 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1241 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1242 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1247 start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
1248 start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
1249 if (lp->mincol > start.x - 1)
1250 lp->mincol = start.x - 1;
1251 if (lp->minrow > start.y - HEX_ADAM_LOOPX)
1252 lp->minrow = start.y - HEX_ADAM_LOOPX;
1253 if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
1254 lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
1255 if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
1256 lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
1257 for (j = 0; j < HEX_ADAM_LOOPY; j++) {
1258 for (i = 0; i < HEX_ADAM_LOOPX; i++) {
1259 k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
1260 ? -(i + j + 1) / 2 : -(i + j) / 2);
1261 lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
1263 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
1264 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
1269 start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
1270 start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
1271 if (lp->mincol > start.x - 2)
1272 lp->mincol = start.x - 2;
1273 if (lp->minrow > start.y - 1)
1274 lp->minrow = start.y - 1;
1275 if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
1276 lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
1277 if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
1278 lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
1279 for (j = 0; j < HEX_ADAM_LOOPX; j++) {
1280 for (i = 0; i < HEX_ADAM_LOOPY; i++) {
1281 k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
1282 lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
1284 hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
1285 hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
1291 /* (void) printf ("s %d s %d \n", start.x, start.y); */
1292 (void) printf ("%d %d %d %d %d\n",
1293 start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1294 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
1295 /* Draw right away */
1296 drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
1297 start.y + j - lp->by,
1298 hex_self_reproducing_loop[j][i]);
1303 start.x = (lp->bncols - ADAM_LOOPX) / 2;
1304 start.y = (lp->bnrows - ADAM_LOOPY) / 2;
1305 dirx.x = 1, dirx.y = 0;
1306 diry.x = 0, diry.y = 1;
1307 if (lp->mincol > start.x)
1308 lp->mincol = start.x;
1309 if (lp->minrow > start.y)
1310 lp->minrow = start.y;
1311 if (lp->maxcol < start.x + ADAM_LOOPX)
1312 lp->maxcol = start.x + ADAM_LOOPX;
1313 if (lp->maxrow < start.y + ADAM_LOOPY)
1314 lp->maxrow = start.y + ADAM_LOOPY;
1317 start.x = (lp->bncols + ADAM_LOOPY) / 2;
1318 start.y = (lp->bnrows - ADAM_LOOPX) / 2;
1319 dirx.x = 0, dirx.y = 1;
1320 diry.x = -1, diry.y = 0;
1321 if (lp->mincol > start.x - ADAM_LOOPY)
1322 lp->mincol = start.x - ADAM_LOOPY;
1323 if (lp->minrow > start.y)
1324 lp->minrow = start.y;
1325 if (lp->maxcol < start.x)
1326 lp->maxcol = start.x;
1327 if (lp->maxrow < start.y + ADAM_LOOPX)
1328 lp->maxrow = start.y + ADAM_LOOPX;
1331 start.x = (lp->bncols + ADAM_LOOPX) / 2;
1332 start.y = (lp->bnrows + ADAM_LOOPY) / 2;
1333 dirx.x = -1, dirx.y = 0;
1334 diry.x = 0, diry.y = -1;
1335 if (lp->mincol > start.x - ADAM_LOOPX)
1336 lp->mincol = start.x - ADAM_LOOPX;
1337 if (lp->minrow > start.y - ADAM_LOOPY)
1338 lp->minrow = start.y - ADAM_LOOPY;
1339 if (lp->maxcol < start.x)
1340 lp->maxcol = start.x;
1341 if (lp->maxrow < start.y)
1342 lp->maxrow = start.y;
1345 start.x = (lp->bncols - ADAM_LOOPY) / 2;
1346 start.y = (lp->bnrows + ADAM_LOOPX) / 2;
1347 dirx.x = 0, dirx.y = -1;
1348 diry.x = 1, diry.y = 0;
1349 if (lp->mincol > start.x)
1350 lp->mincol = start.x;
1351 if (lp->minrow > start.y - ADAM_LOOPX)
1352 lp->minrow = start.y - ADAM_LOOPX;
1353 if (lp->maxcol < start.x + ADAM_LOOPX)
1354 lp->maxcol = start.x + ADAM_LOOPX;
1355 if (lp->maxrow < start.y)
1356 lp->maxrow = start.y;
1359 for (j = 0; j < ADAM_LOOPY; j++)
1360 for (i = 0; i < ADAM_LOOPX; i++)
1361 lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
1362 start.x + dirx.x * i + diry.x * j] =
1364 self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
1365 self_reproducing_loop[j][i];
1367 /* Draw right away */
1368 drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
1369 start.y + dirx.y * i + diry.y * j - lp->by,
1370 (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
1377 do_gen(loopstruct * lp)
1381 unsigned int n[MAXNEIGHBORS];
1384 #define LOC(X, Y) (*(lp->oldcells + (X) + ((Y) * lp->bncols)))
1386 for (j = lp->minrow; j <= lp->maxrow; j++) {
1387 for (i = lp->mincol; i <= lp->maxcol; i++) {
1388 z = lp->newcells + i + j * lp->bncols;
1390 for (k = 0; k < local_neighbors; k++) {
1391 int newi = i, newj = j;
1393 position_of_neighbor(k * ANGLES / local_neighbors, &newi, &newj);
1395 if (withinBounds(lp, newi, newj)) {
1396 n[k] = LOC(newi, newj);
1399 if (local_neighbors == 6) {
1400 *z = (lp->clockwise) ?
1401 HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
1402 HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
1404 *z = (lp->clockwise) ?
1405 TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
1406 TABLE_OUT(c, n[0], n[1], n[2], n[3]);
1413 release_loop(ModeInfo * mi)
1415 if (loops != NULL) {
1418 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1419 free_loop(MI_DISPLAY(mi), &loops[screen]);
1420 (void) free((void *) loops);
1421 loops = (loopstruct *) NULL;
1423 if (table != NULL) {
1424 (void) free((void *) table);
1425 table = (unsigned int *) NULL;
1430 init_loop(ModeInfo * mi)
1432 Display *display = MI_DISPLAY(mi);
1433 Window window = MI_WINDOW(mi);
1434 int i, size = MI_SIZE(mi);
1438 if (loops == NULL) {
1439 if ((loops = (loopstruct *) calloc(MI_NUM_SCREENS(mi),
1440 sizeof (loopstruct))) == NULL)
1443 lp = &loops[MI_SCREEN(mi)];
1447 if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
1448 if (lp->stippledGC == None) {
1449 gcv.fill_style = FillOpaqueStippled;
1450 if ((lp->stippledGC = XCreateGC(display, window,
1451 GCFillStyle, &gcv)) == None) {
1452 free_loop(display, lp);
1456 LOOPBITS(stipples[0], STIPPLESIZE, STIPPLESIZE);
1457 LOOPBITS(stipples[2], STIPPLESIZE, STIPPLESIZE);
1458 LOOPBITS(stipples[3], STIPPLESIZE, STIPPLESIZE);
1459 LOOPBITS(stipples[4], STIPPLESIZE, STIPPLESIZE);
1460 LOOPBITS(stipples[6], STIPPLESIZE, STIPPLESIZE);
1461 LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
1462 LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
1463 LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
1465 if (MI_NPIXELS(mi) >= COLORS) {
1466 /* Maybe these colors should be randomized */
1467 lp->colors[0] = MI_BLACK_PIXEL(mi);
1468 lp->colors[1] = MI_PIXEL(mi, 0); /* RED */
1469 lp->colors[5] = MI_PIXEL(mi, MI_NPIXELS(mi) / REALCOLORS); /* YELLOW */
1470 lp->colors[4] = MI_PIXEL(mi, 2 * MI_NPIXELS(mi) / REALCOLORS); /* GREEN */
1471 lp->colors[6] = MI_PIXEL(mi, 3 * MI_NPIXELS(mi) / REALCOLORS); /* CYAN */
1472 lp->colors[2] = MI_PIXEL(mi, 4 * MI_NPIXELS(mi) / REALCOLORS); /* BLUE */
1473 lp->colors[3] = MI_PIXEL(mi, 5 * MI_NPIXELS(mi) / REALCOLORS); /* MAGENTA */
1474 lp->colors[7] = MI_WHITE_PIXEL(mi);
1478 lp->width = MI_WIDTH(mi);
1479 lp->height = MI_HEIGHT(mi);
1481 if (!local_neighbors) {
1482 for (i = 0; i < NEIGHBORKINDS; i++) {
1483 if (neighbors == plots[i]) {
1484 local_neighbors = neighbors;
1487 if (i == NEIGHBORKINDS - 1) {
1489 local_neighbors = plots[NRAND(NEIGHBORKINDS)];
1491 local_neighbors = 4;
1499 if (local_neighbors == 6) {
1506 if (size < -MINSIZE) {
1507 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1508 HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1509 } else if (size < MINSIZE) {
1511 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / HEX_MINGRIDSIZE);
1515 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1518 nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
1519 ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
1520 lp->ncols = nccols / 2;
1521 lp->nrows = ncrows / 2;
1522 lp->nrows -= !(lp->nrows & 1); /* Must be odd */
1523 lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
1524 lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
1525 for (i = 0; i < 6; i++) {
1526 lp->shape.hexagon[i].x = (lp->xs - 1) * hexagonUnit[i].x;
1527 lp->shape.hexagon[i].y = ((lp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
1530 if (size < -MINSIZE)
1531 lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1532 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
1533 else if (size < MINSIZE) {
1535 lp->ys = MAX(MINSIZE, MIN(lp->width, lp->height) / MINGRIDSIZE);
1539 lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
1542 lp->ncols = MAX(lp->width / lp->xs, ADAM_LOOPX + 1);
1543 lp->nrows = MAX(lp->height / lp->ys, ADAM_LOOPX + 1);
1544 lp->xb = (lp->width - lp->xs * lp->ncols) / 2;
1545 lp->yb = (lp->height - lp->ys * lp->nrows) / 2;
1549 lp->bncols = lp->ncols + 2 * lp->bx;
1550 lp->bnrows = lp->nrows + 2 * lp->by;
1554 if (lp->oldcells != NULL) {
1555 (void) free((void *) lp->oldcells);
1556 lp->oldcells = (unsigned char *) NULL;
1558 if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1559 sizeof (unsigned char))) == NULL) {
1560 free_loop(display, lp);
1563 if (lp->newcells != NULL) {
1564 (void) free((void *) lp->newcells);
1565 lp->newcells = (unsigned char *) NULL;
1567 if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
1568 sizeof (unsigned char))) == NULL) {
1569 free_loop(display, lp);
1572 if (!init_table()) {
1576 lp->mincol = lp->bncols - 1;
1577 lp->minrow = lp->bnrows - 1;
1580 #ifndef DELAYDEBUGLOOP
1582 int flaws = MI_COUNT(mi);
1585 flaws = NRAND(-MI_COUNT(mi) + 1);
1586 for (i = 0; i < flaws; i++) {
1589 /* actual flaws might be less since the adam loop done next */
1596 draw_loop(ModeInfo * mi)
1599 unsigned char *z, *znew;
1604 lp = &loops[MI_SCREEN(mi)];
1605 if (lp->newcells == NULL)
1608 MI_IS_DRAWN(mi) = True;
1610 #ifdef DELAYDEBUGLOOP
1611 if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
1612 (void) sleep(DELAYDEBUGLOOP);
1616 for (j = lp->minrow; j <= lp->maxrow; j++) {
1617 for (i = lp->mincol; i <= lp->maxcol; i++) {
1618 offset = j * lp->bncols + i;
1619 z = lp->oldcells + offset;
1620 znew = lp->newcells + offset;
1624 if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
1626 if (i == lp->mincol && i > lp->bx)
1628 if (j == lp->minrow && j > lp->by)
1630 if (i == lp->maxcol && i < lp->bncols - 2 * lp->bx)
1632 if (j == lp->maxrow && j < lp->bnrows - 2 * lp->by)
1637 for (i = 0; i < COLORS; i++)
1638 if (!draw_state(mi, i)) {
1639 free_loop(MI_DISPLAY(mi), lp);
1642 if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
1648 if (lp->redrawing) {
1649 for (i = 0; i < REDRAWSTEP; i++) {
1650 if ((*(lp->oldcells + lp->redrawpos))) {
1651 drawcell(mi, lp->redrawpos % lp->bncols - lp->bx,
1652 lp->redrawpos / lp->bncols - lp->by,
1653 *(lp->oldcells + lp->redrawpos));
1655 if (++(lp->redrawpos) >= lp->bncols * (lp->bnrows - lp->bx)) {
1664 refresh_loop(ModeInfo * mi)
1670 lp = &loops[MI_SCREEN(mi)];
1674 lp->redrawpos = lp->by * lp->ncols + lp->bx;
1677 #endif /* MODE_loop */