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