1 /*
2 * Play a game of Tag.. this is kind of like the Anti-Swarm
3 * instead of heading towards 'IT' .. everyone runs away from it
4 * Written by Jer (mpython@gnu.ai.mit.edu , jer@gulik.gweep.net)
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <X11/X.h>
10 #include <X11/Xlib.h>
11 #include "lmath.h"
12 #include "trippy.h"
13
14 #ifdef WINDOWS
15 extern foo options;
16 extern HPALETTE hPal;
17 #endif
18
19 #define sgn(x) ((x)==0?0:((x)>0?1:-1))
20
21 struct kid
22 {
23 long x,y;
24 long oldx,oldy;
25 signed int vx,vy;
26 signed int maxvx, maxvy;
27 unsigned int color;
28 };
29
30 int cur_kid;
31
32 struct kid **playground_p;
33 struct kid **it;
34 struct kid **it_target;
35 struct kid **last_it;
36
37 static struct kid* findClosestKid(int);
38
39 void
init_it(int winno)40 init_it(int winno)
41 {
42
43 it[winno] = &playground_p[winno][rndm(options.number)];
44 last_it[winno]=0;
45 #ifdef WINDOWS
46 it[winno]->color = GetNearestPaletteIndex(hPal,RGB(0,255,255));
47 #else
48 it[winno]->color = 3*numcolors/6; /* CYAN */
49 #endif
50 it_target[winno] = findClosestKid(winno);
51 }
52
53 void
init_kid(int winno,struct kid * pt)54 init_kid (int winno, struct kid *pt)
55 {
56 pt->x = (long)rndm(CX[winno])*64;
57 pt->y = (long)rndm(CY[winno])*64;
58 pt->oldx = pt->x;
59 pt->oldy = pt->y;
60 pt->vx= pt->vy=0;
61 pt->maxvx = rndm(8*64)+64;
62 pt->maxvy = rndm(8*64)+64;
63
64 if(options.multi)
65 pt->color = rndm(numcolors);
66 else
67 #ifdef WINDOWS
68 pt->color=GetNearestPaletteIndex(hPal,RGB(255,255,0));
69 #else
70 pt->color=numcolors/6; /* YELLOW */
71 #endif
72 }
73
74 void
draw_kid(int winno,struct kid * b)75 draw_kid (int winno, struct kid *b)
76 {
77 XDrawLine (display, window[winno], color_gcs[b->color], b->x/64,b->y/64,
78 b->oldx/64, b->oldy/64);
79 }
80
81 void
clear_kid(int winno,struct kid * b)82 clear_kid (int winno, struct kid *b)
83 {
84 XDrawLine (display, window[winno], color_gcs[0], b->x/64, b->y/64,
85 b->oldx/64, b->oldy/64);
86 }
87
88 void
moveIt(int winno,long x,long y)89 moveIt(int winno, long x, long y)
90 {
91 clear_kid(winno,it[winno]);
92 it[winno]->x = x*64;
93 it[winno]->y = y*64;
94 it[winno]->vx = it[winno]->vy = 0;
95 }
96
97 int
update_kid(int winno,struct kid * b)98 update_kid (int winno, struct kid * b)
99 {
100 long x, y;
101 unsigned long usecx = (long)CX[winno]*64;
102 unsigned long usecy = (long)CY[winno]*64;
103
104 clear_kid (winno, b);
105
106 x = b->x; y = b->y;
107 if(b==it[winno])
108 {
109 b->vx += sgn(it_target[winno]->x - x)*16;
110 b->vy += sgn(it_target[winno]->y - y)*16;
111 }
112 else
113 {
114 if(math_dist(b->x,b->y,it_target[winno]->x,it_target[winno]->y)<(32*64))
115 { /* too close, run away!!! */
116 b->vx += -sgn(it[winno]->x-x)*16;
117 b->vy += -sgn(it[winno]->y-y)*16;
118 }
119 else
120 {
121 b->vx >>=1; /* slow down by half */
122 b->vy >>=1;
123 }
124
125 #if 0
126 else /* head back into the middle */
127 {
128 b->vx += sgn(usecx>>1-x)*16;
129 b->vy += sgn(usecy>>1-y)*16;
130 }
131 #endif
132 }
133
134 if(abs(b->vx)>b->maxvx) b->vx=b->maxvx*sgn(b->vx);
135 if(abs(b->vy)>b->maxvy) b->vy=b->maxvy*sgn(b->vy);
136
137 b->x += b->vx + (rndm(3)-1);
138 b->y += b->vy + (rndm(3)-1);
139
140 /* keep everyone in the playyard */
141 if(b->x<0)
142 {
143 b->x= 0;
144 b->vx = 0;
145 }
146 else if (b->x>=usecx)
147 {
148 b->x= usecx-64;
149 b->vx = 0;
150 }
151 if(b->y<0)
152 {
153 b->y= 0;
154 b->vy =0;
155 }
156 else if(b->y>=usecy)
157 {
158 b->y= usecy-64;
159 b->vy = 0;
160 }
161
162 b->oldx = x; b->oldy = y;
163
164 draw_kid (winno, b);
165 if(options.multi)
166 b->color = (b->color+1)%numcolors;
167 return 0;
168 }
169
170 int
update_it(int winno)171 update_it(int winno)
172 {
173 /*
174 if(!rndm(100) || (it[winno].x == it_target_x) &&
175 (it[winno].y == it_target_y))
176 {
177 it_target_x = (long)rndm(CX[winno])*64;
178 it_target_y = (long)rndm(CY[winno])*64;
179 }
180 */
181 it_target[winno] = findClosestKid(winno);
182
183 /* update_kid(winno,&it[winno],it_target_x,it_target_y); */
184 return 0;
185 }
186
187 struct kid*
findClosestKid(int winno)188 findClosestKid(int winno)
189 {
190 int d = 999999,temp_d;
191 int i, itnum;
192 struct kid* temp=0;
193
194 itnum=-1;
195 for (i=0;i<options.number;i++)
196 {
197 if(&playground_p[winno][i]==it[winno])
198 continue;
199 if(&playground_p[winno][i]==last_it[winno])
200 continue;
201
202 if((temp_d=math_dist(it[winno]->x,it[winno]->y,
203 playground_p[winno][i].x,playground_p[winno][i].y))<d)
204 {
205 d=temp_d;
206 temp=&playground_p[winno][i];
207 itnum=i;
208 if(d<=64) /* gotcha */
209 break;
210 }
211 }
212
213 if(d<=64) /* TAG! no tagbacks */
214 {
215 it[winno]->color = numcolors/6; /* YELLOW */
216 last_it[winno] = it[winno];
217 it[winno] = temp;
218 it[winno]->color = 3*numcolors/6; /* CYAN */
219 it_target[winno] = &playground_p[winno][rndm(options.number)];
220 fprintf(stderr,"TAG! #%d is it\n",itnum);
221 return it_target[winno];
222
223 }
224 else
225 return temp;
226 }
227
228 static int inited=0;
229
230 void
init_playground(int winno)231 init_playground(int winno)
232 {
233 if(!inited)
234 {
235 playground_p=(struct kid * *) malloc((sizeof(struct kid *) *
236 options.windows));
237 it = (struct kid **) malloc((sizeof(struct kid )*options.windows));
238 it_target =(struct kid **) malloc((sizeof(struct kid )*options.windows));
239 last_it = (struct kid **) malloc((sizeof(struct kid )*options.windows));
240 inited=1;
241 }
242
243 if(options.number < 3)
244 {
245 options.number=3; /* you need at least 3 to play tag */
246 }
247
248
249 playground_p[winno] = (struct kid *) malloc(sizeof (struct kid ) *
250 options.number);
251
252 for (cur_kid=0; cur_kid<options.number; cur_kid++)
253 {
254 init_kid (winno,&(playground_p[winno][cur_kid]));
255 draw_kid (winno,&(playground_p[winno][cur_kid]));
256 }
257 init_it(winno);
258 }
259
260 void
exit_playground(int winno)261 exit_playground(int winno)
262 {
263 if(inited)
264 {
265 free(playground_p[winno]);
266 free(playground_p);
267 free(it);
268 free(it_target);
269 free(last_it);
270 inited=0;
271 }
272 }
273
274 void
exit_tag()275 exit_tag()
276 {
277 exit_playground(0);
278 }
279
280 void
draw_playground(int winno)281 draw_playground(int winno)
282 {
283 for(cur_kid=0;cur_kid<options.number;cur_kid++)
284 {
285 update_kid(winno,&(playground_p[winno][cur_kid]));
286 }
287 update_it(winno);
288 }
289