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