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