source: trunk/third/xscreensaver/hacks/demon.c @ 20148

Revision 20148, 26.7 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r20147, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 4 -*- */
2/* demon --- David Griffeath's cellular automata */
3
4#if 0
5static const char sccsid[] = "@(#)demon.c       5.00 2000/11/01 xlockmore";
6#endif
7
8/*-
9 * Copyright (c) 1995 by David Bagley.
10 *
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.
16 *
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.
22 *
23 * Revision History:
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.
35 */
36
37/*-
38 * A cellular universe of 4 phases debris, droplets, defects, and demons.
39 */
40
41/*-
42  Grid     Number of Neighbors
43  ----     ------------------
44  Square   4 or 8
45  Hexagon  6
46  Triangle 3, 9, or 12
47*/
48
49#ifdef STANDALONE
50#define MODE_demon
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" \
56 "*count: 0 \n" \
57 "*cycles: 1000 \n" \
58 "*size: -7 \n" \
59 "*ncolors: 64 \n" \
60 "*neighbors: 0 \n"
61#define UNIFORM_COLORS
62#include "xlockmore.h"          /* in xscreensaver distribution */
63#else /* STANDALONE */
64#include "xlock.h"              /* in xlockmore distribution */
65
66#endif /* STANDALONE */
67#include "automata.h"
68
69#ifdef MODE_demon
70
71/*-
72 * neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12.
73 */
74#define DEF_NEIGHBORS  "0"      /* choose random value */
75
76static int  neighbors;
77
78static XrmOptionDescRec opts[] =
79{
80        {(char *) "-neighbors", (char *) ".demon.neighbors", XrmoptionSepArg, (caddr_t) NULL}
81};
82
83static argtype vars[] =
84{
85        {(caddr_t *) & neighbors, (char *) "neighbors", (char *) "Neighbors", (char *) DEF_NEIGHBORS, t_Int}
86};
87static OptionStruct desc[] =
88{
89        {(char *) "-neighbors num", (char *) "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"}
90};
91
92ModeSpecOpt demon_opts =
93{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
94
95#ifdef USE_MODULES
96ModStruct   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};
101
102#endif
103
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++;}
108
109#define REDRAWSTEP 2000         /* How many cells to draw per cycle */
110#define MINSTATES 2
111#define MINGRIDSIZE 24
112#define MINSIZE 4
113#define NEIGHBORKINDS 6
114
115/* Singly linked list */
116typedef struct _CellList {
117        XPoint      pt;
118        struct _CellList *next;
119} CellList;
120
121typedef struct {
122        int         generation;
123        int         xs, ys;
124        int         xb, yb;
125        int         nrows, ncols;
126        int         width, height;
127        int         states;
128        int         state;
129        int         redrawing, redrawpos;
130        int        *ncells;
131        CellList  **cellList;
132        unsigned char *oldcell, *newcell;
133        int         neighbors;
134        int         init_bits;
135        GC          stippledGC;
136        Pixmap      pixmaps[NUMSTIPPLES - 1];
137        union {
138                XPoint      hexagon[6];
139                XPoint      triangle[2][3];
140        } shape;
141} demonstruct;
142
143static char plots[2][NEIGHBORKINDS] =
144{
145        {3, 4, 6, 8, 9, 12},    /* Neighborhoods */
146        {12, 16, 18, 20, 22, 24}        /* Number of states */
147};
148
149static demonstruct *demons = (demonstruct *) NULL;
150
151static void
152drawcell(ModeInfo * mi, int col, int row, unsigned char state)
153{
154        demonstruct *dp = &demons[MI_SCREEN(mi)];
155        GC          gc;
156
157        if (!state) {
158                XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
159                gc = MI_GC(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)));
164                gc = MI_GC(mi);
165        } else {
166                XGCValues   gcv;
167
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);
173                gc = dp->stippledGC;
174        }
175        if (dp->neighbors == 6) {
176                int         ccol = 2 * col + !(row & 1), crow = 2 * row;
177
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);
183                else
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));
190        } else {                /* TRI */
191                int         orient = (col + row) % 2;   /* O left 1 right */
192
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);
199                else {
200                        if (orient)
201                                dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
202                        else
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);
206
207                }
208        }
209}
210
211static Bool
212addtolist(ModeInfo * mi, int col, int row, unsigned char state)
213{
214        demonstruct *dp = &demons[MI_SCREEN(mi)];
215        CellList   *current;
216
217        current = dp->cellList[state];
218        if ((dp->cellList[state] = (CellList *)
219                malloc(sizeof (CellList))) == NULL) {
220                return False;
221        }
222        dp->cellList[state]->pt.x = col;
223        dp->cellList[state]->pt.y = row;
224        dp->cellList[state]->next = current;
225        dp->ncells[state]++;
226        return True;
227}
228
229#ifdef DEBUG
230static void
231print_state(ModeInfo * mi, int state)
232{
233        demonstruct *dp = &demons[MI_SCREEN(mi)];
234        CellList   *locallist;
235        int         i = 0;
236
237        locallist = dp->cellList[state];
238        (void) printf("state %d\n", state);
239        while (locallist) {
240                (void) printf("%d       x %d, y %d\n", i,
241                              locallist->pt.x, locallist->pt.y);
242                locallist = locallist->next;
243                i++;
244        }
245}
246
247#endif
248
249static void
250free_state(demonstruct * dp, int state)
251{
252        CellList   *current;
253
254        while (dp->cellList[state]) {
255                current = dp->cellList[state];
256                dp->cellList[state] = dp->cellList[state]->next;
257                (void) free((void *) current);
258        }
259        dp->cellList[state] = (CellList *) NULL;
260        if (dp->ncells != NULL)
261                dp->ncells[state] = 0;
262}
263
264
265static void
266free_list(demonstruct * dp)
267{
268        int         state;
269
270        for (state = 0; state < dp->states; state++)
271                free_state(dp, state);
272        (void) free((void *) dp->cellList);
273        dp->cellList = (CellList **) NULL;
274}
275
276static void
277free_struct(demonstruct * dp)
278{
279        if (dp->cellList != NULL) {
280                free_list(dp);
281        }
282        if (dp->ncells != NULL) {
283                (void) free((void *) dp->ncells);
284                dp->ncells = (int *) NULL;
285        }
286        if (dp->oldcell != NULL) {
287                (void) free((void *) dp->oldcell);
288                dp->oldcell = (unsigned char *) NULL;
289        }
290        if (dp->newcell != NULL) {
291                (void) free((void *) dp->newcell);
292                dp->newcell = (unsigned char *) NULL;
293        }
294}
295
296static void
297free_demon(Display *display, demonstruct *dp)
298{
299        int         shade;
300
301        if (dp->stippledGC != None) {
302                XFreeGC(display, dp->stippledGC);
303                dp->stippledGC = None;
304        }
305        for (shade = 0; shade < dp->init_bits; shade++) {
306                XFreePixmap(display, dp->pixmaps[shade]);
307        }
308        dp->init_bits = 0;
309        free_struct(dp);
310}
311
312static Bool
313draw_state(ModeInfo * mi, int state)
314{
315        demonstruct *dp = &demons[MI_SCREEN(mi)];
316        GC          gc;
317        XRectangle *rects;
318        CellList   *current;
319
320        if (!state) {
321                XSetForeground(MI_DISPLAY(mi), MI_GC(mi), MI_BLACK_PIXEL(mi));
322                gc = MI_GC(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)));
327                gc = MI_GC(mi);
328        } else {
329                XGCValues   gcv;
330
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);
336                gc = dp->stippledGC;
337        }
338        if (dp->neighbors == 6) {       /* Draw right away, slow */
339                current = dp->cellList[state];
340                while (current) {
341                        int         col, row, ccol, crow;
342
343                        col = current->pt.x;
344                        row = current->pt.y;
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);
351                        else
352                                XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
353                                             dp->shape.hexagon, 6, Convex, CoordModePrevious);
354                        current = current->next;
355                }
356        } else if (dp->neighbors == 4 || dp->neighbors == 8) {
357                /* Take advantage of XDrawRectangles */
358                int         ncells = 0;
359
360                /* Create Rectangle list from part of the cellList */
361                if ((rects = (XRectangle *) malloc(dp->ncells[state] *
362                         sizeof (XRectangle))) == NULL) {
363                        return False;
364                }
365                current = dp->cellList[state];
366                while (current) {
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;
372                        ncells++;
373                }
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);
378        } else {                /* TRI */
379                current = dp->cellList[state];
380                while (current) {
381                        int         col, row, orient;
382
383                        col = current->pt.x;
384                        row = current->pt.y;
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);
392                        else {
393                                if (orient)
394                                        dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
395                                else
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);
399                        }
400                        current = current->next;
401                }
402        }
403        free_state(dp, state);
404        XFlush(MI_DISPLAY(mi));
405        return True;
406}
407
408static void
409RandomSoup(ModeInfo * mi)
410{
411        demonstruct *dp = &demons[MI_SCREEN(mi)];
412        int         row, col, mrow = 0;
413
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 */
420                }
421                mrow += dp->ncols;
422        }
423}
424
425void
426init_demon(ModeInfo * mi)
427{
428        Display    *display = MI_DISPLAY(mi);
429        Window      window = MI_WINDOW(mi);
430        int         size = MI_SIZE(mi), nk;
431        demonstruct *dp;
432
433        if (demons == NULL) {
434                if ((demons = (demonstruct *) calloc(MI_NUM_SCREENS(mi),
435                                              sizeof (demonstruct))) == NULL)
436                        return;
437        }
438        dp = &demons[MI_SCREEN(mi)];
439
440        dp->generation = 0;
441        dp->redrawing = 0;
442        if (MI_NPIXELS(mi) < NUMSTIPPLES) {
443                if (dp->stippledGC == None) {
444                        XGCValues   gcv;
445
446                        gcv.fill_style = FillOpaqueStippled;
447                        if ((dp->stippledGC = XCreateGC(display, window,
448                                 GCFillStyle, &gcv)) == None) {
449                                free_demon(display, dp);
450                                return;
451                        }
452                }
453                if (dp->init_bits == 0) {
454                        int         i;
455
456                        for (i = 1; i < NUMSTIPPLES; i++) {
457                                DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
458                        }
459                }
460        }
461        free_struct(dp);
462
463        for (nk = 0; nk < NEIGHBORKINDS; nk++) {
464                if (neighbors == plots[0][nk]) {
465                        dp->neighbors = plots[0][nk];
466                        break;
467                }
468                if (nk == NEIGHBORKINDS - 1) {
469                        nk = NRAND(NEIGHBORKINDS);
470                        dp->neighbors = plots[0][nk];
471                        break;
472                }
473        }
474
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);
483                return;
484        }
485        if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) {
486                free_demon(display, dp);
487                return;
488        }
489
490        dp->state = 0;
491
492        dp->width = MI_WIDTH(mi);
493        dp->height = MI_HEIGHT(mi);
494
495        if (dp->neighbors == 6) {
496                int         nccols, ncrows, i;
497
498                if (dp->width < 8)
499                        dp->width = 8;
500                if (dp->height < 8)
501                        dp->height = 8;
502                if (size < -MINSIZE)
503                        dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
504                                      MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
505                else if (size < MINSIZE) {
506                        if (!size)
507                                dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
508                        else
509                                dp->ys = MINSIZE;
510                } else
511                        dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
512                                               MINGRIDSIZE));
513                dp->xs = dp->ys;
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;
523                }
524        } else if (dp->neighbors == 4 || dp->neighbors == 8) {
525                if (size < -MINSIZE)
526                        dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
527                                      MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
528                else if (size < MINSIZE) {
529                        if (!size)
530                                dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
531                        else
532                                dp->ys = MINSIZE;
533                } else
534                        dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
535                                               MINGRIDSIZE));
536                dp->xs = dp->ys;
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;
541        } else {                /* TRI */
542                int         orient, i;
543
544                if (dp->width < 2)
545                        dp->width = 2;
546                if (dp->height < 2)
547                        dp->height = 2;
548                if (size < -MINSIZE)
549                        dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
550                                      MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
551                else if (size < MINSIZE) {
552                        if (!size)
553                                dp->ys = MAX(MINSIZE, MIN(dp->width, dp->height) / MINGRIDSIZE);
554                        else
555                                dp->ys = MINSIZE;
556                } else
557                        dp->ys = MIN(size, MAX(MINSIZE, MIN(dp->width, dp->height) /
558                                               MINGRIDSIZE));
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;
570                        }
571                }
572        }
573
574        MI_CLEARWINDOW(mi);
575
576        if ((dp->oldcell = (unsigned char *)
577                malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
578                free_demon(display, dp);
579                return;
580        }
581
582        if ((dp->newcell = (unsigned char *)
583                malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
584                free_demon(display, dp);
585                return;
586        }
587
588        RandomSoup(mi);
589}
590
591void
592draw_demon(ModeInfo * mi)
593{
594        int         i, j, k, l, mj = 0, ml;
595        demonstruct *dp;
596
597        if (demons == NULL)
598                return;
599        dp = &demons[MI_SCREEN(mi)];
600        if (dp->cellList == NULL)
601                return;
602
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));
607
608                if (dp->neighbors == 6) {
609                        for (j = 0; j < dp->nrows; j++) {
610                                for (i = 0; i < dp->ncols; i++) {
611                                        /* NE */
612                                        if (!(j & 1))
613                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
614                                        else
615                                                k = i;
616                                        l = (!j) ? dp->nrows - 1 : j - 1;
617                                        ml = l * dp->ncols;
618                                        if (dp->oldcell[k + ml] ==
619                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
620                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
621                                        /* E */
622                                        k = (i + 1 == dp->ncols) ? 0 : i + 1;
623                                        ml = mj;
624                                        if (dp->oldcell[k + ml] ==
625                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
626                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
627                                        /* SE */
628                                        if (!(j & 1))
629                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
630                                        else
631                                                k = i;
632                                        l = (j + 1 == dp->nrows) ? 0 : j + 1;
633                                        ml = l * dp->ncols;
634                                        if (dp->oldcell[k + ml] ==
635                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
636                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
637                                        /* SW */
638                                        if (j & 1)
639                                                k = (!i) ? dp->ncols - 1 : i - 1;
640                                        else
641                                                k = i;
642                                        l = (j + 1 == dp->nrows) ? 0 : j + 1;
643                                        ml = l * dp->ncols;
644                                        if (dp->oldcell[k + ml] ==
645                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
646                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
647                                        /* W */
648                                        k = (!i) ? dp->ncols - 1 : i - 1;
649                                        ml = mj;
650                                        if (dp->oldcell[k + ml] ==
651                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
652                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
653                                        /* NW */
654                                        if (j & 1)
655                                                k = (!i) ? dp->ncols - 1 : i - 1;
656                                        else
657                                                k = i;
658                                        l = (!j) ? dp->nrows - 1 : j - 1;
659                                        ml = l * dp->ncols;
660                                        if (dp->oldcell[k + ml] ==
661                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
662                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
663                                }
664                                mj += dp->ncols;
665                        }
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++) {
669                                        /* N */
670                                        k = i;
671                                        l = (!j) ? dp->nrows - 1 : j - 1;
672                                        ml = l * dp->ncols;
673                                        if (dp->oldcell[k + ml] ==
674                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
675                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
676                                        /* E */
677                                        k = (i + 1 == dp->ncols) ? 0 : i + 1;
678                                        ml = mj;
679                                        if (dp->oldcell[k + ml] ==
680                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
681                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
682                                        /* S */
683                                        k = i;
684                                        l = (j + 1 == dp->nrows) ? 0 : j + 1;
685                                        ml = l * dp->ncols;
686                                        if (dp->oldcell[k + ml] ==
687                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
688                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
689                                        /* W */
690                                        k = (!i) ? dp->ncols - 1 : i - 1;
691                                        l = j;
692                                        ml = mj;
693                                        if (dp->oldcell[k + ml] ==
694                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
695                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
696                                }
697                                mj += dp->ncols;
698                        }
699                        if (dp->neighbors == 8) {
700                                mj = 0;
701                                for (j = 0; j < dp->nrows; j++) {
702                                        for (i = 0; i < dp->ncols; i++) {
703                                                /* NE */
704                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
705                                                l = (!j) ? dp->nrows - 1 : j - 1;
706                                                ml = l * dp->ncols;
707                                                if (dp->oldcell[k + ml] ==
708                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
709                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
710                                                /* SE */
711                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
712                                                l = (j + 1 == dp->nrows) ? 0 : j + 1;
713                                                ml = l * dp->ncols;
714                                                if (dp->oldcell[k + ml] ==
715                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
716                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
717                                                /* SW */
718                                                k = (!i) ? dp->ncols - 1 : i - 1;
719                                                l = (j + 1 == dp->nrows) ? 0 : j + 1;
720                                                ml = l * dp->ncols;
721                                                if (dp->oldcell[k + ml] ==
722                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
723                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
724                                                /* NW */
725                                                k = (!i) ? dp->ncols - 1 : i - 1;
726                                                l = (!j) ? dp->nrows - 1 : j - 1;
727                                                ml = l * dp->ncols;
728                                                if (dp->oldcell[k + ml] ==
729                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
730                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
731                                        }
732                                        mj += dp->ncols;
733                                }
734                        }
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 */
740                                                /* W */
741                                                k = (!i) ? dp->ncols - 1 : i - 1;
742                                                ml = mj;
743                                                if (dp->oldcell[k + ml] ==
744                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
745                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
746                                        } else {        /* left */
747                                                /* E */
748                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
749                                                ml = mj;
750                                                if (dp->oldcell[k + ml] ==
751                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
752                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
753                                        }
754                                        /* N */
755                                        k = i;
756                                        l = (!j) ? dp->nrows - 1 : j - 1;
757                                        ml = l * dp->ncols;
758                                        if (dp->oldcell[k + ml] ==
759                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
760                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
761                                        /* S */
762                                        k = i;
763                                        l = (j + 1 == dp->nrows) ? 0 : j + 1;
764                                        ml = l * dp->ncols;
765                                        if (dp->oldcell[k + ml] ==
766                                            (int) (dp->oldcell[i + mj] + 1) % dp->states)
767                                                dp->newcell[i + mj] = dp->oldcell[k + ml];
768                                }
769                                mj += dp->ncols;
770                        }
771                        if (dp->neighbors == 9 || dp->neighbors == 12) {
772                                mj = 0;
773                                for (j = 0; j < dp->nrows; j++) {
774                                        for (i = 0; i < dp->ncols; i++) {
775                                                /* NN */
776                                                k = i;
777                                                if (!j)
778                                                        l = dp->nrows - 2;
779                                                else if (!(j - 1))
780                                                        l = dp->nrows - 1;
781                                                else
782                                                        l = j - 2;
783                                                ml = l * dp->ncols;
784                                                if (dp->oldcell[k + ml] ==
785                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
786                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
787                                                /* SS */
788                                                k = i;
789                                                if (j + 1 == dp->nrows)
790                                                        l = 1;
791                                                else if (j + 2 == dp->nrows)
792                                                        l = 0;
793                                                else
794                                                        l = j + 2;
795                                                ml = l * dp->ncols;
796                                                if (dp->oldcell[k + ml] ==
797                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
798                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
799                                                /* NW */
800                                                k = (!i) ? dp->ncols - 1 : i - 1;
801                                                l = (!j) ? dp->nrows - 1 : j - 1;
802                                                ml = l * dp->ncols;
803                                                if (dp->oldcell[k + ml] ==
804                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
805                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
806                                                /* NE */
807                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
808                                                l = (!j) ? dp->nrows - 1 : j - 1;
809                                                ml = l * dp->ncols;
810                                                if (dp->oldcell[k + ml] ==
811                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
812                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
813                                                /* SW */
814                                                k = (!i) ? dp->ncols - 1 : i - 1;
815                                                l = (j + 1 == dp->nrows) ? 0 : j + 1;
816                                                ml = l * dp->ncols;
817                                                if (dp->oldcell[k + ml] ==
818                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
819                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
820                                                /* SE */
821                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
822                                                l = (j + 1 == dp->nrows) ? 0 : j + 1;
823                                                ml = l * dp->ncols;
824                                                if (dp->oldcell[k + ml] ==
825                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
826                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
827                                        }
828                                        mj += dp->ncols;
829                                }
830                                if (dp->neighbors == 12) {
831                                        mj = 0;
832                                        for (j = 0; j < dp->nrows; j++) {
833                                                for (i = 0; i < dp->ncols; i++) {
834                                                        if ((i + j) % 2) {      /* right */
835                                                                /* NNW */
836                                                                k = (!i) ? dp->ncols - 1 : i - 1;
837                                                                if (!j)
838                                                                        l = dp->nrows - 2;
839                                                                else if (!(j - 1))
840                                                                        l = dp->nrows - 1;
841                                                                else
842                                                                        l = j - 2;
843                                                                ml = l * dp->ncols;
844                                                                if (dp->oldcell[k + ml] ==
845                                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
846                                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
847                                                                /* SSW */
848                                                                k = (!i) ? dp->ncols - 1 : i - 1;
849                                                                if (j + 1 == dp->nrows)
850                                                                        l = 1;
851                                                                else if (j + 2 == dp->nrows)
852                                                                        l = 0;
853                                                                else
854                                                                        l = j + 2;
855                                                                ml = l * dp->ncols;
856                                                                if (dp->oldcell[k + ml] ==
857                                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
858                                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
859                                                                /* EE */
860                                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
861                                                                l = j;
862                                                                ml = mj;
863                                                                if (dp->oldcell[k + ml] ==
864                                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
865                                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
866                                                        } else {        /* left */
867                                                                /* NNE */
868                                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
869                                                                if (!j)
870                                                                        l = dp->nrows - 2;
871                                                                else if (!(j - 1))
872                                                                        l = dp->nrows - 1;
873                                                                else
874                                                                        l = j - 2;
875                                                                ml = l * dp->ncols;
876                                                                if (dp->oldcell[k + ml] ==
877                                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
878                                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
879                                                                /* SSE */
880                                                                k = (i + 1 == dp->ncols) ? 0 : i + 1;
881                                                                if (j + 1 == dp->nrows)
882                                                                        l = 1;
883                                                                else if (j + 2 == dp->nrows)
884                                                                        l = 0;
885                                                                else
886                                                                        l = j + 2;
887                                                                ml = l * dp->ncols;
888                                                                if (dp->oldcell[k + ml] ==
889                                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
890                                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
891                                                                /* WW */
892                                                                k = (!i) ? dp->ncols - 1 : i - 1;
893                                                                l = j;
894                                                                ml = mj;
895                                                                if (dp->oldcell[k + ml] ==
896                                                                    (int) (dp->oldcell[i + mj] + 1) % dp->states)
897                                                                        dp->newcell[i + mj] = dp->oldcell[k + ml];
898                                                        }
899                                                }
900                                                mj += dp->ncols;
901                                        }
902                                }
903                        }
904                }
905                mj = 0;
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);
912                                                return;
913                                        }
914                                }
915                        mj += dp->ncols;
916                }
917                if (++dp->generation > MI_CYCLES(mi))
918                        init_demon(mi);
919                dp->state = 0;
920        } else {
921                if (dp->ncells[dp->state])
922                        if (!draw_state(mi, dp->state)) {
923                                free_demon(MI_DISPLAY(mi), dp);
924                                return;
925                        }
926                dp->state++;
927        }
928        if (dp->redrawing) {
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]);
933                        }
934                        if (++(dp->redrawpos) >= dp->ncols * dp->nrows) {
935                                dp->redrawing = 0;
936                                break;
937                        }
938                }
939        }
940}
941void
942release_demon(ModeInfo * mi)
943{
944        if (demons != NULL) {
945                int         screen;
946
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;
951        }
952}
953
954void
955refresh_demon(ModeInfo * mi)
956{
957        demonstruct *dp;
958
959        if (demons == NULL)
960                return;
961        dp = &demons[MI_SCREEN(mi)];
962
963        dp->redrawing = 1;
964        dp->redrawpos = 0;
965}
966
967#endif /* MODE_demon */
Note: See TracBrowser for help on using the repository browser.