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