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 # define reshape_demon 0
66 # define demon_handle_event 0
67 # include "xlockmore.h" /* in xscreensaver distribution */
68 #else /* STANDALONE */
69 # include "xlock.h" /* in xlockmore distribution */
70 #endif /* STANDALONE */
76 * neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12.
78 #define DEF_NEIGHBORS "0" /* choose random value */
82 static XrmOptionDescRec opts[] =
84 {"-neighbors", ".demon.neighbors", XrmoptionSepArg, 0}
87 static argtype vars[] =
89 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
91 static OptionStruct desc[] =
93 {"-neighbors num", "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"}
96 ENTRYPOINT ModeSpecOpt demon_opts =
97 {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
100 ModStruct demon_description =
101 {"demon", "init_demon", "draw_demon", (char *) NULL,
102 "refresh_demon", "init_demon", "free_demon", &demon_opts,
103 50000, 0, 1000, -7, 64, 1.0, "",
104 "Shows Griffeath's cellular automata", 0, NULL};
108 #define DEMONBITS(n,w,h)\
109 if ((dp->pixmaps[dp->init_bits]=\
110 XCreatePixmapFromBitmapData(MI_DISPLAY(mi),window,(char *)n,w,h,1,0,1))==None){\
111 free_demon(mi); return;} else {dp->init_bits++;}
113 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
115 #define MINGRIDSIZE 5
117 #define NEIGHBORKINDS 6
119 /* Singly linked list */
120 typedef struct _CellList {
122 struct _CellList *next;
133 int redrawing, redrawpos;
136 unsigned char *oldcell, *newcell;
140 Pixmap pixmaps[NUMSTIPPLES - 1];
143 XPoint triangle[2][3];
147 static char plots[2][NEIGHBORKINDS] =
149 {3, 4, 6, 8, 9, 12}, /* Neighborhoods */
150 {12, 16, 18, 20, 22, 24} /* Number of states */
153 static demonstruct *demons = (demonstruct *) NULL;
156 drawcell(ModeInfo * mi, int col, int row, unsigned char state)
158 demonstruct *dp = &demons[MI_SCREEN(mi)];
162 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
164 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
165 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
166 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
167 (dp->states - 1)) % MI_NPIXELS(mi)));
172 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
173 #endif /* DO_STIPPLE */
174 gcv.foreground = MI_WHITE_PIXEL(mi);
175 gcv.background = MI_BLACK_PIXEL(mi);
176 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
177 GCStipple | GCForeground | GCBackground, &gcv);
180 if (dp->neighbors == 6) {
181 int ccol = 2 * col + !(row & 1), crow = 2 * row;
183 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
184 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
185 if (dp->xs == 1 && dp->ys == 1)
186 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
187 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
189 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
190 dp->shape.hexagon, 6, Convex, CoordModePrevious);
191 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
192 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
193 dp->xb + dp->xs * col, dp->yb + dp->ys * row,
194 dp->xs - (dp->xs > 3), dp->ys - (dp->ys > 3));
196 int orient = (col + row) % 2; /* O left 1 right */
198 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
199 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
200 if (dp->xs <= 3 || dp->ys <= 3)
201 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
202 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
203 dp->shape.triangle[orient][0].y);
206 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
208 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
209 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
210 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
217 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
219 demonstruct *dp = &demons[MI_SCREEN(mi)];
222 current = dp->cellList[state];
223 if ((dp->cellList[state] = (CellList *)
224 malloc(sizeof (CellList))) == NULL) {
227 dp->cellList[state]->pt.x = col;
228 dp->cellList[state]->pt.y = row;
229 dp->cellList[state]->next = current;
236 free_state(demonstruct * dp, int state)
240 while (dp->cellList[state]) {
241 current = dp->cellList[state];
242 dp->cellList[state] = dp->cellList[state]->next;
243 (void) free((void *) current);
245 dp->cellList[state] = (CellList *) NULL;
246 if (dp->ncells != NULL)
247 dp->ncells[state] = 0;
252 free_list(demonstruct * dp)
256 for (state = 0; state < dp->states; state++)
257 free_state(dp, state);
258 (void) free((void *) dp->cellList);
259 dp->cellList = (CellList **) NULL;
263 free_struct(demonstruct * dp)
265 if (dp->cellList != NULL) {
268 if (dp->ncells != NULL) {
269 (void) free((void *) dp->ncells);
270 dp->ncells = (int *) NULL;
272 if (dp->oldcell != NULL) {
273 (void) free((void *) dp->oldcell);
274 dp->oldcell = (unsigned char *) NULL;
276 if (dp->newcell != NULL) {
277 (void) free((void *) dp->newcell);
278 dp->newcell = (unsigned char *) NULL;
283 free_demon(ModeInfo * mi)
285 Display *display = MI_DISPLAY(mi);
286 demonstruct *dp = &demons[MI_SCREEN(mi)];
289 if (dp->stippledGC != None) {
290 XFreeGC(display, dp->stippledGC);
291 dp->stippledGC = None;
293 for (shade = 0; shade < dp->init_bits; shade++) {
294 XFreePixmap(display, dp->pixmaps[shade]);
301 draw_state(ModeInfo * mi, int state)
303 demonstruct *dp = &demons[MI_SCREEN(mi)];
309 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
311 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
312 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
313 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
314 (dp->states - 1)) % MI_NPIXELS(mi)));
320 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
321 #endif /* DO_STIPPLE */
322 gcv.foreground = MI_WHITE_PIXEL(mi);
323 gcv.background = MI_BLACK_PIXEL(mi);
324 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
325 GCStipple | GCForeground | GCBackground, &gcv);
328 if (dp->neighbors == 6) { /* Draw right away, slow */
329 current = dp->cellList[state];
331 int col, row, ccol, crow;
335 ccol = 2 * col + !(row & 1), crow = 2 * row;
336 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
337 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
338 if (dp->xs == 1 && dp->ys == 1)
339 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
340 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
342 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
343 dp->shape.hexagon, 6, Convex, CoordModePrevious);
344 current = current->next;
346 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
347 /* Take advantage of XDrawRectangles */
350 /* Create Rectangle list from part of the cellList */
351 if ((rects = (XRectangle *) malloc(dp->ncells[state] *
352 sizeof (XRectangle))) == NULL) {
355 current = dp->cellList[state];
357 rects[ncells].x = dp->xb + current->pt.x * dp->xs;
358 rects[ncells].y = dp->yb + current->pt.y * dp->ys;
359 rects[ncells].width = dp->xs - (dp->xs > 3);
360 rects[ncells].height = dp->ys - (dp->ys > 3);
361 current = current->next;
364 /* Finally get to draw */
365 XFillRectangles(MI_DISPLAY(mi), MI_WINDOW(mi), gc, rects, ncells);
366 /* Free up rects list and the appropriate part of the cellList */
367 (void) free((void *) rects);
369 current = dp->cellList[state];
371 int col, row, orient;
375 orient = (col + row) % 2; /* O left 1 right */
376 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
377 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
378 if (dp->xs <= 3 || dp->ys <= 3)
379 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
380 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
381 dp->shape.triangle[orient][0].y);
384 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
386 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
387 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
388 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
390 current = current->next;
393 free_state(dp, state);
398 RandomSoup(ModeInfo * mi)
400 demonstruct *dp = &demons[MI_SCREEN(mi)];
401 int row, col, mrow = 0;
403 for (row = 0; row < dp->nrows; ++row) {
404 for (col = 0; col < dp->ncols; ++col) {
405 dp->oldcell[col + mrow] =
406 (unsigned char) LRAND() % ((unsigned char) dp->states);
407 if (!addtolist(mi, col, row, dp->oldcell[col + mrow]))
408 return; /* sparse soup */
415 init_demon (ModeInfo * mi)
417 int size = MI_SIZE(mi), nk;
420 MI_INIT (mi, demons);
421 dp = &demons[MI_SCREEN(mi)];
423 if (MI_WIDTH(mi) < 100 || MI_HEIGHT(mi) < 100) /* tiny window */
424 size = MIN(MI_WIDTH(mi), MI_HEIGHT(mi));
429 if (MI_NPIXELS(mi) < NUMSTIPPLES) {
430 Window window = MI_WINDOW(mi);
431 if (dp->stippledGC == None) {
434 gcv.fill_style = FillOpaqueStippled;
435 if ((dp->stippledGC = XCreateGC(MI_DISPLAY(mi), window,
436 GCFillStyle, &gcv)) == None) {
441 if (dp->init_bits == 0) {
444 for (i = 1; i < NUMSTIPPLES; i++) {
445 DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
449 #endif /* DO_STIPPLE */
453 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
456 for (nk = 0; nk < NEIGHBORKINDS; nk++) {
457 if (neighbors == plots[0][nk]) {
458 dp->neighbors = plots[0][nk];
461 if (nk == NEIGHBORKINDS - 1) {
462 nk = NRAND(NEIGHBORKINDS);
463 dp->neighbors = plots[0][nk];
468 dp->states = MI_COUNT(mi);
469 if (dp->states < -MINSTATES)
470 dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES;
471 else if (dp->states < MINSTATES)
472 dp->states = plots[1][nk];
473 if ((dp->cellList = (CellList **) calloc(dp->states,
474 sizeof (CellList *))) == NULL) {
478 if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) {
485 dp->width = MI_WIDTH(mi);
486 dp->height = MI_HEIGHT(mi);
488 if (dp->neighbors == 6) {
489 int nccols, ncrows, i;
496 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
497 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
498 else if (size < MINSIZE) {
500 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
504 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
507 nccols = MAX(dp->width / dp->xs - 2, 2);
508 ncrows = MAX(dp->height / dp->ys - 1, 4);
509 dp->ncols = nccols / 2;
510 dp->nrows = 2 * (ncrows / 4);
511 dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2;
512 dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys - 2;
513 for (i = 0; i < 6; i++) {
514 dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x;
515 dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
517 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
519 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
520 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
521 else if (size < MINSIZE) {
523 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
527 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
530 dp->ncols = MAX(dp->width / dp->xs, 2);
531 dp->nrows = MAX(dp->height / dp->ys, 2);
532 dp->xb = (dp->width - dp->xs * dp->ncols) / 2;
533 dp->yb = (dp->height - dp->ys * dp->nrows) / 2;
542 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
543 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
544 else if (size < MINSIZE) {
546 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
550 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
552 dp->xs = (int) (1.52 * dp->ys);
553 dp->ncols = (MAX(dp->width / dp->xs - 1, 2) / 2) * 2;
554 dp->nrows = (MAX(dp->height / dp->ys - 1, 2) / 2) * 2;
555 dp->xb = (dp->width - dp->xs * dp->ncols) / 2 + dp->xs / 2;
556 dp->yb = (dp->height - dp->ys * dp->nrows) / 2 + dp->ys / 2;
557 for (orient = 0; orient < 2; orient++) {
558 for (i = 0; i < 3; i++) {
559 dp->shape.triangle[orient][i].x =
560 (dp->xs - 2) * triangleUnit[orient][i].x;
561 dp->shape.triangle[orient][i].y =
562 (dp->ys - 2) * triangleUnit[orient][i].y;
569 if ((dp->oldcell = (unsigned char *)
570 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
575 if ((dp->newcell = (unsigned char *)
576 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
585 draw_demon (ModeInfo * mi)
587 int i, j, k, l, mj = 0, ml;
592 dp = &demons[MI_SCREEN(mi)];
593 if (dp->cellList == NULL)
596 MI_IS_DRAWN(mi) = True;
597 if (dp->state >= dp->states) {
598 (void) memcpy((char *) dp->newcell, (char *) dp->oldcell,
599 dp->ncols * dp->nrows * sizeof (unsigned char));
601 if (dp->neighbors == 6) {
602 for (j = 0; j < dp->nrows; j++) {
603 for (i = 0; i < dp->ncols; i++) {
606 k = (i + 1 == dp->ncols) ? 0 : i + 1;
609 l = (!j) ? dp->nrows - 1 : j - 1;
611 if (dp->oldcell[k + ml] ==
612 (int) (dp->oldcell[i + mj] + 1) % dp->states)
613 dp->newcell[i + mj] = dp->oldcell[k + ml];
615 k = (i + 1 == dp->ncols) ? 0 : i + 1;
617 if (dp->oldcell[k + ml] ==
618 (int) (dp->oldcell[i + mj] + 1) % dp->states)
619 dp->newcell[i + mj] = dp->oldcell[k + ml];
622 k = (i + 1 == dp->ncols) ? 0 : i + 1;
625 l = (j + 1 == dp->nrows) ? 0 : j + 1;
627 if (dp->oldcell[k + ml] ==
628 (int) (dp->oldcell[i + mj] + 1) % dp->states)
629 dp->newcell[i + mj] = dp->oldcell[k + ml];
632 k = (!i) ? dp->ncols - 1 : i - 1;
635 l = (j + 1 == dp->nrows) ? 0 : j + 1;
637 if (dp->oldcell[k + ml] ==
638 (int) (dp->oldcell[i + mj] + 1) % dp->states)
639 dp->newcell[i + mj] = dp->oldcell[k + ml];
641 k = (!i) ? dp->ncols - 1 : i - 1;
643 if (dp->oldcell[k + ml] ==
644 (int) (dp->oldcell[i + mj] + 1) % dp->states)
645 dp->newcell[i + mj] = dp->oldcell[k + ml];
648 k = (!i) ? dp->ncols - 1 : i - 1;
651 l = (!j) ? dp->nrows - 1 : j - 1;
653 if (dp->oldcell[k + ml] ==
654 (int) (dp->oldcell[i + mj] + 1) % dp->states)
655 dp->newcell[i + mj] = dp->oldcell[k + ml];
659 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
660 for (j = 0; j < dp->nrows; j++) {
661 for (i = 0; i < dp->ncols; i++) {
664 l = (!j) ? dp->nrows - 1 : j - 1;
666 if (dp->oldcell[k + ml] ==
667 (int) (dp->oldcell[i + mj] + 1) % dp->states)
668 dp->newcell[i + mj] = dp->oldcell[k + ml];
670 k = (i + 1 == dp->ncols) ? 0 : i + 1;
672 if (dp->oldcell[k + ml] ==
673 (int) (dp->oldcell[i + mj] + 1) % dp->states)
674 dp->newcell[i + mj] = dp->oldcell[k + ml];
677 l = (j + 1 == dp->nrows) ? 0 : j + 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];
683 k = (!i) ? dp->ncols - 1 : i - 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];
692 if (dp->neighbors == 8) {
694 for (j = 0; j < dp->nrows; j++) {
695 for (i = 0; i < dp->ncols; i++) {
697 k = (i + 1 == dp->ncols) ? 0 : i + 1;
698 l = (!j) ? dp->nrows - 1 : j - 1;
700 if (dp->oldcell[k + ml] ==
701 (int) (dp->oldcell[i + mj] + 1) % dp->states)
702 dp->newcell[i + mj] = dp->oldcell[k + ml];
704 k = (i + 1 == dp->ncols) ? 0 : i + 1;
705 l = (j + 1 == dp->nrows) ? 0 : 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) ? dp->ncols - 1 : 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) ? dp->nrows - 1 : 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];
728 } else if (dp->neighbors == 3 || dp->neighbors == 9 ||
729 dp->neighbors == 12) {
730 for (j = 0; j < dp->nrows; j++) {
731 for (i = 0; i < dp->ncols; i++) {
732 if ((i + j) % 2) { /* right */
734 k = (!i) ? dp->ncols - 1 : i - 1;
736 if (dp->oldcell[k + ml] ==
737 (int) (dp->oldcell[i + mj] + 1) % dp->states)
738 dp->newcell[i + mj] = dp->oldcell[k + ml];
741 k = (i + 1 == dp->ncols) ? 0 : 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];
749 l = (!j) ? dp->nrows - 1 : j - 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];
756 l = (j + 1 == dp->nrows) ? 0 : 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];
764 if (dp->neighbors == 9 || dp->neighbors == 12) {
766 for (j = 0; j < dp->nrows; j++) {
767 for (i = 0; i < dp->ncols; i++) {
777 if (dp->oldcell[k + ml] ==
778 (int) (dp->oldcell[i + mj] + 1) % dp->states)
779 dp->newcell[i + mj] = dp->oldcell[k + ml];
782 if (j + 1 == dp->nrows)
784 else if (j + 2 == dp->nrows)
789 if (dp->oldcell[k + ml] ==
790 (int) (dp->oldcell[i + mj] + 1) % dp->states)
791 dp->newcell[i + mj] = dp->oldcell[k + ml];
793 k = (!i) ? dp->ncols - 1 : i - 1;
794 l = (!j) ? dp->nrows - 1 : j - 1;
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 + 1 == dp->ncols) ? 0 : 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) ? dp->ncols - 1 : i - 1;
808 l = (j + 1 == dp->nrows) ? 0 : 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 + 1 == dp->ncols) ? 0 : 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];
823 if (dp->neighbors == 12) {
825 for (j = 0; j < dp->nrows; j++) {
826 for (i = 0; i < dp->ncols; i++) {
827 if ((i + j) % 2) { /* right */
829 k = (!i) ? dp->ncols - 1 : i - 1;
837 if (dp->oldcell[k + ml] ==
838 (int) (dp->oldcell[i + mj] + 1) % dp->states)
839 dp->newcell[i + mj] = dp->oldcell[k + ml];
841 k = (!i) ? dp->ncols - 1 : i - 1;
842 if (j + 1 == dp->nrows)
844 else if (j + 2 == dp->nrows)
849 if (dp->oldcell[k + ml] ==
850 (int) (dp->oldcell[i + mj] + 1) % dp->states)
851 dp->newcell[i + mj] = dp->oldcell[k + ml];
853 k = (i + 1 == dp->ncols) ? 0 : i + 1;
856 if (dp->oldcell[k + ml] ==
857 (int) (dp->oldcell[i + mj] + 1) % dp->states)
858 dp->newcell[i + mj] = dp->oldcell[k + ml];
861 k = (i + 1 == dp->ncols) ? 0 : i + 1;
869 if (dp->oldcell[k + ml] ==
870 (int) (dp->oldcell[i + mj] + 1) % dp->states)
871 dp->newcell[i + mj] = dp->oldcell[k + ml];
873 k = (i + 1 == dp->ncols) ? 0 : i + 1;
874 if (j + 1 == dp->nrows)
876 else if (j + 2 == dp->nrows)
881 if (dp->oldcell[k + ml] ==
882 (int) (dp->oldcell[i + mj] + 1) % dp->states)
883 dp->newcell[i + mj] = dp->oldcell[k + ml];
885 k = (!i) ? dp->ncols - 1 : i - 1;
888 if (dp->oldcell[k + ml] ==
889 (int) (dp->oldcell[i + mj] + 1) % dp->states)
890 dp->newcell[i + mj] = dp->oldcell[k + ml];
899 for (j = 0; j < dp->nrows; j++) {
900 for (i = 0; i < dp->ncols; i++)
901 if (dp->oldcell[i + mj] != dp->newcell[i + mj]) {
902 dp->oldcell[i + mj] = dp->newcell[i + mj];
903 if (!addtolist(mi, i, j, dp->oldcell[i + mj])) {
910 if (++dp->generation > MI_CYCLES(mi))
914 if (dp->ncells[dp->state])
915 if (!draw_state(mi, dp->state)) {
922 for (i = 0; i < REDRAWSTEP; i++) {
923 if (dp->oldcell[dp->redrawpos]) {
924 drawcell(mi, dp->redrawpos % dp->ncols, dp->redrawpos / dp->ncols,
925 dp->oldcell[dp->redrawpos]);
927 if (++(dp->redrawpos) >= dp->ncols * dp->nrows) {
937 refresh_demon (ModeInfo * mi)
943 dp = &demons[MI_SCREEN(mi)];
950 XSCREENSAVER_MODULE ("Demon", demon)
952 #endif /* MODE_demon */