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