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