1 /* $OpenBSD: expl.c,v 1.9 2007/09/04 22:39:31 hshoexer Exp $ */ 2 /* $NetBSD: expl.c,v 1.2 1997/10/10 16:33:18 lukem Exp $ */ 3 /* 4 * Copyright (c) 1983-2003, Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * + Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * + Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * + Neither the name of the University of California, San Francisco nor 17 * the names of its contributors may be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stdlib.h> 35 #include <syslog.h> 36 #include <string.h> 37 #include "hunt.h" 38 #include "server.h" 39 #include "conf.h" 40 41 static void remove_wall(int, int); 42 static void init_removed(void); 43 44 45 /* 46 * showexpl: 47 * Show the explosions as they currently are 48 */ 49 void 50 showexpl(y, x, type) 51 int y, x; 52 char type; 53 { 54 PLAYER *pp; 55 EXPL *ep; 56 57 if (y < 0 || y >= HEIGHT) 58 return; 59 if (x < 0 || x >= WIDTH) 60 return; 61 ep = (EXPL *) malloc(sizeof (EXPL)); /* NOSTRICT */ 62 if (ep == NULL) { 63 logit(LOG_ERR, "malloc"); 64 return; 65 } 66 ep->e_y = y; 67 ep->e_x = x; 68 ep->e_char = type; 69 ep->e_next = NULL; 70 if (Last_expl == NULL) 71 Expl[0] = ep; 72 else 73 Last_expl->e_next = ep; 74 Last_expl = ep; 75 for (pp = Player; pp < End_player; pp++) { 76 if (pp->p_maze[y][x] == type) 77 continue; 78 pp->p_maze[y][x] = type; 79 cgoto(pp, y, x); 80 outch(pp, type); 81 } 82 for (pp = Monitor; pp < End_monitor; pp++) { 83 if (pp->p_maze[y][x] == type) 84 continue; 85 pp->p_maze[y][x] = type; 86 cgoto(pp, y, x); 87 outch(pp, type); 88 } 89 switch (Maze[y][x]) { 90 case WALL1: 91 case WALL2: 92 case WALL3: 93 case DOOR: 94 case WALL4: 95 case WALL5: 96 if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND) 97 remove_wall(y, x); 98 break; 99 } 100 } 101 102 /* 103 * rollexpl: 104 * Roll the explosions over, so the next one in the list is at the 105 * top 106 */ 107 void 108 rollexpl() 109 { 110 EXPL *ep; 111 PLAYER *pp; 112 int y, x; 113 char c; 114 EXPL *nextep; 115 116 for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) { 117 nextep = ep->e_next; 118 y = ep->e_y; 119 x = ep->e_x; 120 if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND) 121 c = Maze[y][x]; 122 else 123 c = SPACE; 124 for (pp = Player; pp < End_player; pp++) 125 if (pp->p_maze[y][x] == ep->e_char) { 126 pp->p_maze[y][x] = c; 127 cgoto(pp, y, x); 128 outch(pp, c); 129 } 130 for (pp = Monitor; pp < End_monitor; pp++) 131 check(pp, y, x); 132 free((char *) ep); 133 } 134 memmove(&Expl[1], &Expl[0], (EXPLEN - 1) * sizeof Expl[0]); 135 /* for (x = EXPLEN - 1; x > 0; x--) 136 Expl[x] = Expl[x - 1]; */ 137 Last_expl = Expl[0] = NULL; 138 } 139 140 int 141 can_rollexpl() 142 { 143 int i; 144 145 for (i = EXPLEN - 1; i >= 0; i--) 146 if (Expl[i] != NULL) 147 return 1; 148 return 0; 149 } 150 151 static REGEN *removed = NULL; 152 static REGEN *rem_index = NULL; 153 154 static void 155 init_removed() 156 { 157 rem_index = removed = calloc(conf_maxremove, sizeof(REGEN)); 158 if (rem_index == NULL) { 159 logit(LOG_ERR, "malloc"); 160 cleanup(1); 161 } 162 } 163 164 /* 165 * remove_wall - add a location where the wall was blown away. 166 * if there is no space left over, put the a wall at 167 * the location currently pointed at. 168 */ 169 static void 170 remove_wall(y, x) 171 int y, x; 172 { 173 REGEN *r; 174 PLAYER *pp; 175 char save_char = 0; 176 177 if (removed == NULL) 178 clearwalls(); 179 180 r = rem_index; 181 while (r->r_y != 0) { 182 switch (Maze[r->r_y][r->r_x]) { 183 case SPACE: 184 case LEFTS: 185 case RIGHT: 186 case ABOVE: 187 case BELOW: 188 case FLYER: 189 save_char = Maze[r->r_y][r->r_x]; 190 goto found; 191 } 192 if (++r >= removed + conf_maxremove) 193 r = removed; 194 } 195 196 found: 197 if (r->r_y != 0) { 198 /* Slot being used, put back this wall */ 199 if (save_char == SPACE) 200 Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x]; 201 else { 202 /* We throw the player off the wall: */ 203 pp = play_at(r->r_y, r->r_x); 204 if (pp->p_flying >= 0) 205 pp->p_flying += rand_num(conf_flytime / 2); 206 else { 207 pp->p_flying = rand_num(conf_flytime); 208 pp->p_flyx = 2 * rand_num(conf_flystep + 1) - 209 conf_flystep; 210 pp->p_flyy = 2 * rand_num(conf_flystep + 1) - 211 conf_flystep; 212 } 213 pp->p_over = Orig_maze[r->r_y][r->r_x]; 214 pp->p_face = FLYER; 215 Maze[r->r_y][r->r_x] = FLYER; 216 showexpl(r->r_y, r->r_x, FLYER); 217 } 218 Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x]; 219 if (conf_random && rand_num(100) < conf_prandom) 220 Maze[r->r_y][r->r_x] = DOOR; 221 if (conf_reflect && rand_num(100) == conf_preflect) 222 Maze[r->r_y][r->r_x] = WALL4; 223 for (pp = Monitor; pp < End_monitor; pp++) 224 check(pp, r->r_y, r->r_x); 225 } 226 227 r->r_y = y; 228 r->r_x = x; 229 if (++r >= removed + conf_maxremove) 230 rem_index = removed; 231 else 232 rem_index = r; 233 234 Maze[y][x] = SPACE; 235 for (pp = Monitor; pp < End_monitor; pp++) 236 check(pp, y, x); 237 } 238 239 /* 240 * clearwalls: 241 * Clear out the walls array 242 */ 243 void 244 clearwalls() 245 { 246 REGEN *rp; 247 248 if (removed == NULL) 249 init_removed(); 250 for (rp = removed; rp < removed + conf_maxremove; rp++) 251 rp->r_y = 0; 252 rem_index = removed; 253 } 254