xref: /netbsd-src/games/hunt/huntd/expl.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
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