Home | History | Annotate | Line # | Download | only in huntd
shots.c revision 1.13
      1  1.13  dholland /*	$NetBSD: shots.c,v 1.13 2014/03/29 19:41:11 dholland 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.13  dholland __RCSID("$NetBSD: shots.c,v 1.13 2014/03/29 19:41:11 dholland 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.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.13  dholland 			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.13  dholland 	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.13  dholland 		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.13  dholland 			return false;
    503   1.1       mrg 		}
    504  1.13  dholland 		bp->b_expl = true;
    505   1.1       mrg 		break;
    506   1.1       mrg 	}
    507  1.13  dholland 	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.13  dholland 		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.13  dholland 					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.2     lukem 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.13  dholland 			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.13  dholland 			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.13  dholland 			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.13  dholland 			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.13  dholland 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.13  dholland 		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.13  dholland 		return true;
    974   1.1       mrg 	}
    975  1.13  dholland 	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.13  dholland 	bool explode;
    988   1.1       mrg 
    989  1.13  dholland 	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.13  dholland 		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.2     lukem 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.13  dholland 			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.13  dholland  *	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.13  dholland 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.13  dholland 		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.13  dholland 			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.13  dholland 			pp->p_undershot = true;
   1135   1.1       mrg 			break;
   1136   1.1       mrg 		}
   1137   1.1       mrg }
   1138  1.10  dholland #endif
   1139