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 ---- ------------------
55 # define DEFAULTS "*delay: 50000 \n" \
60 "*fpsSolid: true \n" \
61 "*ignoreRotation: True \n" \
63 # define UNIFORM_COLORS
64 # define release_demon 0
65 # include "xlockmore.h" /* in xscreensaver distribution */
66 #else /* STANDALONE */
67 # include "xlock.h" /* in xlockmore distribution */
68 #endif /* STANDALONE */
74 * neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12.
76 #define DEF_NEIGHBORS "0" /* choose random value */
80 static XrmOptionDescRec opts[] =
82 {"-neighbors", ".demon.neighbors", XrmoptionSepArg, 0}
85 static argtype vars[] =
87 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
89 static OptionStruct desc[] =
91 {"-neighbors num", "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"}
94 ENTRYPOINT ModeSpecOpt demon_opts =
95 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
98 ModStruct demon_description =
99 {"demon", "init_demon", "draw_demon", (char *) NULL,
100 "refresh_demon", "init_demon", (char *) NULL, &demon_opts,
101 50000, 0, 1000, -7, 64, 1.0, "",
102 "Shows Griffeath's cellular automata", 0, NULL};
106 #define DEMONBITS(n,w,h)\
107 if ((dp->pixmaps[dp->init_bits]=\
108 XCreatePixmapFromBitmapData(MI_DISPLAY(mi),window,(char *)n,w,h,1,0,1))==None){\
109 free_demon(mi); return;} else {dp->init_bits++;}
111 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
113 #define MINGRIDSIZE 24
115 #define NEIGHBORKINDS 6
117 /* Singly linked list */
118 typedef struct _CellList {
120 struct _CellList *next;
131 int redrawing, redrawpos;
134 unsigned char *oldcell, *newcell;
138 Pixmap pixmaps[NUMSTIPPLES - 1];
141 XPoint triangle[2][3];
145 static char plots[2][NEIGHBORKINDS] =
147 {3, 4, 6, 8, 9, 12}, /* Neighborhoods */
148 {12, 16, 18, 20, 22, 24} /* Number of states */
151 static demonstruct *demons = (demonstruct *) NULL;
154 drawcell(ModeInfo * mi, int col, int row, unsigned char state)
156 demonstruct *dp = &demons[MI_SCREEN(mi)];
160 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
162 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
163 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
164 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
165 (dp->states - 1)) % MI_NPIXELS(mi)));
170 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
171 #endif /* DO_STIPPLE */
172 gcv.foreground = MI_WHITE_PIXEL(mi);
173 gcv.background = MI_BLACK_PIXEL(mi);
174 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
175 GCStipple | GCForeground | GCBackground, &gcv);
178 if (dp->neighbors == 6) {
179 int ccol = 2 * col + !(row & 1), crow = 2 * row;
181 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
182 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
183 if (dp->xs == 1 && dp->ys == 1)
184 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
185 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
187 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
188 dp->shape.hexagon, 6, Convex, CoordModePrevious);
189 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
190 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
191 dp->xb + dp->xs * col, dp->yb + dp->ys * row,
192 dp->xs - (dp->xs > 3), dp->ys - (dp->ys > 3));
194 int orient = (col + row) % 2; /* O left 1 right */
196 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
197 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
198 if (dp->xs <= 3 || dp->ys <= 3)
199 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
200 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
201 dp->shape.triangle[orient][0].y);
204 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
206 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
207 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
208 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
215 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
217 demonstruct *dp = &demons[MI_SCREEN(mi)];
220 current = dp->cellList[state];
221 if ((dp->cellList[state] = (CellList *)
222 malloc(sizeof (CellList))) == NULL) {
225 dp->cellList[state]->pt.x = col;
226 dp->cellList[state]->pt.y = row;
227 dp->cellList[state]->next = current;
234 free_state(demonstruct * dp, int state)
238 while (dp->cellList[state]) {
239 current = dp->cellList[state];
240 dp->cellList[state] = dp->cellList[state]->next;
241 (void) free((void *) current);
243 dp->cellList[state] = (CellList *) NULL;
244 if (dp->ncells != NULL)
245 dp->ncells[state] = 0;
250 free_list(demonstruct * dp)
254 for (state = 0; state < dp->states; state++)
255 free_state(dp, state);
256 (void) free((void *) dp->cellList);
257 dp->cellList = (CellList **) NULL;
261 free_struct(demonstruct * dp)
263 if (dp->cellList != NULL) {
266 if (dp->ncells != NULL) {
267 (void) free((void *) dp->ncells);
268 dp->ncells = (int *) NULL;
270 if (dp->oldcell != NULL) {
271 (void) free((void *) dp->oldcell);
272 dp->oldcell = (unsigned char *) NULL;
274 if (dp->newcell != NULL) {
275 (void) free((void *) dp->newcell);
276 dp->newcell = (unsigned char *) NULL;
281 free_demon(ModeInfo * mi)
283 Display *display = MI_DISPLAY(mi);
284 demonstruct *dp = &demons[MI_SCREEN(mi)];
287 if (dp->stippledGC != None) {
288 XFreeGC(display, dp->stippledGC);
289 dp->stippledGC = None;
291 for (shade = 0; shade < dp->init_bits; shade++) {
292 XFreePixmap(display, dp->pixmaps[shade]);
299 draw_state(ModeInfo * mi, int state)
301 demonstruct *dp = &demons[MI_SCREEN(mi)];
307 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
309 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
310 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
311 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
312 (dp->states - 1)) % MI_NPIXELS(mi)));
318 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
319 #endif /* DO_STIPPLE */
320 gcv.foreground = MI_WHITE_PIXEL(mi);
321 gcv.background = MI_BLACK_PIXEL(mi);
322 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
323 GCStipple | GCForeground | GCBackground, &gcv);
326 if (dp->neighbors == 6) { /* Draw right away, slow */
327 current = dp->cellList[state];
329 int col, row, ccol, crow;
333 ccol = 2 * col + !(row & 1), crow = 2 * row;
334 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
335 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
336 if (dp->xs == 1 && dp->ys == 1)
337 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
338 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
340 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
341 dp->shape.hexagon, 6, Convex, CoordModePrevious);
342 current = current->next;
344 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
345 /* Take advantage of XDrawRectangles */
348 /* Create Rectangle list from part of the cellList */
349 if ((rects = (XRectangle *) malloc(dp->ncells[state] *
350 sizeof (XRectangle))) == NULL) {
353 current = dp->cellList[state];
355 rects[ncells].x = dp->xb + current->pt.x * dp->xs;
356 rects[ncells].y = dp->yb + current->pt.y * dp->ys;
357 rects[ncells].width = dp->xs - (dp->xs > 3);
358 rects[ncells].height = dp->ys - (dp->ys > 3);
359 current = current->next;
362 /* Finally get to draw */
363 XFillRectangles(MI_DISPLAY(mi), MI_WINDOW(mi), gc, rects, ncells);
364 /* Free up rects list and the appropriate part of the cellList */
365 (void) free((void *) rects);
367 current = dp->cellList[state];
369 int col, row, orient;
373 orient = (col + row) % 2; /* O left 1 right */
374 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
375 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
376 if (dp->xs <= 3 || dp->ys <= 3)
377 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
378 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
379 dp->shape.triangle[orient][0].y);
382 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
384 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
385 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
386 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
388 current = current->next;
391 free_state(dp, state);
396 RandomSoup(ModeInfo * mi)
398 demonstruct *dp = &demons[MI_SCREEN(mi)];
399 int row, col, mrow = 0;
401 for (row = 0; row < dp->nrows; ++row) {
402 for (col = 0; col < dp->ncols; ++col) {
403 dp->oldcell[col + mrow] =
404 (unsigned char) LRAND() % ((unsigned char) dp->states);
405 if (!addtolist(mi, col, row, dp->oldcell[col + mrow]))
406 return; /* sparse soup */
413 init_demon (ModeInfo * mi)
415 int size = MI_SIZE(mi), nk;
418 MI_INIT (mi, demons, free_demon);
419 dp = &demons[MI_SCREEN(mi)];
424 if (MI_NPIXELS(mi) < NUMSTIPPLES) {
425 Window window = MI_WINDOW(mi);
426 if (dp->stippledGC == None) {
429 gcv.fill_style = FillOpaqueStippled;
430 if ((dp->stippledGC = XCreateGC(MI_DISPLAY(mi), window,
431 GCFillStyle, &gcv)) == None) {
436 if (dp->init_bits == 0) {
439 for (i = 1; i < NUMSTIPPLES; i++) {
440 DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
444 #endif /* DO_STIPPLE */
448 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
451 for (nk = 0; nk < NEIGHBORKINDS; nk++) {
452 if (neighbors == plots[0][nk]) {
453 dp->neighbors = plots[0][nk];
456 if (nk == NEIGHBORKINDS - 1) {
457 nk = NRAND(NEIGHBORKINDS);
458 dp->neighbors = plots[0][nk];
463 dp->states = MI_COUNT(mi);
464 if (dp->states < -MINSTATES)
465 dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES;
466 else if (dp->states < MINSTATES)
467 dp->states = plots[1][nk];
468 if ((dp->cellList = (CellList **) calloc(dp->states,
469 sizeof (CellList *))) == NULL) {
473 if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) {
480 dp->width = MI_WIDTH(mi);
481 dp->height = MI_HEIGHT(mi);
483 if (dp->neighbors == 6) {
484 int nccols, ncrows, i;
491 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
492 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
493 else if (size < MINSIZE) {
495 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
499 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
502 nccols = MAX(dp->width / dp->xs - 2, 2);
503 ncrows = MAX(dp->height / dp->ys - 1, 4);
504 dp->ncols = nccols / 2;
505 dp->nrows = 2 * (ncrows / 4);
506 dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2;
507 dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys - 2;
508 for (i = 0; i < 6; i++) {
509 dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x;
510 dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
512 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
514 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
515 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
516 else if (size < MINSIZE) {
518 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
522 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
525 dp->ncols = MAX(dp->width / dp->xs, 2);
526 dp->nrows = MAX(dp->height / dp->ys, 2);
527 dp->xb = (dp->width - dp->xs * dp->ncols) / 2;
528 dp->yb = (dp->height - dp->ys * dp->nrows) / 2;
537 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
538 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
539 else if (size < MINSIZE) {
541 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
545 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
547 dp->xs = (int) (1.52 * dp->ys);
548 dp->ncols = (MAX(dp->width / dp->xs - 1, 2) / 2) * 2;
549 dp->nrows = (MAX(dp->height / dp->ys - 1, 2) / 2) * 2;
550 dp->xb = (dp->width - dp->xs * dp->ncols) / 2 + dp->xs / 2;
551 dp->yb = (dp->height - dp->ys * dp->nrows) / 2 + dp->ys / 2;
552 for (orient = 0; orient < 2; orient++) {
553 for (i = 0; i < 3; i++) {
554 dp->shape.triangle[orient][i].x =
555 (dp->xs - 2) * triangleUnit[orient][i].x;
556 dp->shape.triangle[orient][i].y =
557 (dp->ys - 2) * triangleUnit[orient][i].y;
564 if ((dp->oldcell = (unsigned char *)
565 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
570 if ((dp->newcell = (unsigned char *)
571 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
580 draw_demon (ModeInfo * mi)
582 int i, j, k, l, mj = 0, ml;
587 dp = &demons[MI_SCREEN(mi)];
588 if (dp->cellList == NULL)
591 MI_IS_DRAWN(mi) = True;
592 if (dp->state >= dp->states) {
593 (void) memcpy((char *) dp->newcell, (char *) dp->oldcell,
594 dp->ncols * dp->nrows * sizeof (unsigned char));
596 if (dp->neighbors == 6) {
597 for (j = 0; j < dp->nrows; j++) {
598 for (i = 0; i < dp->ncols; i++) {
601 k = (i + 1 == dp->ncols) ? 0 : i + 1;
604 l = (!j) ? dp->nrows - 1 : j - 1;
606 if (dp->oldcell[k + ml] ==
607 (int) (dp->oldcell[i + mj] + 1) % dp->states)
608 dp->newcell[i + mj] = dp->oldcell[k + ml];
610 k = (i + 1 == dp->ncols) ? 0 : i + 1;
612 if (dp->oldcell[k + ml] ==
613 (int) (dp->oldcell[i + mj] + 1) % dp->states)
614 dp->newcell[i + mj] = dp->oldcell[k + ml];
617 k = (i + 1 == dp->ncols) ? 0 : i + 1;
620 l = (j + 1 == dp->nrows) ? 0 : j + 1;
622 if (dp->oldcell[k + ml] ==
623 (int) (dp->oldcell[i + mj] + 1) % dp->states)
624 dp->newcell[i + mj] = dp->oldcell[k + ml];
627 k = (!i) ? dp->ncols - 1 : i - 1;
630 l = (j + 1 == dp->nrows) ? 0 : j + 1;
632 if (dp->oldcell[k + ml] ==
633 (int) (dp->oldcell[i + mj] + 1) % dp->states)
634 dp->newcell[i + mj] = dp->oldcell[k + ml];
636 k = (!i) ? dp->ncols - 1 : i - 1;
638 if (dp->oldcell[k + ml] ==
639 (int) (dp->oldcell[i + mj] + 1) % dp->states)
640 dp->newcell[i + mj] = dp->oldcell[k + ml];
643 k = (!i) ? dp->ncols - 1 : i - 1;
646 l = (!j) ? dp->nrows - 1 : j - 1;
648 if (dp->oldcell[k + ml] ==
649 (int) (dp->oldcell[i + mj] + 1) % dp->states)
650 dp->newcell[i + mj] = dp->oldcell[k + ml];
654 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
655 for (j = 0; j < dp->nrows; j++) {
656 for (i = 0; i < dp->ncols; i++) {
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];
665 k = (i + 1 == dp->ncols) ? 0 : i + 1;
667 if (dp->oldcell[k + ml] ==
668 (int) (dp->oldcell[i + mj] + 1) % dp->states)
669 dp->newcell[i + mj] = dp->oldcell[k + ml];
672 l = (j + 1 == dp->nrows) ? 0 : 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) ? dp->ncols - 1 : i - 1;
681 if (dp->oldcell[k + ml] ==
682 (int) (dp->oldcell[i + mj] + 1) % dp->states)
683 dp->newcell[i + mj] = dp->oldcell[k + ml];
687 if (dp->neighbors == 8) {
689 for (j = 0; j < dp->nrows; j++) {
690 for (i = 0; i < dp->ncols; i++) {
692 k = (i + 1 == dp->ncols) ? 0 : i + 1;
693 l = (!j) ? dp->nrows - 1 : j - 1;
695 if (dp->oldcell[k + ml] ==
696 (int) (dp->oldcell[i + mj] + 1) % dp->states)
697 dp->newcell[i + mj] = dp->oldcell[k + ml];
699 k = (i + 1 == dp->ncols) ? 0 : i + 1;
700 l = (j + 1 == dp->nrows) ? 0 : j + 1;
702 if (dp->oldcell[k + ml] ==
703 (int) (dp->oldcell[i + mj] + 1) % dp->states)
704 dp->newcell[i + mj] = dp->oldcell[k + ml];
706 k = (!i) ? dp->ncols - 1 : i - 1;
707 l = (j + 1 == dp->nrows) ? 0 : j + 1;
709 if (dp->oldcell[k + ml] ==
710 (int) (dp->oldcell[i + mj] + 1) % dp->states)
711 dp->newcell[i + mj] = dp->oldcell[k + ml];
713 k = (!i) ? dp->ncols - 1 : i - 1;
714 l = (!j) ? dp->nrows - 1 : j - 1;
716 if (dp->oldcell[k + ml] ==
717 (int) (dp->oldcell[i + mj] + 1) % dp->states)
718 dp->newcell[i + mj] = dp->oldcell[k + ml];
723 } else if (dp->neighbors == 3 || dp->neighbors == 9 ||
724 dp->neighbors == 12) {
725 for (j = 0; j < dp->nrows; j++) {
726 for (i = 0; i < dp->ncols; i++) {
727 if ((i + j) % 2) { /* right */
729 k = (!i) ? dp->ncols - 1 : i - 1;
731 if (dp->oldcell[k + ml] ==
732 (int) (dp->oldcell[i + mj] + 1) % dp->states)
733 dp->newcell[i + mj] = dp->oldcell[k + ml];
736 k = (i + 1 == dp->ncols) ? 0 : i + 1;
738 if (dp->oldcell[k + ml] ==
739 (int) (dp->oldcell[i + mj] + 1) % dp->states)
740 dp->newcell[i + mj] = dp->oldcell[k + ml];
744 l = (!j) ? dp->nrows - 1 : j - 1;
746 if (dp->oldcell[k + ml] ==
747 (int) (dp->oldcell[i + mj] + 1) % dp->states)
748 dp->newcell[i + mj] = dp->oldcell[k + ml];
751 l = (j + 1 == dp->nrows) ? 0 : j + 1;
753 if (dp->oldcell[k + ml] ==
754 (int) (dp->oldcell[i + mj] + 1) % dp->states)
755 dp->newcell[i + mj] = dp->oldcell[k + ml];
759 if (dp->neighbors == 9 || dp->neighbors == 12) {
761 for (j = 0; j < dp->nrows; j++) {
762 for (i = 0; i < dp->ncols; i++) {
772 if (dp->oldcell[k + ml] ==
773 (int) (dp->oldcell[i + mj] + 1) % dp->states)
774 dp->newcell[i + mj] = dp->oldcell[k + ml];
777 if (j + 1 == dp->nrows)
779 else if (j + 2 == dp->nrows)
784 if (dp->oldcell[k + ml] ==
785 (int) (dp->oldcell[i + mj] + 1) % dp->states)
786 dp->newcell[i + mj] = dp->oldcell[k + ml];
788 k = (!i) ? dp->ncols - 1 : i - 1;
789 l = (!j) ? dp->nrows - 1 : j - 1;
791 if (dp->oldcell[k + ml] ==
792 (int) (dp->oldcell[i + mj] + 1) % dp->states)
793 dp->newcell[i + mj] = dp->oldcell[k + ml];
795 k = (i + 1 == dp->ncols) ? 0 : i + 1;
796 l = (!j) ? dp->nrows - 1 : j - 1;
798 if (dp->oldcell[k + ml] ==
799 (int) (dp->oldcell[i + mj] + 1) % dp->states)
800 dp->newcell[i + mj] = dp->oldcell[k + ml];
802 k = (!i) ? dp->ncols - 1 : i - 1;
803 l = (j + 1 == dp->nrows) ? 0 : j + 1;
805 if (dp->oldcell[k + ml] ==
806 (int) (dp->oldcell[i + mj] + 1) % dp->states)
807 dp->newcell[i + mj] = dp->oldcell[k + ml];
809 k = (i + 1 == dp->ncols) ? 0 : i + 1;
810 l = (j + 1 == dp->nrows) ? 0 : j + 1;
812 if (dp->oldcell[k + ml] ==
813 (int) (dp->oldcell[i + mj] + 1) % dp->states)
814 dp->newcell[i + mj] = dp->oldcell[k + ml];
818 if (dp->neighbors == 12) {
820 for (j = 0; j < dp->nrows; j++) {
821 for (i = 0; i < dp->ncols; i++) {
822 if ((i + j) % 2) { /* right */
824 k = (!i) ? dp->ncols - 1 : i - 1;
832 if (dp->oldcell[k + ml] ==
833 (int) (dp->oldcell[i + mj] + 1) % dp->states)
834 dp->newcell[i + mj] = dp->oldcell[k + ml];
836 k = (!i) ? dp->ncols - 1 : i - 1;
837 if (j + 1 == dp->nrows)
839 else if (j + 2 == dp->nrows)
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 + 1 == dp->ncols) ? 0 : i + 1;
851 if (dp->oldcell[k + ml] ==
852 (int) (dp->oldcell[i + mj] + 1) % dp->states)
853 dp->newcell[i + mj] = dp->oldcell[k + ml];
856 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];
868 k = (i + 1 == dp->ncols) ? 0 : i + 1;
869 if (j + 1 == dp->nrows)
871 else if (j + 2 == dp->nrows)
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) ? dp->ncols - 1 : i - 1;
883 if (dp->oldcell[k + ml] ==
884 (int) (dp->oldcell[i + mj] + 1) % dp->states)
885 dp->newcell[i + mj] = dp->oldcell[k + ml];
894 for (j = 0; j < dp->nrows; j++) {
895 for (i = 0; i < dp->ncols; i++)
896 if (dp->oldcell[i + mj] != dp->newcell[i + mj]) {
897 dp->oldcell[i + mj] = dp->newcell[i + mj];
898 if (!addtolist(mi, i, j, dp->oldcell[i + mj])) {
905 if (++dp->generation > MI_CYCLES(mi))
909 if (dp->ncells[dp->state])
910 if (!draw_state(mi, dp->state)) {
917 for (i = 0; i < REDRAWSTEP; i++) {
918 if (dp->oldcell[dp->redrawpos]) {
919 drawcell(mi, dp->redrawpos % dp->ncols, dp->redrawpos / dp->ncols,
920 dp->oldcell[dp->redrawpos]);
922 if (++(dp->redrawpos) >= dp->ncols * dp->nrows) {
932 reshape_demon(ModeInfo * mi, int width, int height)
934 XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
940 refresh_demon (ModeInfo * mi)
946 dp = &demons[MI_SCREEN(mi)];
953 demon_handle_event (ModeInfo *mi, XEvent *event)
955 if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
957 reshape_demon (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
965 XSCREENSAVER_MODULE ("Demon", demon)
967 #endif /* MODE_demon */