Home | History | Annotate | Line # | Download | only in huntd
expl.c revision 1.7
      1 /*	$NetBSD: expl.c,v 1.7 2009/07/04 04:29:54 dholland Exp $	*/
      2 /*
      3  * Copyright (c) 1983-2003, Regents of the University of California.
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions are
      8  * met:
      9  *
     10  * + Redistributions of source code must retain the above copyright
     11  *   notice, this list of conditions and the following disclaimer.
     12  * + Redistributions in binary form must reproduce the above copyright
     13  *   notice, this list of conditions and the following disclaimer in the
     14  *   documentation and/or other materials provided with the distribution.
     15  * + Neither the name of the University of California, San Francisco nor
     16  *   the names of its contributors may be used to endorse or promote
     17  *   products derived from this software without specific prior written
     18  *   permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     23  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 #ifndef lint
     35 __RCSID("$NetBSD: expl.c,v 1.7 2009/07/04 04:29:54 dholland Exp $");
     36 #endif /* not lint */
     37 
     38 #include <stdlib.h>
     39 #include "hunt.h"
     40 
     41 static void remove_wall(int, int);
     42 
     43 
     44 /*
     45  * showexpl:
     46  *	Show the explosions as they currently are
     47  */
     48 void
     49 showexpl(int y, int x, char type)
     50 {
     51 	PLAYER *pp;
     52 	EXPL *ep;
     53 
     54 	if (y < 0 || y >= HEIGHT)
     55 		return;
     56 	if (x < 0 || x >= WIDTH)
     57 		return;
     58 	ep = malloc(sizeof(*ep));
     59 	ep->e_y = y;
     60 	ep->e_x = x;
     61 	ep->e_char = type;
     62 	ep->e_next = NULL;
     63 	if (Last_expl == NULL)
     64 		Expl[0] = ep;
     65 	else
     66 		Last_expl->e_next = ep;
     67 	Last_expl = ep;
     68 	for (pp = Player; pp < End_player; pp++) {
     69 		if (pp->p_maze[y][x] == type)
     70 			continue;
     71 		pp->p_maze[y][x] = type;
     72 		cgoto(pp, y, x);
     73 		outch(pp, type);
     74 	}
     75 #ifdef MONITOR
     76 	for (pp = Monitor; pp < End_monitor; pp++) {
     77 		if (pp->p_maze[y][x] == type)
     78 			continue;
     79 		pp->p_maze[y][x] = type;
     80 		cgoto(pp, y, x);
     81 		outch(pp, type);
     82 	}
     83 #endif
     84 	switch (Maze[y][x]) {
     85 	  case WALL1:
     86 	  case WALL2:
     87 	  case WALL3:
     88 #ifdef RANDOM
     89 	  case DOOR:
     90 #endif
     91 #ifdef REFLECT
     92 	  case WALL4:
     93 	  case WALL5:
     94 #endif
     95 		if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND)
     96 			remove_wall(y, x);
     97 		break;
     98 	}
     99 }
    100 
    101 /*
    102  * rollexpl:
    103  *	Roll the explosions over, so the next one in the list is at the
    104  *	top
    105  */
    106 void
    107 rollexpl(void)
    108 {
    109 	EXPL *ep;
    110 	PLAYER *pp;
    111 	int y, x;
    112 	char c;
    113 	EXPL *nextep;
    114 
    115 	for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) {
    116 		nextep = ep->e_next;
    117 		y = ep->e_y;
    118 		x = ep->e_x;
    119 		if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND)
    120 			c = Maze[y][x];
    121 		else
    122 			c = SPACE;
    123 		for (pp = Player; pp < End_player; pp++)
    124 			if (pp->p_maze[y][x] == ep->e_char) {
    125 				pp->p_maze[y][x] = c;
    126 				cgoto(pp, y, x);
    127 				outch(pp, c);
    128 			}
    129 #ifdef MONITOR
    130 		for (pp = Monitor; pp < End_monitor; pp++)
    131 			check(pp, y, x);
    132 #endif
    133 		free(ep);
    134 	}
    135 	for (x = EXPLEN - 1; x > 0; x--)
    136 		Expl[x] = Expl[x - 1];
    137 	Last_expl = Expl[0] = NULL;
    138 }
    139 
    140 /* There's about 700 walls in the initial maze.  So we pick a number
    141  * that keeps the maze relatively full. */
    142 #define MAXREMOVE	40
    143 
    144 static REGEN removed[MAXREMOVE];
    145 static REGEN *rem_index = removed;
    146 
    147 /*
    148  * remove_wall - add a location where the wall was blown away.
    149  *		 if there is no space left over, put the a wall at
    150  *		 the location currently pointed at.
    151  */
    152 static void
    153 remove_wall(int y, int x)
    154 {
    155 	REGEN *r;
    156 #if defined(MONITOR) || defined(FLY)
    157 	PLAYER *pp;
    158 #endif
    159 #ifdef FLY
    160 	char save_char = 0;
    161 #endif
    162 
    163 	r = rem_index;
    164 	while (r->r_y != 0) {
    165 #ifdef FLY
    166 		switch (Maze[r->r_y][r->r_x]) {
    167 		  case SPACE:
    168 		  case LEFTS:
    169 		  case RIGHT:
    170 		  case ABOVE:
    171 		  case BELOW:
    172 		  case FLYER:
    173 			save_char = Maze[r->r_y][r->r_x];
    174 			goto found;
    175 		}
    176 #else
    177 		if (Maze[r->r_y][r->r_x] == SPACE)
    178 			break;
    179 #endif
    180 		if (++r >= &removed[MAXREMOVE])
    181 			r = removed;
    182 	}
    183 
    184 found:
    185 	if (r->r_y != 0) {
    186 		/* Slot being used, put back this wall */
    187 #ifdef FLY
    188 		if (save_char == SPACE)
    189 			Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
    190 		else {
    191 			pp = play_at(r->r_y, r->r_x);
    192 			if (pp->p_flying >= 0)
    193 				pp->p_flying += rand_num(10);
    194 			else {
    195 				pp->p_flying = rand_num(20);
    196 				pp->p_flyx = 2 * rand_num(6) - 5;
    197 				pp->p_flyy = 2 * rand_num(6) - 5;
    198 			}
    199 			pp->p_over = Orig_maze[r->r_y][r->r_x];
    200 			pp->p_face = FLYER;
    201 			Maze[r->r_y][r->r_x] = FLYER;
    202 			showexpl(r->r_y, r->r_x, FLYER);
    203 		}
    204 #else
    205 		Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
    206 #endif
    207 #ifdef RANDOM
    208 		if (rand_num(100) == 0)
    209 			Maze[r->r_y][r->r_x] = DOOR;
    210 #endif
    211 #ifdef REFLECT
    212 		if (rand_num(100) == 0)		/* one percent of the time */
    213 			Maze[r->r_y][r->r_x] = WALL4;
    214 #endif
    215 #ifdef MONITOR
    216 		for (pp = Monitor; pp < End_monitor; pp++)
    217 			check(pp, r->r_y, r->r_x);
    218 #endif
    219 	}
    220 
    221 	r->r_y = y;
    222 	r->r_x = x;
    223 	if (++r >= &removed[MAXREMOVE])
    224 		rem_index = removed;
    225 	else
    226 		rem_index = r;
    227 
    228 	Maze[y][x] = SPACE;
    229 #ifdef MONITOR
    230 	for (pp = Monitor; pp < End_monitor; pp++)
    231 		check(pp, y, x);
    232 #endif
    233 }
    234 
    235 /*
    236  * clearwalls:
    237  *	Clear out the walls array
    238  */
    239 void
    240 clearwalls(void)
    241 {
    242 	REGEN *rp;
    243 
    244 	for (rp = removed; rp < &removed[MAXREMOVE]; rp++)
    245 		rp->r_y = 0;
    246 	rem_index = removed;
    247 }
    248