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" \
62 # define demon_handle_event 0
63 # define UNIFORM_COLORS
64 # include "xlockmore.h" /* in xscreensaver distribution */
65 #else /* STANDALONE */
66 # 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 {"-neighbors", ".demon.neighbors", XrmoptionSepArg, 0}
84 static argtype vars[] =
86 {&neighbors, "neighbors", "Neighbors", DEF_NEIGHBORS, t_Int}
88 static OptionStruct desc[] =
90 {"-neighbors num", "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"}
93 ENTRYPOINT 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 #endif /* DO_STIPPLE */
171 gcv.foreground = MI_WHITE_PIXEL(mi);
172 gcv.background = MI_BLACK_PIXEL(mi);
173 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
174 GCStipple | GCForeground | GCBackground, &gcv);
177 if (dp->neighbors == 6) {
178 int ccol = 2 * col + !(row & 1), crow = 2 * row;
180 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
181 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
182 if (dp->xs == 1 && dp->ys == 1)
183 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
184 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
186 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
187 dp->shape.hexagon, 6, Convex, CoordModePrevious);
188 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
189 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
190 dp->xb + dp->xs * col, dp->yb + dp->ys * row,
191 dp->xs - (dp->xs > 3), dp->ys - (dp->ys > 3));
193 int orient = (col + row) % 2; /* O left 1 right */
195 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
196 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
197 if (dp->xs <= 3 || dp->ys <= 3)
198 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
199 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
200 dp->shape.triangle[orient][0].y);
203 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
205 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
206 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
207 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
214 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
216 demonstruct *dp = &demons[MI_SCREEN(mi)];
219 current = dp->cellList[state];
220 if ((dp->cellList[state] = (CellList *)
221 malloc(sizeof (CellList))) == NULL) {
224 dp->cellList[state]->pt.x = col;
225 dp->cellList[state]->pt.y = row;
226 dp->cellList[state]->next = current;
233 print_state(ModeInfo * mi, int state)
235 demonstruct *dp = &demons[MI_SCREEN(mi)];
239 locallist = dp->cellList[state];
240 (void) printf("state %d\n", state);
242 (void) printf("%d x %d, y %d\n", i,
243 locallist->pt.x, locallist->pt.y);
244 locallist = locallist->next;
252 free_state(demonstruct * dp, int state)
256 while (dp->cellList[state]) {
257 current = dp->cellList[state];
258 dp->cellList[state] = dp->cellList[state]->next;
259 (void) free((void *) current);
261 dp->cellList[state] = (CellList *) NULL;
262 if (dp->ncells != NULL)
263 dp->ncells[state] = 0;
268 free_list(demonstruct * dp)
272 for (state = 0; state < dp->states; state++)
273 free_state(dp, state);
274 (void) free((void *) dp->cellList);
275 dp->cellList = (CellList **) NULL;
279 free_struct(demonstruct * dp)
281 if (dp->cellList != NULL) {
284 if (dp->ncells != NULL) {
285 (void) free((void *) dp->ncells);
286 dp->ncells = (int *) NULL;
288 if (dp->oldcell != NULL) {
289 (void) free((void *) dp->oldcell);
290 dp->oldcell = (unsigned char *) NULL;
292 if (dp->newcell != NULL) {
293 (void) free((void *) dp->newcell);
294 dp->newcell = (unsigned char *) NULL;
299 free_demon(Display *display, demonstruct *dp)
303 if (dp->stippledGC != None) {
304 XFreeGC(display, dp->stippledGC);
305 dp->stippledGC = None;
307 for (shade = 0; shade < dp->init_bits; shade++) {
308 XFreePixmap(display, dp->pixmaps[shade]);
315 draw_state(ModeInfo * mi, int state)
317 demonstruct *dp = &demons[MI_SCREEN(mi)];
323 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
325 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
326 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
327 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
328 (dp->states - 1)) % MI_NPIXELS(mi)));
334 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
335 #endif /* DO_STIPPLE */
336 gcv.foreground = MI_WHITE_PIXEL(mi);
337 gcv.background = MI_BLACK_PIXEL(mi);
338 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
339 GCStipple | GCForeground | GCBackground, &gcv);
342 if (dp->neighbors == 6) { /* Draw right away, slow */
343 current = dp->cellList[state];
345 int col, row, ccol, crow;
349 ccol = 2 * col + !(row & 1), crow = 2 * row;
350 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
351 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
352 if (dp->xs == 1 && dp->ys == 1)
353 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
354 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
356 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
357 dp->shape.hexagon, 6, Convex, CoordModePrevious);
358 current = current->next;
360 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
361 /* Take advantage of XDrawRectangles */
364 /* Create Rectangle list from part of the cellList */
365 if ((rects = (XRectangle *) malloc(dp->ncells[state] *
366 sizeof (XRectangle))) == NULL) {
369 current = dp->cellList[state];
371 rects[ncells].x = dp->xb + current->pt.x * dp->xs;
372 rects[ncells].y = dp->yb + current->pt.y * dp->ys;
373 rects[ncells].width = dp->xs - (dp->xs > 3);
374 rects[ncells].height = dp->ys - (dp->ys > 3);
375 current = current->next;
378 /* Finally get to draw */
379 XFillRectangles(MI_DISPLAY(mi), MI_WINDOW(mi), gc, rects, ncells);
380 /* Free up rects list and the appropriate part of the cellList */
381 (void) free((void *) rects);
383 current = dp->cellList[state];
385 int col, row, orient;
389 orient = (col + row) % 2; /* O left 1 right */
390 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
391 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
392 if (dp->xs <= 3 || dp->ys <= 3)
393 XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
394 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
395 dp->shape.triangle[orient][0].y);
398 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
400 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
401 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
402 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
404 current = current->next;
407 free_state(dp, state);
412 RandomSoup(ModeInfo * mi)
414 demonstruct *dp = &demons[MI_SCREEN(mi)];
415 int row, col, mrow = 0;
417 for (row = 0; row < dp->nrows; ++row) {
418 for (col = 0; col < dp->ncols; ++col) {
419 dp->oldcell[col + mrow] =
420 (unsigned char) LRAND() % ((unsigned char) dp->states);
421 if (!addtolist(mi, col, row, dp->oldcell[col + mrow]))
422 return; /* sparse soup */
429 init_demon (ModeInfo * mi)
431 Display *display = MI_DISPLAY(mi);
432 int size = MI_SIZE(mi), nk;
435 if (demons == NULL) {
436 if ((demons = (demonstruct *) calloc(MI_NUM_SCREENS(mi),
437 sizeof (demonstruct))) == NULL)
440 dp = &demons[MI_SCREEN(mi)];
445 if (MI_NPIXELS(mi) < NUMSTIPPLES) {
446 Window window = MI_WINDOW(mi);
447 if (dp->stippledGC == None) {
450 gcv.fill_style = FillOpaqueStippled;
451 if ((dp->stippledGC = XCreateGC(display, window,
452 GCFillStyle, &gcv)) == None) {
453 free_demon(display, dp);
457 if (dp->init_bits == 0) {
460 for (i = 1; i < NUMSTIPPLES; i++) {
461 DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
465 #endif /* DO_STIPPLE */
469 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
472 for (nk = 0; nk < NEIGHBORKINDS; nk++) {
473 if (neighbors == plots[0][nk]) {
474 dp->neighbors = plots[0][nk];
477 if (nk == NEIGHBORKINDS - 1) {
478 nk = NRAND(NEIGHBORKINDS);
479 dp->neighbors = plots[0][nk];
484 dp->states = MI_COUNT(mi);
485 if (dp->states < -MINSTATES)
486 dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES;
487 else if (dp->states < MINSTATES)
488 dp->states = plots[1][nk];
489 if ((dp->cellList = (CellList **) calloc(dp->states,
490 sizeof (CellList *))) == NULL) {
491 free_demon(display, dp);
494 if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) {
495 free_demon(display, dp);
501 dp->width = MI_WIDTH(mi);
502 dp->height = MI_HEIGHT(mi);
504 if (dp->neighbors == 6) {
505 int nccols, ncrows, i;
512 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
513 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
514 else if (size < MINSIZE) {
516 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
520 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
523 nccols = MAX(dp->width / dp->xs - 2, 2);
524 ncrows = MAX(dp->height / dp->ys - 1, 4);
525 dp->ncols = nccols / 2;
526 dp->nrows = 2 * (ncrows / 4);
527 dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2;
528 dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys - 2;
529 for (i = 0; i < 6; i++) {
530 dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x;
531 dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
533 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
535 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
536 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
537 else if (size < MINSIZE) {
539 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
543 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
546 dp->ncols = MAX(dp->width / dp->xs, 2);
547 dp->nrows = MAX(dp->height / dp->ys, 2);
548 dp->xb = (dp->width - dp->xs * dp->ncols) / 2;
549 dp->yb = (dp->height - dp->ys * dp->nrows) / 2;
558 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
559 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
560 else if (size < MINSIZE) {
562 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
566 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
568 dp->xs = (int) (1.52 * dp->ys);
569 dp->ncols = (MAX(dp->width / dp->xs - 1, 2) / 2) * 2;
570 dp->nrows = (MAX(dp->height / dp->ys - 1, 2) / 2) * 2;
571 dp->xb = (dp->width - dp->xs * dp->ncols) / 2 + dp->xs / 2;
572 dp->yb = (dp->height - dp->ys * dp->nrows) / 2 + dp->ys / 2;
573 for (orient = 0; orient < 2; orient++) {
574 for (i = 0; i < 3; i++) {
575 dp->shape.triangle[orient][i].x =
576 (dp->xs - 2) * triangleUnit[orient][i].x;
577 dp->shape.triangle[orient][i].y =
578 (dp->ys - 2) * triangleUnit[orient][i].y;
585 if ((dp->oldcell = (unsigned char *)
586 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
587 free_demon(display, dp);
591 if ((dp->newcell = (unsigned char *)
592 malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
593 free_demon(display, dp);
601 draw_demon (ModeInfo * mi)
603 int i, j, k, l, mj = 0, ml;
608 dp = &demons[MI_SCREEN(mi)];
609 if (dp->cellList == NULL)
612 MI_IS_DRAWN(mi) = True;
613 if (dp->state >= dp->states) {
614 (void) memcpy((char *) dp->newcell, (char *) dp->oldcell,
615 dp->ncols * dp->nrows * sizeof (unsigned char));
617 if (dp->neighbors == 6) {
618 for (j = 0; j < dp->nrows; j++) {
619 for (i = 0; i < dp->ncols; i++) {
622 k = (i + 1 == dp->ncols) ? 0 : i + 1;
625 l = (!j) ? dp->nrows - 1 : 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];
631 k = (i + 1 == dp->ncols) ? 0 : i + 1;
633 if (dp->oldcell[k + ml] ==
634 (int) (dp->oldcell[i + mj] + 1) % dp->states)
635 dp->newcell[i + mj] = dp->oldcell[k + ml];
638 k = (i + 1 == dp->ncols) ? 0 : i + 1;
641 l = (j + 1 == dp->nrows) ? 0 : j + 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 + 1 == dp->nrows) ? 0 : 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];
657 k = (!i) ? dp->ncols - 1 : i - 1;
659 if (dp->oldcell[k + ml] ==
660 (int) (dp->oldcell[i + mj] + 1) % dp->states)
661 dp->newcell[i + mj] = dp->oldcell[k + ml];
664 k = (!i) ? dp->ncols - 1 : i - 1;
667 l = (!j) ? dp->nrows - 1 : j - 1;
669 if (dp->oldcell[k + ml] ==
670 (int) (dp->oldcell[i + mj] + 1) % dp->states)
671 dp->newcell[i + mj] = dp->oldcell[k + ml];
675 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
676 for (j = 0; j < dp->nrows; j++) {
677 for (i = 0; i < dp->ncols; i++) {
680 l = (!j) ? dp->nrows - 1 : j - 1;
682 if (dp->oldcell[k + ml] ==
683 (int) (dp->oldcell[i + mj] + 1) % dp->states)
684 dp->newcell[i + mj] = dp->oldcell[k + ml];
686 k = (i + 1 == dp->ncols) ? 0 : i + 1;
688 if (dp->oldcell[k + ml] ==
689 (int) (dp->oldcell[i + mj] + 1) % dp->states)
690 dp->newcell[i + mj] = dp->oldcell[k + ml];
693 l = (j + 1 == dp->nrows) ? 0 : 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) ? dp->ncols - 1 : i - 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];
708 if (dp->neighbors == 8) {
710 for (j = 0; j < dp->nrows; j++) {
711 for (i = 0; i < dp->ncols; i++) {
713 k = (i + 1 == dp->ncols) ? 0 : 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];
720 k = (i + 1 == dp->ncols) ? 0 : i + 1;
721 l = (j + 1 == dp->nrows) ? 0 : j + 1;
723 if (dp->oldcell[k + ml] ==
724 (int) (dp->oldcell[i + mj] + 1) % dp->states)
725 dp->newcell[i + mj] = dp->oldcell[k + ml];
727 k = (!i) ? dp->ncols - 1 : i - 1;
728 l = (j + 1 == dp->nrows) ? 0 : j + 1;
730 if (dp->oldcell[k + ml] ==
731 (int) (dp->oldcell[i + mj] + 1) % dp->states)
732 dp->newcell[i + mj] = dp->oldcell[k + ml];
734 k = (!i) ? dp->ncols - 1 : i - 1;
735 l = (!j) ? dp->nrows - 1 : j - 1;
737 if (dp->oldcell[k + ml] ==
738 (int) (dp->oldcell[i + mj] + 1) % dp->states)
739 dp->newcell[i + mj] = dp->oldcell[k + ml];
744 } else if (dp->neighbors == 3 || dp->neighbors == 9 ||
745 dp->neighbors == 12) {
746 for (j = 0; j < dp->nrows; j++) {
747 for (i = 0; i < dp->ncols; i++) {
748 if ((i + j) % 2) { /* right */
750 k = (!i) ? dp->ncols - 1 : i - 1;
752 if (dp->oldcell[k + ml] ==
753 (int) (dp->oldcell[i + mj] + 1) % dp->states)
754 dp->newcell[i + mj] = dp->oldcell[k + ml];
757 k = (i + 1 == dp->ncols) ? 0 : i + 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];
765 l = (!j) ? dp->nrows - 1 : j - 1;
767 if (dp->oldcell[k + ml] ==
768 (int) (dp->oldcell[i + mj] + 1) % dp->states)
769 dp->newcell[i + mj] = dp->oldcell[k + ml];
772 l = (j + 1 == dp->nrows) ? 0 : j + 1;
774 if (dp->oldcell[k + ml] ==
775 (int) (dp->oldcell[i + mj] + 1) % dp->states)
776 dp->newcell[i + mj] = dp->oldcell[k + ml];
780 if (dp->neighbors == 9 || dp->neighbors == 12) {
782 for (j = 0; j < dp->nrows; j++) {
783 for (i = 0; i < dp->ncols; i++) {
793 if (dp->oldcell[k + ml] ==
794 (int) (dp->oldcell[i + mj] + 1) % dp->states)
795 dp->newcell[i + mj] = dp->oldcell[k + ml];
798 if (j + 1 == dp->nrows)
800 else if (j + 2 == dp->nrows)
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) ? dp->ncols - 1 : i - 1;
810 l = (!j) ? dp->nrows - 1 : 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];
816 k = (i + 1 == dp->ncols) ? 0 : i + 1;
817 l = (!j) ? dp->nrows - 1 : j - 1;
819 if (dp->oldcell[k + ml] ==
820 (int) (dp->oldcell[i + mj] + 1) % dp->states)
821 dp->newcell[i + mj] = dp->oldcell[k + ml];
823 k = (!i) ? dp->ncols - 1 : i - 1;
824 l = (j + 1 == dp->nrows) ? 0 : j + 1;
826 if (dp->oldcell[k + ml] ==
827 (int) (dp->oldcell[i + mj] + 1) % dp->states)
828 dp->newcell[i + mj] = dp->oldcell[k + ml];
830 k = (i + 1 == dp->ncols) ? 0 : i + 1;
831 l = (j + 1 == dp->nrows) ? 0 : j + 1;
833 if (dp->oldcell[k + ml] ==
834 (int) (dp->oldcell[i + mj] + 1) % dp->states)
835 dp->newcell[i + mj] = dp->oldcell[k + ml];
839 if (dp->neighbors == 12) {
841 for (j = 0; j < dp->nrows; j++) {
842 for (i = 0; i < dp->ncols; i++) {
843 if ((i + j) % 2) { /* right */
845 k = (!i) ? dp->ncols - 1 : i - 1;
853 if (dp->oldcell[k + ml] ==
854 (int) (dp->oldcell[i + mj] + 1) % dp->states)
855 dp->newcell[i + mj] = dp->oldcell[k + ml];
857 k = (!i) ? dp->ncols - 1 : i - 1;
858 if (j + 1 == dp->nrows)
860 else if (j + 2 == dp->nrows)
865 if (dp->oldcell[k + ml] ==
866 (int) (dp->oldcell[i + mj] + 1) % dp->states)
867 dp->newcell[i + mj] = dp->oldcell[k + ml];
869 k = (i + 1 == dp->ncols) ? 0 : i + 1;
872 if (dp->oldcell[k + ml] ==
873 (int) (dp->oldcell[i + mj] + 1) % dp->states)
874 dp->newcell[i + mj] = dp->oldcell[k + ml];
877 k = (i + 1 == dp->ncols) ? 0 : i + 1;
885 if (dp->oldcell[k + ml] ==
886 (int) (dp->oldcell[i + mj] + 1) % dp->states)
887 dp->newcell[i + mj] = dp->oldcell[k + ml];
889 k = (i + 1 == dp->ncols) ? 0 : i + 1;
890 if (j + 1 == dp->nrows)
892 else if (j + 2 == dp->nrows)
897 if (dp->oldcell[k + ml] ==
898 (int) (dp->oldcell[i + mj] + 1) % dp->states)
899 dp->newcell[i + mj] = dp->oldcell[k + ml];
901 k = (!i) ? dp->ncols - 1 : i - 1;
904 if (dp->oldcell[k + ml] ==
905 (int) (dp->oldcell[i + mj] + 1) % dp->states)
906 dp->newcell[i + mj] = dp->oldcell[k + ml];
915 for (j = 0; j < dp->nrows; j++) {
916 for (i = 0; i < dp->ncols; i++)
917 if (dp->oldcell[i + mj] != dp->newcell[i + mj]) {
918 dp->oldcell[i + mj] = dp->newcell[i + mj];
919 if (!addtolist(mi, i, j, dp->oldcell[i + mj])) {
920 free_demon(MI_DISPLAY(mi), dp);
926 if (++dp->generation > MI_CYCLES(mi))
930 if (dp->ncells[dp->state])
931 if (!draw_state(mi, dp->state)) {
932 free_demon(MI_DISPLAY(mi), dp);
938 for (i = 0; i < REDRAWSTEP; i++) {
939 if (dp->oldcell[dp->redrawpos]) {
940 drawcell(mi, dp->redrawpos % dp->ncols, dp->redrawpos / dp->ncols,
941 dp->oldcell[dp->redrawpos]);
943 if (++(dp->redrawpos) >= dp->ncols * dp->nrows) {
953 reshape_demon(ModeInfo * mi, int width, int height)
955 XClearWindow (MI_DISPLAY (mi), MI_WINDOW(mi));
961 release_demon (ModeInfo * mi)
963 if (demons != NULL) {
966 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
967 free_demon(MI_DISPLAY(mi), &demons[screen]);
968 (void) free((void *) demons);
969 demons = (demonstruct *) NULL;
974 refresh_demon (ModeInfo * mi)
980 dp = &demons[MI_SCREEN(mi)];
986 XSCREENSAVER_MODULE ("Demon", demon)
988 #endif /* MODE_demon */