xref: /dragonfly/games/hack/hack.vault.c (revision 479ab7f0)
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