1*1182a44cSrillig /* $NetBSD: expl.c,v 1.9 2021/05/02 12:50:45 rillig Exp $ */
24052d13dSmrg /*
311967175Swiz * Copyright (c) 1983-2003, Regents of the University of California.
411967175Swiz * All rights reserved.
511967175Swiz *
611967175Swiz * Redistribution and use in source and binary forms, with or without
711967175Swiz * modification, are permitted provided that the following conditions are
811967175Swiz * met:
911967175Swiz *
1011967175Swiz * + Redistributions of source code must retain the above copyright
1111967175Swiz * notice, this list of conditions and the following disclaimer.
1211967175Swiz * + Redistributions in binary form must reproduce the above copyright
1311967175Swiz * notice, this list of conditions and the following disclaimer in the
1411967175Swiz * documentation and/or other materials provided with the distribution.
1511967175Swiz * + Neither the name of the University of California, San Francisco nor
1611967175Swiz * the names of its contributors may be used to endorse or promote
1711967175Swiz * products derived from this software without specific prior written
1811967175Swiz * permission.
1911967175Swiz *
2011967175Swiz * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
2111967175Swiz * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2211967175Swiz * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2311967175Swiz * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2411967175Swiz * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2511967175Swiz * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2611967175Swiz * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2711967175Swiz * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2811967175Swiz * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2911967175Swiz * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3011967175Swiz * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
314052d13dSmrg */
324052d13dSmrg
33544a5e33Slukem #include <sys/cdefs.h>
34544a5e33Slukem #ifndef lint
35*1182a44cSrillig __RCSID("$NetBSD: expl.c,v 1.9 2021/05/02 12:50:45 rillig Exp $");
36544a5e33Slukem #endif /* not lint */
37544a5e33Slukem
38544a5e33Slukem #include <stdlib.h>
394052d13dSmrg #include "hunt.h"
404052d13dSmrg
41b19465b2Sdholland
42b19465b2Sdholland static EXPL *Expl[EXPLEN]; /* explosion lists */
43b19465b2Sdholland static EXPL *Last_expl; /* last explosion on Expl[0] */
44b19465b2Sdholland
45cb5fd834Sjsm static void remove_wall(int, int);
46544a5e33Slukem
47544a5e33Slukem
484052d13dSmrg /*
494052d13dSmrg * showexpl:
504052d13dSmrg * Show the explosions as they currently are
514052d13dSmrg */
52544a5e33Slukem void
showexpl(int y,int x,char type)53fbca3d8cSdholland showexpl(int y, int x, char type)
544052d13dSmrg {
55544a5e33Slukem PLAYER *pp;
56544a5e33Slukem EXPL *ep;
574052d13dSmrg
584052d13dSmrg if (y < 0 || y >= HEIGHT)
594052d13dSmrg return;
604052d13dSmrg if (x < 0 || x >= WIDTH)
614052d13dSmrg return;
626ffae662Sdholland ep = malloc(sizeof(*ep));
634052d13dSmrg ep->e_y = y;
644052d13dSmrg ep->e_x = x;
654052d13dSmrg ep->e_char = type;
664052d13dSmrg ep->e_next = NULL;
674052d13dSmrg if (Last_expl == NULL)
684052d13dSmrg Expl[0] = ep;
694052d13dSmrg else
704052d13dSmrg Last_expl->e_next = ep;
714052d13dSmrg Last_expl = ep;
724052d13dSmrg for (pp = Player; pp < End_player; pp++) {
734052d13dSmrg if (pp->p_maze[y][x] == type)
744052d13dSmrg continue;
754052d13dSmrg pp->p_maze[y][x] = type;
764052d13dSmrg cgoto(pp, y, x);
774052d13dSmrg outch(pp, type);
784052d13dSmrg }
794052d13dSmrg #ifdef MONITOR
804052d13dSmrg for (pp = Monitor; pp < End_monitor; pp++) {
814052d13dSmrg if (pp->p_maze[y][x] == type)
824052d13dSmrg continue;
834052d13dSmrg pp->p_maze[y][x] = type;
844052d13dSmrg cgoto(pp, y, x);
854052d13dSmrg outch(pp, type);
864052d13dSmrg }
874052d13dSmrg #endif
884052d13dSmrg switch (Maze[y][x]) {
894052d13dSmrg case WALL1:
904052d13dSmrg case WALL2:
914052d13dSmrg case WALL3:
924052d13dSmrg #ifdef RANDOM
934052d13dSmrg case DOOR:
944052d13dSmrg #endif
954052d13dSmrg #ifdef REFLECT
964052d13dSmrg case WALL4:
974052d13dSmrg case WALL5:
984052d13dSmrg #endif
994052d13dSmrg if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND)
1004052d13dSmrg remove_wall(y, x);
1014052d13dSmrg break;
1024052d13dSmrg }
1034052d13dSmrg }
1044052d13dSmrg
1054052d13dSmrg /*
1064052d13dSmrg * rollexpl:
1074052d13dSmrg * Roll the explosions over, so the next one in the list is at the
1084052d13dSmrg * top
1094052d13dSmrg */
110544a5e33Slukem void
rollexpl(void)111fbca3d8cSdholland rollexpl(void)
1124052d13dSmrg {
113544a5e33Slukem EXPL *ep;
114544a5e33Slukem PLAYER *pp;
115544a5e33Slukem int y, x;
116544a5e33Slukem char c;
117544a5e33Slukem EXPL *nextep;
1184052d13dSmrg
1194052d13dSmrg for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) {
1204052d13dSmrg nextep = ep->e_next;
1214052d13dSmrg y = ep->e_y;
1224052d13dSmrg x = ep->e_x;
1234052d13dSmrg if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND)
1244052d13dSmrg c = Maze[y][x];
1254052d13dSmrg else
1264052d13dSmrg c = SPACE;
1274052d13dSmrg for (pp = Player; pp < End_player; pp++)
1284052d13dSmrg if (pp->p_maze[y][x] == ep->e_char) {
1294052d13dSmrg pp->p_maze[y][x] = c;
1304052d13dSmrg cgoto(pp, y, x);
1314052d13dSmrg outch(pp, c);
1324052d13dSmrg }
1334052d13dSmrg #ifdef MONITOR
1344052d13dSmrg for (pp = Monitor; pp < End_monitor; pp++)
1354052d13dSmrg check(pp, y, x);
1364052d13dSmrg #endif
1376ffae662Sdholland free(ep);
1384052d13dSmrg }
1394052d13dSmrg for (x = EXPLEN - 1; x > 0; x--)
1404052d13dSmrg Expl[x] = Expl[x - 1];
1414052d13dSmrg Last_expl = Expl[0] = NULL;
1424052d13dSmrg }
1434052d13dSmrg
1444052d13dSmrg /* There's about 700 walls in the initial maze. So we pick a number
1454052d13dSmrg * that keeps the maze relatively full. */
1464052d13dSmrg #define MAXREMOVE 40
1474052d13dSmrg
1484052d13dSmrg static REGEN removed[MAXREMOVE];
1494052d13dSmrg static REGEN *rem_index = removed;
1504052d13dSmrg
1514052d13dSmrg /*
1524052d13dSmrg * remove_wall - add a location where the wall was blown away.
1534052d13dSmrg * if there is no space left over, put the a wall at
1544052d13dSmrg * the location currently pointed at.
1554052d13dSmrg */
156544a5e33Slukem static void
remove_wall(int y,int x)157fbca3d8cSdholland remove_wall(int y, int x)
1584052d13dSmrg {
159544a5e33Slukem REGEN *r;
1604052d13dSmrg #if defined(MONITOR) || defined(FLY)
161544a5e33Slukem PLAYER *pp;
1624052d13dSmrg #endif
1634052d13dSmrg #ifdef FLY
164544a5e33Slukem char save_char = 0;
1654052d13dSmrg #endif
1664052d13dSmrg
1674052d13dSmrg r = rem_index;
1684052d13dSmrg while (r->r_y != 0) {
1694052d13dSmrg #ifdef FLY
1704052d13dSmrg switch (Maze[r->r_y][r->r_x]) {
1714052d13dSmrg case SPACE:
1724052d13dSmrg case LEFTS:
1734052d13dSmrg case RIGHT:
1744052d13dSmrg case ABOVE:
1754052d13dSmrg case BELOW:
1764052d13dSmrg case FLYER:
1774052d13dSmrg save_char = Maze[r->r_y][r->r_x];
1784052d13dSmrg goto found;
1794052d13dSmrg }
1804052d13dSmrg #else
1814052d13dSmrg if (Maze[r->r_y][r->r_x] == SPACE)
1824052d13dSmrg break;
1834052d13dSmrg #endif
1844052d13dSmrg if (++r >= &removed[MAXREMOVE])
1854052d13dSmrg r = removed;
1864052d13dSmrg }
1874052d13dSmrg
1884052d13dSmrg found:
1894052d13dSmrg if (r->r_y != 0) {
1904052d13dSmrg /* Slot being used, put back this wall */
1914052d13dSmrg #ifdef FLY
1924052d13dSmrg if (save_char == SPACE)
1934052d13dSmrg Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
1944052d13dSmrg else {
1954052d13dSmrg pp = play_at(r->r_y, r->r_x);
1964052d13dSmrg if (pp->p_flying >= 0)
1974052d13dSmrg pp->p_flying += rand_num(10);
1984052d13dSmrg else {
1994052d13dSmrg pp->p_flying = rand_num(20);
2004052d13dSmrg pp->p_flyx = 2 * rand_num(6) - 5;
2014052d13dSmrg pp->p_flyy = 2 * rand_num(6) - 5;
2024052d13dSmrg }
2034052d13dSmrg pp->p_over = Orig_maze[r->r_y][r->r_x];
2044052d13dSmrg pp->p_face = FLYER;
2054052d13dSmrg Maze[r->r_y][r->r_x] = FLYER;
2064052d13dSmrg showexpl(r->r_y, r->r_x, FLYER);
2074052d13dSmrg }
2084052d13dSmrg #else
2094052d13dSmrg Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x];
2104052d13dSmrg #endif
2114052d13dSmrg #ifdef RANDOM
2124052d13dSmrg if (rand_num(100) == 0)
2134052d13dSmrg Maze[r->r_y][r->r_x] = DOOR;
2144052d13dSmrg #endif
2154052d13dSmrg #ifdef REFLECT
2164052d13dSmrg if (rand_num(100) == 0) /* one percent of the time */
2174052d13dSmrg Maze[r->r_y][r->r_x] = WALL4;
2184052d13dSmrg #endif
2194052d13dSmrg #ifdef MONITOR
2204052d13dSmrg for (pp = Monitor; pp < End_monitor; pp++)
2214052d13dSmrg check(pp, r->r_y, r->r_x);
2224052d13dSmrg #endif
2234052d13dSmrg }
2244052d13dSmrg
2254052d13dSmrg r->r_y = y;
2264052d13dSmrg r->r_x = x;
2274052d13dSmrg if (++r >= &removed[MAXREMOVE])
2284052d13dSmrg rem_index = removed;
2294052d13dSmrg else
2304052d13dSmrg rem_index = r;
2314052d13dSmrg
2324052d13dSmrg Maze[y][x] = SPACE;
2334052d13dSmrg #ifdef MONITOR
2344052d13dSmrg for (pp = Monitor; pp < End_monitor; pp++)
2354052d13dSmrg check(pp, y, x);
2364052d13dSmrg #endif
2374052d13dSmrg }
2384052d13dSmrg
2394052d13dSmrg /*
2404052d13dSmrg * clearwalls:
2414052d13dSmrg * Clear out the walls array
2424052d13dSmrg */
243544a5e33Slukem void
clearwalls(void)244fbca3d8cSdholland clearwalls(void)
2454052d13dSmrg {
246544a5e33Slukem REGEN *rp;
2474052d13dSmrg
2484052d13dSmrg for (rp = removed; rp < &removed[MAXREMOVE]; rp++)
2494052d13dSmrg rp->r_y = 0;
2504052d13dSmrg rem_index = removed;
2514052d13dSmrg }
252