186d7f5d3SJohn Marino /*-
286d7f5d3SJohn Marino * Copyright (c) 1983-2003, Regents of the University of California.
386d7f5d3SJohn Marino * All rights reserved.
486d7f5d3SJohn Marino *
586d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
686d7f5d3SJohn Marino * modification, are permitted provided that the following conditions are
786d7f5d3SJohn Marino * met:
886d7f5d3SJohn Marino *
986d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
1086d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
1186d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
1286d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
1386d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
1486d7f5d3SJohn Marino * 3. Neither the name of the University of California, San Francisco nor
1586d7f5d3SJohn Marino * the names of its contributors may be used to endorse or promote
1686d7f5d3SJohn Marino * products derived from this software without specific prior written
1786d7f5d3SJohn Marino * permission.
1886d7f5d3SJohn Marino *
1986d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2086d7f5d3SJohn Marino * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2186d7f5d3SJohn Marino * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2286d7f5d3SJohn Marino * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2386d7f5d3SJohn Marino * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2486d7f5d3SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2586d7f5d3SJohn Marino * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2686d7f5d3SJohn Marino * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2786d7f5d3SJohn Marino * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2886d7f5d3SJohn Marino * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2986d7f5d3SJohn Marino * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3086d7f5d3SJohn Marino *
3186d7f5d3SJohn Marino * $OpenBSD: shots.c,v 1.9 2006/03/27 00:10:15 tedu Exp $
3286d7f5d3SJohn Marino * $NetBSD: shots.c,v 1.3 1997/10/11 08:13:50 lukem Exp $
3386d7f5d3SJohn Marino * $DragonFly: src/games/hunt/huntd/shots.c,v 1.2 2008/09/04 16:12:51 swildner Exp $
3486d7f5d3SJohn Marino */
3586d7f5d3SJohn Marino
3686d7f5d3SJohn Marino #include <err.h>
3786d7f5d3SJohn Marino #include <signal.h>
3886d7f5d3SJohn Marino #include <stdlib.h>
3986d7f5d3SJohn Marino #include <syslog.h>
4086d7f5d3SJohn Marino #include "hunt.h"
4186d7f5d3SJohn Marino #include "conf.h"
4286d7f5d3SJohn Marino #include "server.h"
4386d7f5d3SJohn Marino
4486d7f5d3SJohn Marino #define PLUS_DELTA(x, max) if (x < max) x++; else x--
4586d7f5d3SJohn Marino #define MINUS_DELTA(x, min) if (x > min) x--; else x++
4686d7f5d3SJohn Marino
4786d7f5d3SJohn Marino static void chkshot(BULLET *, BULLET *);
4886d7f5d3SJohn Marino static void chkslime(BULLET *, BULLET *);
4986d7f5d3SJohn Marino static void explshot(BULLET *, int, int);
5086d7f5d3SJohn Marino static void find_under(BULLET *, BULLET *);
5186d7f5d3SJohn Marino static int iswall(int, int);
5286d7f5d3SJohn Marino static void mark_boot(BULLET *);
5386d7f5d3SJohn Marino static void mark_player(BULLET *);
5486d7f5d3SJohn Marino static int move_drone(BULLET *);
5586d7f5d3SJohn Marino static void move_flyer(PLAYER *);
5686d7f5d3SJohn Marino static int move_normal_shot(BULLET *);
5786d7f5d3SJohn Marino static void move_slime(BULLET *, int, BULLET *);
5886d7f5d3SJohn Marino static void save_bullet(BULLET *);
5986d7f5d3SJohn Marino static void zapshot(BULLET *, BULLET *);
6086d7f5d3SJohn Marino
6186d7f5d3SJohn Marino /* Return true if there is pending activity */
6286d7f5d3SJohn Marino int
can_moveshots(void)6386d7f5d3SJohn Marino can_moveshots(void)
6486d7f5d3SJohn Marino {
6586d7f5d3SJohn Marino PLAYER *pp;
6686d7f5d3SJohn Marino
6786d7f5d3SJohn Marino /* Bullets are moving? */
6886d7f5d3SJohn Marino if (Bullets)
6986d7f5d3SJohn Marino return 1;
7086d7f5d3SJohn Marino
7186d7f5d3SJohn Marino /* Explosions are happening? */
7286d7f5d3SJohn Marino if (can_rollexpl())
7386d7f5d3SJohn Marino return 1;
7486d7f5d3SJohn Marino
7586d7f5d3SJohn Marino /* Things are flying? */
7686d7f5d3SJohn Marino for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
7786d7f5d3SJohn Marino if (pp->p_flying >= 0)
7886d7f5d3SJohn Marino return 1;
7986d7f5d3SJohn Marino for (pp = Player; pp < End_player; pp++)
8086d7f5d3SJohn Marino if (pp->p_flying >= 0)
8186d7f5d3SJohn Marino return 1;
8286d7f5d3SJohn Marino
8386d7f5d3SJohn Marino /* Everything is quiet: */
8486d7f5d3SJohn Marino return 0;
8586d7f5d3SJohn Marino }
8686d7f5d3SJohn Marino
8786d7f5d3SJohn Marino /*
8886d7f5d3SJohn Marino * moveshots:
8986d7f5d3SJohn Marino * Move the shots already in the air, taking explosions into account
9086d7f5d3SJohn Marino */
9186d7f5d3SJohn Marino void
moveshots(void)9286d7f5d3SJohn Marino moveshots(void)
9386d7f5d3SJohn Marino {
9486d7f5d3SJohn Marino BULLET *bp, *next;
9586d7f5d3SJohn Marino PLAYER *pp;
9686d7f5d3SJohn Marino int x, y;
9786d7f5d3SJohn Marino BULLET *blist;
9886d7f5d3SJohn Marino
9986d7f5d3SJohn Marino rollexpl();
10086d7f5d3SJohn Marino if (Bullets == NULL)
10186d7f5d3SJohn Marino goto no_bullets;
10286d7f5d3SJohn Marino
10386d7f5d3SJohn Marino /*
10486d7f5d3SJohn Marino * First we move through the bullet list conf_bulspd times, looking
10586d7f5d3SJohn Marino * for things we may have run into. If we do run into
10686d7f5d3SJohn Marino * something, we set up the explosion and disappear, checking
10786d7f5d3SJohn Marino * for damage to any player who got in the way.
10886d7f5d3SJohn Marino */
10986d7f5d3SJohn Marino
11086d7f5d3SJohn Marino /* Move the list to a working list */
11186d7f5d3SJohn Marino blist = Bullets;
11286d7f5d3SJohn Marino Bullets = NULL;
11386d7f5d3SJohn Marino
11486d7f5d3SJohn Marino /* Work with bullets on the working list (blist) */
11586d7f5d3SJohn Marino for (bp = blist; bp != NULL; bp = next) {
11686d7f5d3SJohn Marino next = bp->b_next;
11786d7f5d3SJohn Marino
11886d7f5d3SJohn Marino x = bp->b_x;
11986d7f5d3SJohn Marino y = bp->b_y;
12086d7f5d3SJohn Marino
12186d7f5d3SJohn Marino /* Un-draw the bullet on all screens: */
12286d7f5d3SJohn Marino Maze[y][x] = bp->b_over;
12386d7f5d3SJohn Marino check(ALL_PLAYERS, y, x);
12486d7f5d3SJohn Marino
12586d7f5d3SJohn Marino /* Decide how to move the bullet: */
12686d7f5d3SJohn Marino switch (bp->b_type) {
12786d7f5d3SJohn Marino
12886d7f5d3SJohn Marino /* Normal, atomic bullets: */
12986d7f5d3SJohn Marino case SHOT:
13086d7f5d3SJohn Marino case GRENADE:
13186d7f5d3SJohn Marino case SATCHEL:
13286d7f5d3SJohn Marino case BOMB:
13386d7f5d3SJohn Marino if (move_normal_shot(bp)) {
13486d7f5d3SJohn Marino /* Still there: put back on the active list */
13586d7f5d3SJohn Marino bp->b_next = Bullets;
13686d7f5d3SJohn Marino Bullets = bp;
13786d7f5d3SJohn Marino }
13886d7f5d3SJohn Marino break;
13986d7f5d3SJohn Marino
14086d7f5d3SJohn Marino /* Slime bullets that explode into slime on impact: */
14186d7f5d3SJohn Marino case SLIME:
14286d7f5d3SJohn Marino if (bp->b_expl || move_normal_shot(bp)) {
14386d7f5d3SJohn Marino /* Still there: put back on the active list */
14486d7f5d3SJohn Marino bp->b_next = Bullets;
14586d7f5d3SJohn Marino Bullets = bp;
14686d7f5d3SJohn Marino }
14786d7f5d3SJohn Marino break;
14886d7f5d3SJohn Marino
14986d7f5d3SJohn Marino /* Drones that wander about: */
15086d7f5d3SJohn Marino case DSHOT:
15186d7f5d3SJohn Marino if (move_drone(bp)) {
15286d7f5d3SJohn Marino /* Still there: put back on the active list */
15386d7f5d3SJohn Marino bp->b_next = Bullets;
15486d7f5d3SJohn Marino Bullets = bp;
15586d7f5d3SJohn Marino }
15686d7f5d3SJohn Marino break;
15786d7f5d3SJohn Marino
15886d7f5d3SJohn Marino /* Other/unknown: */
15986d7f5d3SJohn Marino default:
16086d7f5d3SJohn Marino /* Place it back on the active list: */
16186d7f5d3SJohn Marino bp->b_next = Bullets;
16286d7f5d3SJohn Marino Bullets = bp;
16386d7f5d3SJohn Marino break;
16486d7f5d3SJohn Marino }
16586d7f5d3SJohn Marino }
16686d7f5d3SJohn Marino
16786d7f5d3SJohn Marino /* Again, hang the Bullets list off `blist' and work with that: */
16886d7f5d3SJohn Marino blist = Bullets;
16986d7f5d3SJohn Marino Bullets = NULL;
17086d7f5d3SJohn Marino for (bp = blist; bp != NULL; bp = next) {
17186d7f5d3SJohn Marino next = bp->b_next;
17286d7f5d3SJohn Marino /* Is the bullet exploding? */
17386d7f5d3SJohn Marino if (!bp->b_expl) {
17486d7f5d3SJohn Marino /*
17586d7f5d3SJohn Marino * Its still flying through the air.
17686d7f5d3SJohn Marino * Put it back on the bullet list.
17786d7f5d3SJohn Marino */
17886d7f5d3SJohn Marino save_bullet(bp);
17986d7f5d3SJohn Marino
18086d7f5d3SJohn Marino /* All the monitors can see the bullet: */
18186d7f5d3SJohn Marino for (pp = Monitor; pp < End_monitor; pp++)
18286d7f5d3SJohn Marino check(pp, bp->b_y, bp->b_x);
18386d7f5d3SJohn Marino
18486d7f5d3SJohn Marino /* All the scanning players can see the drone: */
18586d7f5d3SJohn Marino if (bp->b_type == DSHOT)
18686d7f5d3SJohn Marino for (pp = Player; pp < End_player; pp++)
18786d7f5d3SJohn Marino if (pp->p_scan >= 0)
18886d7f5d3SJohn Marino check(pp, bp->b_y, bp->b_x);
18986d7f5d3SJohn Marino } else {
19086d7f5d3SJohn Marino /* It is exploding. Check what we hit: */
19186d7f5d3SJohn Marino chkshot(bp, next);
19286d7f5d3SJohn Marino /* Release storage for the destroyed bullet: */
19386d7f5d3SJohn Marino free(bp);
19486d7f5d3SJohn Marino }
19586d7f5d3SJohn Marino }
19686d7f5d3SJohn Marino
19786d7f5d3SJohn Marino /* Re-draw all the players: (in case a bullet wiped them out) */
19886d7f5d3SJohn Marino for (pp = Player; pp < End_player; pp++)
19986d7f5d3SJohn Marino Maze[pp->p_y][pp->p_x] = pp->p_face;
20086d7f5d3SJohn Marino
20186d7f5d3SJohn Marino no_bullets:
20286d7f5d3SJohn Marino
20386d7f5d3SJohn Marino /* Move flying boots through the air: */
20486d7f5d3SJohn Marino for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
20586d7f5d3SJohn Marino if (pp->p_flying >= 0)
20686d7f5d3SJohn Marino move_flyer(pp);
20786d7f5d3SJohn Marino
20886d7f5d3SJohn Marino /* Move flying players through the air: */
20986d7f5d3SJohn Marino for (pp = Player; pp < End_player; pp++) {
21086d7f5d3SJohn Marino if (pp->p_flying >= 0)
21186d7f5d3SJohn Marino move_flyer(pp);
21286d7f5d3SJohn Marino /* Flush out the explosions: */
21386d7f5d3SJohn Marino sendcom(pp, REFRESH);
21486d7f5d3SJohn Marino look(pp);
21586d7f5d3SJohn Marino }
21686d7f5d3SJohn Marino
21786d7f5d3SJohn Marino /* Flush out and synchronise all the displays: */
21886d7f5d3SJohn Marino sendcom(ALL_PLAYERS, REFRESH);
21986d7f5d3SJohn Marino }
22086d7f5d3SJohn Marino
22186d7f5d3SJohn Marino /*
22286d7f5d3SJohn Marino * move_normal_shot:
22386d7f5d3SJohn Marino * Move a normal shot along its trajectory.
22486d7f5d3SJohn Marino * Returns false if the bullet no longer needs tracking.
22586d7f5d3SJohn Marino */
22686d7f5d3SJohn Marino static int
move_normal_shot(BULLET * bp)22786d7f5d3SJohn Marino move_normal_shot(BULLET *bp)
22886d7f5d3SJohn Marino {
22986d7f5d3SJohn Marino int i, x, y;
23086d7f5d3SJohn Marino PLAYER *pp;
23186d7f5d3SJohn Marino
23286d7f5d3SJohn Marino /*
23386d7f5d3SJohn Marino * Walk an unexploded bullet along conf_bulspd times, moving it
23486d7f5d3SJohn Marino * one unit along each step. We flag it as exploding if it
23586d7f5d3SJohn Marino * meets something.
23686d7f5d3SJohn Marino */
23786d7f5d3SJohn Marino
23886d7f5d3SJohn Marino for (i = 0; i < conf_bulspd; i++) {
23986d7f5d3SJohn Marino
24086d7f5d3SJohn Marino /* Stop if the bullet has already exploded: */
24186d7f5d3SJohn Marino if (bp->b_expl)
24286d7f5d3SJohn Marino break;
24386d7f5d3SJohn Marino
24486d7f5d3SJohn Marino /* Adjust the bullet's co-ordinates: */
24586d7f5d3SJohn Marino x = bp->b_x;
24686d7f5d3SJohn Marino y = bp->b_y;
24786d7f5d3SJohn Marino switch (bp->b_face) {
24886d7f5d3SJohn Marino case LEFTS:
24986d7f5d3SJohn Marino x--;
25086d7f5d3SJohn Marino break;
25186d7f5d3SJohn Marino case RIGHT:
25286d7f5d3SJohn Marino x++;
25386d7f5d3SJohn Marino break;
25486d7f5d3SJohn Marino case ABOVE:
25586d7f5d3SJohn Marino y--;
25686d7f5d3SJohn Marino break;
25786d7f5d3SJohn Marino case BELOW:
25886d7f5d3SJohn Marino y++;
25986d7f5d3SJohn Marino break;
26086d7f5d3SJohn Marino }
26186d7f5d3SJohn Marino
26286d7f5d3SJohn Marino
26386d7f5d3SJohn Marino /* Look at what the bullet is colliding with : */
26486d7f5d3SJohn Marino switch (Maze[y][x]) {
26586d7f5d3SJohn Marino /* Gun shots have a chance of collision: */
26686d7f5d3SJohn Marino case SHOT:
26786d7f5d3SJohn Marino if (rand_num(100) < conf_pshot_coll) {
26886d7f5d3SJohn Marino zapshot(Bullets, bp);
26986d7f5d3SJohn Marino zapshot(bp->b_next, bp);
27086d7f5d3SJohn Marino }
27186d7f5d3SJohn Marino break;
27286d7f5d3SJohn Marino /* Grenades only have a chance of collision: */
27386d7f5d3SJohn Marino case GRENADE:
27486d7f5d3SJohn Marino if (rand_num(100) < conf_pgren_coll) {
27586d7f5d3SJohn Marino zapshot(Bullets, bp);
27686d7f5d3SJohn Marino zapshot(bp->b_next, bp);
27786d7f5d3SJohn Marino }
27886d7f5d3SJohn Marino break;
27986d7f5d3SJohn Marino /* Reflecting walls richochet the bullet: */
28086d7f5d3SJohn Marino case WALL4:
28186d7f5d3SJohn Marino switch (bp->b_face) {
28286d7f5d3SJohn Marino case LEFTS:
28386d7f5d3SJohn Marino bp->b_face = BELOW;
28486d7f5d3SJohn Marino break;
28586d7f5d3SJohn Marino case RIGHT:
28686d7f5d3SJohn Marino bp->b_face = ABOVE;
28786d7f5d3SJohn Marino break;
28886d7f5d3SJohn Marino case ABOVE:
28986d7f5d3SJohn Marino bp->b_face = RIGHT;
29086d7f5d3SJohn Marino break;
29186d7f5d3SJohn Marino case BELOW:
29286d7f5d3SJohn Marino bp->b_face = LEFTS;
29386d7f5d3SJohn Marino break;
29486d7f5d3SJohn Marino }
29586d7f5d3SJohn Marino Maze[y][x] = WALL5;
29686d7f5d3SJohn Marino for (pp = Monitor; pp < End_monitor; pp++)
29786d7f5d3SJohn Marino check(pp, y, x);
29886d7f5d3SJohn Marino break;
29986d7f5d3SJohn Marino case WALL5:
30086d7f5d3SJohn Marino switch (bp->b_face) {
30186d7f5d3SJohn Marino case LEFTS:
30286d7f5d3SJohn Marino bp->b_face = ABOVE;
30386d7f5d3SJohn Marino break;
30486d7f5d3SJohn Marino case RIGHT:
30586d7f5d3SJohn Marino bp->b_face = BELOW;
30686d7f5d3SJohn Marino break;
30786d7f5d3SJohn Marino case ABOVE:
30886d7f5d3SJohn Marino bp->b_face = LEFTS;
30986d7f5d3SJohn Marino break;
31086d7f5d3SJohn Marino case BELOW:
31186d7f5d3SJohn Marino bp->b_face = RIGHT;
31286d7f5d3SJohn Marino break;
31386d7f5d3SJohn Marino }
31486d7f5d3SJohn Marino Maze[y][x] = WALL4;
31586d7f5d3SJohn Marino for (pp = Monitor; pp < End_monitor; pp++)
31686d7f5d3SJohn Marino check(pp, y, x);
31786d7f5d3SJohn Marino break;
31886d7f5d3SJohn Marino /* Dispersion doors randomly disperse bullets: */
31986d7f5d3SJohn Marino case DOOR:
32086d7f5d3SJohn Marino switch (rand_num(4)) {
32186d7f5d3SJohn Marino case 0:
32286d7f5d3SJohn Marino bp->b_face = ABOVE;
32386d7f5d3SJohn Marino break;
32486d7f5d3SJohn Marino case 1:
32586d7f5d3SJohn Marino bp->b_face = BELOW;
32686d7f5d3SJohn Marino break;
32786d7f5d3SJohn Marino case 2:
32886d7f5d3SJohn Marino bp->b_face = LEFTS;
32986d7f5d3SJohn Marino break;
33086d7f5d3SJohn Marino case 3:
33186d7f5d3SJohn Marino bp->b_face = RIGHT;
33286d7f5d3SJohn Marino break;
33386d7f5d3SJohn Marino }
33486d7f5d3SJohn Marino break;
33586d7f5d3SJohn Marino /* Bullets zing past fliers: */
33686d7f5d3SJohn Marino case FLYER:
33786d7f5d3SJohn Marino pp = play_at(y, x);
33886d7f5d3SJohn Marino message(pp, "Zing!");
33986d7f5d3SJohn Marino break;
34086d7f5d3SJohn Marino /* Bullets encountering a player: */
34186d7f5d3SJohn Marino case LEFTS:
34286d7f5d3SJohn Marino case RIGHT:
34386d7f5d3SJohn Marino case BELOW:
34486d7f5d3SJohn Marino case ABOVE:
34586d7f5d3SJohn Marino /*
34686d7f5d3SJohn Marino * Give the person a chance to catch a
34786d7f5d3SJohn Marino * grenade if s/he is facing it:
34886d7f5d3SJohn Marino */
34986d7f5d3SJohn Marino pp = play_at(y, x);
35086d7f5d3SJohn Marino pp->p_ident->i_shot += bp->b_charge;
35186d7f5d3SJohn Marino if (opposite(bp->b_face, Maze[y][x])) {
35286d7f5d3SJohn Marino /* Give them a 10% chance: */
35386d7f5d3SJohn Marino if (rand_num(100) < conf_pgren_catch) {
35486d7f5d3SJohn Marino /* They caught it! */
35586d7f5d3SJohn Marino if (bp->b_owner != NULL)
35686d7f5d3SJohn Marino message(bp->b_owner,
35786d7f5d3SJohn Marino "Your charge was absorbed!");
35886d7f5d3SJohn Marino
35986d7f5d3SJohn Marino /*
36086d7f5d3SJohn Marino * The target player stole from the bullet's
36186d7f5d3SJohn Marino * owner. Charge stolen statistics:
36286d7f5d3SJohn Marino */
36386d7f5d3SJohn Marino if (bp->b_score != NULL)
36486d7f5d3SJohn Marino bp->b_score->i_robbed += bp->b_charge;
36586d7f5d3SJohn Marino
36686d7f5d3SJohn Marino /* They acquire more ammo: */
36786d7f5d3SJohn Marino pp->p_ammo += bp->b_charge;
36886d7f5d3SJohn Marino
36986d7f5d3SJohn Marino /* Check if it would have destroyed them: */
37086d7f5d3SJohn Marino if (pp->p_damage + bp->b_size * conf_mindam
37186d7f5d3SJohn Marino > pp->p_damcap)
37286d7f5d3SJohn Marino /* Lucky escape statistics: */
37386d7f5d3SJohn Marino pp->p_ident->i_saved++;
37486d7f5d3SJohn Marino
37586d7f5d3SJohn Marino /* Tell them: */
37686d7f5d3SJohn Marino message(pp, "Absorbed charge (good shield!)");
37786d7f5d3SJohn Marino
37886d7f5d3SJohn Marino /* Absorbtion statistics: */
37986d7f5d3SJohn Marino pp->p_ident->i_absorbed += bp->b_charge;
38086d7f5d3SJohn Marino
38186d7f5d3SJohn Marino /* Deallocate storage: */
38286d7f5d3SJohn Marino free(bp);
38386d7f5d3SJohn Marino
38486d7f5d3SJohn Marino /* Update ammo display: */
38586d7f5d3SJohn Marino ammo_update(pp);
38686d7f5d3SJohn Marino
38786d7f5d3SJohn Marino /* No need for caller to keep tracking it: */
38886d7f5d3SJohn Marino return FALSE;
38986d7f5d3SJohn Marino }
39086d7f5d3SJohn Marino
39186d7f5d3SJohn Marino /* Bullets faced head-on (statistics): */
39286d7f5d3SJohn Marino pp->p_ident->i_faced += bp->b_charge;
39386d7f5d3SJohn Marino }
39486d7f5d3SJohn Marino
39586d7f5d3SJohn Marino /*
39686d7f5d3SJohn Marino * Small chance that the bullet just misses the
39786d7f5d3SJohn Marino * person. If so, the bullet just goes on its
39886d7f5d3SJohn Marino * merry way without exploding. (5% chance)
39986d7f5d3SJohn Marino */
40086d7f5d3SJohn Marino if (rand_num(100) < conf_pmiss) {
40186d7f5d3SJohn Marino /* Ducked statistics: */
40286d7f5d3SJohn Marino pp->p_ident->i_ducked += bp->b_charge;
40386d7f5d3SJohn Marino
40486d7f5d3SJohn Marino /* Check if it would have killed them: */
40586d7f5d3SJohn Marino if (pp->p_damage + bp->b_size * conf_mindam
40686d7f5d3SJohn Marino > pp->p_damcap)
40786d7f5d3SJohn Marino /* Lucky escape statistics: */
40886d7f5d3SJohn Marino pp->p_ident->i_saved++;
40986d7f5d3SJohn Marino
41086d7f5d3SJohn Marino /* Shooter missed statistics: */
41186d7f5d3SJohn Marino if (bp->b_score != NULL)
41286d7f5d3SJohn Marino bp->b_score->i_missed += bp->b_charge;
41386d7f5d3SJohn Marino
41486d7f5d3SJohn Marino /* Tell target that they were missed: */
41586d7f5d3SJohn Marino message(pp, "Zing!");
41686d7f5d3SJohn Marino
41786d7f5d3SJohn Marino /* Tell the bullet owner they missed: */
41886d7f5d3SJohn Marino if (bp->b_owner != NULL)
41986d7f5d3SJohn Marino message(bp->b_owner,
42086d7f5d3SJohn Marino ((bp->b_score->i_missed & 0x7) == 0x7) ?
42186d7f5d3SJohn Marino "My! What a bad shot you are!" :
42286d7f5d3SJohn Marino "Missed him");
42386d7f5d3SJohn Marino
42486d7f5d3SJohn Marino /* Don't fall through */
42586d7f5d3SJohn Marino break;
42686d7f5d3SJohn Marino } else {
42786d7f5d3SJohn Marino /* The player is to be blown up: */
42886d7f5d3SJohn Marino bp->b_expl = TRUE;
42986d7f5d3SJohn Marino }
43086d7f5d3SJohn Marino break;
43186d7f5d3SJohn Marino /* Bullet hits a wall, and always explodes: */
43286d7f5d3SJohn Marino case WALL1:
43386d7f5d3SJohn Marino case WALL2:
43486d7f5d3SJohn Marino case WALL3:
43586d7f5d3SJohn Marino bp->b_expl = TRUE;
43686d7f5d3SJohn Marino break;
43786d7f5d3SJohn Marino }
43886d7f5d3SJohn Marino
43986d7f5d3SJohn Marino /* Update the bullet's new position: */
44086d7f5d3SJohn Marino bp->b_x = x;
44186d7f5d3SJohn Marino bp->b_y = y;
44286d7f5d3SJohn Marino }
44386d7f5d3SJohn Marino
44486d7f5d3SJohn Marino /* Caller should keep tracking the bullet: */
44586d7f5d3SJohn Marino return TRUE;
44686d7f5d3SJohn Marino }
44786d7f5d3SJohn Marino
44886d7f5d3SJohn Marino /*
44986d7f5d3SJohn Marino * move_drone:
45086d7f5d3SJohn Marino * Move the drone to the next square
45186d7f5d3SJohn Marino * Returns FALSE if the drone need no longer be tracked.
45286d7f5d3SJohn Marino */
45386d7f5d3SJohn Marino static int
move_drone(BULLET * bp)45486d7f5d3SJohn Marino move_drone(BULLET *bp)
45586d7f5d3SJohn Marino {
45686d7f5d3SJohn Marino int mask, count;
45786d7f5d3SJohn Marino int n, dir = -1;
45886d7f5d3SJohn Marino PLAYER *pp;
45986d7f5d3SJohn Marino
46086d7f5d3SJohn Marino /* See if we can give someone a blast: */
46186d7f5d3SJohn Marino if (is_player(Maze[bp->b_y][bp->b_x - 1])) {
46286d7f5d3SJohn Marino dir = WEST;
46386d7f5d3SJohn Marino goto drone_move;
46486d7f5d3SJohn Marino }
46586d7f5d3SJohn Marino if (is_player(Maze[bp->b_y - 1][bp->b_x])) {
46686d7f5d3SJohn Marino dir = NORTH;
46786d7f5d3SJohn Marino goto drone_move;
46886d7f5d3SJohn Marino }
46986d7f5d3SJohn Marino if (is_player(Maze[bp->b_y + 1][bp->b_x])) {
47086d7f5d3SJohn Marino dir = SOUTH;
47186d7f5d3SJohn Marino goto drone_move;
47286d7f5d3SJohn Marino }
47386d7f5d3SJohn Marino if (is_player(Maze[bp->b_y][bp->b_x + 1])) {
47486d7f5d3SJohn Marino dir = EAST;
47586d7f5d3SJohn Marino goto drone_move;
47686d7f5d3SJohn Marino }
47786d7f5d3SJohn Marino
47886d7f5d3SJohn Marino /* Find out what directions are clear and move that way: */
47986d7f5d3SJohn Marino mask = count = 0;
48086d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x - 1))
48186d7f5d3SJohn Marino mask |= WEST, count++;
48286d7f5d3SJohn Marino if (!iswall(bp->b_y - 1, bp->b_x))
48386d7f5d3SJohn Marino mask |= NORTH, count++;
48486d7f5d3SJohn Marino if (!iswall(bp->b_y + 1, bp->b_x))
48586d7f5d3SJohn Marino mask |= SOUTH, count++;
48686d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x + 1))
48786d7f5d3SJohn Marino mask |= EAST, count++;
48886d7f5d3SJohn Marino
48986d7f5d3SJohn Marino /* All blocked up, just wait: */
49086d7f5d3SJohn Marino if (count == 0)
49186d7f5d3SJohn Marino return TRUE;
49286d7f5d3SJohn Marino
49386d7f5d3SJohn Marino /* Only one way to go: */
49486d7f5d3SJohn Marino if (count == 1) {
49586d7f5d3SJohn Marino dir = mask;
49686d7f5d3SJohn Marino goto drone_move;
49786d7f5d3SJohn Marino }
49886d7f5d3SJohn Marino
49986d7f5d3SJohn Marino /* Avoid backtracking, and remove the direction we came from: */
50086d7f5d3SJohn Marino switch (bp->b_face) {
50186d7f5d3SJohn Marino case LEFTS:
50286d7f5d3SJohn Marino if (mask & EAST)
50386d7f5d3SJohn Marino mask &= ~EAST, count--;
50486d7f5d3SJohn Marino break;
50586d7f5d3SJohn Marino case RIGHT:
50686d7f5d3SJohn Marino if (mask & WEST)
50786d7f5d3SJohn Marino mask &= ~WEST, count--;
50886d7f5d3SJohn Marino break;
50986d7f5d3SJohn Marino case ABOVE:
51086d7f5d3SJohn Marino if (mask & SOUTH)
51186d7f5d3SJohn Marino mask &= ~SOUTH, count--;
51286d7f5d3SJohn Marino break;
51386d7f5d3SJohn Marino case BELOW:
51486d7f5d3SJohn Marino if (mask & NORTH)
51586d7f5d3SJohn Marino mask &= ~NORTH, count--;
51686d7f5d3SJohn Marino break;
51786d7f5d3SJohn Marino }
51886d7f5d3SJohn Marino
51986d7f5d3SJohn Marino /* Pick one of the remaining directions: */
52086d7f5d3SJohn Marino n = rand_num(count);
52186d7f5d3SJohn Marino if (n >= 0 && mask & NORTH)
52286d7f5d3SJohn Marino dir = NORTH, n--;
52386d7f5d3SJohn Marino if (n >= 0 && mask & SOUTH)
52486d7f5d3SJohn Marino dir = SOUTH, n--;
52586d7f5d3SJohn Marino if (n >= 0 && mask & EAST)
52686d7f5d3SJohn Marino dir = EAST, n--;
52786d7f5d3SJohn Marino if (n >= 0 && mask & WEST)
52886d7f5d3SJohn Marino dir = WEST, n--;
52986d7f5d3SJohn Marino
53086d7f5d3SJohn Marino drone_move:
53186d7f5d3SJohn Marino /* Move the drone: */
53286d7f5d3SJohn Marino switch (dir) {
53386d7f5d3SJohn Marino case -1:
53486d7f5d3SJohn Marino /* no move */
53586d7f5d3SJohn Marino case WEST:
53686d7f5d3SJohn Marino bp->b_x--;
53786d7f5d3SJohn Marino bp->b_face = LEFTS;
53886d7f5d3SJohn Marino break;
53986d7f5d3SJohn Marino case EAST:
54086d7f5d3SJohn Marino bp->b_x++;
54186d7f5d3SJohn Marino bp->b_face = RIGHT;
54286d7f5d3SJohn Marino break;
54386d7f5d3SJohn Marino case NORTH:
54486d7f5d3SJohn Marino bp->b_y--;
54586d7f5d3SJohn Marino bp->b_face = ABOVE;
54686d7f5d3SJohn Marino break;
54786d7f5d3SJohn Marino case SOUTH:
54886d7f5d3SJohn Marino bp->b_y++;
54986d7f5d3SJohn Marino bp->b_face = BELOW;
55086d7f5d3SJohn Marino break;
55186d7f5d3SJohn Marino }
55286d7f5d3SJohn Marino
55386d7f5d3SJohn Marino /* Look at what the drone moved onto: */
55486d7f5d3SJohn Marino switch (Maze[bp->b_y][bp->b_x]) {
55586d7f5d3SJohn Marino case LEFTS:
55686d7f5d3SJohn Marino case RIGHT:
55786d7f5d3SJohn Marino case BELOW:
55886d7f5d3SJohn Marino case ABOVE:
55986d7f5d3SJohn Marino /*
56086d7f5d3SJohn Marino * Players have a 1% chance of absorbing a drone,
56186d7f5d3SJohn Marino * if they are facing it.
56286d7f5d3SJohn Marino */
56386d7f5d3SJohn Marino if (rand_num(100) < conf_pdroneabsorb && opposite(bp->b_face,
56486d7f5d3SJohn Marino Maze[bp->b_y][bp->b_x])) {
56586d7f5d3SJohn Marino
56686d7f5d3SJohn Marino /* Feel the power: */
56786d7f5d3SJohn Marino pp = play_at(bp->b_y, bp->b_x);
56886d7f5d3SJohn Marino pp->p_ammo += bp->b_charge;
56986d7f5d3SJohn Marino message(pp, "**** Absorbed drone ****");
57086d7f5d3SJohn Marino
57186d7f5d3SJohn Marino /* Release drone storage: */
57286d7f5d3SJohn Marino free(bp);
57386d7f5d3SJohn Marino
57486d7f5d3SJohn Marino /* Update ammo: */
57586d7f5d3SJohn Marino ammo_update(pp);
57686d7f5d3SJohn Marino
57786d7f5d3SJohn Marino /* No need for caller to keep tracking drone: */
57886d7f5d3SJohn Marino return FALSE;
57986d7f5d3SJohn Marino }
58086d7f5d3SJohn Marino /* Detonate the drone: */
58186d7f5d3SJohn Marino bp->b_expl = TRUE;
58286d7f5d3SJohn Marino break;
58386d7f5d3SJohn Marino }
58486d7f5d3SJohn Marino
58586d7f5d3SJohn Marino /* Keep tracking the drone. */
58686d7f5d3SJohn Marino return TRUE;
58786d7f5d3SJohn Marino }
58886d7f5d3SJohn Marino
58986d7f5d3SJohn Marino /*
59086d7f5d3SJohn Marino * save_bullet:
59186d7f5d3SJohn Marino * Put a bullet back onto the bullet list
59286d7f5d3SJohn Marino */
59386d7f5d3SJohn Marino static void
save_bullet(BULLET * bp)59486d7f5d3SJohn Marino save_bullet(BULLET *bp)
59586d7f5d3SJohn Marino {
59686d7f5d3SJohn Marino
59786d7f5d3SJohn Marino /* Save what the bullet will be flying over: */
59886d7f5d3SJohn Marino bp->b_over = Maze[bp->b_y][bp->b_x];
59986d7f5d3SJohn Marino
60086d7f5d3SJohn Marino switch (bp->b_over) {
60186d7f5d3SJohn Marino /* Bullets that can pass through each other: */
60286d7f5d3SJohn Marino case SHOT:
60386d7f5d3SJohn Marino case GRENADE:
60486d7f5d3SJohn Marino case SATCHEL:
60586d7f5d3SJohn Marino case BOMB:
60686d7f5d3SJohn Marino case SLIME:
60786d7f5d3SJohn Marino case LAVA:
60886d7f5d3SJohn Marino case DSHOT:
60986d7f5d3SJohn Marino find_under(Bullets, bp);
61086d7f5d3SJohn Marino break;
61186d7f5d3SJohn Marino }
61286d7f5d3SJohn Marino
61386d7f5d3SJohn Marino switch (bp->b_over) {
61486d7f5d3SJohn Marino /* A bullet hits a player: */
61586d7f5d3SJohn Marino case LEFTS:
61686d7f5d3SJohn Marino case RIGHT:
61786d7f5d3SJohn Marino case ABOVE:
61886d7f5d3SJohn Marino case BELOW:
61986d7f5d3SJohn Marino case FLYER:
62086d7f5d3SJohn Marino mark_player(bp);
62186d7f5d3SJohn Marino break;
62286d7f5d3SJohn Marino
62386d7f5d3SJohn Marino /* A bullet passes a boot: */
62486d7f5d3SJohn Marino case BOOT:
62586d7f5d3SJohn Marino case BOOT_PAIR:
62686d7f5d3SJohn Marino mark_boot(bp);
62786d7f5d3SJohn Marino /* FALLTHROUGH */
62886d7f5d3SJohn Marino
62986d7f5d3SJohn Marino /* The bullet flies over everything else: */
63086d7f5d3SJohn Marino default:
63186d7f5d3SJohn Marino Maze[bp->b_y][bp->b_x] = bp->b_type;
63286d7f5d3SJohn Marino break;
63386d7f5d3SJohn Marino }
63486d7f5d3SJohn Marino
63586d7f5d3SJohn Marino /* Insert the bullet into the Bullets list: */
63686d7f5d3SJohn Marino bp->b_next = Bullets;
63786d7f5d3SJohn Marino Bullets = bp;
63886d7f5d3SJohn Marino }
63986d7f5d3SJohn Marino
64086d7f5d3SJohn Marino /*
64186d7f5d3SJohn Marino * move_flyer:
64286d7f5d3SJohn Marino * Update the position of a player in flight
64386d7f5d3SJohn Marino */
64486d7f5d3SJohn Marino static void
move_flyer(PLAYER * pp)64586d7f5d3SJohn Marino move_flyer(PLAYER *pp)
64686d7f5d3SJohn Marino {
64786d7f5d3SJohn Marino int x, y;
64886d7f5d3SJohn Marino
64986d7f5d3SJohn Marino if (pp->p_undershot) {
65086d7f5d3SJohn Marino fixshots(pp->p_y, pp->p_x, pp->p_over);
65186d7f5d3SJohn Marino pp->p_undershot = FALSE;
65286d7f5d3SJohn Marino }
65386d7f5d3SJohn Marino
65486d7f5d3SJohn Marino /* Restore what the flier was flying over */
65586d7f5d3SJohn Marino Maze[pp->p_y][pp->p_x] = pp->p_over;
65686d7f5d3SJohn Marino
65786d7f5d3SJohn Marino /* Fly: */
65886d7f5d3SJohn Marino x = pp->p_x + pp->p_flyx;
65986d7f5d3SJohn Marino y = pp->p_y + pp->p_flyy;
66086d7f5d3SJohn Marino
66186d7f5d3SJohn Marino /* Bouncing off the edges of the maze: */
66286d7f5d3SJohn Marino if (x < 1) {
66386d7f5d3SJohn Marino x = 1 - x;
66486d7f5d3SJohn Marino pp->p_flyx = -pp->p_flyx;
66586d7f5d3SJohn Marino }
66686d7f5d3SJohn Marino else if (x > WIDTH - 2) {
66786d7f5d3SJohn Marino x = (WIDTH - 2) - (x - (WIDTH - 2));
66886d7f5d3SJohn Marino pp->p_flyx = -pp->p_flyx;
66986d7f5d3SJohn Marino }
67086d7f5d3SJohn Marino if (y < 1) {
67186d7f5d3SJohn Marino y = 1 - y;
67286d7f5d3SJohn Marino pp->p_flyy = -pp->p_flyy;
67386d7f5d3SJohn Marino }
67486d7f5d3SJohn Marino else if (y > HEIGHT - 2) {
67586d7f5d3SJohn Marino y = (HEIGHT - 2) - (y - (HEIGHT - 2));
67686d7f5d3SJohn Marino pp->p_flyy = -pp->p_flyy;
67786d7f5d3SJohn Marino }
67886d7f5d3SJohn Marino
67986d7f5d3SJohn Marino /* Make sure we don't land on something we can't: */
68086d7f5d3SJohn Marino again:
68186d7f5d3SJohn Marino switch (Maze[y][x]) {
68286d7f5d3SJohn Marino default:
68386d7f5d3SJohn Marino /*
68486d7f5d3SJohn Marino * Flier is over something other than space, a wall
68586d7f5d3SJohn Marino * or a door. Randomly move (drift) the flier a little bit
68686d7f5d3SJohn Marino * and then try again:
68786d7f5d3SJohn Marino */
68886d7f5d3SJohn Marino switch (rand_num(4)) {
68986d7f5d3SJohn Marino case 0:
69086d7f5d3SJohn Marino PLUS_DELTA(x, WIDTH - 2);
69186d7f5d3SJohn Marino break;
69286d7f5d3SJohn Marino case 1:
69386d7f5d3SJohn Marino MINUS_DELTA(x, 1);
69486d7f5d3SJohn Marino break;
69586d7f5d3SJohn Marino case 2:
69686d7f5d3SJohn Marino PLUS_DELTA(y, HEIGHT - 2);
69786d7f5d3SJohn Marino break;
69886d7f5d3SJohn Marino case 3:
69986d7f5d3SJohn Marino MINUS_DELTA(y, 1);
70086d7f5d3SJohn Marino break;
70186d7f5d3SJohn Marino }
70286d7f5d3SJohn Marino goto again;
70386d7f5d3SJohn Marino /* Give a little boost when about to land on a wall or door: */
70486d7f5d3SJohn Marino case WALL1:
70586d7f5d3SJohn Marino case WALL2:
70686d7f5d3SJohn Marino case WALL3:
70786d7f5d3SJohn Marino case WALL4:
70886d7f5d3SJohn Marino case WALL5:
70986d7f5d3SJohn Marino case DOOR:
71086d7f5d3SJohn Marino if (pp->p_flying == 0)
71186d7f5d3SJohn Marino pp->p_flying++;
71286d7f5d3SJohn Marino break;
71386d7f5d3SJohn Marino /* Spaces are okay: */
71486d7f5d3SJohn Marino case SPACE:
71586d7f5d3SJohn Marino break;
71686d7f5d3SJohn Marino }
71786d7f5d3SJohn Marino
71886d7f5d3SJohn Marino /* Update flier's coordinates: */
71986d7f5d3SJohn Marino pp->p_y = y;
72086d7f5d3SJohn Marino pp->p_x = x;
72186d7f5d3SJohn Marino
72286d7f5d3SJohn Marino /* Consume 'flying' time: */
72386d7f5d3SJohn Marino if (pp->p_flying-- == 0) {
72486d7f5d3SJohn Marino /* Land: */
72586d7f5d3SJohn Marino if (pp->p_face != BOOT && pp->p_face != BOOT_PAIR) {
72686d7f5d3SJohn Marino /* Land a player - they stustain a fall: */
72786d7f5d3SJohn Marino checkdam(pp, NULL, NULL,
72886d7f5d3SJohn Marino rand_num(pp->p_damage / conf_fall_frac), FALL);
72986d7f5d3SJohn Marino pp->p_face = rand_dir();
73086d7f5d3SJohn Marino showstat(pp);
73186d7f5d3SJohn Marino } else {
73286d7f5d3SJohn Marino /* Land boots: */
73386d7f5d3SJohn Marino if (Maze[y][x] == BOOT)
73486d7f5d3SJohn Marino pp->p_face = BOOT_PAIR;
73586d7f5d3SJohn Marino Maze[y][x] = SPACE;
73686d7f5d3SJohn Marino }
73786d7f5d3SJohn Marino }
73886d7f5d3SJohn Marino
73986d7f5d3SJohn Marino /* Save under the flier: */
74086d7f5d3SJohn Marino pp->p_over = Maze[y][x];
74186d7f5d3SJohn Marino /* Draw in the flier: */
74286d7f5d3SJohn Marino Maze[y][x] = pp->p_face;
74386d7f5d3SJohn Marino showexpl(y, x, pp->p_face);
74486d7f5d3SJohn Marino }
74586d7f5d3SJohn Marino
74686d7f5d3SJohn Marino /*
74786d7f5d3SJohn Marino * chkshot
74886d7f5d3SJohn Marino * Handle explosions
74986d7f5d3SJohn Marino */
75086d7f5d3SJohn Marino static void
chkshot(BULLET * bp,BULLET * next)75186d7f5d3SJohn Marino chkshot(BULLET *bp, BULLET *next)
75286d7f5d3SJohn Marino {
75386d7f5d3SJohn Marino int y, x;
75486d7f5d3SJohn Marino int dy, dx, absdy;
75586d7f5d3SJohn Marino int delta, damage;
75686d7f5d3SJohn Marino char expl;
75786d7f5d3SJohn Marino PLAYER *pp;
75886d7f5d3SJohn Marino
75986d7f5d3SJohn Marino delta = 0;
76086d7f5d3SJohn Marino switch (bp->b_type) {
76186d7f5d3SJohn Marino case SHOT:
76286d7f5d3SJohn Marino case MINE:
76386d7f5d3SJohn Marino case GRENADE:
76486d7f5d3SJohn Marino case GMINE:
76586d7f5d3SJohn Marino case SATCHEL:
76686d7f5d3SJohn Marino case BOMB:
76786d7f5d3SJohn Marino delta = bp->b_size - 1;
76886d7f5d3SJohn Marino break;
76986d7f5d3SJohn Marino case SLIME:
77086d7f5d3SJohn Marino case LAVA:
77186d7f5d3SJohn Marino chkslime(bp, next);
77286d7f5d3SJohn Marino return;
77386d7f5d3SJohn Marino case DSHOT:
77486d7f5d3SJohn Marino bp->b_type = SLIME;
77586d7f5d3SJohn Marino chkslime(bp, next);
77686d7f5d3SJohn Marino return;
77786d7f5d3SJohn Marino }
77886d7f5d3SJohn Marino
77986d7f5d3SJohn Marino /* Draw the explosion square: */
78086d7f5d3SJohn Marino for (y = bp->b_y - delta; y <= bp->b_y + delta; y++) {
78186d7f5d3SJohn Marino if (y < 0 || y >= HEIGHT)
78286d7f5d3SJohn Marino continue;
78386d7f5d3SJohn Marino dy = y - bp->b_y;
78486d7f5d3SJohn Marino absdy = (dy < 0) ? -dy : dy;
78586d7f5d3SJohn Marino for (x = bp->b_x - delta; x <= bp->b_x + delta; x++) {
78686d7f5d3SJohn Marino /* Draw a part of the explosion cloud: */
78786d7f5d3SJohn Marino if (x < 0 || x >= WIDTH)
78886d7f5d3SJohn Marino continue;
78986d7f5d3SJohn Marino dx = x - bp->b_x;
79086d7f5d3SJohn Marino if (dx == 0)
79186d7f5d3SJohn Marino expl = (dy == 0) ? '*' : '|';
79286d7f5d3SJohn Marino else if (dy == 0)
79386d7f5d3SJohn Marino expl = '-';
79486d7f5d3SJohn Marino else if (dx == dy)
79586d7f5d3SJohn Marino expl = '\\';
79686d7f5d3SJohn Marino else if (dx == -dy)
79786d7f5d3SJohn Marino expl = '/';
79886d7f5d3SJohn Marino else
79986d7f5d3SJohn Marino expl = '*';
80086d7f5d3SJohn Marino showexpl(y, x, expl);
80186d7f5d3SJohn Marino
80286d7f5d3SJohn Marino /* Check what poor bastard was in the explosion: */
80386d7f5d3SJohn Marino switch (Maze[y][x]) {
80486d7f5d3SJohn Marino case LEFTS:
80586d7f5d3SJohn Marino case RIGHT:
80686d7f5d3SJohn Marino case ABOVE:
80786d7f5d3SJohn Marino case BELOW:
80886d7f5d3SJohn Marino case FLYER:
80986d7f5d3SJohn Marino if (dx < 0)
81086d7f5d3SJohn Marino dx = -dx;
81186d7f5d3SJohn Marino if (absdy > dx)
81286d7f5d3SJohn Marino damage = bp->b_size - absdy;
81386d7f5d3SJohn Marino else
81486d7f5d3SJohn Marino damage = bp->b_size - dx;
81586d7f5d3SJohn Marino
81686d7f5d3SJohn Marino /* Everybody hurts, sometimes. */
81786d7f5d3SJohn Marino pp = play_at(y, x);
81886d7f5d3SJohn Marino checkdam(pp, bp->b_owner, bp->b_score,
81986d7f5d3SJohn Marino damage * conf_mindam, bp->b_type);
82086d7f5d3SJohn Marino break;
82186d7f5d3SJohn Marino case GMINE:
82286d7f5d3SJohn Marino case MINE:
82386d7f5d3SJohn Marino /* Mines detonate in a chain reaction: */
82486d7f5d3SJohn Marino add_shot((Maze[y][x] == GMINE) ?
82586d7f5d3SJohn Marino GRENADE : SHOT,
82686d7f5d3SJohn Marino y, x, LEFTS,
82786d7f5d3SJohn Marino (Maze[y][x] == GMINE) ?
82886d7f5d3SJohn Marino GRENREQ : BULREQ,
82986d7f5d3SJohn Marino NULL, TRUE, SPACE);
83086d7f5d3SJohn Marino Maze[y][x] = SPACE;
83186d7f5d3SJohn Marino break;
83286d7f5d3SJohn Marino }
83386d7f5d3SJohn Marino }
83486d7f5d3SJohn Marino }
83586d7f5d3SJohn Marino }
83686d7f5d3SJohn Marino
83786d7f5d3SJohn Marino /*
83886d7f5d3SJohn Marino * chkslime:
83986d7f5d3SJohn Marino * handle slime shot exploding
84086d7f5d3SJohn Marino */
84186d7f5d3SJohn Marino static void
chkslime(BULLET * bp,BULLET * next)84286d7f5d3SJohn Marino chkslime(BULLET *bp, BULLET *next)
84386d7f5d3SJohn Marino {
84486d7f5d3SJohn Marino BULLET *nbp;
84586d7f5d3SJohn Marino
84686d7f5d3SJohn Marino switch (Maze[bp->b_y][bp->b_x]) {
84786d7f5d3SJohn Marino /* Slime explodes on walls and doors: */
84886d7f5d3SJohn Marino case WALL1:
84986d7f5d3SJohn Marino case WALL2:
85086d7f5d3SJohn Marino case WALL3:
85186d7f5d3SJohn Marino case WALL4:
85286d7f5d3SJohn Marino case WALL5:
85386d7f5d3SJohn Marino case DOOR:
85486d7f5d3SJohn Marino switch (bp->b_face) {
85586d7f5d3SJohn Marino case LEFTS:
85686d7f5d3SJohn Marino bp->b_x++;
85786d7f5d3SJohn Marino break;
85886d7f5d3SJohn Marino case RIGHT:
85986d7f5d3SJohn Marino bp->b_x--;
86086d7f5d3SJohn Marino break;
86186d7f5d3SJohn Marino case ABOVE:
86286d7f5d3SJohn Marino bp->b_y++;
86386d7f5d3SJohn Marino break;
86486d7f5d3SJohn Marino case BELOW:
86586d7f5d3SJohn Marino bp->b_y--;
86686d7f5d3SJohn Marino break;
86786d7f5d3SJohn Marino }
86886d7f5d3SJohn Marino break;
86986d7f5d3SJohn Marino }
87086d7f5d3SJohn Marino
87186d7f5d3SJohn Marino /* Duplicate the unit of slime: */
87286d7f5d3SJohn Marino nbp = (BULLET *) malloc(sizeof (BULLET));
87386d7f5d3SJohn Marino if (nbp == NULL) {
87486d7f5d3SJohn Marino logit(LOG_ERR, "malloc");
87586d7f5d3SJohn Marino return;
87686d7f5d3SJohn Marino }
87786d7f5d3SJohn Marino *nbp = *bp;
87886d7f5d3SJohn Marino
87986d7f5d3SJohn Marino /* Move it around: */
88086d7f5d3SJohn Marino move_slime(nbp, nbp->b_type == SLIME ? conf_slimespeed :
88186d7f5d3SJohn Marino conf_lavaspeed, next);
88286d7f5d3SJohn Marino }
88386d7f5d3SJohn Marino
88486d7f5d3SJohn Marino /*
88586d7f5d3SJohn Marino * move_slime:
88686d7f5d3SJohn Marino * move the given slime shot speed times and add it back if
88786d7f5d3SJohn Marino * it hasn't fizzled yet
88886d7f5d3SJohn Marino */
88986d7f5d3SJohn Marino static void
move_slime(BULLET * bp,int speed,BULLET * next)89086d7f5d3SJohn Marino move_slime(BULLET *bp, int speed, BULLET *next)
89186d7f5d3SJohn Marino {
89286d7f5d3SJohn Marino int i, j, dirmask, count;
89386d7f5d3SJohn Marino PLAYER *pp;
89486d7f5d3SJohn Marino BULLET *nbp;
89586d7f5d3SJohn Marino
89686d7f5d3SJohn Marino if (speed == 0) {
89786d7f5d3SJohn Marino if (bp->b_charge <= 0)
89886d7f5d3SJohn Marino free(bp);
89986d7f5d3SJohn Marino else
90086d7f5d3SJohn Marino save_bullet(bp);
90186d7f5d3SJohn Marino return;
90286d7f5d3SJohn Marino }
90386d7f5d3SJohn Marino
90486d7f5d3SJohn Marino /* Draw it: */
90586d7f5d3SJohn Marino showexpl(bp->b_y, bp->b_x, bp->b_type == LAVA ? LAVA : '*');
90686d7f5d3SJohn Marino
90786d7f5d3SJohn Marino switch (Maze[bp->b_y][bp->b_x]) {
90886d7f5d3SJohn Marino /* Someone got hit by slime or lava: */
90986d7f5d3SJohn Marino case LEFTS:
91086d7f5d3SJohn Marino case RIGHT:
91186d7f5d3SJohn Marino case ABOVE:
91286d7f5d3SJohn Marino case BELOW:
91386d7f5d3SJohn Marino case FLYER:
91486d7f5d3SJohn Marino pp = play_at(bp->b_y, bp->b_x);
91586d7f5d3SJohn Marino message(pp, "You've been slimed.");
91686d7f5d3SJohn Marino checkdam(pp, bp->b_owner, bp->b_score, conf_mindam, bp->b_type);
91786d7f5d3SJohn Marino break;
91886d7f5d3SJohn Marino /* Bullets detonate in slime and lava: */
91986d7f5d3SJohn Marino case SHOT:
92086d7f5d3SJohn Marino case GRENADE:
92186d7f5d3SJohn Marino case SATCHEL:
92286d7f5d3SJohn Marino case BOMB:
92386d7f5d3SJohn Marino case DSHOT:
92486d7f5d3SJohn Marino explshot(next, bp->b_y, bp->b_x);
92586d7f5d3SJohn Marino explshot(Bullets, bp->b_y, bp->b_x);
92686d7f5d3SJohn Marino break;
92786d7f5d3SJohn Marino }
92886d7f5d3SJohn Marino
92986d7f5d3SJohn Marino
93086d7f5d3SJohn Marino /* Drain the slime/lava of some energy: */
93186d7f5d3SJohn Marino if (--bp->b_charge <= 0) {
93286d7f5d3SJohn Marino /* It fizzled: */
93386d7f5d3SJohn Marino free(bp);
93486d7f5d3SJohn Marino return;
93586d7f5d3SJohn Marino }
93686d7f5d3SJohn Marino
93786d7f5d3SJohn Marino /* Figure out which way the slime should flow: */
93886d7f5d3SJohn Marino dirmask = 0;
93986d7f5d3SJohn Marino count = 0;
94086d7f5d3SJohn Marino switch (bp->b_face) {
94186d7f5d3SJohn Marino case LEFTS:
94286d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x - 1))
94386d7f5d3SJohn Marino dirmask |= WEST, count++;
94486d7f5d3SJohn Marino if (!iswall(bp->b_y - 1, bp->b_x))
94586d7f5d3SJohn Marino dirmask |= NORTH, count++;
94686d7f5d3SJohn Marino if (!iswall(bp->b_y + 1, bp->b_x))
94786d7f5d3SJohn Marino dirmask |= SOUTH, count++;
94886d7f5d3SJohn Marino if (dirmask == 0)
94986d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x + 1))
95086d7f5d3SJohn Marino dirmask |= EAST, count++;
95186d7f5d3SJohn Marino break;
95286d7f5d3SJohn Marino case RIGHT:
95386d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x + 1))
95486d7f5d3SJohn Marino dirmask |= EAST, count++;
95586d7f5d3SJohn Marino if (!iswall(bp->b_y - 1, bp->b_x))
95686d7f5d3SJohn Marino dirmask |= NORTH, count++;
95786d7f5d3SJohn Marino if (!iswall(bp->b_y + 1, bp->b_x))
95886d7f5d3SJohn Marino dirmask |= SOUTH, count++;
95986d7f5d3SJohn Marino if (dirmask == 0)
96086d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x - 1))
96186d7f5d3SJohn Marino dirmask |= WEST, count++;
96286d7f5d3SJohn Marino break;
96386d7f5d3SJohn Marino case ABOVE:
96486d7f5d3SJohn Marino if (!iswall(bp->b_y - 1, bp->b_x))
96586d7f5d3SJohn Marino dirmask |= NORTH, count++;
96686d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x - 1))
96786d7f5d3SJohn Marino dirmask |= WEST, count++;
96886d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x + 1))
96986d7f5d3SJohn Marino dirmask |= EAST, count++;
97086d7f5d3SJohn Marino if (dirmask == 0)
97186d7f5d3SJohn Marino if (!iswall(bp->b_y + 1, bp->b_x))
97286d7f5d3SJohn Marino dirmask |= SOUTH, count++;
97386d7f5d3SJohn Marino break;
97486d7f5d3SJohn Marino case BELOW:
97586d7f5d3SJohn Marino if (!iswall(bp->b_y + 1, bp->b_x))
97686d7f5d3SJohn Marino dirmask |= SOUTH, count++;
97786d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x - 1))
97886d7f5d3SJohn Marino dirmask |= WEST, count++;
97986d7f5d3SJohn Marino if (!iswall(bp->b_y, bp->b_x + 1))
98086d7f5d3SJohn Marino dirmask |= EAST, count++;
98186d7f5d3SJohn Marino if (dirmask == 0)
98286d7f5d3SJohn Marino if (!iswall(bp->b_y - 1, bp->b_x))
98386d7f5d3SJohn Marino dirmask |= NORTH, count++;
98486d7f5d3SJohn Marino break;
98586d7f5d3SJohn Marino }
98686d7f5d3SJohn Marino if (count == 0) {
98786d7f5d3SJohn Marino /*
98886d7f5d3SJohn Marino * No place to go. Just sit here for a while and wait
98986d7f5d3SJohn Marino * for adjacent squares to clear out.
99086d7f5d3SJohn Marino */
99186d7f5d3SJohn Marino save_bullet(bp);
99286d7f5d3SJohn Marino return;
99386d7f5d3SJohn Marino }
99486d7f5d3SJohn Marino if (bp->b_charge < count) {
99586d7f5d3SJohn Marino /* Only bp->b_charge paths may be taken */
99686d7f5d3SJohn Marino while (count > bp->b_charge) {
99786d7f5d3SJohn Marino if (dirmask & WEST)
99886d7f5d3SJohn Marino dirmask &= ~WEST;
99986d7f5d3SJohn Marino else if (dirmask & EAST)
100086d7f5d3SJohn Marino dirmask &= ~EAST;
100186d7f5d3SJohn Marino else if (dirmask & NORTH)
100286d7f5d3SJohn Marino dirmask &= ~NORTH;
100386d7f5d3SJohn Marino else if (dirmask & SOUTH)
100486d7f5d3SJohn Marino dirmask &= ~SOUTH;
100586d7f5d3SJohn Marino count--;
100686d7f5d3SJohn Marino }
100786d7f5d3SJohn Marino }
100886d7f5d3SJohn Marino
100986d7f5d3SJohn Marino /* Spawn little slimes off in every possible direction: */
101086d7f5d3SJohn Marino i = bp->b_charge / count;
101186d7f5d3SJohn Marino j = bp->b_charge % count;
101286d7f5d3SJohn Marino if (dirmask & WEST) {
101386d7f5d3SJohn Marino count--;
101486d7f5d3SJohn Marino nbp = create_shot(bp->b_type, bp->b_y, bp->b_x - 1, LEFTS,
101586d7f5d3SJohn Marino i, bp->b_size, bp->b_owner, bp->b_score, TRUE, SPACE);
101686d7f5d3SJohn Marino move_slime(nbp, speed - 1, next);
101786d7f5d3SJohn Marino }
101886d7f5d3SJohn Marino if (dirmask & EAST) {
101986d7f5d3SJohn Marino count--;
102086d7f5d3SJohn Marino nbp = create_shot(bp->b_type, bp->b_y, bp->b_x + 1, RIGHT,
102186d7f5d3SJohn Marino (count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
102286d7f5d3SJohn Marino bp->b_score, TRUE, SPACE);
102386d7f5d3SJohn Marino move_slime(nbp, speed - 1, next);
102486d7f5d3SJohn Marino }
102586d7f5d3SJohn Marino if (dirmask & NORTH) {
102686d7f5d3SJohn Marino count--;
102786d7f5d3SJohn Marino nbp = create_shot(bp->b_type, bp->b_y - 1, bp->b_x, ABOVE,
102886d7f5d3SJohn Marino (count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
102986d7f5d3SJohn Marino bp->b_score, TRUE, SPACE);
103086d7f5d3SJohn Marino move_slime(nbp, speed - 1, next);
103186d7f5d3SJohn Marino }
103286d7f5d3SJohn Marino if (dirmask & SOUTH) {
103386d7f5d3SJohn Marino count--;
103486d7f5d3SJohn Marino nbp = create_shot(bp->b_type, bp->b_y + 1, bp->b_x, BELOW,
103586d7f5d3SJohn Marino (count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
103686d7f5d3SJohn Marino bp->b_score, TRUE, SPACE);
103786d7f5d3SJohn Marino move_slime(nbp, speed - 1, next);
103886d7f5d3SJohn Marino }
103986d7f5d3SJohn Marino
104086d7f5d3SJohn Marino free(bp);
104186d7f5d3SJohn Marino }
104286d7f5d3SJohn Marino
104386d7f5d3SJohn Marino /*
104486d7f5d3SJohn Marino * iswall:
104586d7f5d3SJohn Marino * returns whether the given location is a wall
104686d7f5d3SJohn Marino */
104786d7f5d3SJohn Marino static int
iswall(int y,int x)104886d7f5d3SJohn Marino iswall(int y, int x)
104986d7f5d3SJohn Marino {
105086d7f5d3SJohn Marino if (y < 0 || x < 0 || y >= HEIGHT || x >= WIDTH)
105186d7f5d3SJohn Marino return TRUE;
105286d7f5d3SJohn Marino switch (Maze[y][x]) {
105386d7f5d3SJohn Marino case WALL1:
105486d7f5d3SJohn Marino case WALL2:
105586d7f5d3SJohn Marino case WALL3:
105686d7f5d3SJohn Marino case WALL4:
105786d7f5d3SJohn Marino case WALL5:
105886d7f5d3SJohn Marino case DOOR:
105986d7f5d3SJohn Marino case SLIME:
106086d7f5d3SJohn Marino case LAVA:
106186d7f5d3SJohn Marino return TRUE;
106286d7f5d3SJohn Marino }
106386d7f5d3SJohn Marino return FALSE;
106486d7f5d3SJohn Marino }
106586d7f5d3SJohn Marino
106686d7f5d3SJohn Marino /*
106786d7f5d3SJohn Marino * zapshot:
106886d7f5d3SJohn Marino * Take a shot out of the air.
106986d7f5d3SJohn Marino */
107086d7f5d3SJohn Marino static void
zapshot(BULLET * blist,BULLET * obp)107186d7f5d3SJohn Marino zapshot(BULLET *blist, BULLET *obp)
107286d7f5d3SJohn Marino {
107386d7f5d3SJohn Marino BULLET *bp;
107486d7f5d3SJohn Marino
107586d7f5d3SJohn Marino for (bp = blist; bp != NULL; bp = bp->b_next) {
107686d7f5d3SJohn Marino /* Find co-located bullets not facing the same way: */
107786d7f5d3SJohn Marino if (bp->b_face != obp->b_face
107886d7f5d3SJohn Marino && bp->b_x == obp->b_x && bp->b_y == obp->b_y)
107986d7f5d3SJohn Marino {
108086d7f5d3SJohn Marino /* Bullet collision: */
108186d7f5d3SJohn Marino explshot(blist, obp->b_y, obp->b_x);
108286d7f5d3SJohn Marino return;
108386d7f5d3SJohn Marino }
108486d7f5d3SJohn Marino }
108586d7f5d3SJohn Marino }
108686d7f5d3SJohn Marino
108786d7f5d3SJohn Marino /*
108886d7f5d3SJohn Marino * explshot -
108986d7f5d3SJohn Marino * Make all shots at this location blow up
109086d7f5d3SJohn Marino */
109186d7f5d3SJohn Marino static void
explshot(BULLET * blist,int y,int x)109286d7f5d3SJohn Marino explshot(BULLET *blist, int y, int x)
109386d7f5d3SJohn Marino {
109486d7f5d3SJohn Marino BULLET *bp;
109586d7f5d3SJohn Marino
109686d7f5d3SJohn Marino for (bp = blist; bp != NULL; bp = bp->b_next)
109786d7f5d3SJohn Marino if (bp->b_x == x && bp->b_y == y) {
109886d7f5d3SJohn Marino bp->b_expl = TRUE;
109986d7f5d3SJohn Marino if (bp->b_owner != NULL)
110086d7f5d3SJohn Marino message(bp->b_owner, "Shot intercepted.");
110186d7f5d3SJohn Marino }
110286d7f5d3SJohn Marino }
110386d7f5d3SJohn Marino
110486d7f5d3SJohn Marino /*
110586d7f5d3SJohn Marino * play_at:
110686d7f5d3SJohn Marino * Return a pointer to the player at the given location
110786d7f5d3SJohn Marino */
110886d7f5d3SJohn Marino PLAYER *
play_at(int y,int x)110986d7f5d3SJohn Marino play_at(int y, int x)
111086d7f5d3SJohn Marino {
111186d7f5d3SJohn Marino PLAYER *pp;
111286d7f5d3SJohn Marino
111386d7f5d3SJohn Marino for (pp = Player; pp < End_player; pp++)
111486d7f5d3SJohn Marino if (pp->p_x == x && pp->p_y == y)
111586d7f5d3SJohn Marino return pp;
111686d7f5d3SJohn Marino
111786d7f5d3SJohn Marino /* Internal fault: */
111886d7f5d3SJohn Marino logx(LOG_ERR, "play_at: not a player");
111986d7f5d3SJohn Marino abort();
112086d7f5d3SJohn Marino }
112186d7f5d3SJohn Marino
112286d7f5d3SJohn Marino /*
112386d7f5d3SJohn Marino * opposite:
112486d7f5d3SJohn Marino * Return TRUE if the bullet direction faces the opposite direction
112586d7f5d3SJohn Marino * of the player in the maze
112686d7f5d3SJohn Marino */
112786d7f5d3SJohn Marino int
opposite(int face,char dir)112886d7f5d3SJohn Marino opposite(int face, char dir)
112986d7f5d3SJohn Marino {
113086d7f5d3SJohn Marino switch (face) {
113186d7f5d3SJohn Marino case LEFTS:
113286d7f5d3SJohn Marino return (dir == RIGHT);
113386d7f5d3SJohn Marino case RIGHT:
113486d7f5d3SJohn Marino return (dir == LEFTS);
113586d7f5d3SJohn Marino case ABOVE:
113686d7f5d3SJohn Marino return (dir == BELOW);
113786d7f5d3SJohn Marino case BELOW:
113886d7f5d3SJohn Marino return (dir == ABOVE);
113986d7f5d3SJohn Marino default:
114086d7f5d3SJohn Marino return FALSE;
114186d7f5d3SJohn Marino }
114286d7f5d3SJohn Marino }
114386d7f5d3SJohn Marino
114486d7f5d3SJohn Marino /*
114586d7f5d3SJohn Marino * is_bullet:
114686d7f5d3SJohn Marino * Is there a bullet at the given coordinates? If so, return
114786d7f5d3SJohn Marino * a pointer to the bullet, otherwise return NULL
114886d7f5d3SJohn Marino */
114986d7f5d3SJohn Marino BULLET *
is_bullet(int y,int x)115086d7f5d3SJohn Marino is_bullet(int y, int x)
115186d7f5d3SJohn Marino {
115286d7f5d3SJohn Marino BULLET *bp;
115386d7f5d3SJohn Marino
115486d7f5d3SJohn Marino for (bp = Bullets; bp != NULL; bp = bp->b_next)
115586d7f5d3SJohn Marino if (bp->b_y == y && bp->b_x == x)
115686d7f5d3SJohn Marino return bp;
115786d7f5d3SJohn Marino return NULL;
115886d7f5d3SJohn Marino }
115986d7f5d3SJohn Marino
116086d7f5d3SJohn Marino /*
116186d7f5d3SJohn Marino * fixshots:
116286d7f5d3SJohn Marino * change the underlying character of the shots at a location
116386d7f5d3SJohn Marino * to the given character.
116486d7f5d3SJohn Marino */
116586d7f5d3SJohn Marino void
fixshots(int y,int x,char over)116686d7f5d3SJohn Marino fixshots(int y, int x, char over)
116786d7f5d3SJohn Marino {
116886d7f5d3SJohn Marino BULLET *bp;
116986d7f5d3SJohn Marino
117086d7f5d3SJohn Marino for (bp = Bullets; bp != NULL; bp = bp->b_next)
117186d7f5d3SJohn Marino if (bp->b_y == y && bp->b_x == x)
117286d7f5d3SJohn Marino bp->b_over = over;
117386d7f5d3SJohn Marino }
117486d7f5d3SJohn Marino
117586d7f5d3SJohn Marino /*
117686d7f5d3SJohn Marino * find_under:
117786d7f5d3SJohn Marino * find the underlying character for a bullet when it lands
117886d7f5d3SJohn Marino * on another bullet.
117986d7f5d3SJohn Marino */
118086d7f5d3SJohn Marino static void
find_under(BULLET * blist,BULLET * bp)118186d7f5d3SJohn Marino find_under(BULLET *blist, BULLET *bp)
118286d7f5d3SJohn Marino {
118386d7f5d3SJohn Marino BULLET *nbp;
118486d7f5d3SJohn Marino
118586d7f5d3SJohn Marino for (nbp = blist; nbp != NULL; nbp = nbp->b_next)
118686d7f5d3SJohn Marino if (bp->b_y == nbp->b_y && bp->b_x == nbp->b_x) {
118786d7f5d3SJohn Marino bp->b_over = nbp->b_over;
118886d7f5d3SJohn Marino break;
118986d7f5d3SJohn Marino }
119086d7f5d3SJohn Marino }
119186d7f5d3SJohn Marino
119286d7f5d3SJohn Marino /*
119386d7f5d3SJohn Marino * mark_player:
119486d7f5d3SJohn Marino * mark a player as under a shot
119586d7f5d3SJohn Marino */
119686d7f5d3SJohn Marino static void
mark_player(BULLET * bp)119786d7f5d3SJohn Marino mark_player(BULLET *bp)
119886d7f5d3SJohn Marino {
119986d7f5d3SJohn Marino PLAYER *pp;
120086d7f5d3SJohn Marino
120186d7f5d3SJohn Marino for (pp = Player; pp < End_player; pp++)
120286d7f5d3SJohn Marino if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) {
120386d7f5d3SJohn Marino pp->p_undershot = TRUE;
120486d7f5d3SJohn Marino break;
120586d7f5d3SJohn Marino }
120686d7f5d3SJohn Marino }
120786d7f5d3SJohn Marino
120886d7f5d3SJohn Marino /*
120986d7f5d3SJohn Marino * mark_boot:
121086d7f5d3SJohn Marino * mark a boot as under a shot
121186d7f5d3SJohn Marino */
121286d7f5d3SJohn Marino static void
mark_boot(BULLET * bp)121386d7f5d3SJohn Marino mark_boot(BULLET *bp)
121486d7f5d3SJohn Marino {
121586d7f5d3SJohn Marino PLAYER *pp;
121686d7f5d3SJohn Marino
121786d7f5d3SJohn Marino for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
121886d7f5d3SJohn Marino if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) {
121986d7f5d3SJohn Marino pp->p_undershot = TRUE;
122086d7f5d3SJohn Marino break;
122186d7f5d3SJohn Marino }
122286d7f5d3SJohn Marino }
1223