From: Pasi Kallinen Date: Thu, 2 Apr 2020 15:15:13 +0000 (+0300) Subject: Unify checking if monster is ok in poison gas X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2f64f419ad0e1c5f4bbab55a437002706a949e23;p=nethack Unify checking if monster is ok in poison gas --- diff --git a/include/extern.h b/include/extern.h index 18443b0a2..2e1ad2a09 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1449,6 +1449,7 @@ E int FDECL(cmap_to_type, (int)); /* ### mon.c ### */ E void NDECL(mon_sanity_check); +E int FDECL(m_poisongas_ok, (struct monst *)); E int FDECL(undead_to_corpse, (int)); E int FDECL(genus, (int, int)); E int FDECL(pm_to_cham, (int)); diff --git a/include/hack.h b/include/hack.h index feb24001e..04290861f 100644 --- a/include/hack.h +++ b/include/hack.h @@ -315,6 +315,11 @@ typedef struct sortloot_item Loot; #define SHIFT_SEENMSG 0x01 /* put out a message if in sight */ #define SHIFT_MSG 0x02 /* always put out a message */ +/* m_poisongas_ok() return values */ +#define M_POISONGAS_BAD 0 /* poison gas is bad */ +#define M_POISONGAS_MINOR 1 /* poison gas is ok, maybe causes coughing */ +#define M_POISONGAS_OK 2 /* ignores poison gas completely */ + /* flags for deliver_obj_to_mon */ #define DF_NONE 0x00 #define DF_RANDOM 0x01 diff --git a/src/mon.c b/src/mon.c index 5567048b9..cd5446980 100644 --- a/src/mon.c +++ b/src/mon.c @@ -140,6 +140,40 @@ mon_sanity_check() } } +/* Would monster be OK with poison gas? */ +/* Does not check for actual poison gas at the location. */ +/* Returns one of M_POISONGAS_foo */ +int +m_poisongas_ok(mtmp) +struct monst *mtmp; +{ + int px, py; + + /* Non living and non breathing monsters are not concerned */ + if (nonliving(mtmp->data) || is_vampshifter(mtmp) + || breathless(mtmp->data)) + return M_POISONGAS_OK; + /* not is_swimmer(); assume that non-fish are swimming on + the surface and breathing the air above it periodically + unless located at water spot on plane of water */ + px = (mtmp == &g.youmonst) ? u.ux : mtmp->mx; + py = (mtmp == &g.youmonst) ? u.uy : mtmp->my; + if ((mtmp->data->mlet == S_EEL || Is_waterlevel(&u.uz)) + && isok(px, py) && is_pool(px, py)) + return M_POISONGAS_OK; + /* exclude monsters with poison gas breath attack: + adult green dragon and Chromatic Dragon (and iron golem, + but nonliving() and breathless() tests also catch that) */ + if (attacktype_fordmg(mtmp->data, AT_BREA, AD_DRST) + || attacktype_fordmg(mtmp->data, AT_BREA, AD_RBRE)) + return M_POISONGAS_OK; + if ((mtmp == &g.youmonst) + && (u.uinvulnerable || Breathless || Underwater)) + return M_POISONGAS_OK; + if (resists_poison(mtmp) || (mtmp == &g.youmonst) && Poison_resistance) + return M_POISONGAS_MINOR; + return M_POISONGAS_BAD; +} /* convert the monster index of an undead to its living counterpart */ int @@ -1354,8 +1388,7 @@ long flag; if (mdat == &mons[PM_FLOATING_EYE]) /* prefers to avoid heat */ lavaok = FALSE; thrudoor = ((flag & (ALLOW_WALL | BUSTDOOR)) != 0L); - poisongas_ok = ((nonliving(mdat) || is_vampshifter(mon) - || breathless(mdat)) || resists_poison(mon)); + poisongas_ok = (m_poisongas_ok(mon) == M_POISONGAS_OK); in_poisongas = ((gas_reg = visible_region_at(x,y)) != 0 && gas_reg->glyph == gas_glyph); diff --git a/src/region.c b/src/region.c index cb01de276..b1fefd649 100644 --- a/src/region.c +++ b/src/region.c @@ -1013,8 +1013,7 @@ genericptr_t p2; reg = (NhRegion *) p1; dam = reg->arg.a_int; if (p2 == (genericptr_t) 0) { /* This means *YOU* Bozo! */ - if (u.uinvulnerable || nonliving(g.youmonst.data) || Breathless - || Underwater) + if (m_poisongas_ok(&g.youmonst) == M_POISONGAS_OK) return FALSE; if (!Blind) { Your("%s sting.", makeplural(body_part(EYE))); @@ -1036,20 +1035,7 @@ genericptr_t p2; } else { /* A monster is inside the cloud */ mtmp = (struct monst *) p2; - /* Non living and non breathing monsters are not concerned; - adult green dragon is not affected by gas cloud, baby one is */ - if (!(nonliving(mtmp->data) || is_vampshifter(mtmp)) - && !breathless(mtmp->data) - /* not is_swimmer(); assume that non-fish are swimming on - the surface and breathing the air above it periodically - unless located at water spot on plane of water */ - && !((mtmp->data->mlet == S_EEL || Is_waterlevel(&u.uz)) - && is_pool(mtmp->mx, mtmp->my)) - /* exclude monsters with poison gas breath attack: - adult green dragon and Chromatic Dragon (and iron golem, - but nonliving() and breathless() tests also catch that) */ - && !(attacktype_fordmg(mtmp->data, AT_BREA, AD_DRST) - || attacktype_fordmg(mtmp->data, AT_BREA, AD_RBRE))) { + if (m_poisongas_ok(mtmp) != M_POISONGAS_OK) { if (cansee(mtmp->mx, mtmp->my)) pline("%s coughs!", Monnam(mtmp)); if (heros_fault(reg))