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