diff --git a/include/extern.h b/include/extern.h index ce3d3bd87..4ea7e7575 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1514,6 +1514,7 @@ E void FDECL(seemimic, (struct monst *)); E void NDECL(rescham); E void NDECL(restartcham); E void FDECL(restore_cham, (struct monst *)); +E void FDECL(maybe_unhide_at, (XCHAR_P, XCHAR_P)); E boolean FDECL(hideunder, (struct monst *)); E void FDECL(hide_monst, (struct monst *)); E void FDECL(mon_animal_list, (BOOLEAN_P)); diff --git a/src/ball.c b/src/ball.c index 7bc78dd07..60099a83b 100644 --- a/src/ball.c +++ b/src/ball.c @@ -162,7 +162,7 @@ unplacebc_core() obj_extract_self(uball); if (Blind && (u.bc_felt & BC_BALL)) /* drop glyph */ levl[uball->ox][uball->oy].glyph = u.bglyph; - + maybe_unhide_at(uball->ox, uball->oy); newsym(uball->ox, uball->oy); } obj_extract_self(uchain); @@ -536,9 +536,11 @@ xchar ballx, bally, chainx, chainy; /* only matter !before */ } remove_object(uchain); + maybe_unhide_at(uchain->ox, uchain->oy); newsym(uchain->ox, uchain->oy); if (!carried(uball)) { remove_object(uball); + maybe_unhide_at(uball->ox, uball->oy); newsym(uball->ox, uball->oy); } } else { diff --git a/src/invent.c b/src/invent.c index 7c1393d2d..16d6ff01f 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1225,8 +1225,10 @@ register struct obj *obj; } update_map = (obj->where == OBJ_FLOOR); obj_extract_self(obj); - if (update_map) + if (update_map) { + maybe_unhide_at(obj->ox, obj->oy); newsym(obj->ox, obj->oy); + } obfree(obj, (struct obj *) 0); /* frees contents also */ } diff --git a/src/mkobj.c b/src/mkobj.c index f4960008b..71ef55a88 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -2175,6 +2175,10 @@ struct obj *obj; panic("dealloc_obj with nobj"); if (obj->cobj) panic("dealloc_obj with cobj"); + if (obj == uball || obj == uchain) + impossible("dealloc_obj called on %s, owornmask=%lx", + (obj == uball) ? "uball" : "uchain", + obj->owornmask); /* free up any timers attached to the object */ if (obj->timed) diff --git a/src/mon.c b/src/mon.c index 6ae225d44..6a534d084 100644 --- a/src/mon.c +++ b/src/mon.c @@ -99,6 +99,29 @@ const char *msg; /* guardian angel on astral level is tame but has emin rather than edog */ if (mtmp->mtame && !has_edog(mtmp) && !mtmp->isminion) impossible("pet without edog (%s)", msg); + + if (mtmp->mtrapped) { + if (mtmp->wormno) { + /* TODO: how to check worm in trap? */ + } else if (!t_at(mtmp->mx, mtmp->my)) + impossible("trapped without a trap (%s)", msg); + } + + /* monster is hiding? */ + if (mtmp->mundetected) { + struct trap *t; + + if (mtmp == u.ustuck) + impossible("hiding monster stuck to you (%s)", msg); + if (m_at(mtmp->mx, mtmp->my) == mtmp && hides_under(mtmp->data) && !OBJ_AT(mtmp->mx, mtmp->my)) + impossible("mon hiding under nonexistent obj (%s)", msg); + if (mtmp->data->mlet == S_EEL && !is_pool(mtmp->mx, mtmp->my) && !Is_waterlevel(&u.uz)) + impossible("eel hiding out of water (%s)", msg); + if (mtmp->mtrapped && (t = t_at(mtmp->mx, mtmp->my)) != 0 + && !(t->ttyp == PIT || t->ttyp == SPIKED_PIT)) + impossible("hiding while trapped in a non-pit (%s)", msg); + } + } void @@ -3537,6 +3560,19 @@ register struct monst *mtmp; return FALSE; } +/* reveal a monster at x,y hiding under an object, + if there are no objects there */ +void +maybe_unhide_at(x, y) +xchar x, y; +{ + struct monst *mtmp; + + if (!OBJ_AT(x, y) && (mtmp = m_at(x, y)) != 0 + && mtmp->mundetected && hides_under(mtmp->data)) + (void) hideunder(mtmp); +} + /* monster/hero tries to hide under something at the current location */ boolean hideunder(mtmp) diff --git a/src/restore.c b/src/restore.c index 3ca9c0e2a..deaabb4fb 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1128,6 +1128,8 @@ xchar lev; place_monster(mtmp, mtmp->mx, mtmp->my); if (mtmp->wormno) place_wsegs(mtmp, NULL); + if (hides_under(mtmp->data) && mtmp->mundetected) + (void) hideunder(mtmp); /* regenerate monsters while on another level */ if (!u.uz.dlevel) diff --git a/src/teleport.c b/src/teleport.c index b46a9b56d..e5e34c5ae 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -1258,6 +1258,10 @@ register int x, y; the latter only happens if you've attacked them with polymorph */ if (resident_shk && !inhishop(mtmp)) make_angry_shk(mtmp, oldx, oldy); + + /* trapped monster teleported away */ + if (mtmp->mtrapped && !mtmp->wormno) + (void) mintrap(mtmp); } static stairway *