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