1 /* $NetBSD: expl.c,v 1.9 2021/05/02 12:50:45 rillig 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.9 2021/05/02 12:50:45 rillig Exp $"); 36 #endif /* not lint */ 37 38 #include <stdlib.h> 39 #include "hunt.h" 40 41 42 static EXPL *Expl[EXPLEN]; /* explosion lists */ 43 static EXPL *Last_expl; /* last explosion on Expl[0] */ 44 45 static void remove_wall(int, int); 46 47 48 /* 49 * showexpl: 50 * Show the explosions as they currently are 51 */ 52 void 53 showexpl(int y, int x, 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(*ep)); 63 ep->e_y = y; 64 ep->e_x = x; 65 ep->e_char = type; 66 ep->e_next = NULL; 67 if (Last_expl == NULL) 68 Expl[0] = ep; 69 else 70 Last_expl->e_next = ep; 71 Last_expl = ep; 72 for (pp = Player; pp < End_player; pp++) { 73 if (pp->p_maze[y][x] == type) 74 continue; 75 pp->p_maze[y][x] = type; 76 cgoto(pp, y, x); 77 outch(pp, type); 78 } 79 #ifdef MONITOR 80 for (pp = Monitor; pp < End_monitor; pp++) { 81 if (pp->p_maze[y][x] == type) 82 continue; 83 pp->p_maze[y][x] = type; 84 cgoto(pp, y, x); 85 outch(pp, type); 86 } 87 #endif 88 switch (Maze[y][x]) { 89 case WALL1: 90 case WALL2: 91 case WALL3: 92 #ifdef RANDOM 93 case DOOR: 94 #endif 95 #ifdef REFLECT 96 case WALL4: 97 case WALL5: 98 #endif 99 if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND) 100 remove_wall(y, x); 101 break; 102 } 103 } 104 105 /* 106 * rollexpl: 107 * Roll the explosions over, so the next one in the list is at the 108 * top 109 */ 110 void 111 rollexpl(void) 112 { 113 EXPL *ep; 114 PLAYER *pp; 115 int y, x; 116 char c; 117 EXPL *nextep; 118 119 for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) { 120 nextep = ep->e_next; 121 y = ep->e_y; 122 x = ep->e_x; 123 if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND) 124 c = Maze[y][x]; 125 else 126 c = SPACE; 127 for (pp = Player; pp < End_player; pp++) 128 if (pp->p_maze[y][x] == ep->e_char) { 129 pp->p_maze[y][x] = c; 130 cgoto(pp, y, x); 131 outch(pp, c); 132 } 133 #ifdef MONITOR 134 for (pp = Monitor; pp < End_monitor; pp++) 135 check(pp, y, x); 136 #endif 137 free(ep); 138 } 139 for (x = EXPLEN - 1; x > 0; x--) 140 Expl[x] = Expl[x - 1]; 141 Last_expl = Expl[0] = NULL; 142 } 143 144 /* There's about 700 walls in the initial maze. So we pick a number 145 * that keeps the maze relatively full. */ 146 #define MAXREMOVE 40 147 148 static REGEN removed[MAXREMOVE]; 149 static REGEN *rem_index = removed; 150 151 /* 152 * remove_wall - add a location where the wall was blown away. 153 * if there is no space left over, put the a wall at 154 * the location currently pointed at. 155 */ 156 static void 157 remove_wall(int y, int x) 158 { 159 REGEN *r; 160 #if defined(MONITOR) || defined(FLY) 161 PLAYER *pp; 162 #endif 163 #ifdef FLY 164 char save_char = 0; 165 #endif 166 167 r = rem_index; 168 while (r->r_y != 0) { 169 #ifdef FLY 170 switch (Maze[r->r_y][r->r_x]) { 171 case SPACE: 172 case LEFTS: 173 case RIGHT: 174 case ABOVE: 175 case BELOW: 176 case FLYER: 177 save_char = Maze[r->r_y][r->r_x]; 178 goto found; 179 } 180 #else 181 if (Maze[r->r_y][r->r_x] == SPACE) 182 break; 183 #endif 184 if (++r >= &removed[MAXREMOVE]) 185 r = removed; 186 } 187 188 found: 189 if (r->r_y != 0) { 190 /* Slot being used, put back this wall */ 191 #ifdef FLY 192 if (save_char == SPACE) 193 Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x]; 194 else { 195 pp = play_at(r->r_y, r->r_x); 196 if (pp->p_flying >= 0) 197 pp->p_flying += rand_num(10); 198 else { 199 pp->p_flying = rand_num(20); 200 pp->p_flyx = 2 * rand_num(6) - 5; 201 pp->p_flyy = 2 * rand_num(6) - 5; 202 } 203 pp->p_over = Orig_maze[r->r_y][r->r_x]; 204 pp->p_face = FLYER; 205 Maze[r->r_y][r->r_x] = FLYER; 206 showexpl(r->r_y, r->r_x, FLYER); 207 } 208 #else 209 Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x]; 210 #endif 211 #ifdef RANDOM 212 if (rand_num(100) == 0) 213 Maze[r->r_y][r->r_x] = DOOR; 214 #endif 215 #ifdef REFLECT 216 if (rand_num(100) == 0) /* one percent of the time */ 217 Maze[r->r_y][r->r_x] = WALL4; 218 #endif 219 #ifdef MONITOR 220 for (pp = Monitor; pp < End_monitor; pp++) 221 check(pp, r->r_y, r->r_x); 222 #endif 223 } 224 225 r->r_y = y; 226 r->r_x = x; 227 if (++r >= &removed[MAXREMOVE]) 228 rem_index = removed; 229 else 230 rem_index = r; 231 232 Maze[y][x] = SPACE; 233 #ifdef MONITOR 234 for (pp = Monitor; pp < End_monitor; pp++) 235 check(pp, y, x); 236 #endif 237 } 238 239 /* 240 * clearwalls: 241 * Clear out the walls array 242 */ 243 void 244 clearwalls(void) 245 { 246 REGEN *rp; 247 248 for (rp = removed; rp < &removed[MAXREMOVE]; rp++) 249 rp->r_y = 0; 250 rem_index = removed; 251 } 252