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