Home | History | Annotate | Line # | Download | only in huntd
      1 /*	$NetBSD: expl.c,v 1.9 2021/05/02 12:50:45 rillig 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.9 2021/05/02 12:50:45 rillig Exp $");
     36 #endif /* not lint */
     37 
     38 #include <stdlib.h>
     39 #include "hunt.h"
     40 
     41 
     42 static EXPL *Expl[EXPLEN];		/* explosion lists */
     43 static EXPL *Last_expl;			/* last explosion on Expl[0] */
     44 
     45 static void remove_wall(int, int);
     46 
     47 
     48 /*
     49  * showexpl:
     50  *	Show the explosions as they currently are
     51  */
     52 void
     53 showexpl(int y, int x, char type)
     54 {
     55 	PLAYER *pp;
     56 	EXPL *ep;
     57 
     58 	if (y < 0 || y >= HEIGHT)
     59 		return;
     60 	if (x < 0 || x >= WIDTH)
     61 		return;
     62 	ep = malloc(sizeof(*ep));
     63 	ep->e_y = y;
     64 	ep->e_x = x;
     65 	ep->e_char = type;
     66 	ep->e_next = NULL;
     67 	if (Last_expl == NULL)
     68 		Expl[0] = ep;
     69 	else
     70 		Last_expl->e_next = ep;
     71 	Last_expl = ep;
     72 	for (pp = Player; pp < End_player; pp++) {
     73 		if (pp->p_maze[y][x] == type)
     74 			continue;
     75 		pp->p_maze[y][x] = type;
     76 		cgoto(pp, y, x);
     77 		outch(pp, type);
     78 	}
     79 #ifdef MONITOR
     80 	for (pp = Monitor; pp < End_monitor; pp++) {
     81 		if (pp->p_maze[y][x] == type)
     82 			continue;
     83 		pp->p_maze[y][x] = type;
     84 		cgoto(pp, y, x);
     85 		outch(pp, type);
     86 	}
     87 #endif
     88 	switch (Maze[y][x]) {
     89 	  case WALL1:
     90 	  case WALL2:
     91 	  case WALL3:
     92 #ifdef RANDOM
     93 	  case DOOR:
     94 #endif
     95 #ifdef REFLECT
     96 	  case WALL4:
     97 	  case WALL5:
     98 #endif
     99 		if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND)
    100 			remove_wall(y, x);
    101 		break;
    102 	}
    103 }
    104 
    105 /*
    106  * rollexpl:
    107  *	Roll the explosions over, so the next one in the list is at the
    108  *	top
    109  */
    110 void
    111 rollexpl(void)
    112 {
    113 	EXPL *ep;
    114 	PLAYER *pp;
    115 	int y, x;
    116 	char c;
    117 	EXPL *nextep;
    118 
    119 	for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) {
    120 		nextep = ep->e_next;
    121 		y = ep->e_y;
    122 		x = ep->e_x;
    123 		if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND)
    124 			c = Maze[y][x];
    125 		else
    126 			c = SPACE;
    127 		for (pp = Player; pp < End_player; pp++)
    128 			if (pp->p_maze[y][x] == ep->e_char) {
    129 				pp->p_maze[y][x] = c;
    130 				cgoto(pp, y, x);
    131 				outch(pp, c);
    132 			}
    133 #ifdef MONITOR
    134 		for (pp = Monitor; pp < End_monitor; pp++)
    135 			check(pp, y, x);
    136 #endif
    137 		free(ep);
    138 	}
    139 	for (x = EXPLEN - 1; x > 0; x--)
    140 		Expl[x] = Expl[x - 1];
    141 	Last_expl = Expl[0] = NULL;
    142 }
    143 
    144 /* There's about 700 walls in the initial maze.  So we pick a number
    145  * that keeps the maze relatively full. */
    146 #define MAXREMOVE	40
    147 
    148 static REGEN removed[MAXREMOVE];
    149 static REGEN *rem_index = removed;
    150 
    151 /*
    152  * remove_wall - add a location where the wall was blown away.
    153  *		 if there is no space left over, put the a wall at
    154  *		 the location currently pointed at.
    155  */
    156 static void
    157 remove_wall(int y, int x)
    158 {
    159 	REGEN *r;
    160 #if defined(MONITOR) || defined(FLY)
    161 	PLAYER *pp;
    162 #endif
    163 #ifdef FLY
    164 	char save_char = 0;
    165 #endif
    166 
    167 	r = rem_index;
    168 	while (r->r_y != 0) {
    169 #ifdef FLY
    170 		switch (Maze[r->r_y][r->r_x]) {
    171 		  case SPACE:
    172 		  case LEFTS:
    173 		  case RIGHT:
    174 		  case ABOVE:
    175 		  case BELOW:
    176 		  case FLYER:
    177 			save_char = Maze[r->r_y][r->r_x];
    178 			goto found;
    179 		}
    180 #else
    181 		if (Maze[r->r_y][r->r_x] == SPACE)
    182 			break;
    183 #endif
    184 		if (++r >= &removed[MAXREMOVE])
    185 			r = removed;
    186 	}
    187 
    188 found:
    189 	if (r->r_y != 0) {
    190 		/* Slot being used, put back this wall */
    191 #ifdef FLY
    192 		if (save_char == SPACE)
    193 			Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
    194 		else {
    195 			pp = play_at(r->r_y, r->r_x);
    196 			if (pp->p_flying >= 0)
    197 				pp->p_flying += rand_num(10);
    198 			else {
    199 				pp->p_flying = rand_num(20);
    200 				pp->p_flyx = 2 * rand_num(6) - 5;
    201 				pp->p_flyy = 2 * rand_num(6) - 5;
    202 			}
    203 			pp->p_over = Orig_maze[r->r_y][r->r_x];
    204 			pp->p_face = FLYER;
    205 			Maze[r->r_y][r->r_x] = FLYER;
    206 			showexpl(r->r_y, r->r_x, FLYER);
    207 		}
    208 #else
    209 		Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
    210 #endif
    211 #ifdef RANDOM
    212 		if (rand_num(100) == 0)
    213 			Maze[r->r_y][r->r_x] = DOOR;
    214 #endif
    215 #ifdef REFLECT
    216 		if (rand_num(100) == 0)		/* one percent of the time */
    217 			Maze[r->r_y][r->r_x] = WALL4;
    218 #endif
    219 #ifdef MONITOR
    220 		for (pp = Monitor; pp < End_monitor; pp++)
    221 			check(pp, r->r_y, r->r_x);
    222 #endif
    223 	}
    224 
    225 	r->r_y = y;
    226 	r->r_x = x;
    227 	if (++r >= &removed[MAXREMOVE])
    228 		rem_index = removed;
    229 	else
    230 		rem_index = r;
    231 
    232 	Maze[y][x] = SPACE;
    233 #ifdef MONITOR
    234 	for (pp = Monitor; pp < End_monitor; pp++)
    235 		check(pp, y, x);
    236 #endif
    237 }
    238 
    239 /*
    240  * clearwalls:
    241  *	Clear out the walls array
    242  */
    243 void
    244 clearwalls(void)
    245 {
    246 	REGEN *rp;
    247 
    248 	for (rp = removed; rp < &removed[MAXREMOVE]; rp++)
    249 		rp->r_y = 0;
    250 	rem_index = removed;
    251 }
    252