1 /*
2 * game.c -- xrobots
3 *
4 * Copyright 1989 Brian Warkentine
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the author's name not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. The author makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
15 *
16 * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
18 * AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
19 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
20 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * The author's current employer has no connection with this software, as it
24 * was written before being employed at Sun. The following address is for
25 * contacting the author only and does not imply any responsibility on the
26 * behalf of Sun Microsystems.
27 *
28 * Contact the author at:
29 * Brian Warkentine (brianw@Sun.COM)
30 * Sun Microsystems
31 * 2550 Garcia Avenue
32 * Mountain View, Ca 94043-1100
33 *
34 * HP-UX :- following two defines
35 */
36
37 #include <X11/Intrinsic.h>
38 #include <stdlib.h>
39 #include "xrobots.h"
40
41 /* some of these are global */
42 int human_x, human_y, last_human_x, last_human_y;
43
44 int robot_array[MAXX][MAXY],
45 robot_array_bak[MAXX][MAXY];
46 /* These arrays are filled with the robots and the heaps
47 * They do not include the player(human).
48 */
49 int score,
50 num_robots,
51 level,
52 game_active,
53 sonic_used;
54
55 static void autochase();
56
57 /*----------------------------------------------------------------------*/
58 void
new_game()59 new_game()
60 {
61 score = 0;
62 level = 0;
63 sonic_used = 1;
64 game_active = 1;
65 new_level();
66 update_score(score);
67 }
68
69 /*----------------------------------------------------------------------*/
70 void
add_score(n)71 add_score(n)
72 int n;
73 {
74 score += 10 * n; /* ten points for each wasted robot. */
75 num_robots -= n;
76 if(n) update_score(score);
77 }
78
79 /*----------------------------------------------------------------------*/
80 void
new_level()81 new_level()
82 {
83 int x,y,tmp;
84
85 reset_sonic_button();
86 if(!sonic_used) {
87 score += 50; /* bonus for not using sonic screwdriver on last level*/
88 update_score(score);
89 }
90 sonic_used = 0;
91 level++;
92 num_robots = tmp = level*5;
93
94 for_each /* clean out both the robot arrays */
95 {
96 robot_array[x][y] = EMPTY;
97 robot_array_bak[x][y] = EMPTY;
98 }
99
100 human_x = (int)random()%MAXX; /* assign human to new space */
101 human_y = (int)random()%MAXY;
102 robot_array[human_x][human_y] = ROBOT;
103
104 while(tmp--)
105 {
106 x = (int)random()%MAXX;
107 y = (int)random()%MAXY;
108 if(robot_array[x][y] == ROBOT) tmp++; /* space already occupied */
109 robot_array[x][y] = ROBOT;
110 }
111 robot_array[human_x][human_y] = EMPTY;
112 display_level();
113 display_possible_moves();
114 }
115
116 /*----------------------------------------------------------------------*/
117 int
chase()118 chase()
119 {
120 /* chase() returns the number of robots that were wasted in each call. */
121 /* after each call, be sure to check if all the robots are dead */
122 int x,y;
123 int newx,newy;
124 int num_wasted = 0;
125
126 for_each
127 {
128 robot_array_bak[x][y] = robot_array[x][y];
129 if(robot_array[x][y] != HEAP)
130 robot_array[x][y] = 0;
131 }
132
133 for_each
134 {
135 if(robot_array_bak[x][y] != ROBOT)
136 continue;
137
138 if(x>human_x) /* move toward the human */
139 newx = x-1;
140 else
141 if(x<human_x)
142 newx = x+1;
143 else
144 newx = x;
145
146 if(y>human_y)
147 newy = y-1;
148 else
149 if(y<human_y)
150 newy = y+1;
151 else
152 newy = y;
153
154 # ifdef DEBUG
155 printf("moving (%d,%d) to (%d,%d)\n",x,y,newx,newy);
156 # endif
157
158 /* check to see if a robot or heap was already in that spot */
159 if(robot_array[newx][newy] == ROBOT)
160 {
161 robot_array[newx][newy] = HEAP;
162 num_wasted += 2;
163 continue;
164 }
165 if(robot_array[newx][newy] == HEAP)
166 {
167 num_wasted++;
168 continue;
169 }
170 /* move robot to new location */
171 robot_array[newx][newy] = ROBOT;
172 }
173
174 return(num_wasted);
175 }
176
177 /*----------------------------------------------------------------------*/
178 void
undo_chase()179 undo_chase()
180 {
181 int x,y;
182 for_each
183 robot_array[x][y] = robot_array_bak[x][y];
184 }
185
186 /*----------------------------------------------------------------------*/
187 void
teleport()188 teleport()
189 {
190 int num_wasted;
191
192 if(!game_active) return;
193 do
194 {
195 human_x = (int)random()%MAXX; /* pick a spot not already occupied */
196 human_y = (int)random()%MAXY;
197 }
198 while(robot_array[human_x][human_y] != EMPTY);
199
200 show_teleport();
201
202 num_wasted = chase(0);
203
204 if(robot_array[human_x][human_y] != EMPTY)
205 {
206 /* death... */
207 undo_chase();
208 /* it is a matter of preference to clear the screen when you die... */
209 display_level();
210 do_death();
211 check_score(score);
212 game_active = 0;
213 return;
214 }
215
216 display_level();
217
218 score += num_robots; /* bonus for teleporting */
219 score += num_wasted * 10; /* score for any that collided */
220 num_robots -= num_wasted;
221 update_score(score);
222
223 if(!num_robots)
224 new_level();
225 else
226 display_possible_moves();
227 auto_teleport();
228 XFlush(display);
229 }
230
231 /*----------------------------------------------------------------------*/
232 void
sonic_screwdriver()233 sonic_screwdriver()
234 {
235 /*
236 * a trick - remove the neighboring robots by calling chase() and
237 * letting them crash into each other in the human's spot, then clear out
238 * the human's position of the remains.
239 */
240 int num_wasted;
241
242 if(!game_active) return;
243 if(sonic_used) return;
244 sonic_used = 1;
245 show_sonic();
246 num_wasted = chase(1);
247 if(robot_array[human_x][human_y] == ROBOT)
248 add_score(1);
249 robot_array[human_x][human_y] = EMPTY;
250
251 last_human_x = human_x;
252 last_human_y = human_y;
253 show_movement();
254
255 add_score(num_wasted);
256 if(!num_robots)
257 new_level();
258 else
259 display_possible_moves();
260 auto_teleport();
261 XFlush(display);
262 }
263
264 /*----------------------------------------------------------------------*/
265 void
wait_for_em()266 wait_for_em()
267 {
268 /*
269 * the trick - call chase() until any robot is in the same spot as the
270 * human, then backout as if the last chase() didn't happen.
271 */
272 int num_wasted;
273
274 if(!game_active) return;
275
276 while(1) {
277 num_wasted = chase(1);
278 if(robot_array[human_x][human_y] != EMPTY) {
279 /* backout of latest chase() and break loop */
280 undo_chase();
281
282 if(app_data.diewaiting) { /* for those risk takers out there */
283 display_level();
284 do_death();
285 check_score(score);
286 game_active = 0;
287 return;
288 }
289
290 break;
291 }
292 add_score(num_wasted);
293 if(!num_robots)
294 break;
295 if(app_data.showjumps)
296 show_movement();
297 XFlush(display);
298 }
299 if(!num_robots)
300 new_level();
301 else
302 if(!app_data.showjumps)
303 display_level();
304 display_possible_moves();
305 auto_teleport();
306 XFlush(display);
307 }
308
309 /*----------------------------------------------------------------------*/
310
311
312 int
can_go(x,y)313 can_go(x,y)
314 int x,y;
315 {
316 /* check if (x,y) is a legit move. */
317 if( INYRANGE(y-1) ) {
318 if( INXRANGE(x-1) )
319 if(robot_array[x-1][y-1] == ROBOT) return 0;
320 if( INXRANGE(x) )
321 if(robot_array[x][y-1] == ROBOT) return 0;
322 if( INXRANGE(x+1) )
323 if(robot_array[x+1][y-1] == ROBOT) return 0;
324 }
325
326 if( INYRANGE(y) ) {
327 if( INXRANGE(x-1) )
328 if(robot_array[x-1][y] == ROBOT) return 0;
329 if( INXRANGE(x) ) {
330 if(robot_array[x][y] == ROBOT) return 0;
331 if(robot_array[x][y] == HEAP) return 0;
332 }
333 if( INXRANGE(x+1) )
334 if(robot_array[x+1][y] == ROBOT) return 0;
335 }
336
337 if( INYRANGE(y+1) ) {
338 if( INXRANGE(x-1) )
339 if(robot_array[x-1][y+1] == ROBOT) return 0;
340 if( INXRANGE(x) )
341 if(robot_array[x][y+1] == ROBOT) return 0;
342 if( INXRANGE(x+1) )
343 if(robot_array[x+1][y+1] == ROBOT) return 0;
344 }
345
346 if( !INXRANGE(x) ) return 0;
347 if( !INYRANGE(y) ) return 0;
348
349 return 1;
350 }
351
352