http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.tar.gz
[xscreensaver] / hacks / loop.c
index c7280eaa936e3c92fbe0d5664ec6846124db629f..04419801919d5681feb0379b49a574964022e3aa 100644 (file)
@@ -2,7 +2,7 @@
 /* loop --- Chris Langton's self-producing loops */
 
 #if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)loop.c       4.13 98/10/18 xlockmore";
+static const char sccsid[] = "@(#)loop.c       5.01 2000/03/15 xlockmore";
 
 #endif
 
@@ -22,20 +22,35 @@ static const char sccsid[] = "@(#)loop.c    4.13 98/10/18 xlockmore";
  * other special, indirect and consequential damages.
  *
  * Revision History:
- * 18-Oct-98: Started creating a hexagon version, probably will not work
- *            for a while since some work has to go into getting not
- *            only the program to handle the hexagonal data but the loop
- *            has to be "programmed" as well.  I suspect it should be easier
- *            than the original since the loop will have six sides to
- *            store its genes (data).
- * 10-May-97: Compatible with xscreensaver
- * 15-Nov-95: Coded from Chris Langton's Self-Reproduction in Cellular
- *            Automata Physica 10D 135-144 1984
- *            also used wire.c as a guide.
+ * 15-Mar-2001: Added some flaws, random blue wall spots, to liven it up.
+ *              This mod seems to expose a bug where hexagons are erased
+ *              for no apparent reason.
+ * 01-Nov-2000: Allocation checks
+ * 16-Jun-2000: Fully coded the hexagonal rules.  (Rules that end up in
+ *              state zero were not bothered with since a calloc was used
+ *              to set non-explicit rules to zero.  This allows the
+ *              compile-time option RAND_RULES to work here (at least to
+ *              generation 540).)
+ *              Also added compile-time option DELAYDEBUGLOOP for debugging
+ *              life form.  This also turns off the random initial direction
+ *              of the loop.  Set DELAYDEBUGLOOP to be 10 and use with
+ *              something like this:
+ *       xlock -mode loop -neighbors 6 -size 5 -delay 1 -count 540 -nolock
+ * 18-Oct-1998: Started creating a hexagon version.
+ *              It proved not that difficult because I used Langton's Loop
+ *              as a guide, hexagons have more neighbors so there is more
+ *              freedom to program, and the loop will has six sides to
+ *              store its genes (data).
+ *              (Soon after this a triangular version with neighbors = 6
+ *              was attempted but was unsuccessful).
+ * 10-May-1997: Compatible with xscreensaver
+ * 15-Nov-1995: Coded from Chris Langton's Self-Reproduction in Cellular
+ *              Automata Physica 10D 135-144 1984, also used wire.c as a
+ *              guide.
  */
 
 /*-
-  Grid     Number of Neigbors
+  Grid     Number of Neighbors
   ----     ------------------
   Square   4
   Hexagon  6  (currently in development)
@@ -59,54 +74,84 @@ static const char sccsid[] = "@(#)loop.c    4.13 98/10/18 xlockmore";
    machine is not contained in the loop.  This is a simplification of
    von Neumann and Codd's self-producing Turing machine.
    The data spinning around could be viewed as both its DNA and its internal
-   clock.
+   clock.  The program can be initalized to have the loop spin both ways...
+   but only one way around will work for a given rule.  An open question (at
+   least to me): Is handedness a requirement for (artificial) life?  Here
+   there is handedness at both the initial condition and the transition rule.
  */
 
 #ifdef STANDALONE
-# define PROGCLASS "loop"
-# define HACK_INIT init_loop
-# define HACK_DRAW draw_loop
-# define loop_opts xlockmore_opts
-# define DEFAULTS      "*delay:  100000 \n" \
-                                       "*cycles:   1600 \n" \
-                                       "*size:      -12 \n" \
-                                       "*ncolors:    15 \n" \
-                                       "*neighbors:   0 \n"
-# define SMOOTH_COLORS
-# include "xlockmore.h"                /* in xscreensaver distribution */
+#define MODE_loop
+#define PROGCLASS "loop"
+#define HACK_INIT init_loop
+#define HACK_DRAW draw_loop
+#define loop_opts xlockmore_opts
+#define DEFAULTS "*delay: 100000 \n" \
+ "*count: -5 \n" \
+ "*cycles: 1600 \n" \
+ "*size: -12 \n" \
+ "*ncolors: 15 \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_loop
+
 /*-
  * neighbors of 0 randomizes between 4 and 6.
  */
-#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 *) ".loop.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 hexagons 6"}
+};
 
 ModeSpecOpt loop_opts =
-{0, NULL, 0, NULL, NULL};
+{sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
+
 
 #ifdef USE_MODULES
 ModStruct   loop_description =
 {"loop", "init_loop", "draw_loop", "release_loop",
- "refresh_loop", "init_loop", NULL, &loop_opts,
- 100000, 1, 1600, -12, 64, 1.0, "",
+ "refresh_loop", "init_loop", (char *) NULL, &loop_opts,
+ 100000, 5, 1600, -12, 64, 1.0, "",
  "Shows Langton's self-producing loops", 0, NULL};
 
 #endif
 
 #define LOOPBITS(n,w,h)\
-  lp->pixmaps[lp->init_bits++]=\
-  XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1)
+  if ((lp->pixmaps[lp->init_bits]=\
+  XCreatePixmapFromBitmapData(display,window,(char *)n,w,h,1,0,1))==None){\
+  free_loop(display,lp); return;} else {lp->init_bits++;}
 
 static int  local_neighbors = 0;
-static int  neighbor_kind = 0;
+
+#if 0
+/* Used to fast forward to troubled generations, mainly used for debugging.
+   -delay 1 -count 170 -neighbors 6  # divisions starts
+   540 first cell collision
+   1111 mutant being born from 2 parents
+   1156 mutant born 
+ */
+#define DELAYDEBUGLOOP 10
+#endif
 
 #define COLORS 8
 #define REALCOLORS (COLORS-2)
@@ -114,33 +159,35 @@ static int  neighbor_kind = 0;
 #define REDRAWSTEP 2000                /* How many cells to draw per cycle */
 #define ADAM_SIZE 8 /* MIN 5 */
 #if 1
