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