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