1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* demon --- David Griffeath's cellular automata */
5 static const char sccsid[] = "@(#)demon.c 5.00 2000/11/01 xlockmore";
9 * Copyright (c) 1995 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 * 01-Nov-2000: Allocation checks
25 * 10-May-1997: Compatible with xscreensaver
26 * 16-Apr-1997: -neighbors 3, 9 (not sound mathematically), 12, and 8 added
27 * 30-May-1996: Ron Hitchens <ron@idiom.com>
28 * Fixed memory management that caused leaks
29 * 14-Apr-1996: -neighbors 6 runtime-time option added
30 * 21-Aug-1995: Coded from A.K. Dewdney's "Computer Recreations", Scientific
31 * American Magazine" Aug 1989 pp 102-105. Also very similar
32 * to hodgepodge machine described in A.K. Dewdney's "Computer
33 * Recreations", Scientific American Magazine" Aug 1988
34 * pp 104-107. Also used life.c as a guide.
38 * A cellular universe of 4 phases debris, droplets, defects, and demons.
42 Grid Number of Neighbors
43 ---- ------------------
51 #define PROGCLASS "Demon"
52 #define HACK_INIT init_demon
53 #define HACK_DRAW draw_demon
54 #define demon_opts xlockmore_opts
55 #define DEFAULTS "*delay: 50000 \n" \
61 #define UNIFORM_COLORS
62 #include "xlockmore.h" /* in xscreensaver distribution */
63 #else /* STANDALONE */
64 #include "xlock.h" /* in xlockmore distribution */
66 #endif /* STANDALONE */
72 * neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12.
74 #define DEF_NEIGHBORS "0" /* choose random value */
78 static XrmOptionDescRec opts[] =
80 {"-neighbors", ".demon.neighbors", XrmoptionSepArg, 0}
83 static argtype vars[] =
85 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
87 static OptionStruct desc[] =
89 {"-neighbors num", "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"}
92 ModeSpecOpt demon_opts =
93 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
96 ModStruct demon_description =
97 {"demon", "init_demon", "draw_demon", "release_demon",
98 "refresh_demon", "init_demon", (char *) NULL, &demon_opts,
99 50000, 0, 1000, -7, 64, 1.0, "",
100 "Shows Griffeath's cellular automata", 0, NULL};
104 #define DEMONBITS(n,w,h)\
105 if ((dp->pixmaps[dp->init_bits]=\
106 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
107 free_demon(display,dp); return;} else {dp->init_bits++;}
109 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
111 #define MINGRIDSIZE 24
113 #define NEIGHBORKINDS 6
115 /* Singly linked list */
116 typedef struct _CellList {
118 struct _CellList *next;
129 int redrawing, redrawpos;
132 unsigned char *oldcell, *newcell;
136 Pixmap pixmaps[NUMSTIPPLES - 1];
139 XPoint triangle[2][3];
143 static char plots[2][NEIGHBORKINDS] =
145 {3, 4, 6, 8, 9, 12}, /* Neighborhoods */
146 {12, 16, 18, 20, 22, 24} /* Number of states */
149 static demonstruct *demons = (demonstruct *) NULL;
152 drawcell(ModeInfo * mi, int col, int row, unsigned char state)
154 demonstruct *dp = &demons[MI_SCREEN(mi)];
158 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
160 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
161 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
162 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
163 (dp->states - 1)) % MI_NPIXELS(mi)));
168 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
169 gcv.foreground = MI_WHITE_PIXEL(mi);
170 gcv.background = MI_BLACK_PIXEL(mi);
171 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
172 GCStipple | GCForeground | GCBackground, &gcv);
175 if (dp->neighbors == 6) {
176 int ccol = 2 * col + !(row & 1), crow = 2 * row;
178 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
179 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
180 if (dp->xs == 1 && dp->ys == 1)
181 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
182 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
184 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
185 dp->shape.hexagon, 6, Convex, CoordModePrevious);
186 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
187 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
188 dp->xb + dp->xs * col, dp->yb + dp->ys * row,
189 dp->xs - (dp->xs > 3), dp->ys - (dp->ys > 3));
191 int orient = (col + row) % 2; /* O left 1 right */
193 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
194 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
195 if (dp->xs <= 3 || dp->ys <= 3)
196 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
197 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
198 dp->shape.triangle[orient][0].y);
201 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
203 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
204 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
205 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
212 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
214 demonstruct *dp = &demons[MI_SCREEN(mi)];
217 current = dp->cellList[state];
218 if ((dp->cellList[state] = (CellList *)
219 malloc(sizeof (CellList))) == NULL) {
222 dp->cellList[state]->pt.x = col;
223 dp->cellList[state]->pt.y = row;
224 dp->cellList[state]->next = current;
231 print_state(ModeInfo * mi, int state)
233 demonstruct *dp = &demons[MI_SCREEN(mi)];
237 locallist = dp->cellList[state];
238 (void) printf("state %d\n", state);
240 (void) printf("%d x %d, y %d\n", i,
241 locallist->pt.x, locallist->pt.y);
242 locallist = locallist->next;
250 free_state(demonstruct * dp, int state)
254 while (dp->cellList[state]) {
255 current = dp->cellList[state];
256 dp->cellList[state] = dp->cellList[state]->next;
257 (void) free((void *) current);
259 dp->cellList[state] = (CellList *) NULL;
260 if (dp->ncells != NULL)
261 dp->ncells[state] = 0;
266 free_list(demonstruct * dp)
270 for (state = 0; state < dp->states; state++)
271 free_state(dp, state);
272 (void) free((void *) dp->cellList);
273 dp->cellList = (CellList **) NULL;
277 free_struct(demonstruct * dp)
279 if (dp->cellList != NULL) {
282 if (dp->ncells != NULL) {
283 (void) free((void *) dp->ncells);
284 dp->ncells = (int *) NULL;
286 if (dp->oldcell != NULL) {
287 (void) free((void *) dp->oldcell);
288 dp->oldcell = (unsigned char *) NULL;
290 if (dp->newcell != NULL) {
291 (void) free((void *) dp->newcell);
292 dp->newcell = (unsigned char *) NULL;
297 free_demon(Display *display, demonstruct *dp)
301 if (dp->stippledGC != None) {
302 XFreeGC(display, dp->stippledGC);
303 dp->stippledGC = None;
305 for (shade = 0; shade < dp->init_bits; shade++) {
306 XFreePixmap(display, dp->pixmaps[shade]);
313 draw_state(ModeInfo * mi, int state)
315 demonstruct *dp = &demons[MI_SCREEN(mi)];
321 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
323 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
324 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
325 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
326 (dp->states - 1)) % MI_NPIXELS(mi)));
331 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
332 gcv.foreground = MI_WHITE_PIXEL(mi);
333 gcv.background = MI_BLACK_PIXEL(mi);
334 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
335 GCStipple | GCForeground | GCBackground, &gcv);
338 if (dp->neighbors == 6) { /* Draw right away, slow */
339 current = dp->cellList[state];
341 int col, row, ccol, crow;
345 ccol = 2 * col + !(row & 1), crow = 2 * row;
346 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
347 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
348 if (dp->xs == 1 && dp->ys == 1)
349 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
350 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
352 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
353 dp->shape.hexagon, 6, Convex, CoordModePrevious);
354 current = current->next;
356 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
357 /* Take advantage of XDrawRectangles */
360 /* Create Rectangle list from part of the cellList */
361 if ((rects = (XRectangle *) malloc(dp->ncells[state] *
362 sizeof (XRectangle))) == NULL) {
365 current = dp->cellList[state];
367 rects[ncells].x = dp->xb + current->pt.x * dp->xs;
368 rects[ncells].y = dp->yb + current->pt.y * dp->ys;
369 rects[ncells].width = dp->xs - (dp->xs > 3);
370 rects[ncells].height = dp->ys - (dp->ys > 3);
371 current = current->next;
374 /* Finally get to draw */
375 XFillRectangles(MI_DISPLAY(mi), MI_WINDOW(mi), gc, rects, ncells);
376 /* Free up rects list and the appropriate part of the cellList */
377 (void) free((void *) rects);
379 current = dp->cellList[state];
381 int col, row, orient;
385 orient = (col + row) % 2; /* O left 1 right */
386 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
387 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
388 if (dp->xs <= 3 || dp->ys <= 3)
389 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
390 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
391 dp->shape.triangle[orient][0].y);
394 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
396 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
397 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
398 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
400 current = current->next;
403 free_state(dp, state);
404 XFlush(MI_DISPLAY(mi));
409 RandomSoup(ModeInfo * mi)
411 demonstruct *dp = &demons[MI_SCREEN(mi)];
412 int row, col, mrow = 0;
414 for (row = 0; row < dp->nrows; ++row) {
415 for (col = 0; col < dp->ncols; ++col) {
416 dp->oldcell[col + mrow] =
417 (unsigned char) LRAND() % ((unsigned char) dp->states);
418 if (!addtolist(mi, col, row, dp->oldcell[col + mrow]))
419 return; /* sparse soup */
426 init_demon(ModeInfo * mi)
428 Display *display = MI_DISPLAY(mi);
429 Window window = MI_WINDOW(mi);
430 int size = MI_SIZE(mi), nk;
433 if (demons == NULL) {
434 if ((demons = (demonstruct *) calloc(MI_NUM_SCREENS(mi),
435 sizeof (demonstruct))) == NULL)
438 dp = &demons[MI_SCREEN(mi)];
442 if (MI_NPIXELS(mi) < NUMSTIPPLES) {
443 if (dp->stippledGC == None) {
446 gcv.fill_style = FillOpaqueStippled;
447 if ((dp->stippledGC = XCreateGC(display, window,
448 GCFillStyle, &gcv)) == None) {
449 free_demon(display, dp);
453 if (dp->init_bits == 0) {
456 for (i = 1; i < NUMSTIPPLES; i++) {
457 DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
463 for (nk = 0; nk < NEIGHBORKINDS; nk++) {
464 if (neighbors == plots[0][nk]) {
465 dp->neighbors = plots[0][nk];
468 if (nk == NEIGHBORKINDS - 1) {
469 nk = NRAND(NEIGHBORKINDS);
470 dp->neighbors = plots[0][nk];
475 dp->states = MI_COUNT(mi);
476 if (dp->states < -MINSTATES)
477 dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES;
478 else if (dp->states < MINSTATES)
479 dp->states = plots[1][nk];
480 if ((dp->cellList = (CellList **) calloc(dp->states,
481 sizeof (CellList *))) == NULL) {
482 free_demon(display, dp);
485 if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) {
486 free_demon(display, dp);
492 dp->width = MI_WIDTH(mi);
493 dp->height = MI_HEIGHT(mi);
495 if (dp->neighbors == 6) {
496 int nccols, ncrows, i;
503 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
504 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
505 else if (size < MINSIZE) {
507 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
511 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
514 nccols = MAX(dp->width / dp->xs - 2, 2);
515 ncrows = MAX(dp->height / dp->ys - 1, 4);
516 dp->ncols = nccols / 2;
517 dp->nrows = 2 * (ncrows / 4);
518 dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2;
519 dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys - 2;
520 for (i = 0; i < 6; i++) {
521 dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x;
522 dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
524 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
526 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
527 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
528 else if (size < MINSIZE) {
530 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
534 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
537 dp->ncols = MAX(dp->width / dp->xs, 2);
538 dp->nrows = MAX(dp->height / dp->ys, 2);
539 dp->xb = (dp->width - dp->xs * dp->ncols) / 2;
540 dp->yb = (dp->height - dp->ys * dp->nrows) / 2;
549 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
550 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
551 else if (size < MINSIZE) {
553 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
557 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
559 dp->xs = (int) (1.52 * dp->ys);
560 dp->ncols = (MAX(dp->width / dp->xs - 1, 2) / 2) * 2;
561 dp->nrows = (MAX(dp->height / dp->ys - 1, 2) / 2) * 2;
562 dp->xb = (dp->width - dp->xs * dp->ncols) / 2 + dp->xs / 2;
563 dp->yb = (dp->height - dp->ys * dp->nrows) / 2 + dp->ys / 2;
564 for (orient = 0; orient < 2; orient++) {
565 for (i = 0; i < 3; i++) {
566 dp->shape.triangle[orient][i].x =
567 (dp->xs - 2) * triangleUnit[orient][i].x;
568 dp->shape.triangle[orient][i].y =
569 (dp->ys - 2) * triangleUnit[orient][i].y;
576 if ((dp->oldcell = (unsigned char *)
577 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
578 free_demon(display, dp);
582 if ((dp->newcell = (unsigned char *)
583 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
584 free_demon(display, dp);
592 draw_demon(ModeInfo * mi)
594 int i, j, k, l, mj = 0, ml;
599 dp = &demons[MI_SCREEN(mi)];
600 if (dp->cellList == NULL)
603 MI_IS_DRAWN(mi) = True;
604 if (dp->state >= dp->states) {
605 (void) memcpy((char *) dp->newcell, (char *) dp->oldcell,
606 dp->ncols * dp->nrows * sizeof (unsigned char));
608 if (dp->neighbors == 6) {
609 for (j = 0; j < dp->nrows; j++) {
610 for (i = 0; i < dp->ncols; i++) {
613 k = (i + 1 == dp->ncols) ? 0 : i + 1;
616 l = (!j) ? dp->nrows - 1 : j - 1;
618 if (dp->oldcell[k + ml] ==
619 (int) (dp->oldcell[i + mj] + 1) % dp->states)
620 dp->newcell[i + mj] = dp->oldcell[k + ml];
622 k = (i + 1 == dp->ncols) ? 0 : i + 1;
624 if (dp->oldcell[k + ml] ==
625 (int) (dp->oldcell[i + mj] + 1) % dp->states)
626 dp->newcell[i + mj] = dp->oldcell[k + ml];
629 k = (i + 1 == dp->ncols) ? 0 : i + 1;
632 l = (j + 1 == dp->nrows) ? 0 : j + 1;
634 if (dp->oldcell[k + ml] ==
635 (int) (dp->oldcell[i + mj] + 1) % dp->states)
636 dp->newcell[i + mj] = dp->oldcell[k + ml];
639 k = (!i) ? dp->ncols - 1 : i - 1;
642 l = (j + 1 == dp->nrows) ? 0 : j + 1;
644 if (dp->oldcell[k + ml] ==
645 (int) (dp->oldcell[i + mj] + 1) % dp->states)
646 dp->newcell[i + mj] = dp->oldcell[k + ml];
648 k = (!i) ? dp->ncols - 1 : i - 1;
650 if (dp->oldcell[k + ml] ==
651 (int) (dp->oldcell[i + mj] + 1) % dp->states)
652 dp->newcell[i + mj] = dp->oldcell[k + ml];
655 k = (!i) ? dp->ncols - 1 : i - 1;
658 l = (!j) ? dp->nrows - 1 : j - 1;
660 if (dp->oldcell[k + ml] ==
661 (int) (dp->oldcell[i + mj] + 1) % dp->states)
662 dp->newcell[i + mj] = dp->oldcell[k + ml];
666 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
667 for (j = 0; j < dp->nrows; j++) {
668 for (i = 0; i < dp->ncols; i++) {
671 l = (!j) ? dp->nrows - 1 : j - 1;
673 if (dp->oldcell[k + ml] ==
674 (int) (dp->oldcell[i + mj] + 1) % dp->states)
675 dp->newcell[i + mj] = dp->oldcell[k + ml];
677 k = (i + 1 == dp->ncols) ? 0 : i + 1;
679 if (dp->oldcell[k + ml] ==
680 (int) (dp->oldcell[i + mj] + 1) % dp->states)
681 dp->newcell[i + mj] = dp->oldcell[k + ml];
684 l = (j + 1 == dp->nrows) ? 0 : j + 1;
686 if (dp->oldcell[k + ml] ==
687 (int) (dp->oldcell[i + mj] + 1) % dp->states)
688 dp->newcell[i + mj] = dp->oldcell[k + ml];
690 k = (!i) ? dp->ncols - 1 : i - 1;
693 if (dp->oldcell[k + ml] ==
694 (int) (dp->oldcell[i + mj] + 1) % dp->states)
695 dp->newcell[i + mj] = dp->oldcell[k + ml];
699 if (dp->neighbors == 8) {
701 for (j = 0; j < dp->nrows; j++) {
702 for (i = 0; i < dp->ncols; i++) {
704 k = (i + 1 == dp->ncols) ? 0 : i + 1;
705 l = (!j) ? dp->nrows - 1 : j - 1;
707 if (dp->oldcell[k + ml] ==
708 (int) (dp->oldcell[i + mj] + 1) % dp->states)
709 dp->newcell[i + mj] = dp->oldcell[k + ml];
711 k = (i + 1 == dp->ncols) ? 0 : i + 1;
712 l = (j + 1 == dp->nrows) ? 0 : j + 1;
714 if (dp->oldcell[k + ml] ==
715 (int) (dp->oldcell[i + mj] + 1) % dp->states)
716 dp->newcell[i + mj] = dp->oldcell[k + ml];
718 k = (!i) ? dp->ncols - 1 : i - 1;
719 l = (j + 1 == dp->nrows) ? 0 : j + 1;
721 if (dp->oldcell[k + ml] ==
722 (int) (dp->oldcell[i + mj] + 1) % dp->states)
723 dp->newcell[i + mj] = dp->oldcell[k + ml];
725 k = (!i) ? dp->ncols - 1 : i - 1;
726 l = (!j) ? dp->nrows - 1 : j - 1;
728 if (dp->oldcell[k + ml] ==
729 (int) (dp->oldcell[i + mj] + 1) % dp->states)
730 dp->newcell[i + mj] = dp->oldcell[k + ml];
735 } else if (dp->neighbors == 3 || dp->neighbors == 9 ||
736 dp->neighbors == 12) {
737 for (j = 0; j < dp->nrows; j++) {
738 for (i = 0; i < dp->ncols; i++) {
739 if ((i + j) % 2) { /* right */
741 k = (!i) ? dp->ncols - 1 : i - 1;
743 if (dp->oldcell[k + ml] ==
744 (int) (dp->oldcell[i + mj] + 1) % dp->states)
745 dp->newcell[i + mj] = dp->oldcell[k + ml];
748 k = (i + 1 == dp->ncols) ? 0 : i + 1;
750 if (dp->oldcell[k + ml] ==
751 (int) (dp->oldcell[i + mj] + 1) % dp->states)
752 dp->newcell[i + mj] = dp->oldcell[k + ml];
756 l = (!j) ? dp->nrows - 1 : j - 1;
758 if (dp->oldcell[k + ml] ==
759 (int) (dp->oldcell[i + mj] + 1) % dp->states)
760 dp->newcell[i + mj] = dp->oldcell[k + ml];
763 l = (j + 1 == dp->nrows) ? 0 : j + 1;
765 if (dp->oldcell[k + ml] ==
766 (int) (dp->oldcell[i + mj] + 1) % dp->states)
767 dp->newcell[i + mj] = dp->oldcell[k + ml];
771 if (dp->neighbors == 9 || dp->neighbors == 12) {
773 for (j = 0; j < dp->nrows; j++) {
774 for (i = 0; i < dp->ncols; i++) {
784 if (dp->oldcell[k + ml] ==
785 (int) (dp->oldcell[i + mj] + 1) % dp->states)
786 dp->newcell[i + mj] = dp->oldcell[k + ml];
789 if (j + 1 == dp->nrows)
791 else if (j + 2 == dp->nrows)
796 if (dp->oldcell[k + ml] ==
797 (int) (dp->oldcell[i + mj] + 1) % dp->states)
798 dp->newcell[i + mj] = dp->oldcell[k + ml];
800 k = (!i) ? dp->ncols - 1 : i - 1;
801 l = (!j) ? dp->nrows - 1 : j - 1;
803 if (dp->oldcell[k + ml] ==
804 (int) (dp->oldcell[i + mj] + 1) % dp->states)
805 dp->newcell[i + mj] = dp->oldcell[k + ml];
807 k = (i + 1 == dp->ncols) ? 0 : i + 1;
808 l = (!j) ? dp->nrows - 1 : j - 1;
810 if (dp->oldcell[k + ml] ==
811 (int) (dp->oldcell[i + mj] + 1) % dp->states)
812 dp->newcell[i + mj] = dp->oldcell[k + ml];
814 k = (!i) ? dp->ncols - 1 : i - 1;
815 l = (j + 1 == dp->nrows) ? 0 : j + 1;
817 if (dp->oldcell[k + ml] ==
818 (int) (dp->oldcell[i + mj] + 1) % dp->states)
819 dp->newcell[i + mj] = dp->oldcell[k + ml];
821 k = (i + 1 == dp->ncols) ? 0 : i + 1;
822 l = (j + 1 == dp->nrows) ? 0 : j + 1;
824 if (dp->oldcell[k + ml] ==
825 (int) (dp->oldcell[i + mj] + 1) % dp->states)
826 dp->newcell[i + mj] = dp->oldcell[k + ml];
830 if (dp->neighbors == 12) {
832 for (j = 0; j < dp->nrows; j++) {
833 for (i = 0; i < dp->ncols; i++) {
834 if ((i + j) % 2) { /* right */
836 k = (!i) ? dp->ncols - 1 : i - 1;
844 if (dp->oldcell[k + ml] ==
845 (int) (dp->oldcell[i + mj] + 1) % dp->states)
846 dp->newcell[i + mj] = dp->oldcell[k + ml];
848 k = (!i) ? dp->ncols - 1 : i - 1;
849 if (j + 1 == dp->nrows)
851 else if (j + 2 == dp->nrows)
856 if (dp->oldcell[k + ml] ==
857 (int) (dp->oldcell[i + mj] + 1) % dp->states)
858 dp->newcell[i + mj] = dp->oldcell[k + ml];
860 k = (i + 1 == dp->ncols) ? 0 : i + 1;
863 if (dp->oldcell[k + ml] ==
864 (int) (dp->oldcell[i + mj] + 1) % dp->states)
865 dp->newcell[i + mj] = dp->oldcell[k + ml];
868 k = (i + 1 == dp->ncols) ? 0 : i + 1;
876 if (dp->oldcell[k + ml] ==
877 (int) (dp->oldcell[i + mj] + 1) % dp->states)
878 dp->newcell[i + mj] = dp->oldcell[k + ml];
880 k = (i + 1 == dp->ncols) ? 0 : i + 1;
881 if (j + 1 == dp->nrows)
883 else if (j + 2 == dp->nrows)
888 if (dp->oldcell[k + ml] ==
889 (int) (dp->oldcell[i + mj] + 1) % dp->states)
890 dp->newcell[i + mj] = dp->oldcell[k + ml];
892 k = (!i) ? dp->ncols - 1 : i - 1;
895 if (dp->oldcell[k + ml] ==
896 (int) (dp->oldcell[i + mj] + 1) % dp->states)
897 dp->newcell[i + mj] = dp->oldcell[k + ml];
906 for (j = 0; j < dp->nrows; j++) {
907 for (i = 0; i < dp->ncols; i++)
908 if (dp->oldcell[i + mj] != dp->newcell[i + mj]) {
909 dp->oldcell[i + mj] = dp->newcell[i + mj];
910 if (!addtolist(mi, i, j, dp->oldcell[i + mj])) {
911 free_demon(MI_DISPLAY(mi), dp);
917 if (++dp->generation > MI_CYCLES(mi))
921 if (dp->ncells[dp->state])
922 if (!draw_state(mi, dp->state)) {
923 free_demon(MI_DISPLAY(mi), dp);
929 for (i = 0; i < REDRAWSTEP; i++) {
930 if (dp->oldcell[dp->redrawpos]) {
931 drawcell(mi, dp->redrawpos % dp->ncols, dp->redrawpos / dp->ncols,
932 dp->oldcell[dp->redrawpos]);
934 if (++(dp->redrawpos) >= dp->ncols * dp->nrows) {
942 release_demon(ModeInfo * mi)
944 if (demons != NULL) {
947 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
948 free_demon(MI_DISPLAY(mi), &demons[screen]);
949 (void) free((void *) demons);
950 demons = (demonstruct *) NULL;
955 refresh_demon(ModeInfo * mi)
961 dp = &demons[MI_SCREEN(mi)];
967 #endif /* MODE_demon */