Fix ceiling hiders on pools

While fuzzing, I saw a sanity checking error complaining about
a ceiling hider being on top of a pool; the rock piercer was
teleported on top of the pool while it was hiding in the ceiling.

Try to be a bit more consistent when a monster is hiding in ceiling,
and if it's valid for it to be on a pool.
This commit is contained in:
Pasi Kallinen
2023-02-02 19:04:48 +02:00
parent c2a1b97627
commit 8535b248c8
3 changed files with 19 additions and 6 deletions

View File

@@ -1559,6 +1559,7 @@ extern int max_mon_load(struct monst *);
extern boolean can_touch_safely(struct monst *, struct obj *);
extern int can_carry(struct monst *, struct obj *);
extern long mon_allowflags(struct monst *);
extern boolean m_in_air(struct monst *);
extern int mfndpos(struct monst *, coord *, long *, long);
extern boolean monnear(struct monst *, coordxy, coordxy);
extern void dmonsfree(void);

View File

@@ -153,7 +153,10 @@ sanity_check_single_mon(
if (ceiling_hider(mptr)
/* normally !accessible would be overridable with passes_walls,
but not for hiding on the ceiling */
&& (!has_ceiling(&u.uz) || !accessible(mx, my)))
&& (!has_ceiling(&u.uz) ||
!(levl[mx][my].typ == POOL
|| levl[mx][my].typ == MOAT
|| accessible(mx, my))))
impossible("ceiling hider hiding %s (%s)",
!has_ceiling(&u.uz) ? "without ceiling"
: "in solid stone",
@@ -1854,6 +1857,16 @@ mon_allowflags(struct monst* mtmp)
return allowflags;
}
/* return TRUE if monster is up in the air/on the ceiling */
boolean
m_in_air(struct monst *mtmp)
{
return (is_flyer(mtmp->data)
|| is_floater(mtmp->data)
|| (is_clinger(mtmp->data)
&& has_ceiling(&u.uz) && mtmp->mundetected));
}
/* return number of acceptable neighbour positions */
int
mfndpos(
@@ -1881,11 +1894,11 @@ mfndpos(
nodiag = NODIAG(mdat - mons);
wantpool = (mdat->mlet == S_EEL);
poolok = ((!Is_waterlevel(&u.uz) && !grounded(mdat))
poolok = ((!Is_waterlevel(&u.uz) && m_in_air(mon))
|| (is_swimmer(mdat) && !wantpool));
/* note: floating eye is the only is_floater() so this could be
simplified, but then adding another floater would be error prone */
lavaok = (!grounded(mdat) || likes_lava(mdat));
lavaok = (m_in_air(mon) || likes_lava(mdat));
if (mdat == &mons[PM_FLOATING_EYE]) /* prefers to avoid heat */
lavaok = FALSE;
thrudoor = ((flag & (ALLOW_WALL | BUSTDOOR)) != 0L);

View File

@@ -133,7 +133,7 @@ goodpos(
return (is_swimmer(mdat)
|| (!Is_waterlevel(&u.uz)
&& !is_waterwall(x, y)
&& !grounded(mdat)));
&& m_in_air(mtmp)));
} else if (mdat->mlet == S_EEL && rn2(13) && !ignorewater) {
return FALSE;
} else if (is_lava(x, y) && !ignorelava) {
@@ -147,8 +147,7 @@ goodpos(
&& uarmf->oerodeproof)
|| (Upolyd && likes_lava(gy.youmonst.data)));
else
return (is_floater(mdat) || is_flyer(mdat)
|| likes_lava(mdat));
return (m_in_air(mtmp) || likes_lava(mdat));
}
if (passes_walls(mdat) && may_passwall(x, y))
return TRUE;