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