1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* demon --- David Griffeath's cellular automata */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)demon.c 5.00 2000/11/01 xlockmore";
10 * Copyright (c) 1995 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 * 01-Nov-2000: Allocation checks
26 * 10-May-1997: Compatible with xscreensaver
27 * 16-Apr-1997: -neighbors 3, 9 (not sound mathematically), 12, and 8 added
28 * 30-May-1996: Ron Hitchens <ron@idiom.com>
29 * Fixed memory management that caused leaks
30 * 14-Apr-1996: -neighbors 6 runtime-time option added
31 * 21-Aug-1995: Coded from A.K. Dewdney's "Computer Recreations", Scientific
32 * American Magazine" Aug 1989 pp 102-105. Also very similar
33 * to hodgepodge machine described in A.K. Dewdney's "Computer
34 * Recreations", Scientific American Magazine" Aug 1988
35 * pp 104-107. Also used life.c as a guide.
39 * A cellular universe of 4 phases debris, droplets, defects, and demons.
43 Grid Number of Neighbors
44 ---- ------------------
52 #define PROGCLASS "Demon"
53 #define HACK_INIT init_demon
54 #define HACK_DRAW draw_demon
55 #define demon_opts xlockmore_opts
56 #define DEFAULTS "*delay: 50000 \n" \
62 #define UNIFORM_COLORS
63 #include "xlockmore.h" /* in xscreensaver distribution */
64 #else /* STANDALONE */
65 #include "xlock.h" /* in xlockmore distribution */
67 #endif /* STANDALONE */
73 * neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12.
75 #define DEF_NEIGHBORS "0" /* choose random value */
79 static XrmOptionDescRec opts[] =
81 {(char *) "-neighbors", (char *) ".demon.neighbors", XrmoptionSepArg, (caddr_t) NULL}
84 static argtype vars[] =
86 {(caddr_t *) & neighbors, (char *) "neighbors", (char *) "Neighbors", (char *) DEF_NEIGHBORS, t_Int}
88 static OptionStruct desc[] =
90 {(char *) "-neighbors num", (char *) "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"}
93 ModeSpecOpt demon_opts =
94 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
97 ModStruct demon_description =
98 {"demon", "init_demon", "draw_demon", "release_demon",
99 "refresh_demon", "init_demon", (char *) NULL, &demon_opts,
100 50000, 0, 1000, -7, 64, 1.0, "",
101 "Shows Griffeath's cellular automata", 0, NULL};
105 #define DEMONBITS(n,w,h)\
106 if ((dp->pixmaps[dp->init_bits]=\
107 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
108 free_demon(display,dp); return;} else {dp->init_bits++;}
110 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
112 #define MINGRIDSIZE 24
114 #define NEIGHBORKINDS 6
116 /* Singly linked list */
117 typedef struct _CellList {
119 struct _CellList *next;
130 int redrawing, redrawpos;
133 unsigned char *oldcell, *newcell;
137 Pixmap pixmaps[NUMSTIPPLES - 1];
140 XPoint triangle[2][3];
144 static char plots[2][NEIGHBORKINDS] =
146 {3, 4, 6, 8, 9, 12}, /* Neighborhoods */
147 {12, 16, 18, 20, 22, 24} /* Number of states */
150 static demonstruct *demons = (demonstruct *) NULL;
153 drawcell(ModeInfo * mi, int col, int row, unsigned char state)
155 demonstruct *dp = &demons[MI_SCREEN(mi)];
159 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
161 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
162 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
163 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
164 (dp->states - 1)) % MI_NPIXELS(mi)));
169 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
170 gcv.foreground = MI_WHITE_PIXEL(mi);
171 gcv.background = MI_BLACK_PIXEL(mi);
172 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
173 GCStipple | GCForeground | GCBackground, &gcv);
176 if (dp->neighbors == 6) {
177 int ccol = 2 * col + !(row & 1), crow = 2 * row;
179 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
180 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
181 if (dp->xs == 1 && dp->ys == 1)
182 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
183 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
185 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
186 dp->shape.hexagon, 6, Convex, CoordModePrevious);
187 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
188 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
189 dp->xb + dp->xs * col, dp->yb + dp->ys * row,
190 dp->xs - (dp->xs > 3), dp->ys - (dp->ys > 3));
192 int orient = (col + row) % 2; /* O left 1 right */
194 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
195 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
196 if (dp->xs <= 3 || dp->ys <= 3)
197 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
198 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
199 dp->shape.triangle[orient][0].y);
202 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
204 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
205 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
206 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
213 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
215 demonstruct *dp = &demons[MI_SCREEN(mi)];
218 current = dp->cellList[state];
219 if ((dp->cellList[state] = (CellList *)
220 malloc(sizeof (CellList))) == NULL) {
223 dp->cellList[state]->pt.x = col;
224 dp->cellList[state]->pt.y = row;
225 dp->cellList[state]->next = current;
232 print_state(ModeInfo * mi, int state)
234 demonstruct *dp = &demons[MI_SCREEN(mi)];
238 locallist = dp->cellList[state];
239 (void) printf("state %d\n", state);
241 (void) printf("%d x %d, y %d\n", i,
242 locallist->pt.x, locallist->pt.y);
243 locallist = locallist->next;
251 free_state(demonstruct * dp, int state)
255 while (dp->cellList[state]) {
256 current = dp->cellList[state];
257 dp->cellList[state] = dp->cellList[state]->next;
258 (void) free((void *) current);
260 dp->cellList[state] = (CellList *) NULL;
261 if (dp->ncells != NULL)
262 dp->ncells[state] = 0;
267 free_list(demonstruct * dp)
271 for (state = 0; state < dp->states; state++)
272 free_state(dp, state);
273 (void) free((void *) dp->cellList);
274 dp->cellList = (CellList **) NULL;
278 free_struct(demonstruct * dp)
280 if (dp->cellList != NULL) {
283 if (dp->ncells != NULL) {
284 (void) free((void *) dp->ncells);
285 dp->ncells = (int *) NULL;
287 if (dp->oldcell != NULL) {
288 (void) free((void *) dp->oldcell);
289 dp->oldcell = (unsigned char *) NULL;
291 if (dp->newcell != NULL) {
292 (void) free((void *) dp->newcell);
293 dp->newcell = (unsigned char *) NULL;
298 free_demon(Display *display, demonstruct *dp)
302 if (dp->stippledGC != None) {
303 XFreeGC(display, dp->stippledGC);
304 dp->stippledGC = None;
306 for (shade = 0; shade < dp->init_bits; shade++) {
307 XFreePixmap(display, dp->pixmaps[shade]);
314 draw_state(ModeInfo * mi, int state)
316 demonstruct *dp = &demons[MI_SCREEN(mi)];
322 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
324 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
325 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
326 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
327 (dp->states - 1)) % MI_NPIXELS(mi)));
332 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
333 gcv.foreground = MI_WHITE_PIXEL(mi);
334 gcv.background = MI_BLACK_PIXEL(mi);
335 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
336 GCStipple | GCForeground | GCBackground, &gcv);
339 if (dp->neighbors == 6) { /* Draw right away, slow */
340 current = dp->cellList[state];
342 int col, row, ccol, crow;
346 ccol = 2 * col + !(row & 1), crow = 2 * row;
347 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
348 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
349 if (dp->xs == 1 && dp->ys == 1)
350 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
351 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
353 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
354 dp->shape.hexagon, 6, Convex, CoordModePrevious);
355 current = current->next;
357 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
358 /* Take advantage of XDrawRectangles */
361 /* Create Rectangle list from part of the cellList */
362 if ((rects = (XRectangle *) malloc(dp->ncells[state] *
363 sizeof (XRectangle))) == NULL) {
366 current = dp->cellList[state];
368 rects[ncells].x = dp->xb + current->pt.x * dp->xs;
369 rects[ncells].y = dp->yb + current->pt.y * dp->ys;
370 rects[ncells].width = dp->xs - (dp->xs > 3);
371 rects[ncells].height = dp->ys - (dp->ys > 3);
372 current = current->next;
375 /* Finally get to draw */
376 XFillRectangles(MI_DISPLAY(mi), MI_WINDOW(mi), gc, rects, ncells);
377 /* Free up rects list and the appropriate part of the cellList */
378 (void) free((void *) rects);
380 current = dp->cellList[state];
382 int col, row, orient;
386 orient = (col + row) % 2; /* O left 1 right */
387 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
388 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
389 if (dp->xs <= 3 || dp->ys <= 3)
390 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
391 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
392 dp->shape.triangle[orient][0].y);
395 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
397 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
398 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
399 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
401 current = current->next;
404 free_state(dp, state);
405 XFlush(MI_DISPLAY(mi));
410 RandomSoup(ModeInfo * mi)
412 demonstruct *dp = &demons[MI_SCREEN(mi)];
413 int row, col, mrow = 0;
415 for (row = 0; row < dp->nrows; ++row) {
416 for (col = 0; col < dp->ncols; ++col) {
417 dp->oldcell[col + mrow] =
418 (unsigned char) LRAND() % ((unsigned char) dp->states);
419 if (!addtolist(mi, col, row, dp->oldcell[col + mrow]))
420 return; /* sparse soup */
427 init_demon(ModeInfo * mi)
429 Display *display = MI_DISPLAY(mi);
430 Window window = MI_WINDOW(mi);
431 int size = MI_SIZE(mi), nk;
434 if (demons == NULL) {
435 if ((demons = (demonstruct *) calloc(MI_NUM_SCREENS(mi),
436 sizeof (demonstruct))) == NULL)
439 dp = &demons[MI_SCREEN(mi)];
443 if (MI_NPIXELS(mi) < NUMSTIPPLES) {
444 if (dp->stippledGC == None) {
447 gcv.fill_style = FillOpaqueStippled;
448 if ((dp->stippledGC = XCreateGC(display, window,
449 GCFillStyle, &gcv)) == None) {
450 free_demon(display, dp);
454 if (dp->init_bits == 0) {
457 for (i = 1; i < NUMSTIPPLES; i++) {
458 DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
464 for (nk = 0; nk < NEIGHBORKINDS; nk++) {
465 if (neighbors == plots[0][nk]) {
466 dp->neighbors = plots[0][nk];
469 if (nk == NEIGHBORKINDS - 1) {
470 nk = NRAND(NEIGHBORKINDS);
471 dp->neighbors = plots[0][nk];
476 dp->states = MI_COUNT(mi);
477 if (dp->states < -MINSTATES)
478 dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES;
479 else if (dp->states < MINSTATES)
480 dp->states = plots[1][nk];
481 if ((dp->cellList = (CellList **) calloc(dp->states,
482 sizeof (CellList *))) == NULL) {
483 free_demon(display, dp);
486 if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) {
487 free_demon(display, dp);
493 dp->width = MI_WIDTH(mi);
494 dp->height = MI_HEIGHT(mi);
496 if (dp->neighbors == 6) {
497 int nccols, ncrows, i;
504 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
505 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
506 else if (size < MINSIZE) {
508 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
512 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
515 nccols = MAX(dp->width / dp->xs - 2, 2);
516 ncrows = MAX(dp->height / dp->ys - 1, 4);
517 dp->ncols = nccols / 2;
518 dp->nrows = 2 * (ncrows / 4);
519 dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2;
520 dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys - 2;
521 for (i = 0; i < 6; i++) {
522 dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x;
523 dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
525 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
527 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
528 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
529 else if (size < MINSIZE) {
531 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
535 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
538 dp->ncols = MAX(dp->width / dp->xs, 2);
539 dp->nrows = MAX(dp->height / dp->ys, 2);
540 dp->xb = (dp->width - dp->xs * dp->ncols) / 2;
541 dp->yb = (dp->height - dp->ys * dp->nrows) / 2;
550 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
551 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
552 else if (size < MINSIZE) {
554 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
558 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
560 dp->xs = (int) (1.52 * dp->ys);
561 dp->ncols = (MAX(dp->width / dp->xs - 1, 2) / 2) * 2;
562 dp->nrows = (MAX(dp->height / dp->ys - 1, 2) / 2) * 2;
563 dp->xb = (dp->width - dp->xs * dp->ncols) / 2 + dp->xs / 2;
564 dp->yb = (dp->height - dp->ys * dp->nrows) / 2 + dp->ys / 2;
565 for (orient = 0; orient < 2; orient++) {
566 for (i = 0; i < 3; i++) {
567 dp->shape.triangle[orient][i].x =
568 (dp->xs - 2) * triangleUnit[orient][i].x;
569 dp->shape.triangle[orient][i].y =
570 (dp->ys - 2) * triangleUnit[orient][i].y;
577 if ((dp->oldcell = (unsigned char *)
578 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
579 free_demon(display, dp);
583 if ((dp->newcell = (unsigned char *)
584 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
585 free_demon(display, dp);
593 draw_demon(ModeInfo * mi)
595 int i, j, k, l, mj = 0, ml;
600 dp = &demons[MI_SCREEN(mi)];
601 if (dp->cellList == NULL)
604 MI_IS_DRAWN(mi) = True;
605 if (dp->state >= dp->states) {
606 (void) memcpy((char *) dp->newcell, (char *) dp->oldcell,
607 dp->ncols * dp->nrows * sizeof (unsigned char));
609 if (dp->neighbors == 6) {
610 for (j = 0; j < dp->nrows; j++) {
611 for (i = 0; i < dp->ncols; i++) {
614 k = (i + 1 == dp->ncols) ? 0 : i + 1;
617 l = (!j) ? dp->nrows - 1 : j - 1;
619 if (dp->oldcell[k + ml] ==
620 (int) (dp->oldcell[i + mj] + 1) % dp->states)
621 dp->newcell[i + mj] = dp->oldcell[k + ml];
623 k = (i + 1 == dp->ncols) ? 0 : i + 1;
625 if (dp->oldcell[k + ml] ==
626 (int) (dp->oldcell[i + mj] + 1) % dp->states)
627 dp->newcell[i + mj] = dp->oldcell[k + ml];
630 k = (i + 1 == dp->ncols) ? 0 : i + 1;
633 l = (j + 1 == dp->nrows) ? 0 : j + 1;
635 if (dp->oldcell[k + ml] ==
636 (int) (dp->oldcell[i + mj] + 1) % dp->states)
637 dp->newcell[i + mj] = dp->oldcell[k + ml];
640 k = (!i) ? dp->ncols - 1 : i - 1;
643 l = (j + 1 == dp->nrows) ? 0 : j + 1;
645 if (dp->oldcell[k + ml] ==
646 (int) (dp->oldcell[i + mj] + 1) % dp->states)
647 dp->newcell[i + mj] = dp->oldcell[k + ml];
649 k = (!i) ? dp->ncols - 1 : i - 1;
651 if (dp->oldcell[k + ml] ==
652 (int) (dp->oldcell[i + mj] + 1) % dp->states)
653 dp->newcell[i + mj] = dp->oldcell[k + ml];
656 k = (!i) ? dp->ncols - 1 : i - 1;
659 l = (!j) ? dp->nrows - 1 : j - 1;
661 if (dp->oldcell[k + ml] ==
662 (int) (dp->oldcell[i + mj] + 1) % dp->states)
663 dp->newcell[i + mj] = dp->oldcell[k + ml];
667 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
668 for (j = 0; j < dp->nrows; j++) {
669 for (i = 0; i < dp->ncols; i++) {
672 l = (!j) ? dp->nrows - 1 : j - 1;
674 if (dp->oldcell[k + ml] ==
675 (int) (dp->oldcell[i + mj] + 1) % dp->states)
676 dp->newcell[i + mj] = dp->oldcell[k + ml];
678 k = (i + 1 == dp->ncols) ? 0 : i + 1;
680 if (dp->oldcell[k + ml] ==
681 (int) (dp->oldcell[i + mj] + 1) % dp->states)
682 dp->newcell[i + mj] = dp->oldcell[k + ml];
685 l = (j + 1 == dp->nrows) ? 0 : j + 1;
687 if (dp->oldcell[k + ml] ==
688 (int) (dp->oldcell[i + mj] + 1) % dp->states)
689 dp->newcell[i + mj] = dp->oldcell[k + ml];
691 k = (!i) ? dp->ncols - 1 : i - 1;
694 if (dp->oldcell[k + ml] ==
695 (int) (dp->oldcell[i + mj] + 1) % dp->states)
696 dp->newcell[i + mj] = dp->oldcell[k + ml];
700 if (dp->neighbors == 8) {
702 for (j = 0; j < dp->nrows; j++) {
703 for (i = 0; i < dp->ncols; i++) {
705 k = (i + 1 == dp->ncols) ? 0 : i + 1;
706 l = (!j) ? dp->nrows - 1 : j - 1;
708 if (dp->oldcell[k + ml] ==
709 (int) (dp->oldcell[i + mj] + 1) % dp->states)
710 dp->newcell[i + mj] = dp->oldcell[k + ml];
712 k = (i + 1 == dp->ncols) ? 0 : i + 1;
713 l = (j + 1 == dp->nrows) ? 0 : j + 1;
715 if (dp->oldcell[k + ml] ==
716 (int) (dp->oldcell[i + mj] + 1) % dp->states)
717 dp->newcell[i + mj] = dp->oldcell[k + ml];
719 k = (!i) ? dp->ncols - 1 : i - 1;
720 l = (j + 1 == dp->nrows) ? 0 : j + 1;
722 if (dp->oldcell[k + ml] ==
723 (int) (dp->oldcell[i + mj] + 1) % dp->states)
724 dp->newcell[i + mj] = dp->oldcell[k + ml];
726 k = (!i) ? dp->ncols - 1 : i - 1;
727 l = (!j) ? dp->nrows - 1 : j - 1;
729 if (dp->oldcell[k + ml] ==
730 (int) (dp->oldcell[i + mj] + 1) % dp->states)
731 dp->newcell[i + mj] = dp->oldcell[k + ml];
736 } else if (dp->neighbors == 3 || dp->neighbors == 9 ||
737 dp->neighbors == 12) {
738 for (j = 0; j < dp->nrows; j++) {
739 for (i = 0; i < dp->ncols; i++) {
740 if ((i + j) % 2) { /* right */
742 k = (!i) ? dp->ncols - 1 : i - 1;
744 if (dp->oldcell[k + ml] ==
745 (int) (dp->oldcell[i + mj] + 1) % dp->states)
746 dp->newcell[i + mj] = dp->oldcell[k + ml];
749 k = (i + 1 == dp->ncols) ? 0 : i + 1;
751 if (dp->oldcell[k + ml] ==
752 (int) (dp->oldcell[i + mj] + 1) % dp->states)
753 dp->newcell[i + mj] = dp->oldcell[k + ml];
757 l = (!j) ? dp->nrows - 1 : j - 1;
759 if (dp->oldcell[k + ml] ==
760 (int) (dp->oldcell[i + mj] + 1) % dp->states)
761 dp->newcell[i + mj] = dp->oldcell[k + ml];
764 l = (j + 1 == dp->nrows) ? 0 : j + 1;
766 if (dp->oldcell[k + ml] ==
767 (int) (dp->oldcell[i + mj] + 1) % dp->states)
768 dp->newcell[i + mj] = dp->oldcell[k + ml];
772 if (dp->neighbors == 9 || dp->neighbors == 12) {
774 for (j = 0; j < dp->nrows; j++) {
775 for (i = 0; i < dp->ncols; i++) {
785 if (dp->oldcell[k + ml] ==
786 (int) (dp->oldcell[i + mj] + 1) % dp->states)
787 dp->newcell[i + mj] = dp->oldcell[k + ml];
790 if (j + 1 == dp->nrows)
792 else if (j + 2 == dp->nrows)
797 if (dp->oldcell[k + ml] ==
798 (int) (dp->oldcell[i + mj] + 1) % dp->states)
799 dp->newcell[i + mj] = dp->oldcell[k + ml];
801 k = (!i) ? dp->ncols - 1 : i - 1;
802 l = (!j) ? dp->nrows - 1 : j - 1;
804 if (dp->oldcell[k + ml] ==
805 (int) (dp->oldcell[i + mj] + 1) % dp->states)
806 dp->newcell[i + mj] = dp->oldcell[k + ml];
808 k = (i + 1 == dp->ncols) ? 0 : i + 1;
809 l = (!j) ? dp->nrows - 1 : j - 1;
811 if (dp->oldcell[k + ml] ==
812 (int) (dp->oldcell[i + mj] + 1) % dp->states)
813 dp->newcell[i + mj] = dp->oldcell[k + ml];
815 k = (!i) ? dp->ncols - 1 : i - 1;
816 l = (j + 1 == dp->nrows) ? 0 : j + 1;
818 if (dp->oldcell[k + ml] ==
819 (int) (dp->oldcell[i + mj] + 1) % dp->states)
820 dp->newcell[i + mj] = dp->oldcell[k + ml];
822 k = (i + 1 == dp->ncols) ? 0 : i + 1;
823 l = (j + 1 == dp->nrows) ? 0 : j + 1;
825 if (dp->oldcell[k + ml] ==
826 (int) (dp->oldcell[i + mj] + 1) % dp->states)
827 dp->newcell[i + mj] = dp->oldcell[k + ml];
831 if (dp->neighbors == 12) {
833 for (j = 0; j < dp->nrows; j++) {
834 for (i = 0; i < dp->ncols; i++) {
835 if ((i + j) % 2) { /* right */
837 k = (!i) ? dp->ncols - 1 : i - 1;
845 if (dp->oldcell[k + ml] ==
846 (int) (dp->oldcell[i + mj] + 1) % dp->states)
847 dp->newcell[i + mj] = dp->oldcell[k + ml];
849 k = (!i) ? dp->ncols - 1 : i - 1;
850 if (j + 1 == dp->nrows)
852 else if (j + 2 == dp->nrows)
857 if (dp->oldcell[k + ml] ==
858 (int) (dp->oldcell[i + mj] + 1) % dp->states)
859 dp->newcell[i + mj] = dp->oldcell[k + ml];
861 k = (i + 1 == dp->ncols) ? 0 : i + 1;
864 if (dp->oldcell[k + ml] ==
865 (int) (dp->oldcell[i + mj] + 1) % dp->states)
866 dp->newcell[i + mj] = dp->oldcell[k + ml];
869 k = (i + 1 == dp->ncols) ? 0 : i + 1;
877 if (dp->oldcell[k + ml] ==
878 (int) (dp->oldcell[i + mj] + 1) % dp->states)
879 dp->newcell[i + mj] = dp->oldcell[k + ml];
881 k = (i + 1 == dp->ncols) ? 0 : i + 1;
882 if (j + 1 == dp->nrows)
884 else if (j + 2 == dp->nrows)
889 if (dp->oldcell[k + ml] ==
890 (int) (dp->oldcell[i + mj] + 1) % dp->states)
891 dp->newcell[i + mj] = dp->oldcell[k + ml];
893 k = (!i) ? dp->ncols - 1 : i - 1;
896 if (dp->oldcell[k + ml] ==
897 (int) (dp->oldcell[i + mj] + 1) % dp->states)
898 dp->newcell[i + mj] = dp->oldcell[k + ml];
907 for (j = 0; j < dp->nrows; j++) {
908 for (i = 0; i < dp->ncols; i++)
909 if (dp->oldcell[i + mj] != dp->newcell[i + mj]) {
910 dp->oldcell[i + mj] = dp->newcell[i + mj];
911 if (!addtolist(mi, i, j, dp->oldcell[i + mj])) {
912 free_demon(MI_DISPLAY(mi), dp);
918 if (++dp->generation > MI_CYCLES(mi))
922 if (dp->ncells[dp->state])
923 if (!draw_state(mi, dp->state)) {
924 free_demon(MI_DISPLAY(mi), dp);
930 for (i = 0; i < REDRAWSTEP; i++) {
931 if (dp->oldcell[dp->redrawpos]) {
932 drawcell(mi, dp->redrawpos % dp->ncols, dp->redrawpos / dp->ncols,
933 dp->oldcell[dp->redrawpos]);
935 if (++(dp->redrawpos) >= dp->ncols * dp->nrows) {
943 release_demon(ModeInfo * mi)
945 if (demons != NULL) {
948 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
949 free_demon(MI_DISPLAY(mi), &demons[screen]);
950 (void) free((void *) demons);
951 demons = (demonstruct *) NULL;
956 refresh_demon(ModeInfo * mi)
962 dp = &demons[MI_SCREEN(mi)];
968 #endif /* MODE_demon */