-# define ADAM_LOOPX  (ADAM_SIZE+2)
-# define ADAM_LOOPY  (ADAM_SIZE+2)
+#define ADAM_LOOPX  (ADAM_SIZE+2)
+#define ADAM_LOOPY  (ADAM_SIZE+2)
 #else
-# define ADAM_LOOPX 16
-# define ADAM_LOOPY 10
+#define ADAM_LOOPX 16
+#define ADAM_LOOPY 10
 #endif
 #define MINGRIDSIZE (3*ADAM_LOOPX)
+#if 0
 /* TRIA stuff was an attempt to make a triangular lifeform on a
-   hex grid but I got bored.  You probably need an additional 7th
-   state for a coherent step by step process of separation and
+   hexagonal grid but I got bored.  You may need an additional 7th
+   state for a coherent step by step process of cell separation and
    initial stem development.
  */
-/* #define TRIA 1 */
+#define TRIA 1
+#endif
 #ifdef TRIA
-# define HEX_ADAM_SIZE 3 /* MIN 3 */
+#define HEX_ADAM_SIZE 3 /* MIN 3 */
 #else
-# define HEX_ADAM_SIZE 5 /* MIN 3 */
+#define HEX_ADAM_SIZE 5 /* MIN 3 */
 #endif
 #if 1
-# define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
-# define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
+#define HEX_ADAM_LOOPX (2*HEX_ADAM_SIZE+1)
+#define HEX_ADAM_LOOPY (2*HEX_ADAM_SIZE+1)
 #else
-# define HEX_ADAM_LOOPX 3 
-# define HEX_ADAM_LOOPY 7
+#define HEX_ADAM_LOOPX 3
+#define HEX_ADAM_LOOPY 7
 #endif
 #define HEX_MINGRIDSIZE (6*HEX_ADAM_LOOPX)
-#define MINSIZE 5                        /* jwz -- really tiny cells don't look good */
+#define MINSIZE ((MI_NPIXELS(mi)>=COLORS)?1:(2+(local_neighbors==6)))
 #define NEIGHBORKINDS 2
 #define ANGLES 360
 #define MAXNEIGHBORS 6
@@ -161,6 +208,7 @@ typedef struct {
        int         mincol, minrow, maxcol, maxrow;
        int         width, height;
        int         redrawing, redrawpos;
+       Bool        dead, clockwise;
        unsigned char *newcells, *oldcells;
        int         ncells[COLORS];
        CellList   *cellList[COLORS];
@@ -172,12 +220,22 @@ typedef struct {
        } shape;
 } loopstruct;
 
-static loopstruct *loops = NULL;
+static loopstruct *loops = (loopstruct *) NULL;
 
 #define TRANSITION(TT,V) V=TT&7;TT>>=3
+#define FINALTRANSITION(TT,V) V=TT&7
 #define TABLE(R,T,L,B) (table[((B)<<9)|((L)<<6)|((T)<<3)|(R)])
 #define HEX_TABLE(R,T,t,l,b,B) (table[((B)<<15)|((b)<<12)|((l)<<9)|((t)<<6)|((T)<<3)|(R)])
-#ifdef RAND_RULES              /* Hack, see below */
+
+#if 0
+/* Instead of setting "unused" state rules to zero it randomizes them.
+   These rules take over when something unexpected happens... like when a
+   cell hits a wall (the end of the screen).
+ */
+#define RAND_RULES
+#endif
+
+#ifdef RAND_RULES
 #define TABLE_IN(C,R,T,L,B,I) (TABLE(R,T,L,B)&=~(7<<((C)*3)));\
 (TABLE(R,T,L,B)|=((I)<<((C)*3)))
 #define HEX_TABLE_IN(C,R,T,t,l,b,B,I) (HEX_TABLE(R,T,t,l,b,B)&=~(7<<((C)*3)));\
@@ -189,8 +247,9 @@ static loopstruct *loops = NULL;
 #define TABLE_OUT(C,R,T,L,B) ((TABLE(R,T,L,B)>>((C)*3))&7)
 #define HEX_TABLE_OUT(C,R,T,t,l,b,B) ((HEX_TABLE(R,T,t,l,b,B)>>((C)*3))&7)
 
-static unsigned int *table = NULL;     /* 8*8*8*8 = 2^12 = 2^3^4 = 4K */
-  /* 8*8*8*8*8*8 = too big? */
+static unsigned int *table = (unsigned int *) NULL;
+  /* square:  8*8*8*8     = 2^12 = 2^3^4 = 4096 */
+  /* hexagon: 8*8*8*8*8*8 = 2^18 = 2^3^6 = 262144 = too big? */
 
 static char plots[NEIGHBORKINDS] =
 {
@@ -395,7 +454,7 @@ static unsigned int hex_transition_table[] =
     020102022, 020202112,
 
     000000012, 000000122, 000000212,
-    010002121, 
+    010002121,
     020001122, 020002112, 020011122,
 
 
@@ -442,7 +501,7 @@ static unsigned int hex_transition_table[] =
 
     020040422,
     040002022,
-    
+
     010224224, 010222424, 010202424,
     020142022, 020202412,
     020011722, 020112072, 020172072, 020142072,
@@ -450,7 +509,7 @@ static unsigned int hex_transition_table[] =
 
 
     000210225, 000022015, 000022522,
-    011225521, 
+    011225521,
     020120525, 020020152, 020005122, 020214255, 020021152,
     020255242,
     050215222, 050225121,
@@ -465,7 +524,7 @@ static unsigned int hex_transition_table[] =
     001224251,
     010022152, 010251221, 010522121, 011212151, 011221251,
     011215221,
-    020000220, 020002152, 020020220, 020021020, 020022152,
+    020000220, 020002152, 020020220, 020022152,
     020021422, 020022152, 020022522, 020025425, 020050422,
     020051022, 020051122, 020211122, 020211222, 020215222,
     020245122,
@@ -486,7 +545,7 @@ static unsigned int hex_transition_table[] =
     020021552,
     012252277,
     050002521,
-    020005725,     
+    020005725,
 
     050011022,
     000000155,
@@ -544,7 +603,7 @@ static unsigned int hex_transition_table[] =
     020521122,
     020025022,
     020025522,
-    020020522, 
+    020020522,
 
     020202222,
     020212222,
@@ -557,7 +616,6 @@ static unsigned int hex_transition_table[] =
     020212122,
     020027222,
     020024222,
-    020020222,
     020212722,
     020212422,
     020202122,
@@ -569,6 +627,33 @@ static unsigned int hex_transition_table[] =
     020212052,
 
     020205052,
+    070221250,
+
+    000000050, 000005220, 000002270, 070252220,
+    000000450, 000007220,
+    000220220, 000202220, 000022020, 000020220,
+
+    000222040,
+    000220440,
+    000022040,
+    000040220,
+
+    000252220,
+    050221120, 010221520,
+    002222220,
+
+    000070220, 000220720,
+    000020520, 000070250, 000222070, 000027020,
+    000022070, 000202270, 000024020, 000220420,
+    000220270, 000220240, 000072020, 000042020,
+    000002020, 000002070, 000020270, 000020250,
+    000270270, 000007020, 000040270,
+
+    /* Collision starts (gen 540), not sure to have rules to save it
+       or depend on calloc to intialize remaining rules to 0 so that
+       the mutant will be born
+     */
+    000050220,
 #endif
 };
 
