|
|
1.1 ! root 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: # include <signal.h> ! 13: ! 14: # define PLUS_DELTA(x, max) if (x < max) x++; else x-- ! 15: # define MINUS_DELTA(x, min) if (x > min) x--; else x++ ! 16: ! 17: /* ! 18: * moveshots: ! 19: * Move the shots already in the air, taking explosions into account ! 20: */ ! 21: moveshots() ! 22: { ! 23: register BULLET *bp, *next; ! 24: register PLAYER *pp; ! 25: register int x, y; ! 26: register BULLET *blist; ! 27: ! 28: rollexpl(); ! 29: if (Bullets == NULL) ! 30: goto ret; ! 31: ! 32: /* ! 33: * First we move through the bullet list BULSPD times, looking ! 34: * for things we may have run into. If we do run into ! 35: * something, we set up the explosion and disappear, checking ! 36: * for damage to any player who got in the way. ! 37: */ ! 38: ! 39: blist = Bullets; ! 40: Bullets = NULL; ! 41: for (bp = blist; bp != NULL; bp = next) { ! 42: next = bp->b_next; ! 43: x = bp->b_x; ! 44: y = bp->b_y; ! 45: Maze[y][x] = bp->b_over; ! 46: for (pp = Player; pp < End_player; pp++) ! 47: check(pp, y, x); ! 48: # ifdef MONITOR ! 49: for (pp = Monitor; pp < End_monitor; pp++) ! 50: check(pp, y, x); ! 51: # endif MONITOR ! 52: ! 53: switch (bp->b_type) { ! 54: case SHOT: ! 55: case GRENADE: ! 56: case SATCHEL: ! 57: case BOMB: ! 58: if (move_normal_shot(bp)) { ! 59: bp->b_next = Bullets; ! 60: Bullets = bp; ! 61: } ! 62: break; ! 63: # ifdef OOZE ! 64: case SLIME: ! 65: if (bp->b_expl || move_normal_shot(bp)) { ! 66: bp->b_next = Bullets; ! 67: Bullets = bp; ! 68: } ! 69: break; ! 70: # endif OOZE ! 71: # ifdef DRONE ! 72: case DSHOT: ! 73: if (move_drone(bp)) { ! 74: bp->b_next = Bullets; ! 75: Bullets = bp; ! 76: } ! 77: break; ! 78: # endif DRONE ! 79: default: ! 80: bp->b_next = Bullets; ! 81: Bullets = bp; ! 82: break; ! 83: } ! 84: } ! 85: ! 86: blist = Bullets; ! 87: Bullets = NULL; ! 88: for (bp = blist; bp != NULL; bp = next) { ! 89: next = bp->b_next; ! 90: if (!bp->b_expl) { ! 91: save_bullet(bp); ! 92: # ifdef MONITOR ! 93: for (pp = Monitor; pp < End_monitor; pp++) ! 94: check(pp, bp->b_y, bp->b_x); ! 95: # endif MONITOR ! 96: # ifdef DRONE ! 97: if (bp->b_type == DSHOT) ! 98: for (pp = Player; pp < End_player; pp++) ! 99: if (pp->p_scan >= 0) ! 100: check(pp, bp->b_y, bp->b_x); ! 101: # endif DRONE ! 102: continue; ! 103: } ! 104: ! 105: chkshot(bp, next); ! 106: free((char *) bp); ! 107: } ! 108: ! 109: for (pp = Player; pp < End_player; pp++) ! 110: Maze[pp->p_y][pp->p_x] = pp->p_face; ! 111: ! 112: ret: ! 113: # ifdef BOOTS ! 114: for (pp = Boot; pp < &Boot[NBOOTS]; pp++) ! 115: if (pp->p_flying >= 0) ! 116: move_flyer(pp); ! 117: # endif BOOTS ! 118: for (pp = Player; pp < End_player; pp++) { ! 119: # ifdef FLY ! 120: if (pp->p_flying >= 0) ! 121: move_flyer(pp); ! 122: # endif FLY ! 123: sendcom(pp, REFRESH); /* Flush out the explosions */ ! 124: look(pp); ! 125: sendcom(pp, REFRESH); ! 126: } ! 127: # ifdef MONITOR ! 128: for (pp = Monitor; pp < End_monitor; pp++) ! 129: sendcom(pp, REFRESH); ! 130: # endif MONITOR ! 131: ! 132: return; ! 133: } ! 134: ! 135: /* ! 136: * move_normal_shot: ! 137: * Move a normal shot along its trajectory ! 138: */ ! 139: move_normal_shot(bp) ! 140: register BULLET *bp; ! 141: { ! 142: register int i, x, y; ! 143: register PLAYER *pp; ! 144: ! 145: for (i = 0; i < BULSPD; i++) { ! 146: if (bp->b_expl) ! 147: break; ! 148: ! 149: x = bp->b_x; ! 150: y = bp->b_y; ! 151: ! 152: switch (bp->b_face) { ! 153: case LEFTS: ! 154: x--; ! 155: break; ! 156: case RIGHT: ! 157: x++; ! 158: break; ! 159: case ABOVE: ! 160: y--; ! 161: break; ! 162: case BELOW: ! 163: y++; ! 164: break; ! 165: } ! 166: ! 167: switch (Maze[y][x]) { ! 168: case SHOT: ! 169: if (rand_num(100) < 5) { ! 170: zapshot(Bullets, bp); ! 171: zapshot(bp->b_next, bp); ! 172: } ! 173: break; ! 174: case GRENADE: ! 175: if (rand_num(100) < 10) { ! 176: zapshot(Bullets, bp); ! 177: zapshot(bp->b_next, bp); ! 178: } ! 179: break; ! 180: # ifdef REFLECT ! 181: case WALL4: /* reflecting walls */ ! 182: switch (bp->b_face) { ! 183: case LEFTS: ! 184: bp->b_face = BELOW; ! 185: break; ! 186: case RIGHT: ! 187: bp->b_face = ABOVE; ! 188: break; ! 189: case ABOVE: ! 190: bp->b_face = RIGHT; ! 191: break; ! 192: case BELOW: ! 193: bp->b_face = LEFTS; ! 194: break; ! 195: } ! 196: Maze[y][x] = WALL5; ! 197: # ifdef MONITOR ! 198: for (pp = Monitor; pp < End_monitor; pp++) ! 199: check(pp, y, x); ! 200: # endif MONITOR ! 201: break; ! 202: case WALL5: ! 203: switch (bp->b_face) { ! 204: case LEFTS: ! 205: bp->b_face = ABOVE; ! 206: break; ! 207: case RIGHT: ! 208: bp->b_face = BELOW; ! 209: break; ! 210: case ABOVE: ! 211: bp->b_face = LEFTS; ! 212: break; ! 213: case BELOW: ! 214: bp->b_face = RIGHT; ! 215: break; ! 216: } ! 217: Maze[y][x] = WALL4; ! 218: # ifdef MONITOR ! 219: for (pp = Monitor; pp < End_monitor; pp++) ! 220: check(pp, y, x); ! 221: # endif MONITOR ! 222: break; ! 223: # endif REFLECT ! 224: # ifdef RANDOM ! 225: case DOOR: ! 226: switch (rand_num(4)) { ! 227: case 0: ! 228: bp->b_face = ABOVE; ! 229: break; ! 230: case 1: ! 231: bp->b_face = BELOW; ! 232: break; ! 233: case 2: ! 234: bp->b_face = LEFTS; ! 235: break; ! 236: case 3: ! 237: bp->b_face = RIGHT; ! 238: break; ! 239: } ! 240: break; ! 241: # endif RANDOM ! 242: # ifdef FLY ! 243: case FLYER: ! 244: pp = play_at(y, x); ! 245: message(pp, "Zing!"); ! 246: break; ! 247: # endif FLY ! 248: case LEFTS: ! 249: case RIGHT: ! 250: case BELOW: ! 251: case ABOVE: ! 252: /* ! 253: * give the person a chance to catch a ! 254: * grenade if s/he is facing it ! 255: */ ! 256: pp = play_at(y, x); ! 257: pp->p_ident->i_shot += bp->b_charge; ! 258: if (opposite(bp->b_face, Maze[y][x])) { ! 259: if (rand_num(100) < 10) { ! 260: if (bp->b_owner != NULL) ! 261: message(bp->b_owner, ! 262: "Your charge was absorbed!"); ! 263: if (bp->b_score != NULL) ! 264: bp->b_score->i_robbed += bp->b_charge; ! 265: pp->p_ammo += bp->b_charge; ! 266: if (pp->p_damage + bp->b_size * MINDAM ! 267: > pp->p_damcap) ! 268: pp->p_ident->i_saved++; ! 269: message(pp, "Absorbed charge (good shield!)"); ! 270: pp->p_ident->i_absorbed += bp->b_charge; ! 271: free((char *) bp); ! 272: (void) sprintf(Buf, "%3d", pp->p_ammo); ! 273: cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); ! 274: outstr(pp, Buf, 3); ! 275: return FALSE; ! 276: } ! 277: pp->p_ident->i_faced += bp->b_charge; ! 278: } ! 279: /* ! 280: * Small chance that the bullet just misses the ! 281: * person. If so, the bullet just goes on its ! 282: * merry way without exploding. ! 283: */ ! 284: if (rand_num(100) < 5) { ! 285: pp->p_ident->i_ducked += bp->b_charge; ! 286: if (pp->p_damage + bp->b_size * MINDAM ! 287: > pp->p_damcap) ! 288: pp->p_ident->i_saved++; ! 289: if (bp->b_score != NULL) ! 290: bp->b_score->i_missed += bp->b_charge; ! 291: message(pp, "Zing!"); ! 292: if (bp->b_owner == NULL) ! 293: break; ! 294: message(bp->b_owner, ! 295: ((bp->b_score->i_missed & 0x7) == 0x7) ? ! 296: "My! What a bad shot you are!" : ! 297: "Missed him"); ! 298: break; ! 299: } ! 300: /* ! 301: * The shot hit that sucker! Blow it up. ! 302: */ ! 303: /* FALLTHROUGH */ ! 304: # ifndef RANDOM ! 305: case DOOR: ! 306: # endif RANDOM ! 307: case WALL1: ! 308: case WALL2: ! 309: case WALL3: ! 310: bp->b_expl = TRUE; ! 311: break; ! 312: } ! 313: ! 314: bp->b_x = x; ! 315: bp->b_y = y; ! 316: } ! 317: return TRUE; ! 318: } ! 319: ! 320: # ifdef DRONE ! 321: /* ! 322: * move_drone: ! 323: * Move the drone to the next square ! 324: */ ! 325: move_drone(bp) ! 326: register BULLET *bp; ! 327: { ! 328: register int mask, count; ! 329: register int n, dir; ! 330: register PLAYER *pp; ! 331: ! 332: /* ! 333: * See if we can give someone a blast ! 334: */ ! 335: if (isplayer(Maze[bp->b_y][bp->b_x - 1])) { ! 336: dir = WEST; ! 337: goto drone_move; ! 338: } ! 339: if (isplayer(Maze[bp->b_y - 1][bp->b_x])) { ! 340: dir = NORTH; ! 341: goto drone_move; ! 342: } ! 343: if (isplayer(Maze[bp->b_y + 1][bp->b_x])) { ! 344: dir = SOUTH; ! 345: goto drone_move; ! 346: } ! 347: if (isplayer(Maze[bp->b_y][bp->b_x + 1])) { ! 348: dir = EAST; ! 349: goto drone_move; ! 350: } ! 351: ! 352: /* ! 353: * Find out what directions are clear ! 354: */ ! 355: mask = count = 0; ! 356: if (!iswall(bp->b_y, bp->b_x - 1)) ! 357: mask |= WEST, count++; ! 358: if (!iswall(bp->b_y - 1, bp->b_x)) ! 359: mask |= NORTH, count++; ! 360: if (!iswall(bp->b_y + 1, bp->b_x)) ! 361: mask |= SOUTH, count++; ! 362: if (!iswall(bp->b_y, bp->b_x + 1)) ! 363: mask |= EAST, count++; ! 364: ! 365: /* ! 366: * All blocked up, just you wait ! 367: */ ! 368: if (count == 0) ! 369: return TRUE; ! 370: ! 371: /* ! 372: * Only one way to go. ! 373: */ ! 374: if (count == 1) { ! 375: dir = mask; ! 376: goto drone_move; ! 377: } ! 378: ! 379: /* ! 380: * Get rid of the direction that we came from ! 381: */ ! 382: switch (bp->b_face) { ! 383: case LEFTS: ! 384: if (mask & EAST) ! 385: mask &= ~EAST, count--; ! 386: break; ! 387: case RIGHT: ! 388: if (mask & WEST) ! 389: mask &= ~WEST, count--; ! 390: break; ! 391: case ABOVE: ! 392: if (mask & SOUTH) ! 393: mask &= ~SOUTH, count--; ! 394: break; ! 395: case BELOW: ! 396: if (mask & NORTH) ! 397: mask &= ~NORTH, count--; ! 398: break; ! 399: } ! 400: ! 401: /* ! 402: * Pick one of the remaining directions ! 403: */ ! 404: n = rand_num(count); ! 405: if (n >= 0 && mask & NORTH) ! 406: dir = NORTH, n--; ! 407: if (n >= 0 && mask & SOUTH) ! 408: dir = SOUTH, n--; ! 409: if (n >= 0 && mask & EAST) ! 410: dir = EAST, n--; ! 411: if (n >= 0 && mask & WEST) ! 412: dir = WEST, n--; ! 413: ! 414: /* ! 415: * Now that we know the direction of movement, ! 416: * just update the position of the drone ! 417: */ ! 418: drone_move: ! 419: switch (dir) { ! 420: case WEST: ! 421: bp->b_x--; ! 422: bp->b_face = LEFTS; ! 423: break; ! 424: case EAST: ! 425: bp->b_x++; ! 426: bp->b_face = RIGHT; ! 427: break; ! 428: case NORTH: ! 429: bp->b_y--; ! 430: bp->b_face = ABOVE; ! 431: break; ! 432: case SOUTH: ! 433: bp->b_y++; ! 434: bp->b_face = BELOW; ! 435: break; ! 436: } ! 437: switch (Maze[bp->b_y][bp->b_x]) { ! 438: case LEFTS: ! 439: case RIGHT: ! 440: case BELOW: ! 441: case ABOVE: ! 442: /* ! 443: * give the person a chance to catch a ! 444: * drone if s/he is facing it ! 445: */ ! 446: if (rand_num(100) < 1 && ! 447: opposite(bp->b_face, Maze[bp->b_y][bp->b_x])) { ! 448: pp = play_at(bp->b_y, bp->b_x); ! 449: pp->p_ammo += bp->b_charge; ! 450: message(pp, "**** Absorbed drone ****"); ! 451: free((char *) bp); ! 452: (void) sprintf(Buf, "%3d", pp->p_ammo); ! 453: cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL); ! 454: outstr(pp, Buf, 3); ! 455: return FALSE; ! 456: } ! 457: bp->b_expl = TRUE; ! 458: break; ! 459: } ! 460: return TRUE; ! 461: } ! 462: # endif DRONE ! 463: ! 464: /* ! 465: * save_bullet: ! 466: * Put this bullet back onto the bullet list ! 467: */ ! 468: save_bullet(bp) ! 469: register BULLET *bp; ! 470: { ! 471: bp->b_over = Maze[bp->b_y][bp->b_x]; ! 472: switch (bp->b_over) { ! 473: case SHOT: ! 474: case GRENADE: ! 475: case SATCHEL: ! 476: case BOMB: ! 477: # ifdef OOZE ! 478: case SLIME: ! 479: # ifdef VOLCANO ! 480: case LAVA: ! 481: # endif VOLCANO ! 482: # endif OOZE ! 483: # ifdef DRONE ! 484: case DSHOT: ! 485: # endif DRONE ! 486: find_under(Bullets, bp); ! 487: break; ! 488: } ! 489: ! 490: switch (bp->b_over) { ! 491: case LEFTS: ! 492: case RIGHT: ! 493: case ABOVE: ! 494: case BELOW: ! 495: # ifdef FLY ! 496: case FLYER: ! 497: # endif FLY ! 498: mark_player(bp); ! 499: break; ! 500: # ifdef BOOTS ! 501: case BOOT: ! 502: case BOOT_PAIR: ! 503: mark_boot(bp); ! 504: # endif BOOTS ! 505: ! 506: default: ! 507: Maze[bp->b_y][bp->b_x] = bp->b_type; ! 508: break; ! 509: } ! 510: ! 511: bp->b_next = Bullets; ! 512: Bullets = bp; ! 513: } ! 514: ! 515: /* ! 516: * move_flyer: ! 517: * Update the position of a player in flight ! 518: */ ! 519: move_flyer(pp) ! 520: register PLAYER *pp; ! 521: { ! 522: register int x, y; ! 523: ! 524: if (pp->p_undershot) { ! 525: fixshots(pp->p_y, pp->p_x, pp->p_over); ! 526: pp->p_undershot = FALSE; ! 527: } ! 528: Maze[pp->p_y][pp->p_x] = pp->p_over; ! 529: x = pp->p_x + pp->p_flyx; ! 530: y = pp->p_y + pp->p_flyy; ! 531: if (x < 1) { ! 532: x = 1 - x; ! 533: pp->p_flyx = -pp->p_flyx; ! 534: } ! 535: else if (x > WIDTH - 2) { ! 536: x = (WIDTH - 2) - (x - (WIDTH - 2)); ! 537: pp->p_flyx = -pp->p_flyx; ! 538: } ! 539: if (y < 1) { ! 540: y = 1 - y; ! 541: pp->p_flyy = -pp->p_flyy; ! 542: } ! 543: else if (y > HEIGHT - 2) { ! 544: y = (HEIGHT - 2) - (y - (HEIGHT - 2)); ! 545: pp->p_flyy = -pp->p_flyy; ! 546: } ! 547: again: ! 548: switch (Maze[y][x]) { ! 549: default: ! 550: switch (rand_num(4)) { ! 551: case 0: ! 552: PLUS_DELTA(x, WIDTH - 2); ! 553: break; ! 554: case 1: ! 555: MINUS_DELTA(x, 1); ! 556: break; ! 557: case 2: ! 558: PLUS_DELTA(y, HEIGHT - 2); ! 559: break; ! 560: case 3: ! 561: MINUS_DELTA(y, 1); ! 562: break; ! 563: } ! 564: goto again; ! 565: case WALL1: ! 566: case WALL2: ! 567: case WALL3: ! 568: # ifdef REFLECT ! 569: case WALL4: ! 570: case WALL5: ! 571: # endif REFLECT ! 572: # ifdef RANDOM ! 573: case DOOR: ! 574: # endif RANDOM ! 575: if (pp->p_flying == 0) ! 576: pp->p_flying++; ! 577: break; ! 578: case SPACE: ! 579: break; ! 580: } ! 581: pp->p_y = y; ! 582: pp->p_x = x; ! 583: if (pp->p_flying-- == 0) { ! 584: # ifdef BOOTS ! 585: if (pp->p_face != BOOT && pp->p_face != BOOT_PAIR) { ! 586: # endif ! 587: checkdam(pp, (PLAYER *) NULL, (IDENT *) NULL, ! 588: rand_num(pp->p_damage / 5), FALL); ! 589: pp->p_face = rand_dir(); ! 590: showstat(pp); ! 591: # ifdef BOOTS ! 592: } ! 593: else { ! 594: if (Maze[y][x] == BOOT) ! 595: pp->p_face = BOOT_PAIR; ! 596: Maze[y][x] = SPACE; ! 597: } ! 598: # endif BOOTS ! 599: } ! 600: pp->p_over = Maze[y][x]; ! 601: Maze[y][x] = pp->p_face; ! 602: showexpl(y, x, pp->p_face); ! 603: } ! 604: ! 605: /* ! 606: * chkshot ! 607: * Handle explosions ! 608: */ ! 609: chkshot(bp, next) ! 610: register BULLET *bp; ! 611: BULLET *next; ! 612: { ! 613: register int y, x; ! 614: register int dy, dx, absdy; ! 615: register int delta, damage; ! 616: register char expl; ! 617: register PLAYER *pp; ! 618: ! 619: switch (bp->b_type) { ! 620: case SHOT: ! 621: case MINE: ! 622: case GRENADE: ! 623: case GMINE: ! 624: case SATCHEL: ! 625: case BOMB: ! 626: delta = bp->b_size - 1; ! 627: break; ! 628: # ifdef OOZE ! 629: case SLIME: ! 630: # ifdef VOLCANO ! 631: case LAVA: ! 632: # endif VOLCANO ! 633: chkslime(bp, next); ! 634: return; ! 635: # endif OOZE ! 636: # ifdef DRONE ! 637: case DSHOT: ! 638: bp->b_type = SLIME; ! 639: chkslime(bp, next); ! 640: return; ! 641: # endif DRONE ! 642: } ! 643: for (y = bp->b_y - delta; y <= bp->b_y + delta; y++) { ! 644: if (y < 0 || y >= HEIGHT) ! 645: continue; ! 646: dy = y - bp->b_y; ! 647: absdy = (dy < 0) ? -dy : dy; ! 648: for (x = bp->b_x - delta; x <= bp->b_x + delta; x++) { ! 649: if (x < 0 || x >= WIDTH) ! 650: continue; ! 651: dx = x - bp->b_x; ! 652: if (dx == 0) ! 653: expl = (dy == 0) ? '*' : '|'; ! 654: else if (dy == 0) ! 655: expl = '-'; ! 656: else if (dx == dy) ! 657: expl = '\\'; ! 658: else if (dx == -dy) ! 659: expl = '/'; ! 660: else ! 661: expl = '*'; ! 662: showexpl(y, x, expl); ! 663: switch (Maze[y][x]) { ! 664: case LEFTS: ! 665: case RIGHT: ! 666: case ABOVE: ! 667: case BELOW: ! 668: # ifdef FLY ! 669: case FLYER: ! 670: # endif FLY ! 671: if (dx < 0) ! 672: dx = -dx; ! 673: if (absdy > dx) ! 674: damage = bp->b_size - absdy; ! 675: else ! 676: damage = bp->b_size - dx; ! 677: pp = play_at(y, x); ! 678: checkdam(pp, bp->b_owner, bp->b_score, ! 679: damage * MINDAM, bp->b_type); ! 680: break; ! 681: case GMINE: ! 682: case MINE: ! 683: add_shot((Maze[y][x] == GMINE) ? ! 684: GRENADE : SHOT, ! 685: y, x, LEFTS, ! 686: (Maze[y][x] == GMINE) ? ! 687: GRENREQ : BULREQ, ! 688: (PLAYER *) NULL, TRUE, SPACE); ! 689: Maze[y][x] = SPACE; ! 690: break; ! 691: } ! 692: } ! 693: } ! 694: } ! 695: ! 696: # ifdef OOZE ! 697: /* ! 698: * chkslime: ! 699: * handle slime shot exploding ! 700: */ ! 701: chkslime(bp, next) ! 702: register BULLET *bp; ! 703: BULLET *next; ! 704: { ! 705: register BULLET *nbp; ! 706: ! 707: switch (Maze[bp->b_y][bp->b_x]) { ! 708: case WALL1: ! 709: case WALL2: ! 710: case WALL3: ! 711: # ifdef REFLECT ! 712: case WALL4: ! 713: case WALL5: ! 714: # endif REFLECT ! 715: # ifdef RANDOM ! 716: case DOOR: ! 717: # endif RANDOM ! 718: switch (bp->b_face) { ! 719: case LEFTS: ! 720: bp->b_x++; ! 721: break; ! 722: case RIGHT: ! 723: bp->b_x--; ! 724: break; ! 725: case ABOVE: ! 726: bp->b_y++; ! 727: break; ! 728: case BELOW: ! 729: bp->b_y--; ! 730: break; ! 731: } ! 732: break; ! 733: } ! 734: nbp = (BULLET *) malloc(sizeof (BULLET)); ! 735: *nbp = *bp; ! 736: # ifdef VOLCANO ! 737: move_slime(nbp, nbp->b_type == SLIME ? SLIMESPEED : LAVASPEED, next); ! 738: # else VOLCANO ! 739: move_slime(nbp, SLIMESPEED, next); ! 740: # endif VOLCANO ! 741: } ! 742: ! 743: /* ! 744: * move_slime: ! 745: * move the given slime shot speed times and add it back if ! 746: * it hasn't fizzled yet ! 747: */ ! 748: move_slime(bp, speed, next) ! 749: register BULLET *bp; ! 750: register int speed; ! 751: BULLET *next; ! 752: { ! 753: register int i, j, dirmask, count; ! 754: register PLAYER *pp; ! 755: register BULLET *nbp; ! 756: ! 757: if (speed == 0) { ! 758: if (bp->b_charge <= 0) ! 759: free((char *) bp); ! 760: else ! 761: save_bullet(bp); ! 762: return; ! 763: } ! 764: ! 765: # ifdef VOLCANO ! 766: showexpl(bp->b_y, bp->b_x, bp->b_type == LAVA ? LAVA : '*'); ! 767: # else VOLCANO ! 768: showexpl(bp->b_y, bp->b_x, '*'); ! 769: # endif VOLCANO ! 770: switch (Maze[bp->b_y][bp->b_x]) { ! 771: case LEFTS: ! 772: case RIGHT: ! 773: case ABOVE: ! 774: case BELOW: ! 775: # ifdef FLY ! 776: case FLYER: ! 777: # endif FLY ! 778: pp = play_at(bp->b_y, bp->b_x); ! 779: message(pp, "You've been slimed."); ! 780: checkdam(pp, bp->b_owner, bp->b_score, MINDAM, bp->b_type); ! 781: break; ! 782: case SHOT: ! 783: case GRENADE: ! 784: case SATCHEL: ! 785: case BOMB: ! 786: # ifdef DRONE ! 787: case DSHOT: ! 788: # endif DRONE ! 789: explshot(next, bp->b_y, bp->b_x); ! 790: explshot(Bullets, bp->b_y, bp->b_x); ! 791: break; ! 792: } ! 793: ! 794: if (--bp->b_charge <= 0) { ! 795: free((char *) bp); ! 796: return; ! 797: } ! 798: ! 799: dirmask = 0; ! 800: count = 0; ! 801: switch (bp->b_face) { ! 802: case LEFTS: ! 803: if (!iswall(bp->b_y, bp->b_x - 1)) ! 804: dirmask |= WEST, count++; ! 805: if (!iswall(bp->b_y - 1, bp->b_x)) ! 806: dirmask |= NORTH, count++; ! 807: if (!iswall(bp->b_y + 1, bp->b_x)) ! 808: dirmask |= SOUTH, count++; ! 809: if (dirmask == 0) ! 810: if (!iswall(bp->b_y, bp->b_x + 1)) ! 811: dirmask |= EAST, count++; ! 812: break; ! 813: case RIGHT: ! 814: if (!iswall(bp->b_y, bp->b_x + 1)) ! 815: dirmask |= EAST, count++; ! 816: if (!iswall(bp->b_y - 1, bp->b_x)) ! 817: dirmask |= NORTH, count++; ! 818: if (!iswall(bp->b_y + 1, bp->b_x)) ! 819: dirmask |= SOUTH, count++; ! 820: if (dirmask == 0) ! 821: if (!iswall(bp->b_y, bp->b_x - 1)) ! 822: dirmask |= WEST, count++; ! 823: break; ! 824: case ABOVE: ! 825: if (!iswall(bp->b_y - 1, bp->b_x)) ! 826: dirmask |= NORTH, count++; ! 827: if (!iswall(bp->b_y, bp->b_x - 1)) ! 828: dirmask |= WEST, count++; ! 829: if (!iswall(bp->b_y, bp->b_x + 1)) ! 830: dirmask |= EAST, count++; ! 831: if (dirmask == 0) ! 832: if (!iswall(bp->b_y + 1, bp->b_x)) ! 833: dirmask |= SOUTH, count++; ! 834: break; ! 835: case BELOW: ! 836: if (!iswall(bp->b_y + 1, bp->b_x)) ! 837: dirmask |= SOUTH, count++; ! 838: if (!iswall(bp->b_y, bp->b_x - 1)) ! 839: dirmask |= WEST, count++; ! 840: if (!iswall(bp->b_y, bp->b_x + 1)) ! 841: dirmask |= EAST, count++; ! 842: if (dirmask == 0) ! 843: if (!iswall(bp->b_y - 1, bp->b_x)) ! 844: dirmask |= NORTH, count++; ! 845: break; ! 846: } ! 847: if (count == 0) { ! 848: /* ! 849: * No place to go. Just sit here for a while and wait ! 850: * for adjacent squares to clear out. ! 851: */ ! 852: save_bullet(bp); ! 853: return; ! 854: } ! 855: if (bp->b_charge < count) { ! 856: /* Only bp->b_charge paths may be taken */ ! 857: while (count > bp->b_charge) { ! 858: if (dirmask & WEST) ! 859: dirmask &= ~WEST; ! 860: else if (dirmask & EAST) ! 861: dirmask &= ~EAST; ! 862: else if (dirmask & NORTH) ! 863: dirmask &= ~NORTH; ! 864: else if (dirmask & SOUTH) ! 865: dirmask &= ~SOUTH; ! 866: count--; ! 867: } ! 868: } ! 869: ! 870: i = bp->b_charge / count; ! 871: j = bp->b_charge % count; ! 872: if (dirmask & WEST) { ! 873: count--; ! 874: nbp = create_shot(bp->b_type, bp->b_y, bp->b_x - 1, LEFTS, ! 875: i, bp->b_size, bp->b_owner, bp->b_score, TRUE, SPACE); ! 876: move_slime(nbp, speed - 1, next); ! 877: } ! 878: if (dirmask & EAST) { ! 879: count--; ! 880: nbp = create_shot(bp->b_type, bp->b_y, bp->b_x + 1, RIGHT, ! 881: (count < j) ? i + 1 : i, bp->b_size, bp->b_owner, ! 882: bp->b_score, TRUE, SPACE); ! 883: move_slime(nbp, speed - 1, next); ! 884: } ! 885: if (dirmask & NORTH) { ! 886: count--; ! 887: nbp = create_shot(bp->b_type, bp->b_y - 1, bp->b_x, ABOVE, ! 888: (count < j) ? i + 1 : i, bp->b_size, bp->b_owner, ! 889: bp->b_score, TRUE, SPACE); ! 890: move_slime(nbp, speed - 1, next); ! 891: } ! 892: if (dirmask & SOUTH) { ! 893: count--; ! 894: nbp = create_shot(bp->b_type, bp->b_y + 1, bp->b_x, BELOW, ! 895: (count < j) ? i + 1 : i, bp->b_size, bp->b_owner, ! 896: bp->b_score, TRUE, SPACE); ! 897: move_slime(nbp, speed - 1, next); ! 898: } ! 899: ! 900: free((char *) bp); ! 901: } ! 902: ! 903: /* ! 904: * iswall: ! 905: * returns whether the given location is a wall ! 906: */ ! 907: iswall(y, x) ! 908: register int y, x; ! 909: { ! 910: if (y < 0 || x < 0 || y >= HEIGHT || x >= WIDTH) ! 911: return TRUE; ! 912: switch (Maze[y][x]) { ! 913: case WALL1: ! 914: case WALL2: ! 915: case WALL3: ! 916: # ifdef REFLECT ! 917: case WALL4: ! 918: case WALL5: ! 919: # endif REFLECT ! 920: # ifdef RANDOM ! 921: case DOOR: ! 922: # endif RANDOM ! 923: # ifdef OOZE ! 924: case SLIME: ! 925: # ifdef VOLCANO ! 926: case LAVA: ! 927: # endif VOLCANO ! 928: # endif OOZE ! 929: return TRUE; ! 930: } ! 931: return FALSE; ! 932: } ! 933: # endif OOZE ! 934: ! 935: /* ! 936: * zapshot: ! 937: * Take a shot out of the air. ! 938: */ ! 939: zapshot(blist, obp) ! 940: register BULLET *blist, *obp; ! 941: { ! 942: register BULLET *bp; ! 943: register FLAG explode; ! 944: ! 945: explode = FALSE; ! 946: for (bp = blist; bp != NULL; bp = bp->b_next) { ! 947: if (bp->b_x != obp->b_x || bp->b_y != obp->b_y) ! 948: continue; ! 949: if (bp->b_face == obp->b_face) ! 950: continue; ! 951: explode = TRUE; ! 952: break; ! 953: } ! 954: if (!explode) ! 955: return; ! 956: explshot(blist, obp->b_y, obp->b_x); ! 957: } ! 958: ! 959: /* ! 960: * explshot - ! 961: * Make all shots at this location blow up ! 962: */ ! 963: explshot(blist, y, x) ! 964: register BULLET *blist; ! 965: register int y, x; ! 966: { ! 967: register BULLET *bp; ! 968: ! 969: for (bp = blist; bp != NULL; bp = bp->b_next) ! 970: if (bp->b_x == x && bp->b_y == y) { ! 971: bp->b_expl = TRUE; ! 972: if (bp->b_owner != NULL) ! 973: message(bp->b_owner, "Shot intercepted"); ! 974: } ! 975: } ! 976: ! 977: /* ! 978: * play_at: ! 979: * Return a pointer to the player at the given location ! 980: */ ! 981: PLAYER * ! 982: play_at(y, x) ! 983: register int y, x; ! 984: { ! 985: register PLAYER *pp; ! 986: ! 987: for (pp = Player; pp < End_player; pp++) ! 988: if (pp->p_x == x && pp->p_y == y) ! 989: return pp; ! 990: fprintf(stderr, "driver: couldn't find player at (%d,%d)\n", x, y); ! 991: abort(); ! 992: /* NOTREACHED */ ! 993: } ! 994: ! 995: /* ! 996: * opposite: ! 997: * Return TRUE if the bullet direction faces the opposite direction ! 998: * of the player in the maze ! 999: */ ! 1000: opposite(face, dir) ! 1001: int face; ! 1002: char dir; ! 1003: { ! 1004: switch (face) { ! 1005: case LEFTS: ! 1006: return (dir == RIGHT); ! 1007: case RIGHT: ! 1008: return (dir == LEFTS); ! 1009: case ABOVE: ! 1010: return (dir == BELOW); ! 1011: case BELOW: ! 1012: return (dir == ABOVE); ! 1013: default: ! 1014: return FALSE; ! 1015: } ! 1016: } ! 1017: ! 1018: /* ! 1019: * is_bullet: ! 1020: * Is there a bullet at the given coordinates? If so, return ! 1021: * a pointer to the bullet, otherwise return NULL ! 1022: */ ! 1023: BULLET * ! 1024: is_bullet(y, x) ! 1025: register int y, x; ! 1026: { ! 1027: register BULLET *bp; ! 1028: ! 1029: for (bp = Bullets; bp != NULL; bp = bp->b_next) ! 1030: if (bp->b_y == y && bp->b_x == x) ! 1031: return bp; ! 1032: return NULL; ! 1033: } ! 1034: ! 1035: /* ! 1036: * fixshots: ! 1037: * change the underlying character of the shots at a location ! 1038: * to the given character. ! 1039: */ ! 1040: fixshots(y, x, over) ! 1041: register int y, x; ! 1042: char over; ! 1043: { ! 1044: register BULLET *bp; ! 1045: ! 1046: for (bp = Bullets; bp != NULL; bp = bp->b_next) ! 1047: if (bp->b_y == y && bp->b_x == x) ! 1048: bp->b_over = over; ! 1049: } ! 1050: ! 1051: /* ! 1052: * find_under: ! 1053: * find the underlying character for a bullet when it lands ! 1054: * on another bullet. ! 1055: */ ! 1056: find_under(blist, bp) ! 1057: register BULLET *blist, *bp; ! 1058: { ! 1059: register BULLET *nbp; ! 1060: ! 1061: for (nbp = blist; nbp != NULL; nbp = nbp->b_next) ! 1062: if (bp->b_y == nbp->b_y && bp->b_x == nbp->b_x) { ! 1063: bp->b_over = nbp->b_over; ! 1064: break; ! 1065: } ! 1066: } ! 1067: ! 1068: /* ! 1069: * mark_player: ! 1070: * mark a player as under a shot ! 1071: */ ! 1072: mark_player(bp) ! 1073: register BULLET *bp; ! 1074: { ! 1075: register PLAYER *pp; ! 1076: ! 1077: for (pp = Player; pp < End_player; pp++) ! 1078: if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) { ! 1079: pp->p_undershot = TRUE; ! 1080: break; ! 1081: } ! 1082: } ! 1083: ! 1084: # ifdef BOOTS ! 1085: /* ! 1086: * mark_boot: ! 1087: * mark a boot as under a shot ! 1088: */ ! 1089: mark_boot(bp) ! 1090: register BULLET *bp; ! 1091: { ! 1092: register PLAYER *pp; ! 1093: ! 1094: for (pp = Boot; pp < &Boot[NBOOTS]; pp++) ! 1095: if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) { ! 1096: pp->p_undershot = TRUE; ! 1097: break; ! 1098: } ! 1099: } ! 1100: # endif BOOTS
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.