Home | History | Annotate | Line # | Download | only in huntd
shots.c revision 1.12.2.1
      1  1.12.2.1      yamt /*	$NetBSD: shots.c,v 1.12.2.1 2014/05/22 11:36:23 yamt 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.4       wiz  *
      6       1.4       wiz  * Redistribution and use in source and binary forms, with or without
      7       1.4       wiz  * modification, are permitted provided that the following conditions are
      8       1.4       wiz  * met:
      9       1.4       wiz  *
     10       1.4       wiz  * + Redistributions of source code must retain the above copyright
     11       1.4       wiz  *   notice, this list of conditions and the following disclaimer.
     12       1.4       wiz  * + Redistributions in binary form must reproduce the above copyright
     13       1.4       wiz  *   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.4       wiz  * + Neither the name of the University of California, San Francisco nor
     16       1.4       wiz  *   the names of its contributors may be used to endorse or promote
     17       1.4       wiz  *   products derived from this software without specific prior written
     18       1.4       wiz  *   permission.
     19       1.4       wiz  *
     20       1.4       wiz  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     21       1.4       wiz  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22       1.4       wiz  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     23       1.4       wiz  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24       1.4       wiz  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25       1.4       wiz  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26       1.4       wiz  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27       1.4       wiz  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28       1.4       wiz  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29       1.4       wiz  * (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.12.2.1      yamt __RCSID("$NetBSD: shots.c,v 1.12.2.1 2014/05/22 11:36:23 yamt 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.12.2.1      yamt 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.12.2.1      yamt 				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.1       mrg 			/* FALLTHROUGH */
    351      1.10  dholland #ifndef RANDOM
    352       1.1       mrg 		  case DOOR:
    353      1.10  dholland #endif
    354       1.1       mrg 		  case WALL1:
    355       1.1       mrg 		  case WALL2:
    356       1.1       mrg 		  case WALL3:
    357  1.12.2.1      yamt 			bp->b_expl = true;
    358       1.1       mrg 			break;
    359       1.1       mrg 		}
    360       1.1       mrg 
    361       1.1       mrg 		bp->b_x = x;
    362       1.1       mrg 		bp->b_y = y;
    363       1.1       mrg 	}
    364  1.12.2.1      yamt 	return true;
    365       1.1       mrg }
    366       1.1       mrg 
    367      1.10  dholland #ifdef DRONE
    368       1.1       mrg /*
    369       1.1       mrg  * move_drone:
    370       1.1       mrg  *	Move the drone to the next square
    371       1.1       mrg  */
    372       1.2     lukem static void
    373       1.9  dholland move_drone(BULLET *bp)
    374       1.1       mrg {
    375      1.10  dholland 	int mask, count;
    376      1.10  dholland 	int n, dir;
    377      1.10  dholland 	PLAYER *pp;
    378       1.1       mrg 
    379       1.1       mrg 	/*
    380       1.1       mrg 	 * See if we can give someone a blast
    381       1.1       mrg 	 */
    382       1.1       mrg 	if (isplayer(Maze[bp->b_y][bp->b_x - 1])) {
    383       1.1       mrg 		dir = WEST;
    384       1.1       mrg 		goto drone_move;
    385       1.1       mrg 	}
    386       1.1       mrg 	if (isplayer(Maze[bp->b_y - 1][bp->b_x])) {
    387       1.1       mrg 		dir = NORTH;
    388       1.1       mrg 		goto drone_move;
    389       1.1       mrg 	}
    390       1.1       mrg 	if (isplayer(Maze[bp->b_y + 1][bp->b_x])) {
    391       1.1       mrg 		dir = SOUTH;
    392       1.1       mrg 		goto drone_move;
    393       1.1       mrg 	}
    394       1.1       mrg 	if (isplayer(Maze[bp->b_y][bp->b_x + 1])) {
    395       1.1       mrg 		dir = EAST;
    396       1.1       mrg 		goto drone_move;
    397       1.1       mrg 	}
    398       1.1       mrg 
    399       1.1       mrg 	/*
    400       1.1       mrg 	 * Find out what directions are clear
    401       1.1       mrg 	 */
    402       1.1       mrg 	mask = count = 0;
    403       1.1       mrg 	if (!iswall(bp->b_y, bp->b_x - 1))
    404       1.1       mrg 		mask |= WEST, count++;
    405       1.1       mrg 	if (!iswall(bp->b_y - 1, bp->b_x))
    406       1.1       mrg 		mask |= NORTH, count++;
    407       1.1       mrg 	if (!iswall(bp->b_y + 1, bp->b_x))
    408       1.1       mrg 		mask |= SOUTH, count++;
    409       1.1       mrg 	if (!iswall(bp->b_y, bp->b_x + 1))
    410       1.1       mrg 		mask |= EAST, count++;
    411       1.1       mrg 
    412       1.1       mrg 	/*
    413       1.1       mrg 	 * All blocked up, just you wait
    414       1.1       mrg 	 */
    415       1.1       mrg 	if (count == 0)
    416  1.12.2.1      yamt 		return true;
    417       1.1       mrg 
    418       1.1       mrg 	/*
    419       1.1       mrg 	 * Only one way to go.
    420       1.1       mrg 	 */
    421       1.1       mrg 	if (count == 1) {
    422       1.1       mrg 		dir = mask;
    423       1.1       mrg 		goto drone_move;
    424       1.1       mrg 	}
    425       1.1       mrg 
    426       1.1       mrg 	/*
    427       1.1       mrg 	 * Get rid of the direction that we came from
    428       1.1       mrg 	 */
    429       1.1       mrg 	switch (bp->b_face) {
    430       1.1       mrg 	  case LEFTS:
    431       1.1       mrg 		if (mask & EAST)
    432       1.1       mrg 			mask &= ~EAST, count--;
    433       1.1       mrg 		break;
    434       1.1       mrg 	  case RIGHT:
    435       1.1       mrg 		if (mask & WEST)
    436       1.1       mrg 			mask &= ~WEST, count--;
    437       1.1       mrg 		break;
    438       1.1       mrg 	  case ABOVE:
    439       1.1       mrg 		if (mask & SOUTH)
    440       1.1       mrg 			mask &= ~SOUTH, count--;
    441       1.1       mrg 		break;
    442       1.1       mrg 	  case BELOW:
    443       1.1       mrg 		if (mask & NORTH)
    444       1.1       mrg 			mask &= ~NORTH, count--;
    445       1.1       mrg 		break;
    446       1.1       mrg 	}
    447       1.1       mrg 
    448       1.1       mrg 	/*
    449       1.1       mrg 	 * Pick one of the remaining directions
    450       1.1       mrg 	 */
    451       1.1       mrg 	n = rand_num(count);
    452       1.1       mrg 	if (n >= 0 && mask & NORTH)
    453       1.1       mrg 		dir = NORTH, n--;
    454       1.1       mrg 	if (n >= 0 && mask & SOUTH)
    455       1.1       mrg 		dir = SOUTH, n--;
    456       1.1       mrg 	if (n >= 0 && mask & EAST)
    457       1.1       mrg 		dir = EAST, n--;
    458       1.1       mrg 	if (n >= 0 && mask & WEST)
    459       1.1       mrg 		dir = WEST, n--;
    460       1.1       mrg 
    461       1.1       mrg 	/*
    462       1.1       mrg 	 * Now that we know the direction of movement,
    463       1.1       mrg 	 * just update the position of the drone
    464       1.1       mrg 	 */
    465       1.1       mrg drone_move:
    466       1.1       mrg 	switch (dir) {
    467       1.1       mrg 	  case WEST:
    468       1.1       mrg 		bp->b_x--;
    469       1.1       mrg 		bp->b_face = LEFTS;
    470       1.1       mrg 		break;
    471       1.1       mrg 	  case EAST:
    472       1.1       mrg 		bp->b_x++;
    473       1.1       mrg 		bp->b_face = RIGHT;
    474       1.1       mrg 		break;
    475       1.1       mrg 	  case NORTH:
    476       1.1       mrg 		bp->b_y--;
    477       1.1       mrg 		bp->b_face = ABOVE;
    478       1.1       mrg 		break;
    479       1.1       mrg 	  case SOUTH:
    480       1.1       mrg 		bp->b_y++;
    481       1.1       mrg 		bp->b_face = BELOW;
    482       1.1       mrg 		break;
    483       1.1       mrg 	}
    484       1.1       mrg 	switch (Maze[bp->b_y][bp->b_x]) {
    485       1.1       mrg 	  case LEFTS:
    486       1.1       mrg 	  case RIGHT:
    487       1.1       mrg 	  case BELOW:
    488       1.1       mrg 	  case ABOVE:
    489       1.1       mrg 		/*
    490       1.1       mrg 		 * give the person a chance to catch a
    491       1.1       mrg 		 * drone if s/he is facing it
    492       1.1       mrg 		 */
    493       1.1       mrg 		if (rand_num(100) < 1 &&
    494       1.1       mrg 		opposite(bp->b_face, Maze[bp->b_y][bp->b_x])) {
    495       1.1       mrg 			pp = play_at(bp->b_y, bp->b_x);
    496       1.1       mrg 			pp->p_ammo += bp->b_charge;
    497       1.1       mrg 			message(pp, "**** Absorbed drone ****");
    498       1.8  dholland 			free(bp);
    499       1.7  dholland 			(void) snprintf(Buf, sizeof(buf), "%3d", pp->p_ammo);
    500       1.1       mrg 			cgoto(pp, STAT_AMMO_ROW, STAT_VALUE_COL);
    501       1.1       mrg 			outstr(pp, Buf, 3);
    502  1.12.2.1      yamt 			return false;
    503       1.1       mrg 		}
    504  1.12.2.1      yamt 		bp->b_expl = true;
    505       1.1       mrg 		break;
    506       1.1       mrg 	}
    507  1.12.2.1      yamt 	return true;
    508       1.1       mrg }
    509      1.10  dholland #endif
    510       1.1       mrg 
    511       1.1       mrg /*
    512       1.1       mrg  * save_bullet:
    513       1.1       mrg  *	Put this bullet back onto the bullet list
    514       1.1       mrg  */
    515       1.2     lukem static void
    516       1.9  dholland save_bullet(BULLET *bp)
    517       1.1       mrg {
    518       1.1       mrg 	bp->b_over = Maze[bp->b_y][bp->b_x];
    519       1.1       mrg 	switch (bp->b_over) {
    520       1.1       mrg 	  case SHOT:
    521       1.1       mrg 	  case GRENADE:
    522       1.1       mrg 	  case SATCHEL:
    523       1.1       mrg 	  case BOMB:
    524      1.10  dholland #ifdef OOZE
    525       1.1       mrg 	  case SLIME:
    526      1.10  dholland #ifdef VOLCANO
    527       1.1       mrg 	  case LAVA:
    528      1.10  dholland #endif
    529      1.10  dholland #endif
    530      1.10  dholland #ifdef DRONE
    531       1.1       mrg 	  case DSHOT:
    532      1.10  dholland #endif
    533       1.1       mrg 		find_under(Bullets, bp);
    534       1.1       mrg 		break;
    535       1.1       mrg 	}
    536       1.1       mrg 
    537       1.1       mrg 	switch (bp->b_over) {
    538       1.1       mrg 	  case LEFTS:
    539       1.1       mrg 	  case RIGHT:
    540       1.1       mrg 	  case ABOVE:
    541       1.1       mrg 	  case BELOW:
    542      1.10  dholland #ifdef FLY
    543       1.1       mrg 	  case FLYER:
    544      1.10  dholland #endif
    545       1.1       mrg 		mark_player(bp);
    546       1.1       mrg 		break;
    547      1.10  dholland #ifdef BOOTS
    548       1.1       mrg 	  case BOOT:
    549       1.1       mrg 	  case BOOT_PAIR:
    550       1.1       mrg 		mark_boot(bp);
    551      1.10  dholland #endif
    552      1.11  dholland 
    553       1.1       mrg 	  default:
    554       1.1       mrg 		Maze[bp->b_y][bp->b_x] = bp->b_type;
    555       1.1       mrg 		break;
    556       1.1       mrg 	}
    557       1.1       mrg 
    558       1.1       mrg 	bp->b_next = Bullets;
    559       1.1       mrg 	Bullets = bp;
    560       1.1       mrg }
    561       1.1       mrg 
    562       1.1       mrg /*
    563       1.1       mrg  * move_flyer:
    564       1.1       mrg  *	Update the position of a player in flight
    565       1.1       mrg  */
    566       1.2     lukem static void
    567       1.9  dholland move_flyer(PLAYER *pp)
    568       1.1       mrg {
    569      1.10  dholland 	int x, y;
    570       1.1       mrg 
    571       1.1       mrg 	if (pp->p_undershot) {
    572       1.1       mrg 		fixshots(pp->p_y, pp->p_x, pp->p_over);
    573  1.12.2.1      yamt 		pp->p_undershot = false;
    574       1.1       mrg 	}
    575       1.1       mrg 	Maze[pp->p_y][pp->p_x] = pp->p_over;
    576       1.1       mrg 	x = pp->p_x + pp->p_flyx;
    577       1.1       mrg 	y = pp->p_y + pp->p_flyy;
    578       1.1       mrg 	if (x < 1) {
    579       1.1       mrg 		x = 1 - x;
    580       1.1       mrg 		pp->p_flyx = -pp->p_flyx;
    581       1.1       mrg 	}
    582       1.1       mrg 	else if (x > WIDTH - 2) {
    583       1.1       mrg 		x = (WIDTH - 2) - (x - (WIDTH - 2));
    584       1.1       mrg 		pp->p_flyx = -pp->p_flyx;
    585       1.1       mrg 	}
    586       1.1       mrg 	if (y < 1) {
    587       1.1       mrg 		y = 1 - y;
    588       1.1       mrg 		pp->p_flyy = -pp->p_flyy;
    589       1.1       mrg 	}
    590       1.1       mrg 	else if (y > HEIGHT - 2) {
    591       1.1       mrg 		y = (HEIGHT - 2) - (y - (HEIGHT - 2));
    592       1.1       mrg 		pp->p_flyy = -pp->p_flyy;
    593       1.1       mrg 	}
    594       1.1       mrg again:
    595       1.1       mrg 	switch (Maze[y][x]) {
    596       1.1       mrg 	  default:
    597       1.1       mrg 		switch (rand_num(4)) {
    598       1.1       mrg 		  case 0:
    599       1.1       mrg 			PLUS_DELTA(x, WIDTH - 2);
    600       1.1       mrg 			break;
    601       1.1       mrg 		  case 1:
    602       1.1       mrg 			MINUS_DELTA(x, 1);
    603       1.1       mrg 			break;
    604       1.1       mrg 		  case 2:
    605       1.1       mrg 			PLUS_DELTA(y, HEIGHT - 2);
    606       1.1       mrg 			break;
    607       1.1       mrg 		  case 3:
    608       1.1       mrg 			MINUS_DELTA(y, 1);
    609       1.1       mrg 			break;
    610       1.1       mrg 		}
    611       1.1       mrg 		goto again;
    612       1.1       mrg 	  case WALL1:
    613       1.1       mrg 	  case WALL2:
    614       1.1       mrg 	  case WALL3:
    615      1.10  dholland #ifdef REFLECT
    616       1.1       mrg 	  case WALL4:
    617       1.1       mrg 	  case WALL5:
    618      1.10  dholland #endif
    619      1.10  dholland #ifdef RANDOM
    620       1.1       mrg 	  case DOOR:
    621      1.10  dholland #endif
    622       1.1       mrg 		if (pp->p_flying == 0)
    623       1.1       mrg 			pp->p_flying++;
    624       1.1       mrg 		break;
    625       1.1       mrg 	  case SPACE:
    626       1.1       mrg 		break;
    627       1.1       mrg 	}
    628       1.1       mrg 	pp->p_y = y;
    629       1.1       mrg 	pp->p_x = x;
    630       1.1       mrg 	if (pp->p_flying-- == 0) {
    631      1.10  dholland #ifdef BOOTS
    632       1.1       mrg 		if (pp->p_face != BOOT && pp->p_face != BOOT_PAIR) {
    633      1.10  dholland #endif
    634      1.12    plunky 			checkdam(pp, NULL, NULL,
    635       1.1       mrg 				rand_num(pp->p_damage / 5), FALL);
    636       1.1       mrg 			pp->p_face = rand_dir();
    637       1.1       mrg 			showstat(pp);
    638      1.10  dholland #ifdef BOOTS
    639       1.1       mrg 		}
    640       1.1       mrg 		else {
    641       1.1       mrg 			if (Maze[y][x] == BOOT)
    642       1.1       mrg 				pp->p_face = BOOT_PAIR;
    643       1.1       mrg 			Maze[y][x] = SPACE;
    644       1.1       mrg 		}
    645      1.10  dholland #endif
    646       1.1       mrg 	}
    647       1.1       mrg 	pp->p_over = Maze[y][x];
    648       1.1       mrg 	Maze[y][x] = pp->p_face;
    649       1.1       mrg 	showexpl(y, x, pp->p_face);
    650       1.1       mrg }
    651       1.1       mrg 
    652       1.1       mrg /*
    653       1.1       mrg  * chkshot
    654       1.1       mrg  *	Handle explosions
    655       1.1       mrg  */
    656       1.2     lukem static void
    657       1.9  dholland chkshot(BULLET *bp, BULLET *next)
    658       1.1       mrg {
    659      1.10  dholland 	int y, x;
    660      1.10  dholland 	int dy, dx, absdy;
    661      1.10  dholland 	int delta, damage;
    662      1.10  dholland 	char expl;
    663      1.10  dholland 	PLAYER *pp;
    664       1.1       mrg 
    665       1.2     lukem 	delta = 0;
    666       1.1       mrg 	switch (bp->b_type) {
    667       1.1       mrg 	  case SHOT:
    668       1.1       mrg 	  case MINE:
    669       1.1       mrg 	  case GRENADE:
    670       1.1       mrg 	  case GMINE:
    671       1.1       mrg 	  case SATCHEL:
    672       1.1       mrg 	  case BOMB:
    673       1.1       mrg 		delta = bp->b_size - 1;
    674       1.1       mrg 		break;
    675      1.10  dholland #ifdef OOZE
    676       1.1       mrg 	  case SLIME:
    677      1.10  dholland #ifdef VOLCANO
    678       1.1       mrg 	  case LAVA:
    679      1.10  dholland #endif
    680       1.1       mrg 		chkslime(bp, next);
    681       1.1       mrg 		return;
    682      1.10  dholland #endif
    683      1.10  dholland #ifdef DRONE
    684       1.1       mrg 	  case DSHOT:
    685       1.1       mrg 		bp->b_type = SLIME;
    686       1.1       mrg 		chkslime(bp, next);
    687       1.1       mrg 		return;
    688      1.10  dholland #endif
    689       1.1       mrg 	}
    690       1.1       mrg 	for (y = bp->b_y - delta; y <= bp->b_y + delta; y++) {
    691       1.1       mrg 		if (y < 0 || y >= HEIGHT)
    692       1.1       mrg 			continue;
    693       1.1       mrg 		dy = y - bp->b_y;
    694       1.1       mrg 		absdy = (dy < 0) ? -dy : dy;
    695       1.1       mrg 		for (x = bp->b_x - delta; x <= bp->b_x + delta; x++) {
    696       1.1       mrg 			if (x < 0 || x >= WIDTH)
    697       1.1       mrg 				continue;
    698       1.1       mrg 			dx = x - bp->b_x;
    699       1.1       mrg 			if (dx == 0)
    700       1.1       mrg 				expl = (dy == 0) ? '*' : '|';
    701       1.1       mrg 			else if (dy == 0)
    702       1.1       mrg 				expl = '-';
    703       1.1       mrg 			else if (dx == dy)
    704       1.1       mrg 				expl = '\\';
    705       1.1       mrg 			else if (dx == -dy)
    706       1.1       mrg 				expl = '/';
    707       1.1       mrg 			else
    708       1.1       mrg 				expl = '*';
    709       1.1       mrg 			showexpl(y, x, expl);
    710       1.1       mrg 			switch (Maze[y][x]) {
    711       1.1       mrg 			  case LEFTS:
    712       1.1       mrg 			  case RIGHT:
    713       1.1       mrg 			  case ABOVE:
    714       1.1       mrg 			  case BELOW:
    715      1.10  dholland #ifdef FLY
    716       1.1       mrg 			  case FLYER:
    717      1.10  dholland #endif
    718       1.1       mrg 				if (dx < 0)
    719       1.1       mrg 					dx = -dx;
    720       1.1       mrg 				if (absdy > dx)
    721       1.1       mrg 					damage = bp->b_size - absdy;
    722       1.1       mrg 				else
    723       1.1       mrg 					damage = bp->b_size - dx;
    724       1.1       mrg 				pp = play_at(y, x);
    725       1.1       mrg 				checkdam(pp, bp->b_owner, bp->b_score,
    726       1.1       mrg 					damage * MINDAM, bp->b_type);
    727       1.1       mrg 				break;
    728       1.1       mrg 			  case GMINE:
    729       1.1       mrg 			  case MINE:
    730       1.1       mrg 				add_shot((Maze[y][x] == GMINE) ?
    731       1.1       mrg 					GRENADE : SHOT,
    732       1.1       mrg 					y, x, LEFTS,
    733       1.1       mrg 					(Maze[y][x] == GMINE) ?
    734       1.1       mrg 					GRENREQ : BULREQ,
    735  1.12.2.1      yamt 					NULL, true, SPACE);
    736       1.1       mrg 				Maze[y][x] = SPACE;
    737       1.1       mrg 				break;
    738       1.1       mrg 			}
    739       1.1       mrg 		}
    740       1.1       mrg 	}
    741       1.1       mrg }
    742       1.1       mrg 
    743      1.10  dholland #ifdef OOZE
    744       1.1       mrg /*
    745       1.1       mrg  * chkslime:
    746       1.1       mrg  *	handle slime shot exploding
    747       1.1       mrg  */
    748       1.2     lukem static void
    749       1.9  dholland chkslime(BULLET *bp, BULLET *next)
    750       1.1       mrg {
    751       1.2     lukem 	BULLET	*nbp;
    752       1.1       mrg 
    753       1.1       mrg 	switch (Maze[bp->b_y][bp->b_x]) {
    754       1.1       mrg 	  case WALL1:
    755       1.1       mrg 	  case WALL2:
    756       1.1       mrg 	  case WALL3:
    757      1.10  dholland #ifdef REFLECT
    758       1.1       mrg 	  case WALL4:
    759       1.1       mrg 	  case WALL5:
    760      1.10  dholland #endif
    761      1.10  dholland #ifdef RANDOM
    762       1.1       mrg 	  case DOOR:
    763      1.10  dholland #endif
    764       1.1       mrg 		switch (bp->b_face) {
    765       1.1       mrg 		  case LEFTS:
    766       1.1       mrg 			bp->b_x++;
    767       1.1       mrg 			break;
    768       1.1       mrg 		  case RIGHT:
    769       1.1       mrg 			bp->b_x--;
    770       1.1       mrg 			break;
    771       1.1       mrg 		  case ABOVE:
    772       1.1       mrg 			bp->b_y++;
    773       1.1       mrg 			break;
    774       1.1       mrg 		  case BELOW:
    775       1.1       mrg 			bp->b_y--;
    776       1.1       mrg 			break;
    777       1.1       mrg 		}
    778       1.1       mrg 		break;
    779       1.1       mrg 	}
    780       1.8  dholland 	nbp = malloc(sizeof(*nbp));
    781       1.1       mrg 	*nbp = *bp;
    782      1.10  dholland #ifdef VOLCANO
    783       1.1       mrg 	move_slime(nbp, nbp->b_type == SLIME ? SLIMESPEED : LAVASPEED, next);
    784      1.10  dholland #else
    785       1.1       mrg 	move_slime(nbp, SLIMESPEED, next);
    786      1.10  dholland #endif
    787       1.1       mrg }
    788       1.1       mrg 
    789       1.1       mrg /*
    790       1.1       mrg  * move_slime:
    791       1.1       mrg  *	move the given slime shot speed times and add it back if
    792       1.1       mrg  *	it hasn't fizzled yet
    793       1.1       mrg  */
    794  1.12.2.1      yamt static void
    795       1.9  dholland move_slime(BULLET *bp, int speed, BULLET *next)
    796       1.1       mrg {
    797      1.10  dholland 	int i, j, dirmask, count;
    798      1.10  dholland 	PLAYER *pp;
    799      1.10  dholland 	BULLET *nbp;
    800       1.1       mrg 
    801       1.1       mrg 	if (speed == 0) {
    802       1.1       mrg 		if (bp->b_charge <= 0)
    803       1.8  dholland 			free(bp);
    804       1.1       mrg 		else
    805       1.1       mrg 			save_bullet(bp);
    806       1.1       mrg 		return;
    807       1.1       mrg 	}
    808       1.1       mrg 
    809      1.10  dholland #ifdef VOLCANO
    810       1.1       mrg 	showexpl(bp->b_y, bp->b_x, bp->b_type == LAVA ? LAVA : '*');
    811      1.10  dholland #else
    812       1.1       mrg 	showexpl(bp->b_y, bp->b_x, '*');
    813      1.10  dholland #endif
    814       1.1       mrg 	switch (Maze[bp->b_y][bp->b_x]) {
    815       1.1       mrg 	  case LEFTS:
    816       1.1       mrg 	  case RIGHT:
    817       1.1       mrg 	  case ABOVE:
    818       1.1       mrg 	  case BELOW:
    819      1.10  dholland #ifdef FLY
    820       1.1       mrg 	  case FLYER:
    821      1.10  dholland #endif
    822       1.1       mrg 		pp = play_at(bp->b_y, bp->b_x);
    823       1.1       mrg 		message(pp, "You've been slimed.");
    824       1.1       mrg 		checkdam(pp, bp->b_owner, bp->b_score, MINDAM, bp->b_type);
    825       1.1       mrg 		break;
    826       1.1       mrg 	  case SHOT:
    827       1.1       mrg 	  case GRENADE:
    828       1.1       mrg 	  case SATCHEL:
    829       1.1       mrg 	  case BOMB:
    830      1.10  dholland #ifdef DRONE
    831       1.1       mrg 	  case DSHOT:
    832      1.10  dholland #endif
    833       1.1       mrg 		explshot(next, bp->b_y, bp->b_x);
    834       1.1       mrg 		explshot(Bullets, bp->b_y, bp->b_x);
    835       1.1       mrg 		break;
    836       1.1       mrg 	}
    837       1.1       mrg 
    838       1.1       mrg 	if (--bp->b_charge <= 0) {
    839       1.8  dholland 		free(bp);
    840       1.1       mrg 		return;
    841       1.1       mrg 	}
    842       1.1       mrg 
    843       1.1       mrg 	dirmask = 0;
    844       1.1       mrg 	count = 0;
    845       1.1       mrg 	switch (bp->b_face) {
    846       1.1       mrg 	  case LEFTS:
    847       1.1       mrg 		if (!iswall(bp->b_y, bp->b_x - 1))
    848       1.1       mrg 			dirmask |= WEST, count++;
    849       1.1       mrg 		if (!iswall(bp->b_y - 1, bp->b_x))
    850       1.1       mrg 			dirmask |= NORTH, count++;
    851       1.1       mrg 		if (!iswall(bp->b_y + 1, bp->b_x))
    852       1.1       mrg 			dirmask |= SOUTH, count++;
    853       1.1       mrg 		if (dirmask == 0)
    854       1.1       mrg 			if (!iswall(bp->b_y, bp->b_x + 1))
    855       1.1       mrg 				dirmask |= EAST, count++;
    856       1.1       mrg 		break;
    857       1.1       mrg 	  case RIGHT:
    858       1.1       mrg 		if (!iswall(bp->b_y, bp->b_x + 1))
    859       1.1       mrg 			dirmask |= EAST, count++;
    860       1.1       mrg 		if (!iswall(bp->b_y - 1, bp->b_x))
    861       1.1       mrg 			dirmask |= NORTH, count++;
    862       1.1       mrg 		if (!iswall(bp->b_y + 1, bp->b_x))
    863       1.1       mrg 			dirmask |= SOUTH, count++;
    864       1.1       mrg 		if (dirmask == 0)
    865       1.1       mrg 			if (!iswall(bp->b_y, bp->b_x - 1))
    866       1.1       mrg 				dirmask |= WEST, count++;
    867       1.1       mrg 		break;
    868       1.1       mrg 	  case ABOVE:
    869       1.1       mrg 		if (!iswall(bp->b_y - 1, bp->b_x))
    870       1.1       mrg 			dirmask |= NORTH, count++;
    871       1.1       mrg 		if (!iswall(bp->b_y, bp->b_x - 1))
    872       1.1       mrg 			dirmask |= WEST, count++;
    873       1.1       mrg 		if (!iswall(bp->b_y, bp->b_x + 1))
    874       1.1       mrg 			dirmask |= EAST, count++;
    875       1.1       mrg 		if (dirmask == 0)
    876       1.1       mrg 			if (!iswall(bp->b_y + 1, bp->b_x))
    877       1.1       mrg 				dirmask |= SOUTH, count++;
    878       1.1       mrg 		break;
    879       1.1       mrg 	  case BELOW:
    880       1.1       mrg 		if (!iswall(bp->b_y + 1, bp->b_x))
    881       1.1       mrg 			dirmask |= SOUTH, count++;
    882       1.1       mrg 		if (!iswall(bp->b_y, bp->b_x - 1))
    883       1.1       mrg 			dirmask |= WEST, count++;
    884       1.1       mrg 		if (!iswall(bp->b_y, bp->b_x + 1))
    885       1.1       mrg 			dirmask |= EAST, count++;
    886       1.1       mrg 		if (dirmask == 0)
    887       1.1       mrg 			if (!iswall(bp->b_y - 1, bp->b_x))
    888       1.1       mrg 				dirmask |= NORTH, count++;
    889       1.1       mrg 		break;
    890       1.1       mrg 	}
    891       1.1       mrg 	if (count == 0) {
    892       1.1       mrg 		/*
    893       1.1       mrg 		 * No place to go.  Just sit here for a while and wait
    894       1.1       mrg 		 * for adjacent squares to clear out.
    895       1.1       mrg 		 */
    896       1.1       mrg 		save_bullet(bp);
    897       1.1       mrg 		return;
    898       1.1       mrg 	}
    899       1.1       mrg 	if (bp->b_charge < count) {
    900       1.1       mrg 		/* Only bp->b_charge paths may be taken */
    901       1.1       mrg 		while (count > bp->b_charge) {
    902       1.1       mrg 			if (dirmask & WEST)
    903       1.1       mrg 				dirmask &= ~WEST;
    904       1.1       mrg 			else if (dirmask & EAST)
    905       1.1       mrg 				dirmask &= ~EAST;
    906       1.1       mrg 			else if (dirmask & NORTH)
    907       1.1       mrg 				dirmask &= ~NORTH;
    908       1.1       mrg 			else if (dirmask & SOUTH)
    909       1.1       mrg 				dirmask &= ~SOUTH;
    910       1.1       mrg 			count--;
    911       1.1       mrg 		}
    912       1.1       mrg 	}
    913       1.1       mrg 
    914       1.1       mrg 	i = bp->b_charge / count;
    915       1.1       mrg 	j = bp->b_charge % count;
    916       1.1       mrg 	if (dirmask & WEST) {
    917       1.1       mrg 		count--;
    918       1.1       mrg 		nbp = create_shot(bp->b_type, bp->b_y, bp->b_x - 1, LEFTS,
    919  1.12.2.1      yamt 			i, bp->b_size, bp->b_owner, bp->b_score, true, SPACE);
    920       1.1       mrg 		move_slime(nbp, speed - 1, next);
    921       1.1       mrg 	}
    922       1.1       mrg 	if (dirmask & EAST) {
    923       1.1       mrg 		count--;
    924       1.1       mrg 		nbp = create_shot(bp->b_type, bp->b_y, bp->b_x + 1, RIGHT,
    925       1.1       mrg 			(count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
    926  1.12.2.1      yamt 			bp->b_score, true, SPACE);
    927       1.1       mrg 		move_slime(nbp, speed - 1, next);
    928       1.1       mrg 	}
    929       1.1       mrg 	if (dirmask & NORTH) {
    930       1.1       mrg 		count--;
    931       1.1       mrg 		nbp = create_shot(bp->b_type, bp->b_y - 1, bp->b_x, ABOVE,
    932       1.1       mrg 			(count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
    933  1.12.2.1      yamt 			bp->b_score, true, SPACE);
    934       1.1       mrg 		move_slime(nbp, speed - 1, next);
    935       1.1       mrg 	}
    936       1.1       mrg 	if (dirmask & SOUTH) {
    937       1.1       mrg 		count--;
    938       1.1       mrg 		nbp = create_shot(bp->b_type, bp->b_y + 1, bp->b_x, BELOW,
    939       1.1       mrg 			(count < j) ? i + 1 : i, bp->b_size, bp->b_owner,
    940  1.12.2.1      yamt 			bp->b_score, true, SPACE);
    941       1.1       mrg 		move_slime(nbp, speed - 1, next);
    942       1.1       mrg 	}
    943       1.1       mrg 
    944       1.8  dholland 	free(bp);
    945       1.1       mrg }
    946       1.1       mrg 
    947       1.1       mrg /*
    948       1.1       mrg  * iswall:
    949       1.1       mrg  *	returns whether the given location is a wall
    950       1.1       mrg  */
    951  1.12.2.1      yamt static bool
    952       1.9  dholland iswall(int y, int x)
    953       1.1       mrg {
    954       1.1       mrg 	if (y < 0 || x < 0 || y >= HEIGHT || x >= WIDTH)
    955  1.12.2.1      yamt 		return true;
    956       1.1       mrg 	switch (Maze[y][x]) {
    957       1.1       mrg 	  case WALL1:
    958       1.1       mrg 	  case WALL2:
    959       1.1       mrg 	  case WALL3:
    960      1.10  dholland #ifdef REFLECT
    961       1.1       mrg 	  case WALL4:
    962       1.1       mrg 	  case WALL5:
    963      1.10  dholland #endif
    964      1.10  dholland #ifdef RANDOM
    965       1.1       mrg 	  case DOOR:
    966      1.10  dholland #endif
    967      1.10  dholland #ifdef OOZE
    968       1.1       mrg 	  case SLIME:
    969      1.10  dholland #ifdef VOLCANO
    970       1.1       mrg 	  case LAVA:
    971      1.10  dholland #endif
    972      1.10  dholland #endif
    973  1.12.2.1      yamt 		return true;
    974       1.1       mrg 	}
    975  1.12.2.1      yamt 	return false;
    976       1.1       mrg }
    977      1.10  dholland #endif
    978       1.1       mrg 
    979       1.1       mrg /*
    980       1.1       mrg  * zapshot:
    981       1.1       mrg  *	Take a shot out of the air.
    982       1.1       mrg  */
    983       1.2     lukem static void
    984       1.9  dholland zapshot(BULLET *blist, BULLET *obp)
    985       1.1       mrg {
    986      1.10  dholland 	BULLET *bp;
    987  1.12.2.1      yamt 	bool explode;
    988       1.1       mrg 
    989  1.12.2.1      yamt 	explode = false;
    990       1.1       mrg 	for (bp = blist; bp != NULL; bp = bp->b_next) {
    991       1.1       mrg 		if (bp->b_x != obp->b_x || bp->b_y != obp->b_y)
    992       1.1       mrg 			continue;
    993       1.1       mrg 		if (bp->b_face == obp->b_face)
    994       1.1       mrg 			continue;
    995  1.12.2.1      yamt 		explode = true;
    996       1.1       mrg 		break;
    997       1.1       mrg 	}
    998       1.1       mrg 	if (!explode)
    999       1.1       mrg 		return;
   1000       1.1       mrg 	explshot(blist, obp->b_y, obp->b_x);
   1001       1.1       mrg }
   1002       1.1       mrg 
   1003       1.1       mrg /*
   1004       1.1       mrg  * explshot -
   1005       1.1       mrg  *	Make all shots at this location blow up
   1006       1.1       mrg  */
   1007  1.12.2.1      yamt static void
   1008       1.9  dholland explshot(BULLET *blist, int y, int x)
   1009       1.1       mrg {
   1010      1.10  dholland 	BULLET *bp;
   1011       1.1       mrg 
   1012       1.1       mrg 	for (bp = blist; bp != NULL; bp = bp->b_next)
   1013       1.1       mrg 		if (bp->b_x == x && bp->b_y == y) {
   1014  1.12.2.1      yamt 			bp->b_expl = true;
   1015       1.1       mrg 			if (bp->b_owner != NULL)
   1016       1.1       mrg 				message(bp->b_owner, "Shot intercepted");
   1017       1.1       mrg 		}
   1018       1.1       mrg }
   1019       1.1       mrg 
   1020       1.1       mrg /*
   1021       1.1       mrg  * play_at:
   1022       1.1       mrg  *	Return a pointer to the player at the given location
   1023       1.1       mrg  */
   1024       1.1       mrg PLAYER *
   1025       1.9  dholland play_at(int y, int x)
   1026       1.1       mrg {
   1027      1.10  dholland 	PLAYER *pp;
   1028       1.1       mrg 
   1029       1.1       mrg 	for (pp = Player; pp < End_player; pp++)
   1030       1.1       mrg 		if (pp->p_x == x && pp->p_y == y)
   1031       1.1       mrg 			return pp;
   1032       1.3     lukem 	errx(1, "driver: couldn't find player at (%d,%d)", x, y);
   1033       1.1       mrg 	/* NOTREACHED */
   1034       1.1       mrg }
   1035       1.1       mrg 
   1036       1.1       mrg /*
   1037       1.1       mrg  * opposite:
   1038  1.12.2.1      yamt  *	Return true if the bullet direction faces the opposite direction
   1039       1.1       mrg  *	of the player in the maze
   1040       1.1       mrg  */
   1041  1.12.2.1      yamt bool
   1042       1.9  dholland opposite(int face, char dir)
   1043       1.1       mrg {
   1044       1.1       mrg 	switch (face) {
   1045       1.1       mrg 	  case LEFTS:
   1046       1.1       mrg 		return (dir == RIGHT);
   1047       1.1       mrg 	  case RIGHT:
   1048       1.1       mrg 		return (dir == LEFTS);
   1049       1.1       mrg 	  case ABOVE:
   1050       1.1       mrg 		return (dir == BELOW);
   1051       1.1       mrg 	  case BELOW:
   1052       1.1       mrg 		return (dir == ABOVE);
   1053       1.1       mrg 	  default:
   1054  1.12.2.1      yamt 		return false;
   1055       1.1       mrg 	}
   1056       1.1       mrg }
   1057       1.1       mrg 
   1058       1.1       mrg /*
   1059       1.1       mrg  * is_bullet:
   1060       1.1       mrg  *	Is there a bullet at the given coordinates?  If so, return
   1061       1.1       mrg  *	a pointer to the bullet, otherwise return NULL
   1062       1.1       mrg  */
   1063       1.1       mrg BULLET *
   1064       1.9  dholland is_bullet(int y, int x)
   1065       1.1       mrg {
   1066      1.10  dholland 	BULLET *bp;
   1067       1.1       mrg 
   1068       1.1       mrg 	for (bp = Bullets; bp != NULL; bp = bp->b_next)
   1069       1.1       mrg 		if (bp->b_y == y && bp->b_x == x)
   1070       1.1       mrg 			return bp;
   1071       1.1       mrg 	return NULL;
   1072       1.1       mrg }
   1073       1.1       mrg 
   1074       1.1       mrg /*
   1075       1.1       mrg  * fixshots:
   1076       1.1       mrg  *	change the underlying character of the shots at a location
   1077       1.1       mrg  *	to the given character.
   1078       1.1       mrg  */
   1079       1.2     lukem void
   1080       1.9  dholland fixshots(int y, int x, char over)
   1081       1.1       mrg {
   1082      1.10  dholland 	BULLET *bp;
   1083       1.1       mrg 
   1084       1.1       mrg 	for (bp = Bullets; bp != NULL; bp = bp->b_next)
   1085       1.1       mrg 		if (bp->b_y == y && bp->b_x == x)
   1086       1.1       mrg 			bp->b_over = over;
   1087       1.1       mrg }
   1088       1.1       mrg 
   1089       1.1       mrg /*
   1090       1.1       mrg  * find_under:
   1091       1.1       mrg  *	find the underlying character for a bullet when it lands
   1092       1.1       mrg  *	on another bullet.
   1093       1.1       mrg  */
   1094       1.2     lukem static void
   1095       1.9  dholland find_under(BULLET *blist, BULLET *bp)
   1096       1.1       mrg {
   1097      1.10  dholland 	BULLET *nbp;
   1098       1.1       mrg 
   1099       1.1       mrg 	for (nbp = blist; nbp != NULL; nbp = nbp->b_next)
   1100       1.1       mrg 		if (bp->b_y == nbp->b_y && bp->b_x == nbp->b_x) {
   1101       1.1       mrg 			bp->b_over = nbp->b_over;
   1102       1.1       mrg 			break;
   1103       1.1       mrg 		}
   1104       1.1       mrg }
   1105       1.1       mrg 
   1106       1.1       mrg /*
   1107       1.1       mrg  * mark_player:
   1108       1.1       mrg  *	mark a player as under a shot
   1109       1.1       mrg  */
   1110       1.2     lukem static void
   1111       1.9  dholland mark_player(BULLET *bp)
   1112       1.1       mrg {
   1113      1.10  dholland 	PLAYER *pp;
   1114       1.1       mrg 
   1115       1.1       mrg 	for (pp = Player; pp < End_player; pp++)
   1116       1.1       mrg 		if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) {
   1117  1.12.2.1      yamt 			pp->p_undershot = true;
   1118       1.1       mrg 			break;
   1119       1.1       mrg 		}
   1120       1.1       mrg }
   1121       1.1       mrg 
   1122      1.10  dholland #ifdef BOOTS
   1123       1.1       mrg /*
   1124       1.1       mrg  * mark_boot:
   1125       1.1       mrg  *	mark a boot as under a shot
   1126       1.1       mrg  */
   1127       1.2     lukem static void
   1128       1.9  dholland mark_boot(BULLET *bp)
   1129       1.1       mrg {
   1130      1.10  dholland 	PLAYER *pp;
   1131       1.1       mrg 
   1132       1.1       mrg 	for (pp = Boot; pp < &Boot[NBOOTS]; pp++)
   1133       1.1       mrg 		if (pp->p_y == bp->b_y && pp->p_x == bp->b_x) {
   1134  1.12.2.1      yamt 			pp->p_undershot = true;
   1135       1.1       mrg 			break;
   1136       1.1       mrg 		}
   1137       1.1       mrg }
   1138      1.10  dholland #endif
   1139