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:
@@ -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);
|
||||
|
||||
19
src/mon.c
19
src/mon.c
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user