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