@@ -687,30 +772,26 @@ position_of_neighbor(int dir, int *pcol, int *prow)
        if (local_neighbors == 6) {
                switch (dir) {
                        case 0:
-                               col = col + 1;
+                               col++;
                                break;
                        case 60:
-                               if (row & 1)
-                                       col = col + 1;
-                               row = row - 1;
+                               col += (row & 1);
+                               row--;
                                break;
                        case 120:
-                               if (!(row & 1))
-                                       col = col - 1;
-                               row = row - 1;
+                               col -= !(row & 1);
+                               row--;
                                break;
                        case 180:
-                               col = col - 1;
+                               col--;
                                break;
                        case 240:
-                               if (!(row & 1))
-                                       col = col - 1;
-                               row = row + 1;
+                               col -= !(row & 1);
+                               row++;
                                break;
                        case 300:
-                               if (row & 1)
-                                       col = col + 1;
-                               row = row + 1;
+                               col += (row & 1);
+                               row++;
                                break;
                        default:
                                (void) fprintf(stderr, "wrong direction %d\n", dir);
@@ -718,16 +799,16 @@ position_of_neighbor(int dir, int *pcol, int *prow)
        } else {
                switch (dir) {
                        case 0:
-                               col = col + 1;
+                               col++;
                                break;
                        case 90:
-                               row = row - 1;
+                               row--;
                                break;
                        case 180:
-                               col = col - 1;
+                               col--;
                                break;
                        case 270:
-                               row = row + 1;
+                               row++;
                                break;
                        default:
                                (void) fprintf(stderr, "wrong direction %d\n", dir);
@@ -755,8 +836,8 @@ fillcell(ModeInfo * mi, GC gc, int col, int row)
                lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
                lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
                if (lp->xs == 1 && lp->ys == 1)
-                       XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
-                               lp->shape.hexagon[0].x, lp->shape.hexagon[0].y, 1, 1);
+                       XDrawPoint(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
+                               lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
                else
                        XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
                                lp->shape.hexagon, 6, Convex, CoordModePrevious);
@@ -788,23 +869,6 @@ drawcell(ModeInfo * mi, int col, int row, int state)
        fillcell(mi, gc, col, row);
 }
 
-static void
-addtolist(ModeInfo * mi, int col, int row, unsigned char state)
-{
-       loopstruct *lp = &loops[MI_SCREEN(mi)];
-       CellList   *current = lp->cellList[state];
-
-       lp->cellList[state] = NULL;
-       if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) == NULL) {
-               lp->cellList[state] = current;
-               return;
-       }
-       lp->cellList[state]->pt.x = col;
-       lp->cellList[state]->pt.y = row;
-       lp->cellList[state]->next = current;
-       lp->ncells[state]++;
-}
-
 #ifdef DEBUG
 static void
 print_state(ModeInfo * mi, int state)
@@ -838,21 +902,75 @@ free_state(loopstruct * lp, int state)
 }
 
 static void
