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