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