1 /* $OpenBSD: hack.vault.c,v 1.8 2016/01/09 18:33:15 mestre Exp $ */ 2 3 /* 4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, 5 * Amsterdam 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are 10 * met: 11 * 12 * - Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * - Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * - Neither the name of the Stichting Centrum voor Wiskunde en 20 * Informatica, nor the names of its contributors may be used to endorse or 21 * promote products derived from this software without specific prior 22 * written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 /* 38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> 39 * All rights reserved. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 #include <stdlib.h> 65 66 #include "hack.h" 67 68 #ifdef QUEST 69 void 70 setgd(void) 71 {} 72 73 int 74 gd_move(void) 75 { 76 return(2); 77 } 78 79 void 80 gddead(void) 81 {} 82 83 void 84 replgd(struct monst *mtmp, struct monst *mtmp2) 85 {} 86 87 void 88 invault(void) 89 {} 90 91 #else 92 extern struct monst *makemon(struct permonst *, int, int); 93 #define FCSIZ (ROWNO+COLNO) 94 struct fakecorridor { 95 xchar fx,fy,ftyp; 96 }; 97 98 struct egd { 99 int fcbeg, fcend; /* fcend: first unused pos */ 100 xchar gdx, gdy; /* goal of guard's walk */ 101 unsigned gddone:1; 102 struct fakecorridor fakecorr[FCSIZ]; 103 }; 104 105 static struct permonst pm_guard = 106 { "guard", '@', 12, 12, -1, 4, 10, sizeof(struct egd) }; 107 108 static struct monst *guard; 109 static int gdlevel; 110 #define EGD ((struct egd *)(&(guard->mextra[0]))) 111 112 static void restfakecorr(void); 113 static int goldincorridor(void); 114 115 116 static void 117 restfakecorr(void) 118 { 119 int fcx,fcy,fcbeg; 120 struct rm *crm; 121 122 while((fcbeg = EGD->fcbeg) < EGD->fcend) { 123 fcx = EGD->fakecorr[fcbeg].fx; 124 fcy = EGD->fakecorr[fcbeg].fy; 125 if((u.ux == fcx && u.uy == fcy) || cansee(fcx,fcy) || 126 m_at(fcx,fcy)) 127 return; 128 crm = &levl[fcx][fcy]; 129 crm->typ = EGD->fakecorr[fcbeg].ftyp; 130 if(!crm->typ) crm->seen = 0; 131 newsym(fcx,fcy); 132 EGD->fcbeg++; 133 } 134 /* it seems he left the corridor - let the guard disappear */ 135 mondead(guard); 136 guard = 0; 137 } 138 139 static int 140 goldincorridor(void) 141 { 142 int fci; 143 144 for(fci = EGD->fcbeg; fci < EGD->fcend; fci++) 145 if(g_at(EGD->fakecorr[fci].fx, EGD->fakecorr[fci].fy)) 146 return(1); 147 return(0); 148 } 149 150 void 151 setgd(void) 152 { 153 struct monst *mtmp; 154 155 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isgd){ 156 guard = mtmp; 157 gdlevel = dlevel; 158 return; 159 } 160 guard = 0; 161 } 162 163 void 164 invault(void) 165 { 166 int tmp = inroom(u.ux, u.uy); 167 168 if(tmp < 0 || rooms[tmp].rtype != VAULT) { 169 u.uinvault = 0; 170 return; 171 } 172 if(++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) { 173 char buf[BUFSZ]; 174 int x,y,dd,gx,gy; 175 176 /* first find the goal for the guard */ 177 for(dd = 1; (dd < ROWNO || dd < COLNO); dd++) { 178 for(y = u.uy-dd; y <= u.uy+dd; y++) { 179 if(y < 0 || y > ROWNO-1) continue; 180 for(x = u.ux-dd; x <= u.ux+dd; x++) { 181 if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd) 182 x = u.ux+dd; 183 if(x < 0 || x > COLNO-1) continue; 184 if(levl[x][y].typ == CORR) goto fnd; 185 } 186 } 187 } 188 impossible("Not a single corridor on this level??"); 189 tele(); 190 return; 191 fnd: 192 gx = x; gy = y; 193 194 /* next find a good place for a door in the wall */ 195 x = u.ux; y = u.uy; 196 while(levl[x][y].typ == ROOM) { 197 int dx,dy; 198 199 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; 200 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; 201 if(abs(gx-x) >= abs(gy-y)) 202 x += dx; 203 else 204 y += dy; 205 } 206 207 /* make something interesting happen */ 208 if(!(guard = makemon(&pm_guard,x,y))) return; 209 guard->isgd = guard->mpeaceful = 1; 210 EGD->gddone = 0; 211 gdlevel = dlevel; 212 if(!cansee(guard->mx, guard->my)) { 213 mondead(guard); 214 guard = 0; 215 return; 216 } 217 218 pline("Suddenly one of the Vault's guards enters!"); 219 pmon(guard); 220 do { 221 pline("\"Hello stranger, who are you?\" - "); 222 getlin(buf); 223 } while (!letter(buf[0])); 224 225 if(!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) { 226 pline("\"Oh, yes - of course. Sorry to have disturbed you.\""); 227 mondead(guard); 228 guard = 0; 229 return; 230 } 231 clrlin(); 232 pline("\"I don't know you.\""); 233 if(!u.ugold) 234 pline("\"Please follow me.\""); 235 else { 236 pline("\"Most likely all that gold was stolen from this vault.\""); 237 pline("\"Please drop your gold (say d$ ) and follow me.\""); 238 } 239 EGD->gdx = gx; 240 EGD->gdy = gy; 241 EGD->fcbeg = 0; 242 EGD->fakecorr[0].fx = x; 243 EGD->fakecorr[0].fy = y; 244 EGD->fakecorr[0].ftyp = levl[x][y].typ; 245 levl[x][y].typ = DOOR; 246 EGD->fcend = 1; 247 } 248 } 249 250 int 251 gd_move(void) 252 { 253 int x,y,dx,dy,gx,gy,nx,ny,typ; 254 struct fakecorridor *fcp; 255 struct rm *crm; 256 257 if(!guard || gdlevel != dlevel){ 258 impossible("Where is the guard?"); 259 return(2); /* died */ 260 } 261 if(u.ugold || goldincorridor()) 262 return(0); /* didnt move */ 263 if(dist(guard->mx,guard->my) > 1 || EGD->gddone) { 264 restfakecorr(); 265 return(0); /* didnt move */ 266 } 267 x = guard->mx; 268 y = guard->my; 269 /* look around (hor & vert only) for accessible places */ 270 for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) { 271 if(nx == x || ny == y) if(nx != x || ny != y) 272 if(isok(nx,ny)) 273 if(!IS_WALL(typ = (crm = &levl[nx][ny])->typ) && typ != POOL) { 274 int i; 275 for(i = EGD->fcbeg; i < EGD->fcend; i++) 276 if(EGD->fakecorr[i].fx == nx && 277 EGD->fakecorr[i].fy == ny) 278 goto nextnxy; 279 if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT) 280 goto nextnxy; 281 /* seems we found a good place to leave him alone */ 282 EGD->gddone = 1; 283 if(ACCESSIBLE(typ)) goto newpos; 284 crm->typ = (typ == SCORR) ? CORR : DOOR; 285 goto proceed; 286 } 287 nextnxy: ; 288 } 289 nx = x; 290 ny = y; 291 gx = EGD->gdx; 292 gy = EGD->gdy; 293 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; 294 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; 295 if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy; 296 297 while((typ = (crm = &levl[nx][ny])->typ) != 0) { 298 /* in view of the above we must have IS_WALL(typ) or typ == POOL */ 299 /* must be a wall here */ 300 if(isok(nx+nx-x,ny+ny-y) && typ != POOL && 301 ZAP_POS(levl[nx+nx-x][ny+ny-y].typ)){ 302 crm->typ = DOOR; 303 goto proceed; 304 } 305 if(dy && nx != x) { 306 nx = x; ny = y+dy; 307 continue; 308 } 309 if(dx && ny != y) { 310 ny = y; nx = x+dx; dy = 0; 311 continue; 312 } 313 /* I don't like this, but ... */ 314 crm->typ = DOOR; 315 goto proceed; 316 } 317 crm->typ = CORR; 318 proceed: 319 if(cansee(nx,ny)) { 320 mnewsym(nx,ny); 321 prl(nx,ny); 322 } 323 fcp = &(EGD->fakecorr[EGD->fcend]); 324 if(EGD->fcend++ == FCSIZ) panic("fakecorr overflow"); 325 fcp->fx = nx; 326 fcp->fy = ny; 327 fcp->ftyp = typ; 328 newpos: 329 if(EGD->gddone) nx = ny = 0; 330 guard->mx = nx; 331 guard->my = ny; 332 pmon(guard); 333 restfakecorr(); 334 return(1); 335 } 336 337 void 338 gddead(void) 339 { 340 guard = 0; 341 } 342 343 void 344 replgd(struct monst *mtmp, struct monst *mtmp2) 345 { 346 if(mtmp == guard) 347 guard = mtmp2; 348 } 349 350 #endif /* QUEST */ 351