1 /* $OpenBSD: hack.vault.c,v 1.6 2003/05/19 09:00:54 pjanzen 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 #ifndef lint 65 static const char rcsid[] = "$OpenBSD: hack.vault.c,v 1.6 2003/05/19 09:00:54 pjanzen Exp $"; 66 #endif /* not lint */ 67 68 #include <stdlib.h> 69 #include "hack.h" 70 #ifdef QUEST 71 void 72 setgd() 73 {} 74 75 int 76 gd_move() 77 { 78 return(2); 79 } 80 81 void 82 gddead() 83 {} 84 85 void 86 replgd(struct monst *mtmp, struct monst *mtmp2) 87 {} 88 89 void 90 invault() 91 {} 92 93 #else 94 95 96 extern struct monst *makemon(); 97 #define FCSIZ (ROWNO+COLNO) 98 struct fakecorridor { 99 xchar fx,fy,ftyp; 100 }; 101 102 struct egd { 103 int fcbeg, fcend; /* fcend: first unused pos */ 104 xchar gdx, gdy; /* goal of guard's walk */ 105 unsigned gddone:1; 106 struct fakecorridor fakecorr[FCSIZ]; 107 }; 108 109 static struct permonst pm_guard = 110 { "guard", '@', 12, 12, -1, 4, 10, sizeof(struct egd) }; 111 112 static struct monst *guard; 113 static int gdlevel; 114 #define EGD ((struct egd *)(&(guard->mextra[0]))) 115 116 static void restfakecorr(void); 117 static int goldincorridor(void); 118 119 120 static void 121 restfakecorr() 122 { 123 int fcx,fcy,fcbeg; 124 struct rm *crm; 125 126 while((fcbeg = EGD->fcbeg) < EGD->fcend) { 127 fcx = EGD->fakecorr[fcbeg].fx; 128 fcy = EGD->fakecorr[fcbeg].fy; 129 if((u.ux == fcx && u.uy == fcy) || cansee(fcx,fcy) || 130 m_at(fcx,fcy)) 131 return; 132 crm = &levl[fcx][fcy]; 133 crm->typ = EGD->fakecorr[fcbeg].ftyp; 134 if(!crm->typ) crm->seen = 0; 135 newsym(fcx,fcy); 136 EGD->fcbeg++; 137 } 138 /* it seems he left the corridor - let the guard disappear */ 139 mondead(guard); 140 guard = 0; 141 } 142 143 static int 144 goldincorridor() 145 { 146 int fci; 147 148 for(fci = EGD->fcbeg; fci < EGD->fcend; fci++) 149 if(g_at(EGD->fakecorr[fci].fx, EGD->fakecorr[fci].fy)) 150 return(1); 151 return(0); 152 } 153 154 void 155 setgd() 156 { 157 struct monst *mtmp; 158 159 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isgd){ 160 guard = mtmp; 161 gdlevel = dlevel; 162 return; 163 } 164 guard = 0; 165 } 166 167 void 168 invault() 169 { 170 int tmp = inroom(u.ux, u.uy); 171 172 if(tmp < 0 || rooms[tmp].rtype != VAULT) { 173 u.uinvault = 0; 174 return; 175 } 176 if(++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) { 177 char buf[BUFSZ]; 178 int x,y,dd,gx,gy; 179 180 /* first find the goal for the guard */ 181 for(dd = 1; (dd < ROWNO || dd < COLNO); dd++) { 182 for(y = u.uy-dd; y <= u.uy+dd; y++) { 183 if(y < 0 || y > ROWNO-1) continue; 184 for(x = u.ux-dd; x <= u.ux+dd; x++) { 185 if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd) 186 x = u.ux+dd; 187 if(x < 0 || x > COLNO-1) continue; 188 if(levl[x][y].typ == CORR) goto fnd; 189 } 190 } 191 } 192 impossible("Not a single corridor on this level??"); 193 tele(); 194 return; 195 fnd: 196 gx = x; gy = y; 197 198 /* next find a good place for a door in the wall */ 199 x = u.ux; y = u.uy; 200 while(levl[x][y].typ == ROOM) { 201 int dx,dy; 202 203 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; 204 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; 205 if(abs(gx-x) >= abs(gy-y)) 206 x += dx; 207 else 208 y += dy; 209 } 210 211 /* make something interesting happen */ 212 if(!(guard = makemon(&pm_guard,x,y))) return; 213 guard->isgd = guard->mpeaceful = 1; 214 EGD->gddone = 0; 215 gdlevel = dlevel; 216 if(!cansee(guard->mx, guard->my)) { 217 mondead(guard); 218 guard = 0; 219 return; 220 } 221 222 pline("Suddenly one of the Vault's guards enters!"); 223 pmon(guard); 224 do { 225 pline("\"Hello stranger, who are you?\" - "); 226 getlin(buf); 227 } while (!letter(buf[0])); 228 229 if(!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) { 230 pline("\"Oh, yes - of course. Sorry to have disturbed you.\""); 231 mondead(guard); 232 guard = 0; 233 return; 234 } 235 clrlin(); 236 pline("\"I don't know you.\""); 237 if(!u.ugold) 238 pline("\"Please follow me.\""); 239 else { 240 pline("\"Most likely all that gold was stolen from this vault.\""); 241 pline("\"Please drop your gold (say d$ ) and follow me.\""); 242 } 243 EGD->gdx = gx; 244 EGD->gdy = gy; 245 EGD->fcbeg = 0; 246 EGD->fakecorr[0].fx = x; 247 EGD->fakecorr[0].fy = y; 248 EGD->fakecorr[0].ftyp = levl[x][y].typ; 249 levl[x][y].typ = DOOR; 250 EGD->fcend = 1; 251 } 252 } 253 254 int 255 gd_move() 256 { 257 int x,y,dx,dy,gx,gy,nx,ny,typ; 258 struct fakecorridor *fcp; 259 struct rm *crm; 260 261 if(!guard || gdlevel != dlevel){ 262 impossible("Where is the guard?"); 263 return(2); /* died */ 264 } 265 if(u.ugold || goldincorridor()) 266 return(0); /* didnt move */ 267 if(dist(guard->mx,guard->my) > 1 || EGD->gddone) { 268 restfakecorr(); 269 return(0); /* didnt move */ 270 } 271 x = guard->mx; 272 y = guard->my; 273 /* look around (hor & vert only) for accessible places */ 274 for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) { 275 if(nx == x || ny == y) if(nx != x || ny != y) 276 if(isok(nx,ny)) 277 if(!IS_WALL(typ = (crm = &levl[nx][ny])->typ) && typ != POOL) { 278 int i; 279 for(i = EGD->fcbeg; i < EGD->fcend; i++) 280 if(EGD->fakecorr[i].fx == nx && 281 EGD->fakecorr[i].fy == ny) 282 goto nextnxy; 283 if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT) 284 goto nextnxy; 285 /* seems we found a good place to leave him alone */ 286 EGD->gddone = 1; 287 if(ACCESSIBLE(typ)) goto newpos; 288 crm->typ = (typ == SCORR) ? CORR : DOOR; 289 goto proceed; 290 } 291 nextnxy: ; 292 } 293 nx = x; 294 ny = y; 295 gx = EGD->gdx; 296 gy = EGD->gdy; 297 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; 298 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; 299 if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy; 300 301 while((typ = (crm = &levl[nx][ny])->typ) != 0) { 302 /* in view of the above we must have IS_WALL(typ) or typ == POOL */ 303 /* must be a wall here */ 304 if(isok(nx+nx-x,ny+ny-y) && typ != POOL && 305 ZAP_POS(levl[nx+nx-x][ny+ny-y].typ)){ 306 crm->typ = DOOR; 307 goto proceed; 308 } 309 if(dy && nx != x) { 310 nx = x; ny = y+dy; 311 continue; 312 } 313 if(dx && ny != y) { 314 ny = y; nx = x+dx; dy = 0; 315 continue; 316 } 317 /* I don't like this, but ... */ 318 crm->typ = DOOR; 319 goto proceed; 320 } 321 crm->typ = CORR; 322 proceed: 323 if(cansee(nx,ny)) { 324 mnewsym(nx,ny); 325 prl(nx,ny); 326 } 327 fcp = &(EGD->fakecorr[EGD->fcend]); 328 if(EGD->fcend++ == FCSIZ) panic("fakecorr overflow"); 329 fcp->fx = nx; 330 fcp->fy = ny; 331 fcp->ftyp = typ; 332 newpos: 333 if(EGD->gddone) nx = ny = 0; 334 guard->mx = nx; 335 guard->my = ny; 336 pmon(guard); 337 restfakecorr(); 338 return(1); 339 } 340 341 void 342 gddead() 343 { 344 guard = 0; 345 } 346 347 void 348 replgd(struct monst *mtmp, struct monst *mtmp2) 349 { 350 if(mtmp == guard) 351 guard = mtmp2; 352 } 353 354 #endif /* QUEST */ 355