+free_list(loopstruct * lp)
+{
+       int         state;
+
+       for (state = 0; state < COLORS; state++)
+               free_state(lp, state);
+}
+
+static void
+free_loop(Display *display, loopstruct * lp)
+{
+       int         shade;
+
+       for (shade = 0; shade < lp->init_bits; shade++)
+               if (lp->pixmaps[shade] != None) {
+                       XFreePixmap(display, lp->pixmaps[shade]);
+                       lp->pixmaps[shade] = None;
+               }
+       if (lp->stippledGC != None) {
+               XFreeGC(display, lp->stippledGC);
+               lp->stippledGC = None;
+       }
+       if (lp->oldcells != NULL) {
+               (void) free((void *) lp->oldcells);
+               lp->oldcells = (unsigned char *) NULL;
+       }
+       if (lp->newcells != NULL) {
+               (void) free((void *) lp->newcells);
+               lp->newcells = (unsigned char *) NULL;
+       }
+       free_list(lp);
+}
+
+static Bool
+addtolist(ModeInfo * mi, int col, int row, unsigned char state)
+{
+       loopstruct *lp = &loops[MI_SCREEN(mi)];
+       CellList   *current = lp->cellList[state];
+
+       if ((lp->cellList[state] = (CellList *) malloc(sizeof (CellList))) ==
+                       NULL) {
+               lp->cellList[state] = current;
+               free_loop(MI_DISPLAY(mi), lp);
+               return False;
+       }
+       lp->cellList[state]->pt.x = col;
+       lp->cellList[state]->pt.y = row;
+       lp->cellList[state]->next = current;
+       lp->ncells[state]++;
+       return True;
+}
+
+static Bool
 draw_state(ModeInfo * mi, int state)
 {
        loopstruct *lp = &loops[MI_SCREEN(mi)];
+       Display    *display = MI_DISPLAY(mi);
        GC          gc;
        XGCValues   gcv;
        CellList   *current = lp->cellList[state];
 
        if (MI_NPIXELS(mi) >= COLORS) {
                gc = MI_GC(mi);
-               XSetForeground(MI_DISPLAY(mi), gc, lp->colors[state]);
+               XSetForeground(display, gc, lp->colors[state]);
        } else {
                gcv.stipple = lp->pixmaps[state];
                gcv.foreground = MI_WHITE_PIXEL(mi);
                gcv.background = MI_BLACK_PIXEL(mi);
-               XChangeGC(MI_DISPLAY(mi), lp->stippledGC,
+               XChangeGC(display, lp->stippledGC,
                          GCStipple | GCForeground | GCBackground, &gcv);
                gc = lp->stippledGC;
        }
@@ -867,21 +985,22 @@ draw_state(ModeInfo * mi, int state)
                        lp->shape.hexagon[0].x = lp->xb + ccol * lp->xs;
                        lp->shape.hexagon[0].y = lp->yb + crow * lp->ys;
                        if (lp->xs == 1 && lp->ys == 1)
-                               XFillRectangle(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
-                                       lp->shape.hexagon[0].x, lp->shape.hexagon[0].y, 1, 1);
+                               XDrawPoint(display, MI_WINDOW(mi), gc,
+                                       lp->shape.hexagon[0].x, lp->shape.hexagon[0].y);
                        else
-                               XFillPolygon(MI_DISPLAY(mi), MI_WINDOW(mi), gc,
+                               XFillPolygon(display, MI_WINDOW(mi), gc,
                                        lp->shape.hexagon, 6, Convex, CoordModePrevious);
                        current = current->next;
                }
        } else {
                /* Take advantage of XFillRectangles */
-               XRectangle *rects = NULL;
+               XRectangle *rects;
                int         nrects = 0;
 
                /* Create Rectangle list from part of the cellList */
-               if ((rects = (XRectangle *) malloc(lp->ncells[state] * sizeof (XRectangle))) == NULL) {
-                       return;
+               if ((rects = (XRectangle *) malloc(lp->ncells[state] *
+                               sizeof (XRectangle))) == NULL) {
+                       return False;
                }
 
                while (current) {
@@ -893,15 +1012,16 @@ draw_state(ModeInfo * mi, int state)
                        nrects++;
                }
                /* Finally get to draw */
-               XFillRectangles(MI_DISPLAY(mi), MI_WINDOW(mi), gc, rects, nrects);
+               XFillRectangles(display, MI_WINDOW(mi), gc, rects, nrects);
                /* Free up rects list and the appropriate part of the cellList */
                (void) free((void *) rects);
        }
        free_state(lp, state);
-       XFlush(MI_DISPLAY(mi));
+       XFlush(display);
+       return True;
 }
 
-static int
+static Bool
 init_table(void)
 {
        if (table == NULL) {
@@ -917,16 +1037,21 @@ init_table(void)
                        mult *= 8;
 
                if ((table = (unsigned int *) calloc(mult, sizeof (unsigned int))) == NULL) {
-                       return 1;
+                       return False;
                }
 
+
 #ifdef RAND_RULES
                /* Here I was interested to see what happens when it hits a wall....
                   Rules not normally used take over... takes too much time though */
-               {
+               /* Each state = 3 bits */
+               if (MAXRAND < 16777216.0) {
                        for (j = 0; j < mult; j++) {
-                               for (k = 0; k < 8; k++)
-                                       table[j] |= (unsigned int) ((unsigned int) (NRAND(8)) << (k * 3));
+                               table[j] = (unsigned int) ((NRAND(4096) << 12) & NRAND(4096));
+                       }
+               } else {
+                       for  (j = 0; j < mult; j++) {
+                               table[j] = (unsigned int) (NRAND(16777216));
                        }
                }
 #endif
@@ -937,7 +1062,7 @@ init_table(void)
                                for (k = 0; k < local_neighbors; k++) {
                                        TRANSITION(tt, n[k]);
                                }
-                               TRANSITION(tt, c);
+                               FINALTRANSITION(tt, c);
                                HEX_TABLE_IN(c, n[0], n[1], n[2], n[3], n[4], n[5], i);
                                HEX_TABLE_IN(c, n[1], n[2], n[3], n[4], n[5], n[0], i);
                                HEX_TABLE_IN(c, n[2], n[3], n[4], n[5], n[0], n[1], i);
@@ -952,7 +1077,7 @@ init_table(void)
                                for (k = 0; k < local_neighbors; k++) {
                                        TRANSITION(tt, n[k]);
                                }
-                               TRANSITION(tt, c);
+                               FINALTRANSITION(tt, c);
                                TABLE_IN(c, n[0], n[1], n[2], n[3], i);
                                TABLE_IN(c, n[1], n[2], n[3], n[0], i);
                                TABLE_IN(c, n[2], n[3], n[0], n[1], i);
@@ -960,7 +1085,56 @@ init_table(void)
                        }
                }
        }
-       return 0;
+       return True;
+}
+
+static void
+init_flaw(ModeInfo * mi)
+{
+       loopstruct *lp = &loops[MI_SCREEN(mi)];
+       int a, b;
+
+#define        BLUE 2
+       if (lp->bncols <= 3 || lp->bnrows <= 3)
+               return;
+       a = MIN(lp->bncols - 3, 2 * ((local_neighbors == 6) ?
+                HEX_MINGRIDSIZE : MINGRIDSIZE));
+       a = NRAND(a) + (lp->bncols - a) / 2;
+       b = MIN(lp->bnrows - 3, 2 * ((local_neighbors == 6) ?
+                HEX_MINGRIDSIZE : MINGRIDSIZE));
+       b = NRAND(b) + (lp->bnrows - b) / 2;
+       if (lp->mincol > a)
+               lp->mincol = a;
+       if (lp->minrow > b)
+               lp->minrow = b;
+       if (lp->maxcol < a + 2)
+               lp->maxcol = a + 2;
+       if (lp->maxrow < b + 2)
+               lp->maxrow = b + 2;
+
+       if (local_neighbors == 6) {
+               lp->newcells[b * lp->bncols + a + !(b % 2) ] = BLUE;
+               lp->newcells[b * lp->bncols + a + 1 + !(b % 2)] = BLUE;
+               lp->newcells[(b + 1) * lp->bncols + a] = BLUE;
+               lp->newcells[(b + 1) * lp->bncols + a + 2] = BLUE;
+               lp->newcells[(b + 2) * lp->bncols + a + !(b % 2)] = BLUE;
+               lp->newcells[(b + 2) * lp->bncols + a + 1 + !(b % 2)] = BLUE;
+       } else {
+               int orient = NRAND(4);
+               lp->newcells[lp->bncols * (b + 1) + a + 1] = BLUE;
+               if (orient == 0 || orient == 1) {
+                       lp->newcells[lp->bncols * b + a + 1] = BLUE;
+               }
+               if (orient == 1 || orient == 2) {
+                       lp->newcells[lp->bncols * (b + 1) + a + 2] = BLUE;
+               }
+               if (orient == 2 || orient == 3) {
+                       lp->newcells[lp->bncols * (b + 2) + a + 1] = BLUE;
+               }
+               if (orient == 3 || orient == 0) {
+                       lp->newcells[lp->bncols * (b + 1) + a] = BLUE;
+               }
+       }
 }
 
 static void
