http://ftp.ussg.iu.edu/linux/slackware/slackware-9.0/source/xap/xscreensaver/xscreens...
[xscreensaver] / hacks / petri.c
index b4c748f65f36b7c572b2b9d64604ba0f6a7df905..b9da70ad7cec69c48d17fe10fdea1c9ed715dbc7 100644 (file)
@@ -1,4 +1,4 @@
-/* petri, simulate mold in a petri dish. v2.6
+/* petri, simulate mold in a petri dish. v2.7
  * by Dan Bornstein, danfuzz@milk.com
  * with help from Jamie Zawinski, jwz@jwz.org
  * Copyright (c) 1992-1999 Dan Bornstein.
 
 typedef struct cell_s 
 {
-    short x;                        /*  0    - */
-    short y;                        /*  2      */
-    unsigned char col;              /*  4      */
-    unsigned char isnext;           /*  5      */
-    unsigned char nextcol;          /*  6      */
-                                    /*  7      */
-    struct cell_s *next;            /*  8    - */
-    struct cell_s *prev;            /* 12      */
-    FLOAT speed;                    /* 16    - */
-    FLOAT growth;                   /* 20 24   */
-    FLOAT nextspeed;                /* 24 32 - */
-                                    /* 28 40   */
+    unsigned char col;              /*  0      */
+    unsigned char isnext;           /*  1      */
+    unsigned char nextcol;          /*  2      */
+                                    /*  3      */
+    struct cell_s *next;            /*  4      */
+    struct cell_s *prev;            /*  8    - */
+    FLOAT speed;                    /* 12      */
+    FLOAT growth;                   /* 16 20 - */
+    FLOAT nextspeed;                /* 20 28   */
+                                    /* 24 36 - */
 } cell;
 
 static int arr_width;
@@ -116,6 +114,10 @@ static FLOAT mindeathspeed;
 static FLOAT maxdeathspeed;
 static Bool originalcolors;
 
+#define cell_x(c) (((c) - arr) % arr_width)
+#define cell_y(c) (((c) - arr) / arr_width)
+
+
 static int random_life_value (void)
 {
     return (int) ((RAND_FLOAT * (maxlifespan - minlifespan)) + minlifespan);
@@ -273,9 +275,16 @@ static void setup_display (void)
 
     count = get_integer_resource ("count", "Integer");
     if (count < 2) count = 2;
+
+    /* number of colors can't be greater than the half depth of the screen. */
     if (count > (1L << (xgwa.depth-1)))
       count = (1L << (xgwa.depth-1));
 
+    /* Actually, since cell->col is of type char, this has to be small. */
+    if (count >= (1L << ((sizeof(arr[0].col) * 8) - 1)))
+      count = (1L << ((sizeof(arr[0].col) * 8) - 1));
+
+
     if (originalcolors && (count > 8))
     {
        count = 8;
@@ -480,8 +489,6 @@ static void setup_arr (void)
       int row = y * arr_width;
        for (x = 0; x < arr_width; x++) 
        {
-           arr[row+x].x = x;
-           arr[row+x].y = y;
            arr[row+x].speed = 0.0;
            arr[row+x].growth = 0.0;
            arr[row+x].col = 0;
@@ -533,7 +540,7 @@ static void killcell (cell *c)
     c->next->prev = c->prev;
     c->prev = 0;
     c->speed = 0.0;
-    drawblock (c->x, c->y, c->col);
+    drawblock (cell_x(c), cell_y(c), c->col);
 }
 
 
@@ -596,33 +603,42 @@ static void update (void)
     
     for (a = head->next; a != tail; a = a->next) 
     {
-        static XPoint coords1[] = {{-1,  0}, { 1, 0}, {0, -1}, {0, 1}};
-        static XPoint coords2[] = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
+       static XPoint all_coords[] = {{-1, -1}, {-1, 1}, {1, -1}, {1, 1},
+                                     {-1,  0}, { 1, 0}, {0, -1}, {0, 1},
+                                     {99, 99}};
+
         XPoint *coords = 0;
-        int i;
 
         if (a->speed == 0) continue;
         a->growth += a->speed;
-        if (a->growth >= orthlim) 
-          coords = coords1;
 
        if (a->growth >= diaglim) 
-          coords = coords2;
-
-        if (coords)
-          for (i = 0; i < 4; i++)
-            {
-              int x = a->x + coords[i].x;
-              int y = a->y + coords[i].y;
-
-              if (x < 0) x = arr_width - 1;
-              else if (x >= arr_width) x = 0;
-
-              if (y < 0) y = arr_height - 1;
-              else if (y >= arr_height) y = 0;
+       {
+           coords = all_coords;
+       }
+        else if (a->growth >= orthlim)
+       {
+           coords = &all_coords[4];
+       }
+       else
+       {
+           continue;
+       }
 
-              newcell (&arr[y * arr_width + x], a->col, a->speed);
-            }
+       while (coords->x != 99)
+       {
+           int x = cell_x(a) + coords->x;
+           int y = cell_y(a) + coords->y;
+           coords++;
+           
+           if (x < 0) x = arr_width - 1;
+           else if (x >= arr_width) x = 0;
+           
+           if (y < 0) y = arr_height - 1;
+           else if (y >= arr_height) y = 0;
+           
+           newcell (&arr[y * arr_width + x], a->col, a->speed);
+       }
 
        if (a->growth >= diaglim) 
            killcell (a);
@@ -638,7 +654,7 @@ static void update (void)
            a->speed = a->nextspeed;
            a->growth = 0.0;
            a->col = a->nextcol;
-           drawblock (a->x, a->y, a->col + count);
+           drawblock (cell_x(a), cell_y(a), a->col + count);
        }
     }
 }