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