/* demon --- David Griffeath's cellular automata */
#if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)demon.c 4.07 97/11/24 xlockmore";
+static const char sccsid[] = "@(#)demon.c 5.00 2000/11/01 xlockmore";
#endif
* other special, indirect and consequential damages.
*
* Revision History:
- * 10-May-97: Compatible with xscreensaver
- * 16-Apr-97: -neighbors 3, 9 (not sound mathematically), 12, and 8 added
- * 30-May-96: Ron Hitchens <ron@idiom.com>
+ * 01-Nov-2000: Allocation checks
+ * 10-May-1997: Compatible with xscreensaver
+ * 16-Apr-1997: -neighbors 3, 9 (not sound mathematically), 12, and 8 added
+ * 30-May-1996: Ron Hitchens <ron@idiom.com>
* Fixed memory management that caused leaks
- * 14-Apr-96: -neighbors 6 runtime-time option added
- * 21-Aug-95: Coded from A.K. Dewdney's "Computer Recreations", Scientific
- * American Magazine" Aug 1989 pp 102-105. Also very similar to
- * hodgepodge machine described in A.K. Dewdney's "Computer
- * Recreations", Scientific American Magazine" Aug 1988 pp 104-107.
- * also used life.c as a guide.
+ * 14-Apr-1996: -neighbors 6 runtime-time option added
+ * 21-Aug-1995: Coded from A.K. Dewdney's "Computer Recreations", Scientific
+ * American Magazine" Aug 1989 pp 102-105. Also very similar
+ * to hodgepodge machine described in A.K. Dewdney's "Computer
+ * Recreations", Scientific American Magazine" Aug 1988
+ * pp 104-107. Also used life.c as a guide.
*/
/*-
*/
/*-
- Grid Number of Neigbors
+ Grid Number of Neighbors
---- ------------------
Square 4 or 8
Hexagon 6
*/
#ifdef STANDALONE
+#define MODE_demon
#define PROGCLASS "Demon"
#define HACK_INIT init_demon
#define HACK_DRAW draw_demon
#define demon_opts xlockmore_opts
-#define DEFAULTS "*delay: 50000 \n" \
- "*count: 0 \n" \
- "*cycles: 1000 \n" \
- "*size: -7 \n" \
- "*ncolors: 64 \n" \
- "*neighbors: 0 \n"
-# define SMOOTH_COLORS
-# include "xlockmore.h" /* in xscreensaver distribution */
+#define DEFAULTS "*delay: 50000 \n" \
+ "*count: 0 \n" \
+ "*cycles: 1000 \n" \
+ "*size: -7 \n" \
+ "*ncolors: 64 \n" \
+ "*neighbors: 0 \n"
+#define UNIFORM_COLORS
+#include "xlockmore.h" /* in xscreensaver distribution */
#else /* STANDALONE */
-# include "xlock.h" /* in xlockmore distribution */
+#include "xlock.h" /* in xlockmore distribution */
+
#endif /* STANDALONE */
#include "automata.h"
+#ifdef MODE_demon
+
/*-
* neighbors of 0 randomizes it between 3, 4, 6, 8, 9, and 12.
*/
-#ifdef STANDALONE
-static int neighbors;
-#else
-extern int neighbors;
-#endif /* !STANDALONE */
+#define DEF_NEIGHBORS "0" /* choose random value */
+
+static int neighbors;
+
+static XrmOptionDescRec opts[] =
+{
+ {(char *) "-neighbors", (char *) ".demon.neighbors", XrmoptionSepArg, (caddr_t) NULL}
+};
+
+static argtype vars[] =
+{
+ {(caddr_t *) & neighbors, (char *) "neighbors", (char *) "Neighbors", (char *) DEF_NEIGHBORS, t_Int}
+};
+static OptionStruct desc[] =
+{
+ {(char *) "-neighbors num", (char *) "squares 4 or 8, hexagons 6, triangles 3, 9 or 12"}
+};
ModeSpecOpt demon_opts =
-{0, NULL, 0, NULL, NULL};
+{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
#ifdef USE_MODULES
ModStruct demon_description =
{"demon", "init_demon", "draw_demon", "release_demon",
- "refresh_demon", "init_demon", NULL, &demon_opts,
+ "refresh_demon", "init_demon", (char *) NULL, &demon_opts,
50000, 0, 1000, -7, 64, 1.0, "",
"Shows Griffeath's cellular automata", 0, NULL};
#endif
#define DEMONBITS(n,w,h)\
- dp->pixmaps[dp->init_bits++]=\
- XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1)
+ if ((dp->pixmaps[dp->init_bits]=\
+ XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
+ free_demon(display,dp); return;} else {dp->init_bits++;}
#define REDRAWSTEP 2000 /* How many cells to draw per cycle */
#define MINSTATES 2
{12, 16, 18, 20, 22, 24} /* Number of states */
};
-static demonstruct *demons = NULL;
+static demonstruct *demons = (demonstruct *) NULL;
static void
drawcell(ModeInfo * mi, int col, int row, unsigned char state)
dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
if (dp->xs == 1 && dp->ys == 1)
- XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi),
- gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y, 1, 1);
+ XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
+ gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
else
XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
dp->shape.hexagon, 6, Convex, CoordModePrevious);
dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
if (dp->xs <= 3 || dp->ys <= 3)
- XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
+ XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
- dp->shape.triangle[orient][0].y, 1, 1);
+ dp->shape.triangle[orient][0].y);
else {
if (orient)
dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
}
}
-static void
+static Bool
addtolist(ModeInfo * mi, int col, int row, unsigned char state)
{
demonstruct *dp = &demons[MI_SCREEN(mi)];
CellList *current;
current = dp->cellList[state];
- dp->cellList[state] = (CellList *) malloc(sizeof (CellList));
+ if ((dp->cellList[state] = (CellList *)
+ malloc(sizeof (CellList))) == NULL) {
+ return False;
+ }
dp->cellList[state]->pt.x = col;
dp->cellList[state]->pt.y = row;
dp->cellList[state]->next = current;
dp->ncells[state]++;
+ return True;
}
#ifdef DEBUG
dp->cellList[state] = dp->cellList[state]->next;
(void) free((void *) current);
}
- dp->cellList[state] = NULL;
- if (dp->ncells)
+ dp->cellList[state] = (CellList *) NULL;
+ if (dp->ncells != NULL)
dp->ncells[state] = 0;
}
for (state = 0; state < dp->states; state++)
free_state(dp, state);
(void) free((void *) dp->cellList);
- dp->cellList = NULL;
+ dp->cellList = (CellList **) NULL;
}
static void
}
if (dp->ncells != NULL) {
(void) free((void *) dp->ncells);
- dp->ncells = NULL;
+ dp->ncells = (int *) NULL;
}
if (dp->oldcell != NULL) {
(void) free((void *) dp->oldcell);
- dp->oldcell = NULL;
+ dp->oldcell = (unsigned char *) NULL;
}
if (dp->newcell != NULL) {
(void) free((void *) dp->newcell);
- dp->newcell = NULL;
+ dp->newcell = (unsigned char *) NULL;
}
}
static void
+free_demon(Display *display, demonstruct *dp)
+{
+ int shade;
+
+ if (dp->stippledGC != None) {
+ XFreeGC(display, dp->stippledGC);
+ dp->stippledGC = None;
+ }
+ for (shade = 0; shade < dp->init_bits; shade++) {
+ XFreePixmap(display, dp->pixmaps[shade]);
+ }
+ dp->init_bits = 0;
+ free_struct(dp);
+}
+
+static Bool
draw_state(ModeInfo * mi, int state)
{
demonstruct *dp = &demons[MI_SCREEN(mi)];
dp->shape.hexagon[0].x = dp->xb + ccol * dp->xs;
dp->shape.hexagon[0].y = dp->yb + crow * dp->ys;
if (dp->xs == 1 && dp->ys == 1)
- XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi),
- gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y, 1, 1);
+ XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi),
+ gc, dp->shape.hexagon[0].x, dp->shape.hexagon[0].y);
else
XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
dp->shape.hexagon, 6, Convex, CoordModePrevious);
int ncells = 0;
/* Create Rectangle list from part of the cellList */
- rects = (XRectangle *) malloc(dp->ncells[state] * sizeof (XRectangle));
+ if ((rects = (XRectangle *) malloc(dp->ncells[state] *
+ sizeof (XRectangle))) == NULL) {
+ return False;
+ }
current = dp->cellList[state];
while (current) {
rects[ncells].x = dp->xb + current->pt.x * dp->xs;
dp->shape.triangle[orient][0].x = dp->xb + col * dp->xs;
dp->shape.triangle[orient][0].y = dp->yb + row * dp->ys;
if (dp->xs <= 3 || dp->ys <= 3)
- XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
+ XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
((orient) ? -1 : 1) + dp->shape.triangle[orient][0].x,
- dp->shape.triangle[orient][0].y, 1, 1);
+ dp->shape.triangle[orient][0].y);
else {
if (orient)
dp->shape.triangle[orient][0].x += (dp->xs / 2 - 1);
}
free_state(dp, state);
XFlush(MI_DISPLAY(mi));
+ return True;
}
static void
for (col = 0; col < dp->ncols; ++col) {
dp->oldcell[col + mrow] =
(unsigned char) LRAND() % ((unsigned char) dp->states);
- addtolist(mi, col, row, dp->oldcell[col + mrow]);
+ if (!addtolist(mi, col, row, dp->oldcell[col + mrow]))
+ return; /* sparse soup */
}
mrow += dp->ncols;
}
return;
}
dp = &demons[MI_SCREEN(mi)];
+
dp->generation = 0;
dp->redrawing = 0;
if (MI_NPIXELS(mi) < NUMSTIPPLES) {
XGCValues gcv;
gcv.fill_style = FillOpaqueStippled;
- dp->stippledGC = XCreateGC(display, window, GCFillStyle, &gcv);
+ if ((dp->stippledGC = XCreateGC(display, window,
+ GCFillStyle, &gcv)) == None) {
+ free_demon(display, dp);
+ return;
+ }
}
if (dp->init_bits == 0) {
int i;
- for (i = 1; i < NUMSTIPPLES; i++)
+ for (i = 1; i < NUMSTIPPLES; i++) {
DEMONBITS(stipples[i], STIPPLESIZE, STIPPLESIZE);
+ }
}
}
free_struct(dp);
dp->states = NRAND(-dp->states - MINSTATES + 1) + MINSTATES;
else if (dp->states < MINSTATES)
dp->states = plots[1][nk];
- dp->cellList = (CellList **) calloc(dp->states, sizeof (CellList *));
- dp->ncells = (int *) calloc(dp->states, sizeof (int));
+ if ((dp->cellList = (CellList **) calloc(dp->states,
+ sizeof (CellList *))) == NULL) {
+ free_demon(display, dp);
+ return;
+ }
+ if ((dp->ncells = (int *) calloc(dp->states, sizeof (int))) == NULL) {
+ free_demon(display, dp);
+ return;
+ }
dp->state = 0;
if (dp->neighbors == 6) {
int nccols, ncrows, i;
- if (dp->width < 2)
- dp->width = 2;
- if (dp->height < 4)
- dp->height = 4;
+ if (dp->width < 8)
+ dp->width = 8;
+ if (dp->height < 8)
+ dp->height = 8;
if (size < -MINSIZE)
dp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(dp->width, dp->height) /
MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
MINGRIDSIZE));
dp->xs = dp->ys;
nccols = MAX(dp->width / dp->xs - 2, 2);
- ncrows = MAX(dp->height / dp->ys - 1, 2);
+ ncrows = MAX(dp->height / dp->ys - 1, 4);
dp->ncols = nccols / 2;
dp->nrows = 2 * (ncrows / 4);
dp->xb = (dp->width - dp->xs * nccols) / 2 + dp->xs / 2;
- dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys;
+ dp->yb = (dp->height - dp->ys * (ncrows / 2) * 2) / 2 + dp->ys - 2;
for (i = 0; i < 6; i++) {
dp->shape.hexagon[i].x = (dp->xs - 1) * hexagonUnit[i].x;
dp->shape.hexagon[i].y = ((dp->ys - 1) * hexagonUnit[i].y / 2) * 4 / 3;
MI_CLEARWINDOW(mi);
- dp->oldcell = (unsigned char *)
- malloc(dp->ncols * dp->nrows * sizeof (unsigned char));
+ if ((dp->oldcell = (unsigned char *)
+ malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
+ free_demon(display, dp);
+ return;
+ }
- dp->newcell = (unsigned char *)
- malloc(dp->ncols * dp->nrows * sizeof (unsigned char));
+ if ((dp->newcell = (unsigned char *)
+ malloc(dp->ncols * dp->nrows * sizeof (unsigned char))) == NULL) {
+ free_demon(display, dp);
+ return;
+ }
RandomSoup(mi);
}
void
draw_demon(ModeInfo * mi)
{
- demonstruct *dp = &demons[MI_SCREEN(mi)];
int i, j, k, l, mj = 0, ml;
+ demonstruct *dp;
- MI_IS_DRAWN(mi) = True;
+ if (demons == NULL)
+ return;
+ dp = &demons[MI_SCREEN(mi)];
+ if (dp->cellList == NULL)
+ return;
+ MI_IS_DRAWN(mi) = True;
if (dp->state >= dp->states) {
(void) memcpy((char *) dp->newcell, (char *) dp->oldcell,
dp->ncols * dp->nrows * sizeof (unsigned char));
dp->newcell[i + mj] = dp->oldcell[k + ml];
/* E */
k = (i + 1 == dp->ncols) ? 0 : i + 1;
- l = j;
ml = mj;
if (dp->oldcell[k + ml] ==
(int) (dp->oldcell[i + mj] + 1) % dp->states)
dp->newcell[i + mj] = dp->oldcell[k + ml];
/* W */
k = (!i) ? dp->ncols - 1 : i - 1;
- l = j;
ml = mj;
if (dp->oldcell[k + ml] ==
(int) (dp->oldcell[i + mj] + 1) % dp->states)
dp->newcell[i + mj] = dp->oldcell[k + ml];
/* E */
k = (i + 1 == dp->ncols) ? 0 : i + 1;
- l = j;
ml = mj;
if (dp->oldcell[k + ml] ==
(int) (dp->oldcell[i + mj] + 1) % dp->states)
if ((i + j) % 2) { /* right */
/* W */
k = (!i) ? dp->ncols - 1 : i - 1;
- l = j;
ml = mj;
if (dp->oldcell[k + ml] ==
(int) (dp->oldcell[i + mj] + 1) % dp->states)
} else { /* left */
/* E */
k = (i + 1 == dp->ncols) ? 0 : i + 1;
- l = j;
ml = mj;
if (dp->oldcell[k + ml] ==
(int) (dp->oldcell[i + mj] + 1) % dp->states)
for (i = 0; i < dp->ncols; i++)
if (dp->oldcell[i + mj] != dp->newcell[i + mj]) {
dp->oldcell[i + mj] = dp->newcell[i + mj];
- addtolist(mi, i, j, dp->oldcell[i + mj]);
+ if (!addtolist(mi, i, j, dp->oldcell[i + mj])) {
+ free_demon(MI_DISPLAY(mi), dp);
+ return;
+ }
}
mj += dp->ncols;
}
dp->state = 0;
} else {
if (dp->ncells[dp->state])
- draw_state(mi, dp->state);
+ if (!draw_state(mi, dp->state)) {
+ free_demon(MI_DISPLAY(mi), dp);
+ return;
+ }
dp->state++;
}
if (dp->redrawing) {
if (demons != NULL) {
int screen;
- for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
- demonstruct *dp = &demons[screen];
- int shade;
-
- if (dp->stippledGC != None) {
- XFreeGC(MI_DISPLAY(mi), dp->stippledGC);
- }
- for (shade = 0; shade < dp->init_bits; shade++)
- XFreePixmap(MI_DISPLAY(mi), dp->pixmaps[shade]);
- free_struct(dp);
- }
+ for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+ free_demon(MI_DISPLAY(mi), &demons[screen]);
(void) free((void *) demons);
- demons = NULL;
+ demons = (demonstruct *) NULL;
}
-} void
+}
+void
refresh_demon(ModeInfo * mi)
{
- demonstruct *dp = &demons[MI_SCREEN(mi)];
+ demonstruct *dp;
+
+ if (demons == NULL)
+ return;
+ dp = &demons[MI_SCREEN(mi)];
dp->redrawing = 1;
dp->redrawpos = 0;
}
+
+#endif /* MODE_demon */