xref: /netbsd-src/games/hunt/huntd/expl.c (revision 1182a44c59cae4d586117d55eca24b4b8b173211)
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
showexpl(int y,int x,char type)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
rollexpl(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
remove_wall(int y,int x)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
clearwalls(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