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 4.07 97/11/24 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 * 10-May-97: Compatible with xscreensaver
26 * 16-Apr-97: -neighbors 3, 9 (not sound mathematically), 12, and 8 added
27 * 30-May-96: Ron Hitchens <ron@idiom.com>
28 * Fixed memory management that caused leaks
29 * 14-Apr-96: -neighbors 6 runtime-time option added
30 * 21-Aug-95: Coded from A.K. Dewdney's "Computer Recreations", Scientific
31 * American Magazine" Aug 1989 pp 102-105. Also very similar to
32 * hodgepodge machine described in A.K. Dewdney's "Computer
33 * Recreations", Scientific American Magazine" Aug 1988 pp 104-107.
34 * also used life.c as a guide.
38 * A cellular universe of 4 phases debris, droplets, defects, and demons.
42 Grid Number of Neigbors
43 ---- ------------------
50 #define PROGCLASS "Demon"
51 #define HACK_INIT init_demon
52 #define HACK_DRAW draw_demon
53 #define demon_opts xlockmore_opts
54 #define DEFAULTS "*delay: 50000 \n" \
60 # define SMOOTH_COLORS
61 # include "xlockmore.h" /* in xscreensaver distribution */
62 #else /* STANDALONE */
63 # include "xlock.h" /* in xlockmore distribution */
64 #endif /* STANDALONE */
68 * neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12.
74 #endif /* !STANDALONE */
76 ModeSpecOpt demon_opts =
77 {0, NULL, 0, NULL, NULL};
80 ModStruct demon_description =
81 {"demon", "init_demon", "draw_demon", "release_demon",
82 "refresh_demon", "init_demon", NULL, &demon_opts,
83 50000, 0, 1000, -7, 64, 1.0, "",
84 "Shows Griffeath's cellular automata", 0, NULL};
88 #define DEMONBITS(n,w,h)\
89 dp->pixmaps[dp->init_bits++]=\
90 XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1)
92 #define REDRAWSTEP 2000 /* How many cells to draw per cycle */
94 #define MINGRIDSIZE 24
96 #define NEIGHBORKINDS 6
98 /* Singly linked list */
99 typedef struct _CellList {
101 struct _CellList *next;
112 int redrawing, redrawpos;
115 unsigned char *oldcell, *newcell;
119 Pixmap pixmaps[NUMSTIPPLES - 1];
122 XPoint triangle[2][3];
126 static char plots[2][NEIGHBORKINDS] =
128 {3, 4, 6, 8, 9, 12}, /* Neighborhoods */
129 {12, 16, 18, 20, 22, 24} /* Number of states */
132 static demonstruct *demons = NULL;
135 drawcell(ModeInfo * mi, int col, int row, unsigned char state)
137 demonstruct *dp = &demons[MI_SCREEN(mi)];
141 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
143 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
144 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
145 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
146 (dp->states - 1)) % MI_NPIXELS(mi)));
151 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
152 gcv.foreground = MI_WHITE_PIXEL(mi);
153 gcv.background = MI_BLACK_PIXEL(mi);
154 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
155 GCStipple | GCForeground | GCBackground, &gcv);
158 if (dp->neighbors == 6) {
159 int ccol = 2 * col + !(row & 1), crow = 2 * row;
161 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
162 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
163 if (dp->xs == 1 && dp->ys == 1)
164 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi),
165 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y, 1, 1);
167 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
168 dp->shape.hexagon, 6, Convex, CoordModePrevious);
169 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
170 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
171 dp->xb + dp->xs * col, dp->yb + dp->ys * row,
172 dp->xs - (dp->xs > 3), dp->ys - (dp->ys > 3));
174 int orient = (col + row) % 2; /* O left 1 right */
176 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
177 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
178 if (dp->xs <= 3 || dp->ys <= 3)
179 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
180 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
181 dp->shape.triangle[orient][0].y, 1, 1);
184 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
186 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
187 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
188 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
195 addtolist(ModeInfo * mi, int col, int row, unsigned char state)
197 demonstruct *dp = &demons[MI_SCREEN(mi)];
200 current = dp->cellList[state];
201 dp->cellList[state] = (CellList *) malloc(sizeof (CellList));
202 dp->cellList[state]->pt.x = col;
203 dp->cellList[state]->pt.y = row;
204 dp->cellList[state]->next = current;
210 print_state(ModeInfo * mi, int state)
212 demonstruct *dp = &demons[MI_SCREEN(mi)];
216 locallist = dp->cellList[state];
217 (void) printf("state %d\n", state);
219 (void) printf("%d x %d, y %d\n", i,
220 locallist->pt.x, locallist->pt.y);
221 locallist = locallist->next;
229 free_state(demonstruct * dp, int state)
233 while (dp->cellList[state]) {
234 current = dp->cellList[state];
235 dp->cellList[state] = dp->cellList[state]->next;
236 (void) free((void *) current);
238 dp->cellList[state] = NULL;
240 dp->ncells[state] = 0;
245 free_list(demonstruct * dp)
249 for (state = 0; state < dp->states; state++)
250 free_state(dp, state);
251 (void) free((void *) dp->cellList);
256 free_struct(demonstruct * dp)
258 if (dp->cellList != NULL) {
261 if (dp->ncells != NULL) {
262 (void) free((void *) dp->ncells);
265 if (dp->oldcell != NULL) {
266 (void) free((void *) dp->oldcell);
269 if (dp->newcell != NULL) {
270 (void) free((void *) dp->newcell);
276 draw_state(ModeInfo * mi, int state)
278 demonstruct *dp = &demons[MI_SCREEN(mi)];
284 XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
286 } else if (MI_NPIXELS(mi) >= NUMSTIPPLES) {
287 XSetForeground(MI_DISPLAY(mi), MI_GC(mi),
288 MI_PIXEL(mi, (((int) state - 1) * MI_NPIXELS(mi) /
289 (dp->states - 1)) % MI_NPIXELS(mi)));
294 gcv.stipple = dp->pixmaps[(state - 1) % (NUMSTIPPLES - 1)];
295 gcv.foreground = MI_WHITE_PIXEL(mi);
296 gcv.background = MI_BLACK_PIXEL(mi);
297 XChangeGC(MI_DISPLAY(mi), dp->stippledGC,
298 GCStipple | GCForeground | GCBackground, &gcv);
301 if (dp->neighbors == 6) { /* Draw right away, slow */
302 current = dp->cellList[state];
304 int col, row, ccol, crow;
308 ccol = 2 * col + !(row & 1), crow = 2 * row;
309 dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
310 dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
311 if (dp->xs == 1 && dp->ys == 1)
312 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi),
313 gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y, 1, 1);
315 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
316 dp->shape.hexagon, 6, Convex, CoordModePrevious);
317 current = current->next;
319 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
320 /* Take advantage of XDrawRectangles */
323 /* Create Rectangle list from part of the cellList */
324 rects = (XRectangle *) malloc(dp->ncells[state] * sizeof (XRectangle));
325 current = dp->cellList[state];
327 rects[ncells].x = dp->xb + current->pt.x * dp->xs;
328 rects[ncells].y = dp->yb + current->pt.y * dp->ys;
329 rects[ncells].width = dp->xs - (dp->xs > 3);
330 rects[ncells].height = dp->ys - (dp->ys > 3);
331 current = current->next;
334 /* Finally get to draw */
335 XFillRectangles(MI_DISPLAY(mi), MI_WINDOW(mi), gc, rects, ncells);
336 /* Free up rects list and the appropriate part of the cellList */
337 (void) free((void *) rects);
339 current = dp->cellList[state];
341 int col, row, orient;
345 orient = (col + row) % 2; /* O left 1 right */
346 dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
347 dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
348 if (dp->xs <= 3 || dp->ys <= 3)
349 XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
350 ((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
351 dp->shape.triangle[orient][0].y, 1, 1);
354 dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
356 dp->shape.triangle[orient][0].x -= (dp->xs / 2 - 1);
357 XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
358 dp->shape.triangle[orient], 3, Convex, CoordModePrevious);
360 current = current->next;
363 free_state(dp, state);
364 XFlush(MI_DISPLAY(mi));
368 RandomSoup(ModeInfo * mi)
370 demonstruct *dp = &demons[MI_SCREEN(mi)];
371 int row, col, mrow = 0;
373 for (row = 0; row < dp->nrows; ++row) {
374 for (col = 0; col < dp->ncols; ++col) {
375 dp->oldcell[col + mrow] =
376 (unsigned char) LRAND() % ((unsigned char) dp->states);
377 addtolist(mi, col, row, dp->oldcell[col + mrow]);
384 init_demon(ModeInfo * mi)
386 Display *display = MI_DISPLAY(mi);
387 Window window = MI_WINDOW(mi);
388 int size = MI_SIZE(mi), nk;
391 if (demons == NULL) {
392 if ((demons = (demonstruct *) calloc(MI_NUM_SCREENS(mi),
393 sizeof (demonstruct))) == NULL)
396 dp = &demons[MI_SCREEN(mi)];
399 if (MI_NPIXELS(mi) < NUMSTIPPLES) {
400 if (dp->stippledGC == None) {
403 gcv.fill_style = FillOpaqueStippled;
404 dp->stippledGC = XCreateGC(display, window, GCFillStyle, &gcv);
406 if (dp->init_bits == 0) {
409 for (i = 1; i < NUMSTIPPLES; i++)
410 DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
415 for (nk = 0; nk < NEIGHBORKINDS; nk++) {
416 if (neighbors == plots[0][nk]) {
417 dp->neighbors = plots[0][nk];
420 if (nk == NEIGHBORKINDS - 1) {
421 nk = NRAND(NEIGHBORKINDS);
422 dp->neighbors = plots[0][nk];
427 dp->states = MI_COUNT(mi);
428 if (dp->states < -MINSTATES)
429 dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES;
430 else if (dp->states < MINSTATES)
431 dp->states = plots[1][nk];
432 dp->cellList = (CellList **) calloc(dp->states, sizeof (CellList *));
433 dp->ncells = (int *) calloc(dp->states, sizeof (int));
437 dp->width = MI_WIDTH(mi);
438 dp->height = MI_HEIGHT(mi);
440 if (dp->neighbors == 6) {
441 int nccols, ncrows, i;
448 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
449 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
450 else if (size < MINSIZE) {
452 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
456 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
459 nccols = MAX(dp->width / dp->xs - 2, 2);
460 ncrows = MAX(dp->height / dp->ys - 1, 2);
461 dp->ncols = nccols / 2;
462 dp->nrows = 2 * (ncrows / 4);
463 dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2;
464 dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys;
465 for (i = 0; i < 6; i++) {
466 dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x;
467 dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
469 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
471 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
472 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
473 else if (size < MINSIZE) {
475 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
479 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
482 dp->ncols = MAX(dp->width / dp->xs, 2);
483 dp->nrows = MAX(dp->height / dp->ys, 2);
484 dp->xb = (dp->width - dp->xs * dp->ncols) / 2;
485 dp->yb = (dp->height - dp->ys * dp->nrows) / 2;
494 dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
495 MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
496 else if (size < MINSIZE) {
498 dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
502 dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
504 dp->xs = (int) (1.52 * dp->ys);
505 dp->ncols = (MAX(dp->width / dp->xs - 1, 2) / 2) * 2;
506 dp->nrows = (MAX(dp->height / dp->ys - 1, 2) / 2) * 2;
507 dp->xb = (dp->width - dp->xs * dp->ncols) / 2 + dp->xs / 2;
508 dp->yb = (dp->height - dp->ys * dp->nrows) / 2 + dp->ys / 2;
509 for (orient = 0; orient < 2; orient++) {
510 for (i = 0; i < 3; i++) {
511 dp->shape.triangle[orient][i].x =
512 (dp->xs - 2) * triangleUnit[orient][i].x;
513 dp->shape.triangle[orient][i].y =
514 (dp->ys - 2) * triangleUnit[orient][i].y;
521 dp->oldcell = (unsigned char *)
522 malloc(dp->ncols * dp->nrows * sizeof (unsigned char));
524 dp->newcell = (unsigned char *)
525 malloc(dp->ncols * dp->nrows * sizeof (unsigned char));
531 draw_demon(ModeInfo * mi)
533 demonstruct *dp = &demons[MI_SCREEN(mi)];
534 int i, j, k, l, mj = 0, ml;
536 MI_IS_DRAWN(mi) = True;
538 if (dp->state >= dp->states) {
539 (void) memcpy((char *) dp->newcell, (char *) dp->oldcell,
540 dp->ncols * dp->nrows * sizeof (unsigned char));
542 if (dp->neighbors == 6) {
543 for (j = 0; j < dp->nrows; j++) {
544 for (i = 0; i < dp->ncols; i++) {
547 k = (i + 1 == dp->ncols) ? 0 : i + 1;
550 l = (!j) ? dp->nrows - 1 : j - 1;
552 if (dp->oldcell[k + ml] ==
553 (int) (dp->oldcell[i + mj] + 1) % dp->states)
554 dp->newcell[i + mj] = dp->oldcell[k + ml];
556 k = (i + 1 == dp->ncols) ? 0 : i + 1;
559 if (dp->oldcell[k + ml] ==
560 (int) (dp->oldcell[i + mj] + 1) % dp->states)
561 dp->newcell[i + mj] = dp->oldcell[k + ml];
564 k = (i + 1 == dp->ncols) ? 0 : i + 1;
567 l = (j + 1 == dp->nrows) ? 0 : j + 1;
569 if (dp->oldcell[k + ml] ==
570 (int) (dp->oldcell[i + mj] + 1) % dp->states)
571 dp->newcell[i + mj] = dp->oldcell[k + ml];
574 k = (!i) ? dp->ncols - 1 : i - 1;
577 l = (j + 1 == dp->nrows) ? 0 : j + 1;
579 if (dp->oldcell[k + ml] ==
580 (int) (dp->oldcell[i + mj] + 1) % dp->states)
581 dp->newcell[i + mj] = dp->oldcell[k + ml];
583 k = (!i) ? dp->ncols - 1 : i - 1;
586 if (dp->oldcell[k + ml] ==
587 (int) (dp->oldcell[i + mj] + 1) % dp->states)
588 dp->newcell[i + mj] = dp->oldcell[k + ml];
591 k = (!i) ? dp->ncols - 1 : i - 1;
594 l = (!j) ? dp->nrows - 1 : j - 1;
596 if (dp->oldcell[k + ml] ==
597 (int) (dp->oldcell[i + mj] + 1) % dp->states)
598 dp->newcell[i + mj] = dp->oldcell[k + ml];
602 } else if (dp->neighbors == 4 || dp->neighbors == 8) {
603 for (j = 0; j < dp->nrows; j++) {
604 for (i = 0; i < dp->ncols; i++) {
607 l = (!j) ? dp->nrows - 1 : j - 1;
609 if (dp->oldcell[k + ml] ==
610 (int) (dp->oldcell[i + mj] + 1) % dp->states)
611 dp->newcell[i + mj] = dp->oldcell[k + ml];
613 k = (i + 1 == dp->ncols) ? 0 : i + 1;
616 if (dp->oldcell[k + ml] ==
617 (int) (dp->oldcell[i + mj] + 1) % dp->states)
618 dp->newcell[i + mj] = dp->oldcell[k + ml];
621 l = (j + 1 == dp->nrows) ? 0 : j + 1;
623 if (dp->oldcell[k + ml] ==
624 (int) (dp->oldcell[i + mj] + 1) % dp->states)
625 dp->newcell[i + mj] = dp->oldcell[k + ml];
627 k = (!i) ? dp->ncols - 1 : i - 1;
630 if (dp->oldcell[k + ml] ==
631 (int) (dp->oldcell[i + mj] + 1) % dp->states)
632 dp->newcell[i + mj] = dp->oldcell[k + ml];
636 if (dp->neighbors == 8) {
638 for (j = 0; j < dp->nrows; j++) {
639 for (i = 0; i < dp->ncols; i++) {
641 k = (i + 1 == dp->ncols) ? 0 : i + 1;
642 l = (!j) ? dp->nrows - 1 : 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 + 1 == dp->ncols) ? 0 : i + 1;
649 l = (j + 1 == dp->nrows) ? 0 : j + 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];
655 k = (!i) ? dp->ncols - 1 : i - 1;
656 l = (j + 1 == dp->nrows) ? 0 : j + 1;
658 if (dp->oldcell[k + ml] ==
659 (int) (dp->oldcell[i + mj] + 1) % dp->states)
660 dp->newcell[i + mj] = dp->oldcell[k + ml];
662 k = (!i) ? dp->ncols - 1 : i - 1;
663 l = (!j) ? dp->nrows - 1 : j - 1;
665 if (dp->oldcell[k + ml] ==
666 (int) (dp->oldcell[i + mj] + 1) % dp->states)
667 dp->newcell[i + mj] = dp->oldcell[k + ml];
672 } else if (dp->neighbors == 3 || dp->neighbors == 9 ||
673 dp->neighbors == 12) {
674 for (j = 0; j < dp->nrows; j++) {
675 for (i = 0; i < dp->ncols; i++) {
676 if ((i + j) % 2) { /* right */
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];
686 k = (i + 1 == dp->ncols) ? 0 : i + 1;
689 if (dp->oldcell[k + ml] ==
690 (int) (dp->oldcell[i + mj] + 1) % dp->states)
691 dp->newcell[i + mj] = dp->oldcell[k + ml];
695 l = (!j) ? dp->nrows - 1 : j - 1;
697 if (dp->oldcell[k + ml] ==
698 (int) (dp->oldcell[i + mj] + 1) % dp->states)
699 dp->newcell[i + mj] = dp->oldcell[k + ml];
702 l = (j + 1 == dp->nrows) ? 0 : j + 1;
704 if (dp->oldcell[k + ml] ==
705 (int) (dp->oldcell[i + mj] + 1) % dp->states)
706 dp->newcell[i + mj] = dp->oldcell[k + ml];
710 if (dp->neighbors == 9 || dp->neighbors == 12) {
712 for (j = 0; j < dp->nrows; j++) {
713 for (i = 0; i < dp->ncols; i++) {
723 if (dp->oldcell[k + ml] ==
724 (int) (dp->oldcell[i + mj] + 1) % dp->states)
725 dp->newcell[i + mj] = dp->oldcell[k + ml];
728 if (j + 1 == dp->nrows)
730 else if (j + 2 == dp->nrows)
735 if (dp->oldcell[k + ml] ==
736 (int) (dp->oldcell[i + mj] + 1) % dp->states)
737 dp->newcell[i + mj] = dp->oldcell[k + ml];
739 k = (!i) ? dp->ncols - 1 : i - 1;
740 l = (!j) ? dp->nrows - 1 : j - 1;
742 if (dp->oldcell[k + ml] ==
743 (int) (dp->oldcell[i + mj] + 1) % dp->states)
744 dp->newcell[i + mj] = dp->oldcell[k + ml];
746 k = (i + 1 == dp->ncols) ? 0 : i + 1;
747 l = (!j) ? dp->nrows - 1 : j - 1;
749 if (dp->oldcell[k + ml] ==
750 (int) (dp->oldcell[i + mj] + 1) % dp->states)
751 dp->newcell[i + mj] = dp->oldcell[k + ml];
753 k = (!i) ? dp->ncols - 1 : i - 1;
754 l = (j + 1 == dp->nrows) ? 0 : j + 1;
756 if (dp->oldcell[k + ml] ==
757 (int) (dp->oldcell[i + mj] + 1) % dp->states)
758 dp->newcell[i + mj] = dp->oldcell[k + ml];
760 k = (i + 1 == dp->ncols) ? 0 : i + 1;
761 l = (j + 1 == dp->nrows) ? 0 : j + 1;
763 if (dp->oldcell[k + ml] ==
764 (int) (dp->oldcell[i + mj] + 1) % dp->states)
765 dp->newcell[i + mj] = dp->oldcell[k + ml];
769 if (dp->neighbors == 12) {
771 for (j = 0; j < dp->nrows; j++) {
772 for (i = 0; i < dp->ncols; i++) {
773 if ((i + j) % 2) { /* right */
775 k = (!i) ? dp->ncols - 1 : i - 1;
783 if (dp->oldcell[k + ml] ==
784 (int) (dp->oldcell[i + mj] + 1) % dp->states)
785 dp->newcell[i + mj] = dp->oldcell[k + ml];
787 k = (!i) ? dp->ncols - 1 : i - 1;
788 if (j + 1 == dp->nrows)
790 else if (j + 2 == dp->nrows)
795 if (dp->oldcell[k + ml] ==
796 (int) (dp->oldcell[i + mj] + 1) % dp->states)
797 dp->newcell[i + mj] = dp->oldcell[k + ml];
799 k = (i + 1 == dp->ncols) ? 0 : i + 1;
802 if (dp->oldcell[k + ml] ==
803 (int) (dp->oldcell[i + mj] + 1) % dp->states)
804 dp->newcell[i + mj] = dp->oldcell[k + ml];
807 k = (i + 1 == dp->ncols) ? 0 : i + 1;
815 if (dp->oldcell[k + ml] ==
816 (int) (dp->oldcell[i + mj] + 1) % dp->states)
817 dp->newcell[i + mj] = dp->oldcell[k + ml];
819 k = (i + 1 == dp->ncols) ? 0 : i + 1;
820 if (j + 1 == dp->nrows)
822 else if (j + 2 == dp->nrows)
827 if (dp->oldcell[k + ml] ==
828 (int) (dp->oldcell[i + mj] + 1) % dp->states)
829 dp->newcell[i + mj] = dp->oldcell[k + ml];
831 k = (!i) ? dp->ncols - 1 : i - 1;
834 if (dp->oldcell[k + ml] ==
835 (int) (dp->oldcell[i + mj] + 1) % dp->states)
836 dp->newcell[i + mj] = dp->oldcell[k + ml];
845 for (j = 0; j < dp->nrows; j++) {
846 for (i = 0; i < dp->ncols; i++)
847 if (dp->oldcell[i + mj] != dp->newcell[i + mj]) {
848 dp->oldcell[i + mj] = dp->newcell[i + mj];
849 addtolist(mi, i, j, dp->oldcell[i + mj]);
853 if (++dp->generation > MI_CYCLES(mi))
857 if (dp->ncells[dp->state])
858 draw_state(mi, dp->state);
862 for (i = 0; i < REDRAWSTEP; i++) {
863 if (dp->oldcell[dp->redrawpos]) {
864 drawcell(mi, dp->redrawpos % dp->ncols, dp->redrawpos / dp->ncols,
865 dp->oldcell[dp->redrawpos]);
867 if (++(dp->redrawpos) >= dp->ncols * dp->nrows) {
875 release_demon(ModeInfo * mi)
877 if (demons != NULL) {
880 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
881 demonstruct *dp = &demons[screen];
884 if (dp->stippledGC != None) {
885 XFreeGC(MI_DISPLAY(mi), dp->stippledGC);
887 for (shade = 0; shade < dp->init_bits; shade++)
888 XFreePixmap(MI_DISPLAY(mi), dp->pixmaps[shade]);
891 (void) free((void *) demons);
896 refresh_demon(ModeInfo * mi)
898 demonstruct *dp = &demons[MI_SCREEN(mi)];