@@ -968,165 +1142,232 @@ init_adam(ModeInfo * mi)
 {
        loopstruct *lp = &loops[MI_SCREEN(mi)];
        XPoint      start, dirx, diry;
-       int         i, j;
+       int         i, j, dir;
 
-  if (local_neighbors == 6) {
+#ifdef DELAYDEBUGLOOP
+       lp->clockwise = 0;
+       if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
+#endif
+       lp->clockwise = (Bool) (LRAND() & 1);
+#ifdef DELAYDEBUGLOOP
+       dir = 0;
+       if (!MI_COUNT(mi)) /* Probably doing testing so do not confuse */
+#endif
+       dir = NRAND(local_neighbors);
+       if (local_neighbors == 6) {
                int k;
 
-               /* switch (0) */
-               switch (NRAND(6)) {
+               switch (dir) {
                        case 0:
                                start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
                                start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
-                               lp->mincol = start.x - 2;
-                               lp->minrow = start.y - 1;
-                               lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
-                               lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
+                               if (lp->mincol > start.x - 2)
+                                       lp->mincol = start.x - 2;
+                               if (lp->minrow > start.y - 1)
+                                       lp->minrow = start.y - 1;
+                               if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
+                                       lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
+                               if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
+                                       lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
                                for (j = 0; j < HEX_ADAM_LOOPY; j++) {
                                        for (i = 0; i < HEX_ADAM_LOOPX; i++) {
                                                k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
                                                lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
-                                                       hex_self_reproducing_loop[j][i];
+                                                       (lp->clockwise) ?
+                                       hex_self_reproducing_loop[i][j] :
+                                       hex_self_reproducing_loop[j][i];
                                        }
                                }
                                break;
                        case 1:
                                start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
                                start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
-                               lp->mincol = start.x - 1;
-                               lp->minrow = start.y - HEX_ADAM_LOOPX;
-                               lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
-                               lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
+                               if (lp->mincol > start.x - 1)
+                                       lp->mincol = start.x - 1;
+                               if (lp->minrow > start.y - HEX_ADAM_LOOPX)
+                                       lp->minrow = start.y - HEX_ADAM_LOOPX;
+                               if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
+                                       lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
+                               if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
+                                       lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
                                for (j = 0; j < HEX_ADAM_LOOPY; j++) {
                                        for (i = 0; i < HEX_ADAM_LOOPX; i++) {
                                                k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
               ? -(i + j + 1) / 2 : -(i + j) / 2);
                                                lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
-                                                       hex_self_reproducing_loop[j][i];
+                                                       (lp->clockwise) ?
+                                                       hex_self_reproducing_loop[i][j] :
+                                                       hex_self_reproducing_loop[j][i];
                                        }
                                }
                                break;
                        case 2:
                                start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
                                start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
-                               lp->mincol = start.x - 2;
-                               lp->minrow = start.y - 1;
-                               lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
-                               lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
+                               if (lp->mincol > start.x - 2)
+                                       lp->mincol = start.x - 2;
+                               if (lp->minrow > start.y - 1)
+                                       lp->minrow = start.y - 1;
+                               if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
+                                       lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
+                               if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
+                                       lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
                                for (j = 0; j < HEX_ADAM_LOOPX; j++) {
                                        for (i = 0; i < HEX_ADAM_LOOPY; i++) {
                                                k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
                                                lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
-                                                       hex_self_reproducing_loop[i][HEX_ADAM_LOOPX - j - 1];
+                                                       (lp->clockwise) ?
+                                                       hex_self_reproducing_loop[j][HEX_ADAM_LOOPX - i - 1] :
+                                                       hex_self_reproducing_loop[i][HEX_ADAM_LOOPY - j - 1];
                                        }
                                }
                                break;
                        case 3:
                                start.x = (lp->bncols - HEX_ADAM_LOOPX / 2) / 2;
                                start.y = (lp->bnrows - HEX_ADAM_LOOPY) / 2;
-                               lp->mincol = start.x - 1, lp->minrow = start.y - 1;
-                               lp->maxcol = start.x + HEX_ADAM_LOOPX + 1, lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
+                               if (lp->mincol > start.x - 1)
+                                       lp->mincol = start.x - 1;
+                               if (lp->minrow > start.y - 1)
+                                       lp->minrow = start.y - 1;
+                               if (lp->maxcol < start.x + HEX_ADAM_LOOPX + 1)
+                                       lp->maxcol = start.x + HEX_ADAM_LOOPX + 1;
+                               if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
+                                       lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
                                for (j = 0; j < HEX_ADAM_LOOPY; j++) {
                                        for (i = 0; i < HEX_ADAM_LOOPX; i++) {
                                                k = (((lp->bnrows / 2 + HEX_ADAM_LOOPY / 2) % 2) ? -j / 2 : -(j + 1) / 2);
                                                lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
-                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
+                                                       (lp->clockwise) ?
+                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
+                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
                                        }
                                }
                                break;
                        case 4:
                                start.x = (lp->bncols - (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) / 2;
                                start.y = (lp->bnrows - HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2;
-                               lp->mincol = start.x - 1;
-                               lp->minrow = start.y - HEX_ADAM_LOOPX;
-                               lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
-                               lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
+                               if (lp->mincol > start.x - 1)
+                                       lp->mincol = start.x - 1;
+                               if (lp->minrow > start.y - HEX_ADAM_LOOPX)
+                                       lp->minrow = start.y - HEX_ADAM_LOOPX;
+                               if (lp->maxcol < start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1)
+                                       lp->maxcol = start.x + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2 + 1;
+                               if (lp->maxrow < start.y + HEX_ADAM_LOOPY + 1)
+                                       lp->maxrow = start.y + HEX_ADAM_LOOPY + 1;
                                for (j = 0; j < HEX_ADAM_LOOPY; j++) {
                                        for (i = 0; i < HEX_ADAM_LOOPX; i++) {
                                                k = (((lp->bnrows / 2 + (HEX_ADAM_LOOPX + HEX_ADAM_LOOPY) / 2) % 2)
               ? -(i + j + 1) / 2 : -(i + j) / 2);
                                                lp->newcells[(start.y + j - i) * lp->bncols + start.x + i + j + k] =
-                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
+                                                       (lp->clockwise) ?
+                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][HEX_ADAM_LOOPY - j - 1] :
+                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][HEX_ADAM_LOOPX - i - 1];
                                        }
                                }
                                break;
                        case 5:
                                start.x = (lp->bncols - HEX_ADAM_LOOPY / 2) / 2;
                                start.y = (lp->bnrows - HEX_ADAM_LOOPX) / 2;
-                               lp->mincol = start.x - 2;
-                               lp->minrow = start.y - 1;
-                               lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
-                               lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
+                               if (lp->mincol > start.x - 2)
+                                       lp->mincol = start.x - 2;
+                               if (lp->minrow > start.y - 1)
+                                       lp->minrow = start.y - 1;
+                               if (lp->maxcol < start.x + HEX_ADAM_LOOPY + 1)
+                                       lp->maxcol = start.x + HEX_ADAM_LOOPY + 1;
+                               if (lp->maxrow < start.y + HEX_ADAM_LOOPX + 1)
+                                       lp->maxrow = start.y + HEX_ADAM_LOOPX + 1;
                                for (j = 0; j < HEX_ADAM_LOOPX; j++) {
                                        for (i = 0; i < HEX_ADAM_LOOPY; i++) {
                                                k = (((lp->bnrows / 2 + HEX_ADAM_LOOPX / 2) % 2) ? -(HEX_ADAM_LOOPX - j - 1) / 2 : -(HEX_ADAM_LOOPX - j) / 2);
                                                lp->newcells[(start.y + j) * lp->bncols + start.x + i + k] =
-                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
+                                                       (lp->clockwise) ?
+                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPY - j - 1][i] :
+                                                       hex_self_reproducing_loop[HEX_ADAM_LOOPX - i - 1][j];
                                        }
                                }
                                break;
                }
 #if DEBUGTEST
-                               /* printf ("s %d  s %d \n", start.x, start.y); */
-               printf ("%d %d %d %d %d\t",
+                               /* (void) printf ("s %d  s %d \n", start.x, start.y); */
+               (void) printf ("%d %d %d %d %d\n",
      start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
                 start.y + j - lp->by, i, j, hex_self_reproducing_loop[j][i]);
                /* Draw right away */
                drawcell(mi, start.x + i + ((lp->bnrows / 2 % 2) ? -j / 2 : -(j + 1) / 2) - lp->bx,
                 start.y + j - lp->by,
                 hex_self_reproducing_loop[j][i]);
-#endif
-#if DEBUGTEST
-                        printf ("\n");
-#endif
-#if DEBUGTEST
-                        printf ("\n");
 #endif
   } else {
-               switch (NRAND(4)) {
+               switch (dir) {
                        case 0:
                                start.x = (lp->bncols - ADAM_LOOPX) / 2;
                                start.y = (lp->bnrows - ADAM_LOOPY) / 2;
                                dirx.x = 1, dirx.y = 0;
                                diry.x = 0, diry.y = 1;
-                               lp->mincol = start.x, lp->minrow = start.y;
-                               lp->maxcol = start.x + ADAM_LOOPX, lp->maxrow = start.y + ADAM_LOOPY;
+                               if (lp->mincol > start.x)
+                                       lp->mincol = start.x;
+                               if (lp->minrow > start.y)
+                                       lp->minrow = start.y;
+                               if (lp->maxcol < start.x + ADAM_LOOPX)
+                                       lp->maxcol = start.x + ADAM_LOOPX;
+                               if (lp->maxrow < start.y + ADAM_LOOPY)
+                                       lp->maxrow = start.y + ADAM_LOOPY;
                                break;
                        case 1:
                                start.x = (lp->bncols + ADAM_LOOPY) / 2;
                                start.y = (lp->bnrows - ADAM_LOOPX) / 2;
                                dirx.x = 0, dirx.y = 1;
                                diry.x = -1, diry.y = 0;
-                               lp->mincol = start.x - ADAM_LOOPY, lp->minrow = start.y;
-                               lp->maxcol = start.x, lp->maxrow = start.y + ADAM_LOOPX;
+                               if (lp->mincol > start.x - ADAM_LOOPY)
+                                       lp->mincol = start.x - ADAM_LOOPY;
+                               if (lp->minrow > start.y)
+                                       lp->minrow = start.y;
+                               if (lp->maxcol < start.x)
+                                       lp->maxcol = start.x;
+                               if (lp->maxrow < start.y + ADAM_LOOPX)
+                                       lp->maxrow = start.y + ADAM_LOOPX;
                                break;
                        case 2:
                                start.x = (lp->bncols + ADAM_LOOPX) / 2;
                                start.y = (lp->bnrows + ADAM_LOOPY) / 2;
                                dirx.x = -1, dirx.y = 0;
                                diry.x = 0, diry.y = -1;
-                               lp->mincol = start.x - ADAM_LOOPX, lp->minrow = start.y - ADAM_LOOPY;
-                               lp->maxcol = start.x, lp->maxrow = start.y;
+                               if (lp->mincol > start.x - ADAM_LOOPX)
+                                       lp->mincol = start.x - ADAM_LOOPX;
+                               if (lp->minrow > start.y - ADAM_LOOPY)
+                                       lp->minrow = start.y - ADAM_LOOPY;
+                               if (lp->maxcol < start.x)
+                                       lp->maxcol = start.x;
+                               if (lp->maxrow < start.y)
+                                       lp->maxrow = start.y;
                                break;
                        case 3:
                                start.x = (lp->bncols - ADAM_LOOPY) / 2;
                                start.y = (lp->bnrows + ADAM_LOOPX) / 2;
                                dirx.x = 0, dirx.y = -1;
                                diry.x = 1, diry.y = 0;
-                               lp->mincol = start.x, lp->minrow = start.y - ADAM_LOOPX;
-                               lp->maxcol = start.x + ADAM_LOOPY, lp->maxrow = start.y;
+                               if (lp->mincol > start.x)
+                                       lp->mincol = start.x;
+                               if (lp->minrow > start.y - ADAM_LOOPX)
+                                       lp->minrow = start.y - ADAM_LOOPX;
+                               if (lp->maxcol < start.x + ADAM_LOOPX)
+                                       lp->maxcol = start.x + ADAM_LOOPX;
+                               if (lp->maxrow < start.y)
+                                       lp->maxrow = start.y;
                                break;
                }
                for (j = 0; j < ADAM_LOOPY; j++)
                        for (i = 0; i < ADAM_LOOPX; i++)
-                               lp->newcells[(start.y + dirx.y * i + diry.y * j) * lp->bncols +
-                                            start.x + dirx.x * i + diry.x * j] =
-                                       self_reproducing_loop[j][i];
+                         lp->newcells[lp->bncols * (start.y + dirx.y * i + diry.y * j) +
+                           start.x + dirx.x * i + diry.x * j] =
+                           (lp->clockwise) ?
+                             self_reproducing_loop[j][ADAM_LOOPX - i - 1] :
+                             self_reproducing_loop[j][i];
 #if DEBUG
                /* Draw right away */
                drawcell(mi, start.x + dirx.x * i + diry.x * j - lp->bx,
                 start.y + dirx.y * i + diry.y * j - lp->by,
-                self_reproducing_loop[j][i]);
+                (lp->clockwise) ? self_reproducing_loop[j][ADAM_LOOPX - i - i] : self_reproducing_loop[j][i]);
 #endif
        }
 }
@@ -1156,50 +1397,32 @@ do_gen(loopstruct * lp)
                                }
                        }
                        if (local_neighbors == 6) {
-                               *z = HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
+                               *z = (lp->clockwise) ?
+                                       HEX_TABLE_OUT(c, n[5], n[4], n[3], n[2], n[1], n[0]) :
+                                       HEX_TABLE_OUT(c, n[0], n[1], n[2], n[3], n[4], n[5]);
                        } else {
-                               *z = TABLE_OUT(c, n[0], n[1], n[2], n[3]);
+                               *z = (lp->clockwise) ?
+                                       TABLE_OUT(c, n[3], n[2], n[1], n[0]) :
+                                       TABLE_OUT(c, n[0], n[1], n[2], n[3]);
                        }
                }
        }
 }
 
