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