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