]> granicus.if.org Git - nethack/commitdiff
Unify checking if monster is ok in poison gas
authorPasi Kallinen <paxed@alt.org>
Thu, 2 Apr 2020 15:15:13 +0000 (18:15 +0300)
committerPasi Kallinen <paxed@alt.org>
Thu, 2 Apr 2020 17:53:08 +0000 (20:53 +0300)
include/extern.h
include/hack.h
src/mon.c
src/region.c

index 18443b0a25241a395b7f07c08ed0c3fbc6be7267..2e1ad2a0979bf99f5d2e2180f5b277dd8e68e25c 100644 (file)
@@ -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));
index feb24001e39d45bbf61b677c1c8eafa1c0e2ace6..04290861fa24a345a603aefa64e1c1c1d6416bc9 100644 (file)
@@ -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
index 5567048b948f25cc5f335b9a1f2396055cebaecb..cd544698043ba90cfc75981b07718d994ee46cbf 100644 (file)
--- 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);
 
index cb01de2768f1862ba130d0f0aef584e5eee68b1e..b1fefd649cfe58cfed97196827821b15595689a3 100644 (file)
@@ -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))