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