1*72db7ca9Schristos /* $NetBSD: hack.vault.c,v 1.9 2011/08/16 09:26:22 christos Exp $ */
23ea4a95cSchristos
3210cab45Smycroft /*
41c7f94e5Sjsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm * Amsterdam
61c7f94e5Sjsm * All rights reserved.
71c7f94e5Sjsm *
81c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm * met:
111c7f94e5Sjsm *
121c7f94e5Sjsm * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm * this list of conditions and the following disclaimer.
141c7f94e5Sjsm *
151c7f94e5Sjsm * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm *
191c7f94e5Sjsm * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm * promote products derived from this software without specific prior
221c7f94e5Sjsm * written permission.
231c7f94e5Sjsm *
241c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm */
361c7f94e5Sjsm
371c7f94e5Sjsm /*
381c7f94e5Sjsm * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm * All rights reserved.
401c7f94e5Sjsm *
411c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm * modification, are permitted provided that the following conditions
431c7f94e5Sjsm * are met:
441c7f94e5Sjsm * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm * notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm * derived from this software without specific prior written permission.
511c7f94e5Sjsm *
521c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
551c7f94e5Sjsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62210cab45Smycroft */
63210cab45Smycroft
643ea4a95cSchristos #include <sys/cdefs.h>
65210cab45Smycroft #ifndef lint
66*72db7ca9Schristos __RCSID("$NetBSD: hack.vault.c,v 1.9 2011/08/16 09:26:22 christos Exp $");
67210cab45Smycroft #endif /* not lint */
6861f28255Scgd
6961f28255Scgd #include "hack.h"
703ea4a95cSchristos #include "extern.h"
7161f28255Scgd #ifdef QUEST
723ea4a95cSchristos void
setgd(void)731fa8a9a6Sdholland setgd(void)
741fa8a9a6Sdholland {
753ea4a95cSchristos }
761fa8a9a6Sdholland
773ea4a95cSchristos int
gd_move(void)781fa8a9a6Sdholland gd_move(void)
791fa8a9a6Sdholland {
803ea4a95cSchristos return (2);
813ea4a95cSchristos }
821fa8a9a6Sdholland
833ea4a95cSchristos void
gddead(void)841fa8a9a6Sdholland gddead(void)
853ea4a95cSchristos {
863ea4a95cSchristos }
871fa8a9a6Sdholland
883ea4a95cSchristos void
replgd(struct monst * mtmp __unused,struct monst * mtmp2 __unused)891fa8a9a6Sdholland replgd(struct monst *mtmp __unused, struct monst *mtmp2 __unused)
903ea4a95cSchristos {
913ea4a95cSchristos }
921fa8a9a6Sdholland
933ea4a95cSchristos void
invault(void)941fa8a9a6Sdholland invault(void)
953ea4a95cSchristos {
963ea4a95cSchristos }
9761f28255Scgd
9861f28255Scgd #else
9961f28255Scgd
10061f28255Scgd
10161f28255Scgd #include "def.mkroom.h"
10261f28255Scgd #define FCSIZ (ROWNO+COLNO)
10361f28255Scgd struct fakecorridor {
10461f28255Scgd xchar fx, fy, ftyp;
10561f28255Scgd };
10661f28255Scgd
10761f28255Scgd struct egd {
10861f28255Scgd int fcbeg, fcend; /* fcend: first unused pos */
10961f28255Scgd xchar gdx, gdy; /* goal of guard's walk */
11061f28255Scgd unsigned gddone:1;
11161f28255Scgd struct fakecorridor fakecorr[FCSIZ];
11261f28255Scgd };
11361f28255Scgd
114ab8b6343Sjsm static const struct permonst pm_guard =
11561f28255Scgd {"guard", '@', 12, 12, -1, 4, 10, sizeof(struct egd)};
11661f28255Scgd
11761f28255Scgd static struct monst *guard;
11861f28255Scgd static int gdlevel;
11961f28255Scgd
120cb5fd834Sjsm static void restfakecorr(void);
121cb5fd834Sjsm static int goldincorridor(void);
1223ea4a95cSchristos
1233ea4a95cSchristos static void
restfakecorr(void)1241fa8a9a6Sdholland restfakecorr(void)
12561f28255Scgd {
1263ea4a95cSchristos int fcx, fcy, fcbeg;
1273ea4a95cSchristos struct rm *crm;
128*72db7ca9Schristos struct egd *egd = monster_private(guard);
12961f28255Scgd
130*72db7ca9Schristos while ((fcbeg = egd->fcbeg) < egd->fcend) {
131*72db7ca9Schristos fcx = egd->fakecorr[fcbeg].fx;
132*72db7ca9Schristos fcy = egd->fakecorr[fcbeg].fy;
13361f28255Scgd if ((u.ux == fcx && u.uy == fcy) || cansee(fcx, fcy) ||
13461f28255Scgd m_at(fcx, fcy))
13561f28255Scgd return;
13661f28255Scgd crm = &levl[fcx][fcy];
137*72db7ca9Schristos crm->typ = egd->fakecorr[fcbeg].ftyp;
1383ea4a95cSchristos if (!crm->typ)
1393ea4a95cSchristos crm->seen = 0;
14061f28255Scgd newsym(fcx, fcy);
141*72db7ca9Schristos egd->fcbeg++;
14261f28255Scgd }
14361f28255Scgd /* it seems he left the corridor - let the guard disappear */
14461f28255Scgd mondead(guard);
14561f28255Scgd guard = 0;
14661f28255Scgd }
14761f28255Scgd
1483ea4a95cSchristos static int
goldincorridor(void)1491fa8a9a6Sdholland goldincorridor(void)
15061f28255Scgd {
1513ea4a95cSchristos int fci;
152*72db7ca9Schristos struct egd *egd = monster_private(guard);
15361f28255Scgd
154*72db7ca9Schristos for (fci = egd->fcbeg; fci < egd->fcend; fci++)
155*72db7ca9Schristos if (g_at(egd->fakecorr[fci].fx, egd->fakecorr[fci].fy))
15661f28255Scgd return (1);
15761f28255Scgd return (0);
15861f28255Scgd }
15961f28255Scgd
1603ea4a95cSchristos void
setgd(void)1611fa8a9a6Sdholland setgd(void)
1623ea4a95cSchristos {
1633ea4a95cSchristos struct monst *mtmp;
1643ea4a95cSchristos for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
1653ea4a95cSchristos if (mtmp->isgd) {
16661f28255Scgd guard = mtmp;
16761f28255Scgd gdlevel = dlevel;
16861f28255Scgd return;
16961f28255Scgd }
17061f28255Scgd guard = 0;
17161f28255Scgd }
17261f28255Scgd
1733ea4a95cSchristos void
invault(void)1741fa8a9a6Sdholland invault(void)
1753ea4a95cSchristos {
1763ea4a95cSchristos int tmp = inroom(u.ux, u.uy);
177*72db7ca9Schristos struct egd *egd;
17861f28255Scgd if (tmp < 0 || rooms[tmp].rtype != VAULT) {
17961f28255Scgd u.uinvault = 0;
18061f28255Scgd return;
18161f28255Scgd }
18261f28255Scgd if (++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) {
18361f28255Scgd char buf[BUFSZ];
1843ea4a95cSchristos int x, y, dd, gx, gy;
18561f28255Scgd
18661f28255Scgd /* first find the goal for the guard */
18761f28255Scgd for (dd = 1; (dd < ROWNO || dd < COLNO); dd++) {
18861f28255Scgd for (y = u.uy - dd; y <= u.uy + dd; y++) {
1893ea4a95cSchristos if (y < 0 || y > ROWNO - 1)
1903ea4a95cSchristos continue;
19161f28255Scgd for (x = u.ux - dd; x <= u.ux + dd; x++) {
19261f28255Scgd if (y != u.uy - dd && y != u.uy + dd && x != u.ux - dd)
19361f28255Scgd x = u.ux + dd;
1943ea4a95cSchristos if (x < 0 || x > COLNO - 1)
1953ea4a95cSchristos continue;
1963ea4a95cSchristos if (levl[x][y].typ == CORR)
1973ea4a95cSchristos goto fnd;
19861f28255Scgd }
19961f28255Scgd }
20061f28255Scgd }
20161f28255Scgd impossible("Not a single corridor on this level??");
20261f28255Scgd tele();
20361f28255Scgd return;
20461f28255Scgd fnd:
2053ea4a95cSchristos gx = x;
2063ea4a95cSchristos gy = y;
20761f28255Scgd
20861f28255Scgd /* next find a good place for a door in the wall */
2093ea4a95cSchristos x = u.ux;
2103ea4a95cSchristos y = u.uy;
21161f28255Scgd while (levl[x][y].typ == ROOM) {
2123ea4a95cSchristos int dx, dy;
21361f28255Scgd
21461f28255Scgd dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
21561f28255Scgd dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
21661f28255Scgd if (abs(gx - x) >= abs(gy - y))
21761f28255Scgd x += dx;
21861f28255Scgd else
21961f28255Scgd y += dy;
22061f28255Scgd }
22161f28255Scgd
22261f28255Scgd /* make something interesting happen */
2233ea4a95cSchristos if (!(guard = makemon(&pm_guard, x, y)))
2243ea4a95cSchristos return;
22561f28255Scgd guard->isgd = guard->mpeaceful = 1;
226*72db7ca9Schristos egd = monster_private(guard);
227*72db7ca9Schristos egd->gddone = 0;
22861f28255Scgd gdlevel = dlevel;
22961f28255Scgd if (!cansee(guard->mx, guard->my)) {
23061f28255Scgd mondead(guard);
23161f28255Scgd guard = 0;
23261f28255Scgd return;
23361f28255Scgd }
23461f28255Scgd pline("Suddenly one of the Vault's guards enters!");
23561f28255Scgd pmon(guard);
23661f28255Scgd do {
23761f28255Scgd pline("\"Hello stranger, who are you?\" - ");
23861f28255Scgd getlin(buf);
23961f28255Scgd } while (!letter(buf[0]));
24061f28255Scgd
24161f28255Scgd if (!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) {
24261f28255Scgd pline("\"Oh, yes - of course. Sorry to have disturbed you.\"");
24361f28255Scgd mondead(guard);
24461f28255Scgd guard = 0;
24561f28255Scgd return;
24661f28255Scgd }
24761f28255Scgd clrlin();
24861f28255Scgd pline("\"I don't know you.\"");
24961f28255Scgd if (!u.ugold)
25061f28255Scgd pline("\"Please follow me.\"");
25161f28255Scgd else {
25261f28255Scgd pline("\"Most likely all that gold was stolen from this vault.\"");
25361f28255Scgd pline("\"Please drop your gold (say d$ ) and follow me.\"");
25461f28255Scgd }
255*72db7ca9Schristos egd->gdx = gx;
256*72db7ca9Schristos egd->gdy = gy;
257*72db7ca9Schristos egd->fcbeg = 0;
258*72db7ca9Schristos egd->fakecorr[0].fx = x;
259*72db7ca9Schristos egd->fakecorr[0].fy = y;
260*72db7ca9Schristos egd->fakecorr[0].ftyp = levl[x][y].typ;
26161f28255Scgd levl[x][y].typ = DOOR;
262*72db7ca9Schristos egd->fcend = 1;
26361f28255Scgd }
26461f28255Scgd }
26561f28255Scgd
2663ea4a95cSchristos int
gd_move(void)2671fa8a9a6Sdholland gd_move(void)
2683ea4a95cSchristos {
2693ea4a95cSchristos int x, y, dx, dy, gx, gy, nx, ny, typ;
2703ea4a95cSchristos struct fakecorridor *fcp;
2713ea4a95cSchristos struct rm *crm;
272*72db7ca9Schristos struct egd *egd = monster_private(guard);
27361f28255Scgd if (!guard || gdlevel != dlevel) {
27461f28255Scgd impossible("Where is the guard?");
27561f28255Scgd return (2); /* died */
27661f28255Scgd }
27761f28255Scgd if (u.ugold || goldincorridor())
27861f28255Scgd return (0); /* didnt move */
279*72db7ca9Schristos if (dist(guard->mx, guard->my) > 1 || egd->gddone) {
28061f28255Scgd restfakecorr();
28161f28255Scgd return (0); /* didnt move */
28261f28255Scgd }
28361f28255Scgd x = guard->mx;
28461f28255Scgd y = guard->my;
28561f28255Scgd /* look around (hor & vert only) for accessible places */
2863ea4a95cSchristos for (nx = x - 1; nx <= x + 1; nx++)
2873ea4a95cSchristos for (ny = y - 1; ny <= y + 1; ny++) {
2883ea4a95cSchristos if (nx == x || ny == y)
2893ea4a95cSchristos if (nx != x || ny != y)
29061f28255Scgd if (isok(nx, ny))
29161f28255Scgd if (!IS_WALL(typ = (crm = &levl[nx][ny])->typ) && typ != POOL) {
2923ea4a95cSchristos int i;
293*72db7ca9Schristos for (i = egd->fcbeg; i < egd->fcend; i++)
294*72db7ca9Schristos if (egd->fakecorr[i].fx == nx &&
295*72db7ca9Schristos egd->fakecorr[i].fy == ny)
29661f28255Scgd goto nextnxy;
29761f28255Scgd if ((i = inroom(nx, ny)) >= 0 && rooms[i].rtype == VAULT)
29861f28255Scgd goto nextnxy;
2993ea4a95cSchristos /*
3003ea4a95cSchristos * seems we found a
3013ea4a95cSchristos * good place to
3023ea4a95cSchristos * leave him alone
3033ea4a95cSchristos */
304*72db7ca9Schristos egd->gddone = 1;
3053ea4a95cSchristos if (ACCESSIBLE(typ))
3063ea4a95cSchristos goto newpos;
30761f28255Scgd crm->typ = (typ == SCORR) ? CORR : DOOR;
30861f28255Scgd goto proceed;
30961f28255Scgd }
31061f28255Scgd nextnxy: ;
31161f28255Scgd }
31261f28255Scgd nx = x;
31361f28255Scgd ny = y;
314*72db7ca9Schristos gx = egd->gdx;
315*72db7ca9Schristos gy = egd->gdy;
31661f28255Scgd dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
31761f28255Scgd dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
3183ea4a95cSchristos if (abs(gx - x) >= abs(gy - y))
3193ea4a95cSchristos nx += dx;
3203ea4a95cSchristos else
3213ea4a95cSchristos ny += dy;
32261f28255Scgd
32361f28255Scgd while ((typ = (crm = &levl[nx][ny])->typ) != 0) {
3243ea4a95cSchristos /*
3253ea4a95cSchristos * in view of the above we must have IS_WALL(typ) or typ ==
3263ea4a95cSchristos * POOL
3273ea4a95cSchristos */
32861f28255Scgd /* must be a wall here */
32961f28255Scgd if (isok(nx + nx - x, ny + ny - y) && typ != POOL &&
33061f28255Scgd ZAP_POS(levl[nx + nx - x][ny + ny - y].typ)) {
33161f28255Scgd crm->typ = DOOR;
33261f28255Scgd goto proceed;
33361f28255Scgd }
33461f28255Scgd if (dy && nx != x) {
3353ea4a95cSchristos nx = x;
3363ea4a95cSchristos ny = y + dy;
33761f28255Scgd continue;
33861f28255Scgd }
33961f28255Scgd if (dx && ny != y) {
3403ea4a95cSchristos ny = y;
3413ea4a95cSchristos nx = x + dx;
3423ea4a95cSchristos dy = 0;
34361f28255Scgd continue;
34461f28255Scgd }
34561f28255Scgd /* I don't like this, but ... */
34661f28255Scgd crm->typ = DOOR;
34761f28255Scgd goto proceed;
34861f28255Scgd }
34961f28255Scgd crm->typ = CORR;
35061f28255Scgd proceed:
35161f28255Scgd if (cansee(nx, ny)) {
35261f28255Scgd mnewsym(nx, ny);
35361f28255Scgd prl(nx, ny);
35461f28255Scgd }
355*72db7ca9Schristos fcp = &(egd->fakecorr[egd->fcend]);
356*72db7ca9Schristos if (egd->fcend++ == FCSIZ)
3573ea4a95cSchristos panic("fakecorr overflow");
35861f28255Scgd fcp->fx = nx;
35961f28255Scgd fcp->fy = ny;
36061f28255Scgd fcp->ftyp = typ;
36161f28255Scgd newpos:
362*72db7ca9Schristos if (egd->gddone)
3633ea4a95cSchristos nx = ny = 0;
36461f28255Scgd guard->mx = nx;
36561f28255Scgd guard->my = ny;
36661f28255Scgd pmon(guard);
36761f28255Scgd restfakecorr();
36861f28255Scgd return (1);
36961f28255Scgd }
37061f28255Scgd
3713ea4a95cSchristos void
gddead(void)3721fa8a9a6Sdholland gddead(void)
3733ea4a95cSchristos {
37461f28255Scgd guard = 0;
37561f28255Scgd }
37661f28255Scgd
3773ea4a95cSchristos void
replgd(struct monst * mtmp,struct monst * mtmp2)3781fa8a9a6Sdholland replgd(struct monst *mtmp, struct monst *mtmp2)
37961f28255Scgd {
38061f28255Scgd if (mtmp == guard)
38161f28255Scgd guard = mtmp2;
38261f28255Scgd }
38361f28255Scgd
3843ea4a95cSchristos #endif /* QUEST */
385