-static void
-free_list(loopstruct * lp)
-{
-       int         state;
-
-       for (state = 0; state < COLORS; state++)
-               free_state(lp, state);
-}
-
 void
 release_loop(ModeInfo * mi)
 {
        if (loops != NULL) {
                int         screen;
 
-               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-                       loopstruct *lp = &loops[screen];
-                       int         shade;
-
-                       for (shade = 0; shade < lp->init_bits; shade++)
-                               if (lp->pixmaps[shade] != None)
-                                       XFreePixmap(MI_DISPLAY(mi), lp->pixmaps[shade]);
-                       if (lp->stippledGC != None)
-                               XFreeGC(MI_DISPLAY(mi), lp->stippledGC);
-                       if (lp->oldcells != NULL)
-                               (void) free((void *) lp->oldcells);
-                       if (lp->newcells != NULL)
-                               (void) free((void *) lp->newcells);
-                       free_list(lp);
-               }
+               for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
+                       free_loop(MI_DISPLAY(mi), &loops[screen]);
                (void) free((void *) loops);
-               loops = NULL;
+               loops = (loopstruct *) NULL;
        }
        if (table != NULL) {
                (void) free((void *) table);
-               table = NULL;
+               table = (unsigned int *) NULL;
        }
 }
 
@@ -1224,9 +1447,9 @@ init_loop(ModeInfo * mi)
        if ((MI_NPIXELS(mi) < COLORS) && (lp->init_bits == 0)) {
                if (lp->stippledGC == None) {
                        gcv.fill_style = FillOpaqueStippled;
-                       lp->stippledGC = XCreateGC(display, window, GCFillStyle, &gcv);
-                       if (lp->stippledGC == None) {
-                               release_loop(mi);
+                       if ((lp->stippledGC = XCreateGC(display, window,
+                                GCFillStyle, &gcv)) == None) {
+                               free_loop(display, lp);
                                return;
                        }
                }
@@ -1238,10 +1461,6 @@ init_loop(ModeInfo * mi)
                LOOPBITS(stipples[7], STIPPLESIZE, STIPPLESIZE);
                LOOPBITS(stipples[8], STIPPLESIZE, STIPPLESIZE);
                LOOPBITS(stipples[10], STIPPLESIZE, STIPPLESIZE);
-       if (lp->pixmaps[COLORS - 1] == None) {
-                       release_loop(mi);
-                       return;
-               }
        }
        if (MI_NPIXELS(mi) >= COLORS) {
                /* Maybe these colors should be randomized */
@@ -1259,21 +1478,17 @@ init_loop(ModeInfo * mi)
        lp->width = MI_WIDTH(mi);
        lp->height = MI_HEIGHT(mi);
 
-  if (!local_neighbors) {
-    for (i = 0; i < NEIGHBORKINDS; i++) {
-      if (neighbors == plots[i]) {
-        local_neighbors = neighbors;
-        neighbor_kind = i;
-        break;
-      }
+       if (!local_neighbors) {
+               for (i = 0; i < NEIGHBORKINDS; i++) {
+                       if (neighbors == plots[i]) {
+                               local_neighbors = neighbors;
+                               break;
+                       }
                        if (i == NEIGHBORKINDS - 1) {
-
 #if 1
                                local_neighbors = plots[NRAND(NEIGHBORKINDS)];
-                               neighbor_kind = (local_neighbors == 4) ? 0 : 1;
 #else
                                local_neighbors = 4;
-                               neighbor_kind = 0;
 #endif
                                break;
                        }
@@ -1284,10 +1499,10 @@ init_loop(ModeInfo * mi)
   if (local_neighbors == 6) {
     int         nccols, ncrows;
 
-    if (lp->width < 4)
-      lp->width = 4;
-    if (lp->height < 4)
-      lp->height = 4;
+    if (lp->width < 8)
+      lp->width = 8;
+    if (lp->height < 8)
+      lp->height = 8;
     if (size < -MINSIZE) {
       lp->ys = NRAND(MIN(-size, MAX(MINSIZE, MIN(lp->width, lp->height) /
               HEX_MINGRIDSIZE)) - MINSIZE + 1) + MINSIZE;
@@ -1300,11 +1515,11 @@ init_loop(ModeInfo * mi)
       lp->ys = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) /
                  HEX_MINGRIDSIZE));
     lp->xs = lp->ys;
-               nccols = MAX(lp->width / lp->xs - 2, HEX_ADAM_LOOPX + 1);
-               ncrows = MAX(lp->height / lp->ys - 1, HEX_ADAM_LOOPY + 1);
+    nccols = MAX(lp->width / lp->xs - 2, HEX_MINGRIDSIZE);
+    ncrows = MAX(lp->height / lp->ys - 1, HEX_MINGRIDSIZE);
     lp->ncols = nccols / 2;
     lp->nrows = ncrows / 2;
-               lp->nrows -= !(lp->nrows & 1);  /* Must be odd */
+    lp->nrows -= !(lp->nrows & 1);  /* Must be odd */
     lp->xb = (lp->width - lp->xs * nccols) / 2 + lp->xs;
     lp->yb = (lp->height - lp->ys * ncrows) / 2 + lp->ys;
     for (i = 0; i < 6; i++) {
@@ -1338,39 +1553,65 @@ init_loop(ModeInfo * mi)
 
        if (lp->oldcells != NULL) {
                (void) free((void *) lp->oldcells);
-               lp->oldcells = NULL;
-       }       
-       if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows, sizeof (unsigned char))) == NULL) {
-               release_loop(mi);
+               lp->oldcells = (unsigned char *) NULL;
+       }
+       if ((lp->oldcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
+                       sizeof (unsigned char))) == NULL) {
+               free_loop(display, lp);
                return;
        }
        if (lp->newcells != NULL) {
                (void) free((void *) lp->newcells);
-               lp->newcells = NULL;
+               lp->newcells = (unsigned char *) NULL;
        }
-       if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows, sizeof (unsigned char))) == NULL) {
-               release_loop(mi);
+       if ((lp->newcells = (unsigned char *) calloc(lp->bncols * lp->bnrows,
+                       sizeof (unsigned char))) == NULL) {
+               free_loop(display, lp);
                return;
        }
-  if (init_table()) {
+       if (!init_table()) {
                release_loop(mi);
                return;
        }
+       lp->mincol = lp->bncols - 1;
+       lp->minrow = lp->bnrows - 1;
+       lp->maxcol = 0; 
+       lp->maxrow = 0;
+#ifndef DELAYDEBUGLOOP
+       {
+               int flaws = MI_COUNT(mi);
+
+               if (flaws < 0)
+                       flaws = NRAND(-MI_COUNT(mi) + 1);
+               for (i = 0; i < flaws; i++) {
+                       init_flaw(mi);
+               }
+               /* actual flaws might be less since the adam loop done next */
+       }
+#endif
        init_adam(mi);
 }
 
 void
 draw_loop(ModeInfo * mi)
 {
-       loopstruct *lp = &loops[MI_SCREEN(mi)];
-       int         offset, i, j, life = 0;
+       int         offset, i, j;
        unsigned char *z, *znew;
+       loopstruct *lp;
 
-       if (loops == NULL) {
-               init_loop(mi);
+       if (loops == NULL)
                return;
-       }
+       lp = &loops[MI_SCREEN(mi)];
+       if (lp->newcells == NULL)
+               return;
+
        MI_IS_DRAWN(mi) = True;
+       lp->dead = True;
+#ifdef DELAYDEBUGLOOP
+       if (MI_COUNT(mi) && lp->generation > MI_COUNT(mi)) {
+               (void) sleep(DELAYDEBUGLOOP);
+       }
+#endif
 
        for (j = lp->minrow; j <= lp->maxrow; j++) {
                for (i = lp->mincol; i <= lp->maxcol; i++) {
@@ -1378,9 +1619,10 @@ draw_loop(ModeInfo * mi)
                        z = lp->oldcells + offset;
                        znew = lp->newcells + offset;
                        if (*z != *znew) {
+                               lp->dead = False;
                                *z = *znew;
-                               addtolist(mi, i - lp->bx, j - lp->by, *znew);
-                               life = 1;
+                               if (!addtolist(mi, i - lp->bx, j - lp->by, *znew))
+                                       return;
                                if (i == lp->mincol && i > lp->bx)
                                        lp->mincol--;
                                if (j == lp->minrow && j > lp->by)
@@ -1393,8 +1635,11 @@ draw_loop(ModeInfo * mi)
                }
        }
        for (i = 0; i < COLORS; i++)
-               draw_state(mi, i);
-       if (++lp->generation > MI_CYCLES(mi) /* || !life */) {
+               if (!draw_state(mi, i)) {
+                       free_loop(MI_DISPLAY(mi), lp);
+                       return;
+               }
+       if (++lp->generation > MI_CYCLES(mi) || lp->dead) {
                init_loop(mi);
                return;
        } else
@@ -1418,13 +1663,15 @@ draw_loop(ModeInfo * mi)
 void
 refresh_loop(ModeInfo * mi)
 {
-       loopstruct *lp = &loops[MI_SCREEN(mi)];
+       loopstruct *lp;
 
-       if (loops == NULL) {
-               init_loop(mi);
+       if (loops == NULL)
                return;
-       }
+       lp = &loops[MI_SCREEN(mi)];
+
        MI_CLEARWINDOW(mi);
        lp->redrawing = 1;
        lp->redrawpos = lp->by * lp->ncols + lp->bx;
 }
+
+#endif /* MODE_loop */