Expand PMF_FN_* macros.
[netbsd-mini2440.git] / games / hunt / huntd / execute.c
blob1592b870ab5961c706c6a9b1b3cdca5c4e33ff67
1 /* $NetBSD: execute.c,v 1.8 2009/07/04 02:37:20 dholland Exp $ */
2 /*
3 * Copyright (c) 1983-2003, Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * + Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * + Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * + Neither the name of the University of California, San Francisco nor
16 * the names of its contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 #ifndef lint
35 __RCSID("$NetBSD: execute.c,v 1.8 2009/07/04 02:37:20 dholland Exp $");
36 #endif /* not lint */
38 #include <stdlib.h>
39 #include "hunt.h"
41 static void cloak(PLAYER *);
42 static void turn_player(PLAYER *, int);
43 static void fire(PLAYER *, int);
44 static void fire_slime(PLAYER *, int);
45 static void move_player(PLAYER *, int);
46 static void pickup(PLAYER *, int, int, int, int);
47 static void scan(PLAYER *);
50 #ifdef MONITOR
52 * mon_execute:
53 * Execute a single monitor command
55 void
56 mon_execute(PLAYER *pp)
58 char ch;
60 ch = pp->p_cbuf[pp->p_ncount++];
61 switch (ch) {
62 case CTRL('L'):
63 sendcom(pp, REDRAW);
64 break;
65 case 'q':
66 (void) strcpy(pp->p_death, "| Quit |");
67 break;
70 #endif
73 * execute:
74 * Execute a single command
76 void
77 execute(PLAYER *pp)
79 char ch;
81 ch = pp->p_cbuf[pp->p_ncount++];
83 #ifdef FLY
84 if (pp->p_flying >= 0) {
85 switch (ch) {
86 case CTRL('L'):
87 sendcom(pp, REDRAW);
88 break;
89 case 'q':
90 (void) strcpy(pp->p_death, "| Quit |");
91 break;
93 return;
95 #endif
97 switch (ch) {
98 case CTRL('L'):
99 sendcom(pp, REDRAW);
100 break;
101 case 'h':
102 move_player(pp, LEFTS);
103 break;
104 case 'H':
105 turn_player(pp, LEFTS);
106 break;
107 case 'j':
108 move_player(pp, BELOW);
109 break;
110 case 'J':
111 turn_player(pp, BELOW);
112 break;
113 case 'k':
114 move_player(pp, ABOVE);
115 break;
116 case 'K':
117 turn_player(pp, ABOVE);
118 break;
119 case 'l':
120 move_player(pp, RIGHT);
121 break;
122 case 'L':
123 turn_player(pp, RIGHT);
124 break;
125 case 'f':
126 case '1':
127 fire(pp, 0); /* SHOT */
128 break;
129 case 'g':
130 case '2':
131 fire(pp, 1); /* GRENADE */
132 break;
133 case 'F':
134 case '3':
135 fire(pp, 2); /* SATCHEL */
136 break;
137 case 'G':
138 case '4':
139 fire(pp, 3); /* 7x7 BOMB */
140 break;
141 case '5':
142 fire(pp, 4); /* 9x9 BOMB */
143 break;
144 case '6':
145 fire(pp, 5); /* 11x11 BOMB */
146 break;
147 case '7':
148 fire(pp, 6); /* 13x13 BOMB */
149 break;
150 case '8':
151 fire(pp, 7); /* 15x15 BOMB */
152 break;
153 case '9':
154 fire(pp, 8); /* 17x17 BOMB */
155 break;
156 case '0':
157 fire(pp, 9); /* 19x19 BOMB */
158 break;
159 case '@':
160 fire(pp, 10); /* 21x21 BOMB */
161 break;
162 #ifdef OOZE
163 case 'o':
164 fire_slime(pp, 0); /* SLIME */
165 break;
166 case 'O':
167 fire_slime(pp, 1); /* SSLIME */
168 break;
169 case 'p':
170 fire_slime(pp, 2);
171 break;
172 case 'P':
173 fire_slime(pp, 3);
174 break;
175 #endif
176 case 's':
177 scan(pp);
178 break;
179 case 'c':
180 cloak(pp);
181 break;
182 case 'q':
183 (void) strcpy(pp->p_death, "| Quit |");
184 break;
189 * move_player:
190 * Execute a move in the given direction
192 static void
193 move_player(PLAYER *pp, int dir)
195 PLAYER *newp;
196 int x, y;
197 FLAG moved;
198 BULLET *bp;
200 y = pp->p_y;
201 x = pp->p_x;
203 switch (dir) {
204 case LEFTS:
205 x--;
206 break;
207 case RIGHT:
208 x++;
209 break;
210 case ABOVE:
211 y--;
212 break;
213 case BELOW:
214 y++;
215 break;
218 moved = FALSE;
219 switch (Maze[y][x]) {
220 case SPACE:
221 #ifdef RANDOM
222 case DOOR:
223 #endif
224 moved = TRUE;
225 break;
226 case WALL1:
227 case WALL2:
228 case WALL3:
229 #ifdef REFLECT
230 case WALL4:
231 case WALL5:
232 #endif
233 break;
234 case MINE:
235 case GMINE:
236 if (dir == pp->p_face)
237 pickup(pp, y, x, 2, Maze[y][x]);
238 else if (opposite(dir, pp->p_face))
239 pickup(pp, y, x, 95, Maze[y][x]);
240 else
241 pickup(pp, y, x, 50, Maze[y][x]);
242 Maze[y][x] = SPACE;
243 moved = TRUE;
244 break;
245 case SHOT:
246 case GRENADE:
247 case SATCHEL:
248 case BOMB:
249 #ifdef OOZE
250 case SLIME:
251 #endif
252 #ifdef DRONE
253 case DSHOT:
254 #endif
255 bp = is_bullet(y, x);
256 if (bp != NULL)
257 bp->b_expl = TRUE;
258 Maze[y][x] = SPACE;
259 moved = TRUE;
260 break;
261 case LEFTS:
262 case RIGHT:
263 case ABOVE:
264 case BELOW:
265 if (dir != pp->p_face)
266 sendcom(pp, BELL);
267 else {
268 newp = play_at(y, x);
269 checkdam(newp, pp, pp->p_ident, STABDAM, KNIFE);
271 break;
272 #ifdef FLY
273 case FLYER:
274 newp = play_at(y, x);
275 message(newp, "Oooh, there's a short guy waving at you!");
276 message(pp, "You couldn't quite reach him!");
277 break;
278 #endif
279 #ifdef BOOTS
280 case BOOT:
281 case BOOT_PAIR:
282 if (Maze[y][x] == BOOT)
283 pp->p_nboots++;
284 else
285 pp->p_nboots += 2;
286 for (newp = Boot; newp < &Boot[NBOOTS]; newp++) {
287 if (newp->p_flying < 0)
288 continue;
289 if (newp->p_y == y && newp->p_x == x) {
290 newp->p_flying = -1;
291 if (newp->p_undershot)
292 fixshots(y, x, newp->p_over);
295 if (pp->p_nboots == 2)
296 message(pp, "Wow! A pair of boots!");
297 else
298 message(pp, "You can hobble around on one boot.");
299 Maze[y][x] = SPACE;
300 moved = TRUE;
301 break;
302 #endif
304 if (moved) {
305 if (pp->p_ncshot > 0)
306 if (--pp->p_ncshot == MAXNCSHOT) {
307 cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
308 outstr(pp, " ok", 3);
310 if (pp->p_undershot) {
311 fixshots(pp->p_y, pp->p_x, pp->p_over);
312 pp->p_undershot = FALSE;
314 drawplayer(pp, FALSE);
315 pp->p_over = Maze[y][x];
316 pp->p_y = y;
317 pp->p_x = x;
318 drawplayer(pp, TRUE);
323 * turn_player:
324 * Change the direction the player is facing
326 static void
327 turn_player(PLAYER *pp, int dir)
329 if (pp->p_face != dir) {
330 pp->p_face = dir;
331 drawplayer(pp, TRUE);
336 * fire:
337 * Fire a shot of the given type in the given direction
339 static void
340 fire(PLAYER *pp, int req_index)
342 if (pp == NULL)
343 return;
344 #ifdef DEBUG
345 if (req_index < 0 || req_index >= MAXBOMB)
346 message(pp, "What you do?");
347 #endif
348 while (req_index >= 0 && pp->p_ammo < shot_req[req_index])
349 req_index--;
350 if (req_index < 0) {
351 message(pp, "Not enough charges.");
352 return;
354 if (pp->p_ncshot > MAXNCSHOT)
355 return;
356 if (pp->p_ncshot++ == MAXNCSHOT) {
357 cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
358 outstr(pp, " ", 3);
360 pp->p_ammo -= shot_req[req_index];
361 (void) snprintf(Buf, sizeof(Buf), "%3d", pp->p_ammo);
362 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
363 outstr(pp, Buf, 3);
365 add_shot(shot_type[req_index], pp->p_y, pp->p_x, pp->p_face,
366 shot_req[req_index], pp, FALSE, pp->p_face);
367 pp->p_undershot = TRUE;
370 * Show the object to everyone
372 showexpl(pp->p_y, pp->p_x, shot_type[req_index]);
373 for (pp = Player; pp < End_player; pp++)
374 sendcom(pp, REFRESH);
375 #ifdef MONITOR
376 for (pp = Monitor; pp < End_monitor; pp++)
377 sendcom(pp, REFRESH);
378 #endif
381 #ifdef OOZE
383 * fire_slime:
384 * Fire a slime shot in the given direction
386 static void
387 fire_slime(PLAYER *pp, int req_index)
389 if (pp == NULL)
390 return;
391 #ifdef DEBUG
392 if (req_index < 0 || req_index >= MAXSLIME)
393 message(pp, "What you do?");
394 #endif
395 while (req_index >= 0 && pp->p_ammo < slime_req[req_index])
396 req_index--;
397 if (req_index < 0) {
398 message(pp, "Not enough charges.");
399 return;
401 if (pp->p_ncshot > MAXNCSHOT)
402 return;
403 if (pp->p_ncshot++ == MAXNCSHOT) {
404 cgoto(pp, STAT_GUN_ROW, STAT_VALUE_COL);
405 outstr(pp, " ", 3);
407 pp->p_ammo -= slime_req[req_index];
408 (void) snprintf(Buf, sizeof(Buf), "%3d", pp->p_ammo);
409 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
410 outstr(pp, Buf, 3);
412 add_shot(SLIME, pp->p_y, pp->p_x, pp->p_face,
413 slime_req[req_index] * SLIME_FACTOR, pp, FALSE, pp->p_face);
414 pp->p_undershot = TRUE;
417 * Show the object to everyone
419 showexpl(pp->p_y, pp->p_x, SLIME);
420 for (pp = Player; pp < End_player; pp++)
421 sendcom(pp, REFRESH);
422 #ifdef MONITOR
423 for (pp = Monitor; pp < End_monitor; pp++)
424 sendcom(pp, REFRESH);
425 #endif
427 #endif
430 * add_shot:
431 * Create a shot with the given properties
433 void
434 add_shot(int type, int y, int x, char face, int charge,
435 PLAYER *owner, int expl, char over)
437 BULLET *bp;
438 int size;
440 switch (type) {
441 case SHOT:
442 case MINE:
443 size = 1;
444 break;
445 case GRENADE:
446 case GMINE:
447 size = 2;
448 break;
449 case SATCHEL:
450 size = 3;
451 break;
452 case BOMB:
453 for (size = 3; size < MAXBOMB; size++)
454 if (shot_req[size] >= charge)
455 break;
456 size++;
457 break;
458 default:
459 size = 0;
460 break;
463 bp = create_shot(type, y, x, face, charge, size, owner,
464 (owner == NULL) ? NULL : owner->p_ident, expl, over);
465 bp->b_next = Bullets;
466 Bullets = bp;
469 BULLET *
470 create_shot(int type, int y, int x, char face, int charge,
471 int size, PLAYER *owner, IDENT *score, int expl, char over)
473 BULLET *bp;
475 bp = malloc(sizeof(*bp));
476 if (bp == NULL) {
477 if (owner != NULL)
478 message(owner, "Out of memory");
479 return NULL;
482 bp->b_face = face;
483 bp->b_x = x;
484 bp->b_y = y;
485 bp->b_charge = charge;
486 bp->b_owner = owner;
487 bp->b_score = score;
488 bp->b_type = type;
489 bp->b_size = size;
490 bp->b_expl = expl;
491 bp->b_over = over;
492 bp->b_next = NULL;
494 return bp;
498 * cloak:
499 * Turn on or increase length of a cloak
501 static void
502 cloak(PLAYER *pp)
504 if (pp->p_ammo <= 0) {
505 message(pp, "No more charges");
506 return;
508 #ifdef BOOTS
509 if (pp->p_nboots > 0) {
510 message(pp, "Boots are too noisy to cloak!");
511 return;
513 #endif
514 (void) snprintf(Buf, sizeof(Buf), "%3d", --pp->p_ammo);
515 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
516 outstr(pp, Buf, 3);
518 pp->p_cloak += CLOAKLEN;
520 if (pp->p_scan >= 0)
521 pp->p_scan = -1;
523 showstat(pp);
527 * scan:
528 * Turn on or increase length of a scan
530 static void
531 scan(PLAYER *pp)
533 if (pp->p_ammo <= 0) {
534 message(pp, "No more charges");
535 return;
537 (void) snprintf(Buf, sizeof(Buf), "%3d", --pp->p_ammo);
538 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
539 outstr(pp, Buf, 3);
541 pp->p_scan += SCANLEN;
543 if (pp->p_cloak >= 0)
544 pp->p_cloak = -1;
546 showstat(pp);
550 * pickup:
551 * check whether the object blew up or whether he picked it up
553 void
554 pickup(PLAYER *pp, int y, int x, int prob, int obj)
556 int req;
558 switch (obj) {
559 case MINE:
560 req = BULREQ;
561 break;
562 case GMINE:
563 req = GRENREQ;
564 break;
565 default:
566 abort();
568 if (rand_num(100) < prob)
569 add_shot(obj, y, x, LEFTS, req, (PLAYER *) NULL,
570 TRUE, pp->p_face);
571 else {
572 pp->p_ammo += req;
573 (void) snprintf(Buf, sizeof(Buf), "%3d", pp->p_ammo);
574 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
575 outstr(pp, Buf, 3);