#endif does not take an argument, comment it out.
[dragonfly.git] / games / hack / hack.vault.c
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2 /* hack.vault.c - version 1.0.2 */
3 /* $FreeBSD: src/games/hack/hack.vault.c,v 1.4 1999/11/16 10:26:38 marcel Exp $ */
4 /* $DragonFly: src/games/hack/hack.vault.c,v 1.3 2004/11/06 12:29:17 eirikn Exp $ */
5
6 #include        "hack.h"
7 #ifdef QUEST
8 setgd(/* mtmp */) /* struct monst *mtmp; */ {}
9 gd_move() { return(2); }
10 gddead(mtmp) struct monst *mtmp; {}
11 replgd(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}
12 invault(){}
13
14 #else
15
16
17 #include "def.mkroom.h"
18 extern struct monst *makemon();
19 #define FCSIZ   (ROWNO+COLNO)
20 struct fakecorridor {
21         xchar fx,fy,ftyp;
22 };
23
24 struct egd {
25         int fcbeg, fcend;       /* fcend: first unused pos */
26         xchar gdx, gdy;         /* goal of guard's walk */
27         unsigned gddone:1;
28         struct fakecorridor fakecorr[FCSIZ];
29 };
30
31 static struct permonst pm_guard =
32         { "guard", '@', 12, 12, -1, 4, 10, sizeof(struct egd) };
33
34 static struct monst *guard;
35 static int gdlevel;
36 #define EGD     ((struct egd *)(&(guard->mextra[0])))
37
38 static
39 restfakecorr()
40 {
41         int fcx,fcy,fcbeg;
42         struct rm *crm;
43
44         while((fcbeg = EGD->fcbeg) < EGD->fcend) {
45                 fcx = EGD->fakecorr[fcbeg].fx;
46                 fcy = EGD->fakecorr[fcbeg].fy;
47                 if((u.ux == fcx && u.uy == fcy) || cansee(fcx,fcy) ||
48                    m_at(fcx,fcy))
49                         return;
50                 crm = &levl[fcx][fcy];
51                 crm->typ = EGD->fakecorr[fcbeg].ftyp;
52                 if(!crm->typ) crm->seen = 0;
53                 newsym(fcx,fcy);
54                 EGD->fcbeg++;
55         }
56         /* it seems he left the corridor - let the guard disappear */
57         mondead(guard);
58         guard = 0;
59 }
60
61 static
62 goldincorridor()
63 {
64         int fci;
65
66         for(fci = EGD->fcbeg; fci < EGD->fcend; fci++)
67                 if(g_at(EGD->fakecorr[fci].fx, EGD->fakecorr[fci].fy))
68                         return(1);
69         return(0);
70 }
71
72 setgd(){
73 struct monst *mtmp;
74         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isgd){
75                 guard = mtmp;
76                 gdlevel = dlevel;
77                 return;
78         }
79         guard = 0;
80 }
81
82 invault(){
83 int tmp = inroom(u.ux, u.uy);
84     if(tmp < 0 || rooms[tmp].rtype != VAULT) {
85         u.uinvault = 0;
86         return;
87     }
88     if(++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) {
89         char buf[BUFSZ];
90         int x,y,dd,gx,gy;
91
92         /* first find the goal for the guard */
93         for(dd = 1; (dd < ROWNO || dd < COLNO); dd++) {
94           for(y = u.uy-dd; y <= u.uy+dd; y++) {
95             if(y < 0 || y > ROWNO-1) continue;
96             for(x = u.ux-dd; x <= u.ux+dd; x++) {
97               if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd)
98                 x = u.ux+dd;
99               if(x < 0 || x > COLNO-1) continue;
100               if(levl[x][y].typ == CORR) goto fnd;
101             }
102           }
103         }
104         impossible("Not a single corridor on this level??");
105         tele();
106         return;
107 fnd:
108         gx = x; gy = y;
109
110         /* next find a good place for a door in the wall */
111         x = u.ux; y = u.uy;
112         while(levl[x][y].typ == ROOM) {
113                 int dx,dy;
114
115                 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
116                 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
117                 if(abs(gx-x) >= abs(gy-y))
118                         x += dx;
119                 else
120                         y += dy;
121         }
122
123         /* make something interesting happen */
124         if(!(guard = makemon(&pm_guard,x,y))) return;
125         guard->isgd = guard->mpeaceful = 1;
126         EGD->gddone = 0;
127         gdlevel = dlevel;
128         if(!cansee(guard->mx, guard->my)) {
129                 mondead(guard);
130                 guard = 0;
131                 return;
132         }
133
134         pline("Suddenly one of the Vault's guards enters!");
135         pmon(guard);
136         do {
137                 pline("\"Hello stranger, who are you?\" - ");
138                 getlin(buf);
139         } while (!letter(buf[0]));
140
141         if(!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) {
142                 pline("\"Oh, yes - of course. Sorry to have disturbed you.\"");
143                 mondead(guard);
144                 guard = 0;
145                 return;
146         }
147         clrlin();
148         pline("\"I don't know you.\"");
149         if(!u.ugold)
150             pline("\"Please follow me.\"");
151         else {
152             pline("\"Most likely all that gold was stolen from this vault.\"");
153             pline("\"Please drop your gold (say d$ ) and follow me.\"");
154         }
155         EGD->gdx = gx;
156         EGD->gdy = gy;
157         EGD->fcbeg = 0;
158         EGD->fakecorr[0].fx = x;
159         EGD->fakecorr[0].fy = y;
160         EGD->fakecorr[0].ftyp = levl[x][y].typ;
161         levl[x][y].typ = DOOR;
162         EGD->fcend = 1;
163     }
164 }
165
166 gd_move(){
167 int x,y,dx,dy,gx,gy,nx,ny,typ;
168 struct fakecorridor *fcp;
169 struct rm *crm;
170         if(!guard || gdlevel != dlevel){
171                 impossible("Where is the guard?");
172                 return(2);      /* died */
173         }
174         if(u.ugold || goldincorridor())
175                 return(0);      /* didnt move */
176         if(dist(guard->mx,guard->my) > 1 || EGD->gddone) {
177                 restfakecorr();
178                 return(0);      /* didnt move */
179         }
180         x = guard->mx;
181         y = guard->my;
182         /* look around (hor & vert only) for accessible places */
183         for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) {
184             if(nx == x || ny == y) if(nx != x || ny != y)
185             if(isok(nx,ny))
186             if(!IS_WALL(typ = (crm = &levl[nx][ny])->typ) && typ != POOL) {
187                 int i;
188                 for(i = EGD->fcbeg; i < EGD->fcend; i++)
189                         if(EGD->fakecorr[i].fx == nx &&
190                            EGD->fakecorr[i].fy == ny)
191                                 goto nextnxy;
192                 if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT)
193                         goto nextnxy;
194                 /* seems we found a good place to leave him alone */
195                 EGD->gddone = 1;
196                 if(ACCESSIBLE(typ)) goto newpos;
197                 crm->typ = (typ == SCORR) ? CORR : DOOR;
198                 goto proceed;
199             }
200     nextnxy:    ;
201         }
202         nx = x;
203         ny = y;
204         gx = EGD->gdx;
205         gy = EGD->gdy;
206         dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
207         dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
208         if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy;
209
210         while((typ = (crm = &levl[nx][ny])->typ) != 0) {
211         /* in view of the above we must have IS_WALL(typ) or typ == POOL */
212         /* must be a wall here */
213                 if(isok(nx+nx-x,ny+ny-y) && typ != POOL &&
214                     ZAP_POS(levl[nx+nx-x][ny+ny-y].typ)){
215                         crm->typ = DOOR;
216                         goto proceed;
217                 }
218                 if(dy && nx != x) {
219                         nx = x; ny = y+dy;
220                         continue;
221                 }
222                 if(dx && ny != y) {
223                         ny = y; nx = x+dx; dy = 0;
224                         continue;
225                 }
226                 /* I don't like this, but ... */
227                 crm->typ = DOOR;
228                 goto proceed;
229         }
230         crm->typ = CORR;
231 proceed:
232         if(cansee(nx,ny)) {
233                 mnewsym(nx,ny);
234                 prl(nx,ny);
235         }
236         fcp = &(EGD->fakecorr[EGD->fcend]);
237         if(EGD->fcend++ == FCSIZ) panic("fakecorr overflow");
238         fcp->fx = nx;
239         fcp->fy = ny;
240         fcp->ftyp = typ;
241 newpos:
242         if(EGD->gddone) nx = ny = 0;
243         guard->mx = nx;
244         guard->my = ny;
245         pmon(guard);
246         restfakecorr();
247         return(1);
248 }
249
250 gddead(){
251         guard = 0;
252 }
253
254 replgd(mtmp,mtmp2)
255 struct monst *mtmp, *mtmp2;
256 {
257         if(mtmp == guard)
258                 guard = mtmp2;
259 }
260
261 #endif /* QUEST */