expl.c revision 1.12
1/* $OpenBSD: expl.c,v 1.12 2016/01/07 21:29:31 mestre 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 38#include "conf.h" 39#include "hunt.h" 40#include "server.h" 41 42static void remove_wall(int, int); 43static void init_removed(void); 44 45 46/* 47 * showexpl: 48 * Show the explosions as they currently are 49 */ 50void 51showexpl(y, x, type) 52 int y, x; 53 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 (EXPL)); 63 if (ep == NULL) { 64 logit(LOG_ERR, "malloc"); 65 return; 66 } 67 ep->e_y = y; 68 ep->e_x = x; 69 ep->e_char = type; 70 ep->e_next = NULL; 71 if (Last_expl == NULL) 72 Expl[0] = ep; 73 else 74 Last_expl->e_next = ep; 75 Last_expl = ep; 76 for (pp = Player; pp < End_player; 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 for (pp = Monitor; pp < End_monitor; pp++) { 84 if (pp->p_maze[y][x] == type) 85 continue; 86 pp->p_maze[y][x] = type; 87 cgoto(pp, y, x); 88 outch(pp, type); 89 } 90 switch (Maze[y][x]) { 91 case WALL1: 92 case WALL2: 93 case WALL3: 94 case DOOR: 95 case WALL4: 96 case WALL5: 97 if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND) 98 remove_wall(y, x); 99 break; 100 } 101} 102 103/* 104 * rollexpl: 105 * Roll the explosions over, so the next one in the list is at the 106 * top 107 */ 108void 109rollexpl() 110{ 111 EXPL *ep; 112 PLAYER *pp; 113 int y, x; 114 char c; 115 EXPL *nextep; 116 117 for (ep = Expl[EXPLEN - 1]; ep != NULL; ep = nextep) { 118 nextep = ep->e_next; 119 y = ep->e_y; 120 x = ep->e_x; 121 if (y < UBOUND || y >= DBOUND || x < LBOUND || x >= RBOUND) 122 c = Maze[y][x]; 123 else 124 c = SPACE; 125 for (pp = Player; pp < End_player; pp++) 126 if (pp->p_maze[y][x] == ep->e_char) { 127 pp->p_maze[y][x] = c; 128 cgoto(pp, y, x); 129 outch(pp, c); 130 } 131 for (pp = Monitor; pp < End_monitor; pp++) 132 check(pp, y, x); 133 free((char *) ep); 134 } 135 memmove(&Expl[1], &Expl[0], (EXPLEN - 1) * sizeof Expl[0]); 136 /* for (x = EXPLEN - 1; x > 0; x--) 137 Expl[x] = Expl[x - 1]; */ 138 Last_expl = Expl[0] = NULL; 139} 140 141int 142can_rollexpl() 143{ 144 int i; 145 146 for (i = EXPLEN - 1; i >= 0; i--) 147 if (Expl[i] != NULL) 148 return 1; 149 return 0; 150} 151 152static REGEN *removed = NULL; 153static REGEN *rem_index = NULL; 154 155static void 156init_removed() 157{ 158 rem_index = removed = calloc(conf_maxremove, sizeof(REGEN)); 159 if (rem_index == NULL) { 160 logit(LOG_ERR, "malloc"); 161 cleanup(1); 162 } 163} 164 165/* 166 * remove_wall - add a location where the wall was blown away. 167 * if there is no space left over, put the a wall at 168 * the location currently pointed at. 169 */ 170static void 171remove_wall(y, x) 172 int y, x; 173{ 174 REGEN *r; 175 PLAYER *pp; 176 char save_char = 0; 177 178 if (removed == NULL) 179 clearwalls(); 180 181 r = rem_index; 182 while (r->r_y != 0) { 183 switch (Maze[r->r_y][r->r_x]) { 184 case SPACE: 185 case LEFTS: 186 case RIGHT: 187 case ABOVE: 188 case BELOW: 189 case FLYER: 190 save_char = Maze[r->r_y][r->r_x]; 191 goto found; 192 } 193 if (++r >= removed + conf_maxremove) 194 r = removed; 195 } 196 197found: 198 if (r->r_y != 0) { 199 /* Slot being used, put back this wall */ 200 if (save_char == SPACE) 201 Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x]; 202 else { 203 /* We throw the player off the wall: */ 204 pp = play_at(r->r_y, r->r_x); 205 if (pp->p_flying >= 0) 206 pp->p_flying += rand_num(conf_flytime / 2); 207 else { 208 pp->p_flying = rand_num(conf_flytime); 209 pp->p_flyx = 2 * rand_num(conf_flystep + 1) - 210 conf_flystep; 211 pp->p_flyy = 2 * rand_num(conf_flystep + 1) - 212 conf_flystep; 213 } 214 pp->p_over = Orig_maze[r->r_y][r->r_x]; 215 pp->p_face = FLYER; 216 Maze[r->r_y][r->r_x] = FLYER; 217 showexpl(r->r_y, r->r_x, FLYER); 218 } 219 Maze[r->r_y][r->r_x] = Orig_maze[r->r_y][r->r_x]; 220 if (conf_random && rand_num(100) < conf_prandom) 221 Maze[r->r_y][r->r_x] = DOOR; 222 if (conf_reflect && rand_num(100) == conf_preflect) 223 Maze[r->r_y][r->r_x] = WALL4; 224 for (pp = Monitor; pp < End_monitor; pp++) 225 check(pp, r->r_y, r->r_x); 226 } 227 228 r->r_y = y; 229 r->r_x = x; 230 if (++r >= removed + conf_maxremove) 231 rem_index = removed; 232 else 233 rem_index = r; 234 235 Maze[y][x] = SPACE; 236 for (pp = Monitor; pp < End_monitor; pp++) 237 check(pp, y, x); 238} 239 240/* 241 * clearwalls: 242 * Clear out the walls array 243 */ 244void 245clearwalls() 246{ 247 REGEN *rp; 248 249 if (removed == NULL) 250 init_removed(); 251 for (rp = removed; rp < removed + conf_maxremove; rp++) 252 rp->r_y = 0; 253 rem_index = removed; 254} 255