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