diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 303ef1f83..e23786335 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -384,6 +384,14 @@ when dying outside all shops on a level with multiple shopkeepers and one takes hero poly'd into a critter without hands could still open tins if a vault guard was killed, his inventory would be dropped at <0,0> throwing gold to/at a vault guard will no longer be treated as an attack +non-pit traps created in vault guard's temporary corridor would remain after + the location reverted to solid rock +using magic to light vault guard's temporary corridor would produce lit solid + rock after reversion, and then yield lit corridor if dug out again +if hero was blind, killing the vault guard while in his temporary corridor + would leave hero encased in solid rock without informing player +if hero dragged iron ball into temporary corridor and then killed vault guard, + the portion of corridor currently in existence would become permanent Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 3ad7c4d27..24b4f81b6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -332,6 +332,7 @@ E int FDECL(back_to_glyph, (XCHAR_P,XCHAR_P)); E int FDECL(zapdir_to_glyph, (int,int,int)); E int FDECL(glyph_at, (XCHAR_P,XCHAR_P)); E void NDECL(set_wall_state); +E void FDECL(unset_seenv, (struct rm *,int,int,int,int)); /* ### do.c ### */ diff --git a/src/display.c b/src/display.c index 7e1c3b0e0..c9437b1ef 100644 --- a/src/display.c +++ b/src/display.c @@ -1858,9 +1858,22 @@ set_seenv(lev, x0, y0, x, y) int x0, y0, x, y; /* from, to */ { int dx = x-x0, dy = y0-y; + lev->seenv |= seenv_matrix[sign(dy)+1][sign(dx)+1]; } +/* Called by blackout(vault.c) when vault guard removes temporary corridor, + turning spot back into stone; is an adjacent spot. */ +void +unset_seenv(lev, x0, y0, x1, y1) + struct rm *lev; /* &levl[x1][y1] */ + int x0, y0, x1, y1; /* from, to; abs(x1-x0)==1 && abs(y0-y1)==1 */ +{ + int dx = x1 - x0, dy = y0 - y1; + + lev->seenv &= ~seenv_matrix[dy + 1][dx + 1]; +} + /* ------------------------------------------------------------------------- */ /* T wall types, one for each row in wall_matrix[][]. */ diff --git a/src/mon.c b/src/mon.c index 214c2a482..3238792e0 100644 --- a/src/mon.c +++ b/src/mon.c @@ -535,6 +535,9 @@ movemon() } #endif nmtmp = mtmp->nmon; + /* one dead monster needs to perform a move after death: + vault guard whose temporary corridor is still on the map */ + if (mtmp->isgd && !mtmp->mx && mtmp->mhp <= 0) (void)gd_move(mtmp); if (DEADMONSTER(mtmp)) continue; /* Find a monster that we have not treated yet. */ diff --git a/src/vault.c b/src/vault.c index b46ce50bb..af37a0625 100644 --- a/src/vault.c +++ b/src/vault.c @@ -7,6 +7,7 @@ STATIC_DCL struct monst *NDECL(findgd); STATIC_DCL boolean FDECL(clear_fcorr, (struct monst *,BOOLEAN_P)); +STATIC_DCL void FDECL(blackout, (int,int)); STATIC_DCL void FDECL(restfakecorr,(struct monst *)); STATIC_DCL boolean FDECL(in_fcorridor, (struct monst *,int,int)); STATIC_DCL void FDECL(move_gold,(struct obj *,int)); @@ -43,7 +44,8 @@ boolean forceshow; struct monst *mtmp; boolean sawcorridor = FALSE; struct egd *egrd = EGD(grd); - struct trap *trap = (struct trap *)0; + struct trap *trap; + struct rm *lev; if (!on_level(&egrd->gdlevel, &u.uz)) return TRUE; @@ -60,31 +62,60 @@ boolean forceshow; return FALSE; if ((mtmp = m_at(fcx,fcy)) != 0) { - if(mtmp->isgd) return(FALSE); - else if(!in_fcorridor(grd, u.ux, u.uy)) { - if(mtmp->mtame) yelp(mtmp); - (void) rloc(mtmp, FALSE); - } + if (mtmp->isgd) { + return FALSE; + } else if (!in_fcorridor(grd, u.ux, u.uy)) { + if (mtmp->mtame) yelp(mtmp); + (void) rloc(mtmp, FALSE); + } } - if ((trap = t_at(fcx,fcy)) != 0 && - trap->ttyp == PIT && trap->madeby_u && - IS_STWALL(egrd->fakecorr[fcbeg].ftyp)) { - /* you dug a pit while following the guard out, - so fill it in when the location reverts to stone */ - deltrap(trap); - } - if (levl[fcx][fcy].typ == CORR && cansee(fcx, fcy)) + lev = &levl[fcx][fcy]; + if (lev->typ == CORR && cansee(fcx, fcy)) sawcorridor = TRUE; - levl[fcx][fcy].typ = egrd->fakecorr[fcbeg].ftyp; + lev->typ = egrd->fakecorr[fcbeg].ftyp; + if (IS_STWALL(lev->typ)) { + /* destroy any trap here (pit dug by you, hole dug via + wand while levitating or by monster, bear trap or land + mine via object, spun web) when spot reverts to stone */ + if ((trap = t_at(fcx, fcy)) != 0) deltrap(trap); + /* undo scroll/wand/spell of light affecting this spot */ + if (lev->typ == STONE) blackout(fcx, fcy); + } map_location(fcx, fcy, 1); /* bypass vision */ - if(!ACCESSIBLE(levl[fcx][fcy].typ)) block_point(fcx,fcy); + if (!ACCESSIBLE(lev->typ)) block_point(fcx, fcy); + vision_full_recalc = 1; egrd->fcbeg++; } - if (sawcorridor) { + if (sawcorridor) pline_The("corridor disappears."); - if(IS_ROCK(levl[u.ux][u.uy].typ)) You("are encased in rock."); + if (IS_ROCK(levl[u.ux][u.uy].typ)) + You("are encased in rock."); + return TRUE; +} + +/* as a temporary corridor is removed, set stone locations and adjacent + spots to unlit; if player used scroll/wand/spell of light while inside + the corridor, we don't want the light to reappear if/when a new tunnel + goes through the same area */ +STATIC_OVL void +blackout(x, y) +int x, y; +{ + struct rm *lev; + int i, j; + + for (i = x - 1; i <= x + 1; ++i) + for (j = y - 1; j <= y + 1; ++j) { + if (!isok(i, j)) continue; + lev = &levl[i][j]; + /* [possible bug: when (i != x || j != y), perhaps we ought + to check whether the spot on the far side is lit instead + of doing a blanket blackout of adjacent locations] */ + if (lev->typ == STONE) + lev->lit = lev->waslit = 0; + /* mark as not having been seen from */ + unset_seenv(lev, x, y, i, j); } - return(TRUE); } STATIC_OVL void