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) 21 { 22 } 23 24 void 25 replgd(struct monst *mtmp, struct monst *mtmp2) 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) crm->seen = 0; 73 newsym(fcx,fcy); 74 EGD->fcbeg++; 75 } 76 /* it seems he left the corridor - let the guard disappear */ 77 mondead(guard); 78 guard = 0; 79 } 80 81 static bool 82 goldincorridor(void) 83 { 84 int fci; 85 86 for(fci = EGD->fcbeg; fci < EGD->fcend; fci++) 87 if(g_at(EGD->fakecorr[fci].fx, EGD->fakecorr[fci].fy)) 88 return(1); 89 return(0); 90 } 91 92 void 93 setgd(void) 94 { 95 struct monst *mtmp; 96 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isgd){ 97 guard = mtmp; 98 gdlevel = dlevel; 99 return; 100 } 101 guard = 0; 102 } 103 104 void 105 invault(void) 106 { 107 int tmp = inroom(u.ux, u.uy); 108 if(tmp < 0 || rooms[tmp].rtype != VAULT) { 109 u.uinvault = 0; 110 return; 111 } 112 if(++u.uinvault % 50 == 0 && (!guard || gdlevel != dlevel)) { 113 char buf[BUFSZ]; 114 int x,y,dd,gx,gy; 115 116 /* first find the goal for the guard */ 117 for(dd = 1; (dd < ROWNO || dd < COLNO); dd++) { 118 for(y = u.uy-dd; y <= u.uy+dd; y++) { 119 if(y < 0 || y > ROWNO-1) continue; 120 for(x = u.ux-dd; x <= u.ux+dd; x++) { 121 if(y != u.uy-dd && y != u.uy+dd && x != u.ux-dd) 122 x = u.ux+dd; 123 if(x < 0 || x > COLNO-1) continue; 124 if(levl[x][y].typ == CORR) goto fnd; 125 } 126 } 127 } 128 impossible("Not a single corridor on this level??"); 129 tele(); 130 return; 131 fnd: 132 gx = x; gy = y; 133 134 /* next find a good place for a door in the wall */ 135 x = u.ux; y = u.uy; 136 while(levl[x][y].typ == ROOM) { 137 int dx,dy; 138 139 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; 140 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; 141 if(abs(gx-x) >= abs(gy-y)) 142 x += dx; 143 else 144 y += dy; 145 } 146 147 /* make something interesting happen */ 148 if(!(guard = makemon(&pm_guard,x,y))) return; 149 guard->isgd = guard->mpeaceful = 1; 150 EGD->gddone = 0; 151 gdlevel = dlevel; 152 if(!cansee(guard->mx, guard->my)) { 153 mondead(guard); 154 guard = 0; 155 return; 156 } 157 158 pline("Suddenly one of the Vault's guards enters!"); 159 pmon(guard); 160 do { 161 pline("\"Hello stranger, who are you?\" - "); 162 getlin(buf); 163 } while (!letter(buf[0])); 164 165 if(!strcmp(buf, "Croesus") || !strcmp(buf, "Kroisos")) { 166 pline("\"Oh, yes - of course. Sorry to have disturbed you.\""); 167 mondead(guard); 168 guard = 0; 169 return; 170 } 171 clrlin(); 172 pline("\"I don't know you.\""); 173 if(!u.ugold) 174 pline("\"Please follow me.\""); 175 else { 176 pline("\"Most likely all that gold was stolen from this vault.\""); 177 pline("\"Please drop your gold (say d$ ) and follow me.\""); 178 } 179 EGD->gdx = gx; 180 EGD->gdy = gy; 181 EGD->fcbeg = 0; 182 EGD->fakecorr[0].fx = x; 183 EGD->fakecorr[0].fy = y; 184 EGD->fakecorr[0].ftyp = levl[x][y].typ; 185 levl[x][y].typ = DOOR; 186 EGD->fcend = 1; 187 } 188 } 189 190 int 191 gd_move(void) 192 { 193 int x,y,dx,dy,gx,gy,nx,ny,typ; 194 struct fakecorridor *fcp; 195 struct rm *crm; 196 if(!guard || gdlevel != dlevel){ 197 impossible("Where is the guard?"); 198 return(2); /* died */ 199 } 200 if(u.ugold || goldincorridor()) 201 return(0); /* didnt move */ 202 if(dist(guard->mx,guard->my) > 1 || EGD->gddone) { 203 restfakecorr(); 204 return(0); /* didnt move */ 205 } 206 x = guard->mx; 207 y = guard->my; 208 /* look around (hor & vert only) for accessible places */ 209 for(nx = x-1; nx <= x+1; nx++) for(ny = y-1; ny <= y+1; ny++) { 210 if(nx == x || ny == y) if(nx != x || ny != y) 211 if(isok(nx,ny)) 212 if(!IS_WALL(typ = (crm = &levl[nx][ny])->typ) && typ != POOL) { 213 int i; 214 for(i = EGD->fcbeg; i < EGD->fcend; i++) 215 if(EGD->fakecorr[i].fx == nx && 216 EGD->fakecorr[i].fy == ny) 217 goto nextnxy; 218 if((i = inroom(nx,ny)) >= 0 && rooms[i].rtype == VAULT) 219 goto nextnxy; 220 /* seems we found a good place to leave him alone */ 221 EGD->gddone = 1; 222 if(ACCESSIBLE(typ)) goto newpos; 223 crm->typ = (typ == SCORR) ? CORR : DOOR; 224 goto proceed; 225 } 226 nextnxy: ; 227 } 228 nx = x; 229 ny = y; 230 gx = EGD->gdx; 231 gy = EGD->gdy; 232 dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; 233 dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; 234 if(abs(gx-x) >= abs(gy-y)) nx += dx; else ny += dy; 235 236 while((typ = (crm = &levl[nx][ny])->typ) != 0) { 237 /* in view of the above we must have IS_WALL(typ) or typ == POOL */ 238 /* must be a wall here */ 239 if(isok(nx+nx-x,ny+ny-y) && typ != POOL && 240 ZAP_POS(levl[nx+nx-x][ny+ny-y].typ)){ 241 crm->typ = DOOR; 242 goto proceed; 243 } 244 if(dy && nx != x) { 245 nx = x; ny = y+dy; 246 continue; 247 } 248 if(dx && ny != y) { 249 ny = y; nx = x+dx; dy = 0; 250 continue; 251 } 252 /* I don't like this, but ... */ 253 crm->typ = DOOR; 254 goto proceed; 255 } 256 crm->typ = CORR; 257 proceed: 258 if(cansee(nx,ny)) { 259 mnewsym(nx,ny); 260 prl(nx,ny); 261 } 262 fcp = &(EGD->fakecorr[EGD->fcend]); 263 if(EGD->fcend++ == FCSIZ) panic("fakecorr overflow"); 264 fcp->fx = nx; 265 fcp->fy = ny; 266 fcp->ftyp = typ; 267 newpos: 268 if(EGD->gddone) nx = ny = 0; 269 guard->mx = nx; 270 guard->my = ny; 271 pmon(guard); 272 restfakecorr(); 273 return(1); 274 } 275 276 void 277 gddead(void) 278 { 279 guard = 0; 280 } 281 282 void 283 replgd(struct monst *mtmp, struct monst *mtmp2) 284 { 285 if(mtmp == guard) 286 guard = mtmp2; 287 } 288 289 #endif /* QUEST */ 290