]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hunt/huntd/execute.c
avoid uninit memory and use memmove vs strncpy for a will be
[bsdgames-darwin.git] / hunt / huntd / execute.c
1 /* $NetBSD: execute.c,v 1.12 2014/03/29 21:38:54 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.
19 *
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.
31 */
32
33 #include <sys/cdefs.h>
34 #ifndef lint
35 __RCSID("$NetBSD: execute.c,v 1.12 2014/03/29 21:38:54 dholland Exp $");
36 #endif /* not lint */
37
38 #include <stdlib.h>
39 #include "hunt.h"
40
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 *);
48
49
50 #ifdef MONITOR
51 /*
52 * mon_execute:
53 * Execute a single monitor command
54 */
55 void
56 mon_execute(PLAYER *pp)
57 {
58 char ch;
59
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;
68 }
69 }
70 #endif
71
72 /*
73 * execute:
74 * Execute a single command
75 */
76 void
77 execute(PLAYER *pp)
78 {
79 char ch;
80
81 ch = pp->p_cbuf[pp->p_ncount++];
82
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;
92 }
93 return;
94 }
95 #endif
96
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;
185 }
186 }
187
188 /*
189 * move_player:
190 * Execute a move in the given direction
191 */
192 static void
193 move_player(PLAYER *pp, int dir)
194 {
195 PLAYER *newp;
196 int x, y;
197 bool moved;
198 BULLET *bp;
199
200 y = pp->p_y;
201 x = pp->p_x;
202
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;
216 }
217
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);
270 }
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);
293 }
294 }
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
303 }
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);
309 }
310 if (pp->p_undershot) {
311 fixshots(pp->p_y, pp->p_x, pp->p_over);
312 pp->p_undershot = false;
313 }
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);
319 }
320 }
321
322 /*
323 * turn_player:
324 * Change the direction the player is facing
325 */
326 static void
327 turn_player(PLAYER *pp, int dir)
328 {
329 if (pp->p_face != dir) {
330 pp->p_face = dir;
331 drawplayer(pp, true);
332 }
333 }
334
335 /*
336 * fire:
337 * Fire a shot of the given type in the given direction
338 */
339 static void
340 fire(PLAYER *pp, int req_index)
341 {
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;
353 }
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);
359 }
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);
364
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;
368
369 /*
370 * Show the object to everyone
371 */
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
379 }
380
381 #ifdef OOZE
382 /*
383 * fire_slime:
384 * Fire a slime shot in the given direction
385 */
386 static void
387 fire_slime(PLAYER *pp, int req_index)
388 {
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;
400 }
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);
406 }
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);
411
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;
415
416 /*
417 * Show the object to everyone
418 */
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
426 }
427 #endif
428
429 /*
430 * add_shot:
431 * Create a shot with the given properties
432 */
433 void
434 add_shot(int type, int y, int x, char face, int charge,
435 PLAYER *owner, int expl, char over)
436 {
437 BULLET *bp;
438 int size;
439
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;
461 }
462
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;
467 }
468
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)
472 {
473 BULLET *bp;
474
475 bp = malloc(sizeof(*bp));
476 if (bp == NULL) {
477 if (owner != NULL)
478 message(owner, "Out of memory");
479 return NULL;
480 }
481
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;
493
494 return bp;
495 }
496
497 /*
498 * cloak:
499 * Turn on or increase length of a cloak
500 */
501 static void
502 cloak(PLAYER *pp)
503 {
504 if (pp->p_ammo <= 0) {
505 message(pp, "No more charges");
506 return;
507 }
508 #ifdef BOOTS
509 if (pp->p_nboots > 0) {
510 message(pp, "Boots are too noisy to cloak!");
511 return;
512 }
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);
517
518 pp->p_cloak += CLOAKLEN;
519
520 if (pp->p_scan >= 0)
521 pp->p_scan = -1;
522
523 showstat(pp);
524 }
525
526 /*
527 * scan:
528 * Turn on or increase length of a scan
529 */
530 static void
531 scan(PLAYER *pp)
532 {
533 if (pp->p_ammo <= 0) {
534 message(pp, "No more charges");
535 return;
536 }
537 (void) snprintf(Buf, sizeof(Buf), "%3d", --pp->p_ammo);
538 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
539 outstr(pp, Buf, 3);
540
541 pp->p_scan += SCANLEN;
542
543 if (pp->p_cloak >= 0)
544 pp->p_cloak = -1;
545
546 showstat(pp);
547 }
548
549 /*
550 * pickup:
551 * check whether the object blew up or whether he picked it up
552 */
553 static void
554 pickup(PLAYER *pp, int y, int x, int prob, int obj)
555 {
556 int req;
557
558 switch (obj) {
559 case MINE:
560 req = BULREQ;
561 break;
562 case GMINE:
563 req = GRENREQ;
564 break;
565 default:
566 abort();
567 }
568 if (rand_num(100) < prob)
569 add_shot(obj, y, x, LEFTS, req, NULL, true, pp->p_face);
570 else {
571 pp->p_ammo += req;
572 (void) snprintf(Buf, sizeof(Buf), "%3d", pp->p_ammo);
573 cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
574 outstr(pp, Buf, 3);
575 }
576 }