xref: /openbsd-src/games/hunt/huntd/expl.c (revision ac1fa6a8a418bc90e3475167b0e6680f850eeb92)
1*ac1fa6a8Skrw /*	$OpenBSD: expl.c,v 1.15 2017/01/21 08:22:57 krw Exp $	*/
23faf6791Sd /*	$NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $	*/
33faf6791Sd /*
4598075eaSpjanzen  * Copyright (c) 1983-2003, Regents of the University of California.
5598075eaSpjanzen  * All rights reserved.
6598075eaSpjanzen  *
7598075eaSpjanzen  * Redistribution and use in source and binary forms, with or without
8598075eaSpjanzen  * modification, are permitted provided that the following conditions are
9598075eaSpjanzen  * met:
10598075eaSpjanzen  *
11598075eaSpjanzen  * + Redistributions of source code must retain the above copyright
12598075eaSpjanzen  *   notice, this list of conditions and the following disclaimer.
13598075eaSpjanzen  * + Redistributions in binary form must reproduce the above copyright
14598075eaSpjanzen  *   notice, this list of conditions and the following disclaimer in the
15598075eaSpjanzen  *   documentation and/or other materials provided with the distribution.
16598075eaSpjanzen  * + Neither the name of the University of California, San Francisco nor
17598075eaSpjanzen  *   the names of its contributors may be used to endorse or promote
18598075eaSpjanzen  *   products derived from this software without specific prior written
19598075eaSpjanzen  *   permission.
20598075eaSpjanzen  *
21598075eaSpjanzen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22598075eaSpjanzen  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23598075eaSpjanzen  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24598075eaSpjanzen  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25598075eaSpjanzen  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26598075eaSpjanzen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27598075eaSpjanzen  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28598075eaSpjanzen  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29598075eaSpjanzen  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30598075eaSpjanzen  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31598075eaSpjanzen  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
323faf6791Sd  */
333faf6791Sd 
34e29f8a1bSguenther #include <sys/select.h>
353faf6791Sd #include <stdlib.h>
36fab1dce0Sd #include <syslog.h>
37c6d62522Sd #include <string.h>
389ef48543Smestre 
399ef48543Smestre #include "conf.h"
403faf6791Sd #include "hunt.h"
41fab1dce0Sd #include "server.h"
423faf6791Sd 
43c72b5b24Smillert static	void	remove_wall(int, int);
44c72b5b24Smillert static	void	init_removed(void);
453faf6791Sd 
463faf6791Sd 
473faf6791Sd /*
483faf6791Sd  * showexpl:
493faf6791Sd  *	Show the explosions as they currently are
503faf6791Sd  */
513faf6791Sd void
showexpl(int y,int x,char type)520f16a76cSmestre showexpl(int y, int x, char type)
533faf6791Sd {
543faf6791Sd 	PLAYER	*pp;
553faf6791Sd 	EXPL	*ep;
563faf6791Sd 
573faf6791Sd 	if (y < 0 || y >= HEIGHT)
583faf6791Sd 		return;
593faf6791Sd 	if (x < 0 || x >= WIDTH)
603faf6791Sd 		return;
61f06752bbSguenther 	ep = malloc(sizeof (EXPL));
6270a075a5Sd 	if (ep == NULL) {
633fc386a2Sespie 		logit(LOG_ERR, "malloc");
6470a075a5Sd 		return;
6570a075a5Sd 	}
663faf6791Sd 	ep->e_y = y;
673faf6791Sd 	ep->e_x = x;
683faf6791Sd 	ep->e_char = type;
693faf6791Sd 	ep->e_next = NULL;
703faf6791Sd 	if (Last_expl == NULL)
713faf6791Sd 		Expl[0] = ep;
723faf6791Sd 	else
733faf6791Sd 		Last_expl->e_next = ep;
743faf6791Sd 	Last_expl = ep;
753faf6791Sd 	for (pp = Player; pp < End_player; pp++) {
763faf6791Sd 		if (pp->p_maze[y][x] == type)
773faf6791Sd 			continue;
783faf6791Sd 		pp->p_maze[y][x] = type;
793faf6791Sd 		cgoto(pp, y, x);
803faf6791Sd 		outch(pp, type);
813faf6791Sd 	}
823faf6791Sd 	for (pp = Monitor; pp < End_monitor; pp++) {
833faf6791Sd 		if (pp->p_maze[y][x] == type)
843faf6791Sd 			continue;
853faf6791Sd 		pp->p_maze[y][x] = type;
863faf6791Sd 		cgoto(pp, y, x);
873faf6791Sd 		outch(pp, type);
883faf6791Sd 	}
893faf6791Sd 	switch (Maze[y][x]) {
903faf6791Sd 	  case WALL1:
913faf6791Sd 	  case WALL2:
923faf6791Sd 	  case WALL3:
933faf6791Sd 	  case DOOR:
943faf6791Sd 	  case WALL4:
953faf6791Sd 	  case WALL5:
963faf6791Sd 		if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND)
973faf6791Sd 			remove_wall(y, x);
983faf6791Sd 		break;
993faf6791Sd 	}
1003faf6791Sd }
1013faf6791Sd 
1023faf6791Sd /*
1033faf6791Sd  * rollexpl:
1043faf6791Sd  *	Roll the explosions over, so the next one in the list is at the
1053faf6791Sd  *	top
1063faf6791Sd  */
1073faf6791Sd void
rollexpl(void)1080f16a76cSmestre rollexpl(void)
1093faf6791Sd {
1103faf6791Sd 	EXPL	*ep;
1113faf6791Sd 	PLAYER	*pp;
1123faf6791Sd 	int	y, x;
1133faf6791Sd 	char	c;
1143faf6791Sd 	EXPL	*nextep;
1153faf6791Sd 
1163faf6791Sd 	for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) {
1173faf6791Sd 		nextep = ep->e_next;
1183faf6791Sd 		y = ep->e_y;
1193faf6791Sd 		x = ep->e_x;
1203faf6791Sd 		if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND)
1213faf6791Sd 			c = Maze[y][x];
1223faf6791Sd 		else
1233faf6791Sd 			c = SPACE;
1243faf6791Sd 		for (pp = Player; pp < End_player; pp++)
1253faf6791Sd 			if (pp->p_maze[y][x] == ep->e_char) {
1263faf6791Sd 				pp->p_maze[y][x] = c;
1273faf6791Sd 				cgoto(pp, y, x);
1283faf6791Sd 				outch(pp, c);
1293faf6791Sd 			}
1303faf6791Sd 		for (pp = Monitor; pp < End_monitor; pp++)
1313faf6791Sd 			check(pp, y, x);
1323faf6791Sd 		free((char *) ep);
1333faf6791Sd 	}
134c6d62522Sd 	memmove(&Expl[1], &Expl[0], (EXPLEN - 1) * sizeof Expl[0]);
135c6d62522Sd 	/* for (x = EXPLEN - 1; x > 0; x--)
136c6d62522Sd 		Expl[x] = Expl[x - 1]; */
1373faf6791Sd 	Last_expl = Expl[0] = NULL;
1383faf6791Sd }
1393faf6791Sd 
140c6d62522Sd int
can_rollexpl(void)1410f16a76cSmestre can_rollexpl(void)
142c6d62522Sd {
143c6d62522Sd 	int i;
144c6d62522Sd 
145c6d62522Sd 	for (i = EXPLEN - 1; i >= 0; i--)
146c6d62522Sd 		if (Expl[i] != NULL)
147c6d62522Sd 			return 1;
148c6d62522Sd 	return 0;
149c6d62522Sd }
150c6d62522Sd 
151fab1dce0Sd static	REGEN	*removed = NULL;
152fab1dce0Sd static	REGEN	*rem_index = NULL;
1533faf6791Sd 
154fab1dce0Sd static void
init_removed(void)1550f16a76cSmestre init_removed(void)
156fab1dce0Sd {
157a2f41399Shshoexer 	rem_index = removed = calloc(conf_maxremove, sizeof(REGEN));
158fab1dce0Sd 	if (rem_index == NULL) {
1593fc386a2Sespie 		logit(LOG_ERR, "malloc");
160fab1dce0Sd 		cleanup(1);
161fab1dce0Sd 	}
162fab1dce0Sd }
1633faf6791Sd 
1643faf6791Sd /*
1653faf6791Sd  * remove_wall - add a location where the wall was blown away.
1663faf6791Sd  *		 if there is no space left over, put the a wall at
1673faf6791Sd  *		 the location currently pointed at.
1683faf6791Sd  */
1693faf6791Sd static void
remove_wall(int y,int x)1700f16a76cSmestre remove_wall(int y, int x)
1713faf6791Sd {
1723faf6791Sd 	REGEN	*r;
1733faf6791Sd 	PLAYER	*pp;
1743faf6791Sd 	char	save_char = 0;
175fab1dce0Sd 
176fab1dce0Sd 	if (removed == NULL)
177c6d62522Sd 		clearwalls();
1783faf6791Sd 
1793faf6791Sd 	r = rem_index;
1803faf6791Sd 	while (r->r_y != 0) {
1813faf6791Sd 		switch (Maze[r->r_y][r->r_x]) {
1823faf6791Sd 		  case SPACE:
1833faf6791Sd 		  case LEFTS:
1843faf6791Sd 		  case RIGHT:
1853faf6791Sd 		  case ABOVE:
1863faf6791Sd 		  case BELOW:
1873faf6791Sd 		  case FLYER:
1883faf6791Sd 			save_char = Maze[r->r_y][r->r_x];
1893faf6791Sd 			goto found;
1903faf6791Sd 		}
191fab1dce0Sd 		if (++r >= removed + conf_maxremove)
1923faf6791Sd 			r = removed;
1933faf6791Sd 	}
1943faf6791Sd 
1953faf6791Sd found:
1963faf6791Sd 	if (r->r_y != 0) {
1973faf6791Sd 		/* Slot being used, put back this wall */
1983faf6791Sd 		if (save_char == SPACE)
1993faf6791Sd 			Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
2003faf6791Sd 		else {
201fab1dce0Sd 			/* We throw the player off the wall: */
2023faf6791Sd 			pp = play_at(r->r_y, r->r_x);
2033faf6791Sd 			if (pp->p_flying >= 0)
204fab1dce0Sd 				pp->p_flying += rand_num(conf_flytime / 2);
2053faf6791Sd 			else {
206fab1dce0Sd 				pp->p_flying = rand_num(conf_flytime);
207fab1dce0Sd 				pp->p_flyx = 2 * rand_num(conf_flystep + 1) -
208fab1dce0Sd 				    conf_flystep;
209fab1dce0Sd 				pp->p_flyy = 2 * rand_num(conf_flystep + 1) -
210fab1dce0Sd 				    conf_flystep;
2113faf6791Sd 			}
2123faf6791Sd 			pp->p_over = Orig_maze[r->r_y][r->r_x];
2133faf6791Sd 			pp->p_face = FLYER;
2143faf6791Sd 			Maze[r->r_y][r->r_x] = FLYER;
2153faf6791Sd 			showexpl(r->r_y, r->r_x, FLYER);
2163faf6791Sd 		}
2173faf6791Sd 		Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
218fab1dce0Sd 		if (conf_random && rand_num(100) < conf_prandom)
2193faf6791Sd 			Maze[r->r_y][r->r_x] = DOOR;
220fab1dce0Sd 		if (conf_reflect && rand_num(100) == conf_preflect)
2213faf6791Sd 			Maze[r->r_y][r->r_x] = WALL4;
2223faf6791Sd 		for (pp = Monitor; pp < End_monitor; pp++)
2233faf6791Sd 			check(pp, r->r_y, r->r_x);
2243faf6791Sd 	}
2253faf6791Sd 
2263faf6791Sd 	r->r_y = y;
2273faf6791Sd 	r->r_x = x;
228fab1dce0Sd 	if (++r >= removed + conf_maxremove)
2293faf6791Sd 		rem_index = removed;
2303faf6791Sd 	else
2313faf6791Sd 		rem_index = r;
2323faf6791Sd 
2333faf6791Sd 	Maze[y][x] = SPACE;
2343faf6791Sd 	for (pp = Monitor; pp < End_monitor; pp++)
2353faf6791Sd 		check(pp, y, x);
2363faf6791Sd }
2373faf6791Sd 
2383faf6791Sd /*
2393faf6791Sd  * clearwalls:
2403faf6791Sd  *	Clear out the walls array
2413faf6791Sd  */
2423faf6791Sd void
clearwalls(void)2430f16a76cSmestre clearwalls(void)
2443faf6791Sd {
2453faf6791Sd 	REGEN	*rp;
2463faf6791Sd 
247fab1dce0Sd 	if (removed == NULL)
248fab1dce0Sd 		init_removed();
249fab1dce0Sd 	for (rp = removed; rp < removed + conf_maxremove; rp++)
2503faf6791Sd 		rp->r_y = 0;
2513faf6791Sd 	rem_index = removed;
2523faf6791Sd }
253