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