1 /*
2  *  The Rules to Life, as explained to me by Duane Morin
3  *   If a Dead cell has 3 neighbors, it becomes alive. Otherwise, it stays
4  *      dead.
5  *   If a alive cell has 2 or 3 neighbors, it stays alive.
6  */
7 
8 #include <X11/X.h>
9 #include <X11/Xlib.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include "trippy.h"
13 
14 static short** neighbors; /* 0 to 8 , plus an extra bit to tell status*/
15 static short** age;      /* 0 to numcolors */
16 static short *xsize,*mX;
17 static short *ysize,*mY;
18 
19 #define ON 0x0010
20 static void findNeighbors(int,int,int);
21 static void kAA(int,int,int);
22 static int initd=0;
23 
24 void
exit_life()25 exit_life()
26 {
27   int i;
28 
29   initd=0;
30   for(i=0;i<options.windows;i++)
31   {
32     free(age[i]);
33     free(neighbors[i]);
34   }
35   free(age);
36   free(neighbors);
37   free(mY);
38   free(mX);
39   free(xsize);
40   free(ysize);
41 }
42 
43 void
getALife(int winno)44 getALife(int winno)
45 {
46   int x,y;
47 
48   if(!initd)
49   {
50     age=(short **)calloc(options.windows,sizeof(short **));
51     neighbors=(short **)calloc(options.windows,sizeof(short *));
52     mX=(short*)calloc(options.windows,sizeof(short));
53     mY=(short*)calloc(options.windows,sizeof(short));
54     xsize=(short*)calloc(options.windows,sizeof(short));
55     ysize=(short*)calloc(options.windows,sizeof(short));
56     initd=1;
57   }
58   mX[winno]=CX[winno];
59   mY[winno]=CY[winno];
60   xsize[winno]=ysize[winno]=1;
61   while(mX[winno]>=128)
62   {
63     xsize[winno]<<=1;
64     mX[winno]>>=1;
65   }
66   while(mY[winno]>=128)
67   {
68     ysize[winno]<<=1;
69     mY[winno]>>=1;
70   }
71 
72   age[winno]=(short *)calloc((mX[winno]+1)*(mY[winno]+1),sizeof(short));
73   neighbors[winno]=(short *)calloc((mX[winno]+1)*(1+mY[winno]),sizeof(short));
74 
75   for(x=0;x<mX[winno];x++)
76   {
77     for(y=0;y<mY[winno];y++)
78     {
79       if(rndm(100)<options.number)
80       {
81 	int here=y*mX[winno]+x;
82 
83 	neighbors[winno][here]=ON;
84 	XFillRectangle(display,window[winno],
85 		       color_gcs[age[winno][here]=1],
86 		       x*xsize[winno],y*ysize[winno],
87 		       xsize[winno],ysize[winno]);
88       }
89     }
90   }
91 }
92 
93 void
endLife(int winno)94 endLife(int winno)
95 {
96   free(age[winno]);
97   free(neighbors[winno]);
98 }
99 
100 void
dropACell(int winno,int x,int y)101 dropACell(int winno, int x,int y)
102 {
103   x /= xsize[winno];
104   y /= ysize[winno];
105   neighbors[winno][y*mX[winno]+x]^=ON; /* flip it on */
106 }
107 
108 void
drawLife(int winno)109 drawLife(int winno)
110 {
111   int x,y;
112 
113   for(y=0;y<mY[winno]+2;y++)
114   {
115     for(x=0;x<mX[winno];x++)
116     {
117       findNeighbors(x,y,winno);
118       /*      findNeighbors((x+100)%(mX[winno]),y); */
119       if(y-2>=0)      kAA(x,y-2,winno);
120       /*      if((x+98)%(mX[winno])>0) kAA((x+98)%(mX[winno]),y); */
121     }
122   }
123 }
124 
125 void
findNeighbors(int x,int y,int winno)126 findNeighbors(int x,int y, int winno)
127 {
128   int foo,bar;
129   if(x>=mX[winno]) return;
130   if(neighbors[winno][y*mX[winno]+x]&ON)
131   {
132     for(bar=y-1;bar<=y+1;bar++)
133       for(foo=x-1;foo<=x+1;foo++)
134       {
135 	if( (foo<0) || (bar<0) || (foo>=mX[winno]) || (bar>=mY[winno]) ||
136 	    (foo==x&&bar==y))
137 	  continue;
138 	else
139 	{
140 	  neighbors[winno][bar*mX[winno]+foo]++; /* tell everyone around you
141 						    that they have a neighbor*/
142 	}
143       }
144   }
145 }
146 
147 void
kAA(int x,int y,int winno)148 kAA(int x, int y, int winno) /* it's alive... it's dead... */
149 {
150   int nov;
151   int coord = y*mX[winno]+x;
152 
153   if(((nov=neighbors[winno][coord]&0x000f)==3)||
154      ((nov==2)&&(neighbors[winno][coord]&ON)))
155   {
156     neighbors[winno][coord]=ON;
157     if(++age[winno][coord]>=numcolors)
158       age[winno][coord]=1;
159   }
160   else
161   {
162     age[winno][coord]=0;
163     neighbors[winno][coord]=0;
164   }
165 
166   XFillRectangle(display,window[winno],
167 		 color_gcs[age[winno][coord]],
168 		 x*xsize[winno],y*ysize[winno],
169 		 xsize[winno],ysize[winno]);
170 }
171 
172