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