xref: /openbsd-src/games/hack/hack.vault.c (revision aed906e4b20d9afbda31247cdb6acf6f29da8819)
1*aed906e4Smestre /*	$OpenBSD: hack.vault.c,v 1.8 2016/01/09 18:33:15 mestre Exp $	*/
2d0b779f3Sniklas 
3df930be7Sderaadt /*
4d25013f2Scamield  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5d25013f2Scamield  * Amsterdam
6d25013f2Scamield  * All rights reserved.
7d25013f2Scamield  *
8d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
9d25013f2Scamield  * modification, are permitted provided that the following conditions are
10d25013f2Scamield  * met:
11d25013f2Scamield  *
12d25013f2Scamield  * - Redistributions of source code must retain the above copyright notice,
13d25013f2Scamield  * this list of conditions and the following disclaimer.
14d25013f2Scamield  *
15d25013f2Scamield  * - Redistributions in binary form must reproduce the above copyright
16d25013f2Scamield  * notice, this list of conditions and the following disclaimer in the
17d25013f2Scamield  * documentation and/or other materials provided with the distribution.
18d25013f2Scamield  *
19d25013f2Scamield  * - Neither the name of the Stichting Centrum voor Wiskunde en
20d25013f2Scamield  * Informatica, nor the names of its contributors may be used to endorse or
21d25013f2Scamield  * promote products derived from this software without specific prior
22d25013f2Scamield  * written permission.
23d25013f2Scamield  *
24d25013f2Scamield  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25d25013f2Scamield  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26d25013f2Scamield  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27d25013f2Scamield  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28d25013f2Scamield  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31d25013f2Scamield  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32d25013f2Scamield  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33d25013f2Scamield  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34d25013f2Scamield  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35d25013f2Scamield  */
36d25013f2Scamield 
37d25013f2Scamield /*
38d25013f2Scamield  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39d25013f2Scamield  * All rights reserved.
40d25013f2Scamield  *
41d25013f2Scamield  * Redistribution and use in source and binary forms, with or without
42d25013f2Scamield  * modification, are permitted provided that the following conditions
43d25013f2Scamield  * are met:
44d25013f2Scamield  * 1. Redistributions of source code must retain the above copyright
45d25013f2Scamield  *    notice, this list of conditions and the following disclaimer.
46d25013f2Scamield  * 2. Redistributions in binary form must reproduce the above copyright
47d25013f2Scamield  *    notice, this list of conditions and the following disclaimer in the
48d25013f2Scamield  *    documentation and/or other materials provided with the distribution.
49d25013f2Scamield  * 3. The name of the author may not be used to endorse or promote products
50d25013f2Scamield  *    derived from this software without specific prior written permission.
51d25013f2Scamield  *
52d25013f2Scamield  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53d25013f2Scamield  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54d25013f2Scamield  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55d25013f2Scamield  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56d25013f2Scamield  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57d25013f2Scamield  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58d25013f2Scamield  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59d25013f2Scamield  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60d25013f2Scamield  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61d25013f2Scamield  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62df930be7Sderaadt  */
63df930be7Sderaadt 
64d07db98cSpjanzen #include <stdlib.h>
65*aed906e4Smestre 
66df930be7Sderaadt #include "hack.h"
67*aed906e4Smestre 
68df930be7Sderaadt #ifdef QUEST
694a5fbbc4Spjanzen void
setgd(void)70*aed906e4Smestre setgd(void)
714a5fbbc4Spjanzen {}
724a5fbbc4Spjanzen 
734a5fbbc4Spjanzen int
gd_move(void)74*aed906e4Smestre gd_move(void)
754a5fbbc4Spjanzen {
764a5fbbc4Spjanzen 	return(2);
774a5fbbc4Spjanzen }
784a5fbbc4Spjanzen 
794a5fbbc4Spjanzen void
gddead(void)80*aed906e4Smestre gddead(void)
814a5fbbc4Spjanzen {}
824a5fbbc4Spjanzen 
834a5fbbc4Spjanzen void
replgd(struct monst * mtmp,struct monst * mtmp2)844a5fbbc4Spjanzen replgd(struct monst *mtmp, struct monst *mtmp2)
854a5fbbc4Spjanzen {}
864a5fbbc4Spjanzen 
874a5fbbc4Spjanzen void
invault(void)88*aed906e4Smestre invault(void)
894a5fbbc4Spjanzen {}
90df930be7Sderaadt 
91df930be7Sderaadt #else
92*aed906e4Smestre extern struct monst *makemon(struct permonst *, int, int);
93df930be7Sderaadt #define	FCSIZ	(ROWNO+COLNO)
94df930be7Sderaadt struct fakecorridor {
95df930be7Sderaadt 	xchar fx,fy,ftyp;
96df930be7Sderaadt };
97df930be7Sderaadt 
98df930be7Sderaadt struct egd {
99df930be7Sderaadt 	int fcbeg, fcend;	/* fcend: first unused pos */
100df930be7Sderaadt 	xchar gdx, gdy;		/* goal of guard's walk */
101df930be7Sderaadt 	unsigned gddone:1;
102df930be7Sderaadt 	struct fakecorridor fakecorr[FCSIZ];
103df930be7Sderaadt };
104df930be7Sderaadt 
105df930be7Sderaadt static struct permonst pm_guard =
106df930be7Sderaadt 	{ "guard", '@', 12, 12, -1, 4, 10, sizeof(struct egd) };
107df930be7Sderaadt 
108df930be7Sderaadt static struct monst *guard;
109df930be7Sderaadt static int gdlevel;
110df930be7Sderaadt #define	EGD	((struct egd *)(&(guard->mextra[0])))
111df930be7Sderaadt 
1124a5fbbc4Spjanzen static void restfakecorr(void);
1134a5fbbc4Spjanzen static int  goldincorridor(void);
1144a5fbbc4Spjanzen 
1154a5fbbc4Spjanzen 
1164a5fbbc4Spjanzen static void
restfakecorr(void)117*aed906e4Smestre restfakecorr(void)
118df930be7Sderaadt {
1194a5fbbc4Spjanzen 	int fcx,fcy,fcbeg;
1204a5fbbc4Spjanzen 	struct rm *crm;
121df930be7Sderaadt 
122df930be7Sderaadt 	while((fcbeg = EGD->fcbeg) < EGD->fcend) {
123df930be7Sderaadt 		fcx = EGD->fakecorr[fcbeg].fx;
124df930be7Sderaadt 		fcy = EGD->fakecorr[fcbeg].fy;
125df930be7Sderaadt 		if((u.ux == fcx && u.uy == fcy) || cansee(fcx,fcy) ||
126df930be7Sderaadt 		   m_at(fcx,fcy))
127df930be7Sderaadt 			return;
128df930be7Sderaadt 		crm = &levl[fcx][fcy];
129df930be7Sderaadt 		crm->typ = EGD->fakecorr[fcbeg].ftyp;
130df930be7Sderaadt 		if(!crm->typ) crm->seen = 0;
131df930be7Sderaadt 		newsym(fcx,fcy);
132df930be7Sderaadt 		EGD->fcbeg++;
133df930be7Sderaadt 	}
134df930be7Sderaadt 	/* it seems he left the corridor - let the guard disappear */
135df930be7Sderaadt 	mondead(guard);
136df930be7Sderaadt 	guard = 0;
137df930be7Sderaadt }
138df930be7Sderaadt 
1394a5fbbc4Spjanzen static int
goldincorridor(void)140*aed906e4Smestre goldincorridor(void)
141df930be7Sderaadt {
1424a5fbbc4Spjanzen 	int fci;
143df930be7Sderaadt 
144df930be7Sderaadt 	for(fci = EGD->fcbeg; fci < EGD->fcend; fci++)
145df930be7Sderaadt 		if(g_at(EGD->fakecorr[fci].fx, EGD->fakecorr[fci].fy))
146df930be7Sderaadt 			return(1);
147df930be7Sderaadt 	return(0);
148df930be7Sderaadt }
149df930be7Sderaadt 
1504a5fbbc4Spjanzen void
setgd(void)151*aed906e4Smestre setgd(void)
1524a5fbbc4Spjanzen {
1534a5fbbc4Spjanzen 	struct monst *mtmp;
1544a5fbbc4Spjanzen 
155df930be7Sderaadt 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isgd){
156df930be7Sderaadt 		guard = mtmp;
157df930be7Sderaadt 		gdlevel = dlevel;
158df930be7Sderaadt 		return;
159df930be7Sderaadt 	}
160df930be7Sderaadt 	guard = 0;
161df930be7Sderaadt }
162df930be7Sderaadt 
1634a5fbbc4Spjanzen void
invault(void)164*aed906e4Smestre invault(void)
1654a5fbbc4Spjanzen {
1664a5fbbc4Spjanzen 	int tmp = inroom(u.ux, u.uy);
1674a5fbbc4Spjanzen 
168df930be7Sderaadt     if(tmp < 0 || rooms[tmp].rtype != VAULT) {
169df930be7Sderaadt 	u.uinvault = 0;
170df930be7Sderaadt 	return;
171df930be7Sderaadt     }
172df930be7Sderaadt     if(++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) {
173df930be7Sderaadt 	char buf[BUFSZ];
1744a5fbbc4Spjanzen 	int x,y,dd,gx,gy;
175df930be7Sderaadt 
176df930be7Sderaadt 	/* first find the goal for the guard */
177df930be7Sderaadt 	for(dd = 1; (dd < ROWNO || dd < COLNO); dd++) {
178df930be7Sderaadt 	  for(y = u.uy-dd; y <= u.uy+dd; y++) {
179df930be7Sderaadt 	    if(y < 0 || y > ROWNO-1) continue;
180df930be7Sderaadt 	    for(x = u.ux-dd; x <= u.ux+dd; x++) {
181df930be7Sderaadt 	      if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd)
182df930be7Sderaadt 		x = u.ux+dd;
183df930be7Sderaadt 	      if(x < 0 || x > COLNO-1) continue;
184df930be7Sderaadt 	      if(levl[x][y].typ == CORR) goto fnd;
185df930be7Sderaadt 	    }
186df930be7Sderaadt 	  }
187df930be7Sderaadt 	}
188df930be7Sderaadt 	impossible("Not a single corridor on this level??");
189df930be7Sderaadt 	tele();
190df930be7Sderaadt 	return;
191df930be7Sderaadt fnd:
192df930be7Sderaadt 	gx = x; gy = y;
193df930be7Sderaadt 
194df930be7Sderaadt 	/* next find a good place for a door in the wall */
195df930be7Sderaadt 	x = u.ux; y = u.uy;
196df930be7Sderaadt 	while(levl[x][y].typ == ROOM) {
1974a5fbbc4Spjanzen 		int dx,dy;
198df930be7Sderaadt 
199df930be7Sderaadt 		dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
200df930be7Sderaadt 		dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
201df930be7Sderaadt 		if(abs(gx-x) >= abs(gy-y))
202df930be7Sderaadt 			x += dx;
203df930be7Sderaadt 		else
204df930be7Sderaadt 			y += dy;
205df930be7Sderaadt 	}
206df930be7Sderaadt 
207df930be7Sderaadt 	/* make something interesting happen */
208df930be7Sderaadt 	if(!(guard = makemon(&pm_guard,x,y))) return;
209df930be7Sderaadt 	guard->isgd = guard->mpeaceful = 1;
210df930be7Sderaadt 	EGD->gddone = 0;
211df930be7Sderaadt 	gdlevel = dlevel;
212df930be7Sderaadt 	if(!cansee(guard->mx, guard->my)) {
213df930be7Sderaadt 		mondead(guard);
214df930be7Sderaadt 		guard = 0;
215df930be7Sderaadt 		return;
216df930be7Sderaadt 	}
217df930be7Sderaadt 
218df930be7Sderaadt 	pline("Suddenly one of the Vault's guards enters!");
219df930be7Sderaadt 	pmon(guard);
220df930be7Sderaadt 	do {
221df930be7Sderaadt 		pline("\"Hello stranger, who are you?\" - ");
222df930be7Sderaadt 		getlin(buf);
223df930be7Sderaadt 	} while (!letter(buf[0]));
224df930be7Sderaadt 
225df930be7Sderaadt 	if(!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) {
226df930be7Sderaadt 		pline("\"Oh, yes - of course. Sorry to have disturbed you.\"");
227df930be7Sderaadt 		mondead(guard);
228df930be7Sderaadt 		guard = 0;
229df930be7Sderaadt 		return;
230df930be7Sderaadt 	}
231df930be7Sderaadt 	clrlin();
232df930be7Sderaadt 	pline("\"I don't know you.\"");
233df930be7Sderaadt 	if(!u.ugold)
234df930be7Sderaadt 	    pline("\"Please follow me.\"");
235df930be7Sderaadt 	else {
236df930be7Sderaadt 	    pline("\"Most likely all that gold was stolen from this vault.\"");
237df930be7Sderaadt 	    pline("\"Please drop your gold (say d$ ) and follow me.\"");
238df930be7Sderaadt 	}
239df930be7Sderaadt 	EGD->gdx = gx;
240df930be7Sderaadt 	EGD->gdy = gy;
241df930be7Sderaadt 	EGD->fcbeg = 0;
242df930be7Sderaadt 	EGD->fakecorr[0].fx = x;
243df930be7Sderaadt 	EGD->fakecorr[0].fy = y;
244df930be7Sderaadt 	EGD->fakecorr[0].ftyp = levl[x][y].typ;
245df930be7Sderaadt 	levl[x][y].typ = DOOR;
246df930be7Sderaadt 	EGD->fcend = 1;
247df930be7Sderaadt     }
248df930be7Sderaadt }
249df930be7Sderaadt 
2504a5fbbc4Spjanzen int
gd_move(void)251*aed906e4Smestre gd_move(void)
2524a5fbbc4Spjanzen {
2534a5fbbc4Spjanzen 	int x,y,dx,dy,gx,gy,nx,ny,typ;
2544a5fbbc4Spjanzen 	struct fakecorridor *fcp;
2554a5fbbc4Spjanzen 	struct rm *crm;
2564a5fbbc4Spjanzen 
257df930be7Sderaadt 	if(!guard || gdlevel != dlevel){
258df930be7Sderaadt 		impossible("Where is the guard?");
259df930be7Sderaadt 		return(2);	/* died */
260df930be7Sderaadt 	}
261df930be7Sderaadt 	if(u.ugold || goldincorridor())
262df930be7Sderaadt 		return(0);	/* didnt move */
263df930be7Sderaadt 	if(dist(guard->mx,guard->my) > 1 || EGD->gddone) {
264df930be7Sderaadt 		restfakecorr();
265df930be7Sderaadt 		return(0);	/* didnt move */
266df930be7Sderaadt 	}
267df930be7Sderaadt 	x = guard->mx;
268df930be7Sderaadt 	y = guard->my;
269df930be7Sderaadt 	/* look around (hor & vert only) for accessible places */
270df930be7Sderaadt 	for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) {
271df930be7Sderaadt 	    if(nx == x || ny == y) if(nx != x || ny != y)
272df930be7Sderaadt 	    if(isok(nx,ny))
273df930be7Sderaadt 	    if(!IS_WALL(typ = (crm = &levl[nx][ny])->typ) && typ != POOL) {
2744a5fbbc4Spjanzen 		int i;
275df930be7Sderaadt 		for(i = EGD->fcbeg; i < EGD->fcend; i++)
276df930be7Sderaadt 			if(EGD->fakecorr[i].fx == nx &&
277df930be7Sderaadt 			   EGD->fakecorr[i].fy == ny)
278df930be7Sderaadt 				goto nextnxy;
279df930be7Sderaadt 		if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT)
280df930be7Sderaadt 			goto nextnxy;
281df930be7Sderaadt 		/* seems we found a good place to leave him alone */
282df930be7Sderaadt 		EGD->gddone = 1;
283df930be7Sderaadt 		if(ACCESSIBLE(typ)) goto newpos;
284df930be7Sderaadt 		crm->typ = (typ == SCORR) ? CORR : DOOR;
285df930be7Sderaadt 		goto proceed;
286df930be7Sderaadt 	    }
287df930be7Sderaadt     nextnxy:	;
288df930be7Sderaadt 	}
289df930be7Sderaadt 	nx = x;
290df930be7Sderaadt 	ny = y;
291df930be7Sderaadt 	gx = EGD->gdx;
292df930be7Sderaadt 	gy = EGD->gdy;
293df930be7Sderaadt 	dx = (gx > x) ? 1 : (gx < x) ? -1 : 0;
294df930be7Sderaadt 	dy = (gy > y) ? 1 : (gy < y) ? -1 : 0;
295df930be7Sderaadt 	if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy;
296df930be7Sderaadt 
297df930be7Sderaadt 	while((typ = (crm = &levl[nx][ny])->typ) != 0) {
298df930be7Sderaadt 	/* in view of the above we must have IS_WALL(typ) or typ == POOL */
299df930be7Sderaadt 	/* must be a wall here */
300df930be7Sderaadt 		if(isok(nx+nx-x,ny+ny-y) && typ != POOL &&
301df930be7Sderaadt 		    ZAP_POS(levl[nx+nx-x][ny+ny-y].typ)){
302df930be7Sderaadt 			crm->typ = DOOR;
303df930be7Sderaadt 			goto proceed;
304df930be7Sderaadt 		}
305df930be7Sderaadt 		if(dy && nx != x) {
306df930be7Sderaadt 			nx = x; ny = y+dy;
307df930be7Sderaadt 			continue;
308df930be7Sderaadt 		}
309df930be7Sderaadt 		if(dx && ny != y) {
310df930be7Sderaadt 			ny = y; nx = x+dx; dy = 0;
311df930be7Sderaadt 			continue;
312df930be7Sderaadt 		}
313df930be7Sderaadt 		/* I don't like this, but ... */
314df930be7Sderaadt 		crm->typ = DOOR;
315df930be7Sderaadt 		goto proceed;
316df930be7Sderaadt 	}
317df930be7Sderaadt 	crm->typ = CORR;
318df930be7Sderaadt proceed:
319df930be7Sderaadt 	if(cansee(nx,ny)) {
320df930be7Sderaadt 		mnewsym(nx,ny);
321df930be7Sderaadt 		prl(nx,ny);
322df930be7Sderaadt 	}
323df930be7Sderaadt 	fcp = &(EGD->fakecorr[EGD->fcend]);
324df930be7Sderaadt 	if(EGD->fcend++ == FCSIZ) panic("fakecorr overflow");
325df930be7Sderaadt 	fcp->fx = nx;
326df930be7Sderaadt 	fcp->fy = ny;
327df930be7Sderaadt 	fcp->ftyp = typ;
328df930be7Sderaadt newpos:
329df930be7Sderaadt 	if(EGD->gddone) nx = ny = 0;
330df930be7Sderaadt 	guard->mx = nx;
331df930be7Sderaadt 	guard->my = ny;
332df930be7Sderaadt 	pmon(guard);
333df930be7Sderaadt 	restfakecorr();
334df930be7Sderaadt 	return(1);
335df930be7Sderaadt }
336df930be7Sderaadt 
3374a5fbbc4Spjanzen void
gddead(void)338*aed906e4Smestre gddead(void)
3394a5fbbc4Spjanzen {
340df930be7Sderaadt 	guard = 0;
341df930be7Sderaadt }
342df930be7Sderaadt 
3434a5fbbc4Spjanzen void
replgd(struct monst * mtmp,struct monst * mtmp2)3444a5fbbc4Spjanzen replgd(struct monst *mtmp, struct monst *mtmp2)
345df930be7Sderaadt {
346df930be7Sderaadt 	if(mtmp == guard)
347df930be7Sderaadt 		guard = mtmp2;
348df930be7Sderaadt }
349df930be7Sderaadt 
35054da88e4Spjanzen #endif /* QUEST */
351