]> granicus.if.org Git - nethack/commitdiff
Merge branch 'NetHack-3.6'
authornhmall <nhmall@nethack.org>
Fri, 15 Nov 2019 00:48:57 +0000 (19:48 -0500)
committernhmall <nhmall@nethack.org>
Fri, 15 Nov 2019 00:48:57 +0000 (19:48 -0500)
1  2 
include/extern.h
src/dothrow.c
src/files.c
src/mhitm.c
src/mhitu.c
src/mthrowu.c
src/uhitm.c
src/zap.c
sys/share/pcmain.c
win/curses/cursmain.c

Simple merge
diff --cc src/dothrow.c
index 50943d0257f066b7b26d4ec38b22b77b0fcfe2d0,c1a415a58156dfab05bdee39aebfce67dcbc8539..8bf4d7de849a76cb9399ec7322e1a7763780ed52
@@@ -1149,9 -1151,13 +1149,13 @@@ boolean twoweap; /* used to restore two
         will be left with a stale pointer. */
  
      if (u.uswallow) {
+         if (obj == uball) {
+             uball->ox = uchain->ox = u.ux;
+             uball->oy = uchain->oy = u.uy;
+         }
          mon = u.ustuck;
 -        bhitpos.x = mon->mx;
 -        bhitpos.y = mon->my;
 +        g.bhitpos.x = mon->mx;
 +        g.bhitpos.y = mon->my;
          if (tethered_weapon)
              tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng));
      } else if (u.dz) {
              goto throwit_return; /* alert shk caught it */
          }
          (void) snuff_candle(obj);
 -        notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
 +        g.notonhead = (g.bhitpos.x != mon->mx || g.bhitpos.y != mon->my);
          obj_gone = thitmonst(mon, obj);
-         /* Monster may have been tamed; this frees old mon */
+         /* Monster may have been tamed; this frees old mon [obsolete] */
 -        mon = m_at(bhitpos.x, bhitpos.y);
 +        mon = m_at(g.bhitpos.x, g.bhitpos.y);
  
          /* [perhaps this should be moved into thitmonst or hmon] */
          if (mon && mon->isshk
diff --cc src/files.c
Simple merge
diff --cc src/mhitm.c
index 7420cc1ab46d78a67c27216e717dcc07e0abfb26,5d33df493ee018d2b6b3fc091756c6b712d9fb93..ba19dc957506d4e86162ca753a022c93a461e07f
@@@ -52,16 -63,35 +52,35 @@@ struct attack *mattk
  {
      const char *fmt;
      char buf[BUFSZ];
 -        showit |= vis;
+     boolean showit = FALSE;
+     /* unhiding or unmimicking happens even if hero can't see it
+        because the formerly concealed monster is now in action */
+     if (M_AP_TYPE(mdef)) {
+         seemimic(mdef);
 -        showit |= vis;
++        showit |= g.vis;
+     } else if (mdef->mundetected) {
+         mdef->mundetected = 0;
 -        showit |= vis;
++        showit |= g.vis;
+     }
+     if (M_AP_TYPE(magr)) {
+         seemimic(magr);
 -        showit |= vis;
++        showit |= g.vis;
+     } else if (magr->mundetected) {
+         magr->mundetected = 0;
++        showit |= g.vis;
+     }
  
 -    if (vis) {
 +    if (g.vis) {
          if (!canspotmon(magr))
              map_invisible(magr->mx, magr->my);
+         else if (showit)
+             newsym(magr->mx, magr->my);
          if (!canspotmon(mdef))
              map_invisible(mdef->mx, mdef->my);
-         if (M_AP_TYPE(mdef))
-             seemimic(mdef);
-         if (M_AP_TYPE(magr))
-             seemimic(magr);
+         else if (showit)
+             newsym(mdef->mx, mdef->my);
          fmt = (could_seduce(magr, mdef, mattk) && !magr->mcan)
                    ? "%s pretends to be friendly to"
                    : "%s misses";
@@@ -379,13 -409,13 +398,13 @@@ register struct monst *magr, *mdef
                  res[i] = hitmm(magr, mdef, mattk);
                  if ((mdef->data == &mons[PM_BLACK_PUDDING]
                       || mdef->data == &mons[PM_BROWN_PUDDING])
 -                    && (otmp && (objects[otmp->otyp].oc_material == IRON
 -                                 || objects[otmp->otyp].oc_material == METAL))
 +                    && (g.otmp && (objects[g.otmp->otyp].oc_material == IRON
 +                                 || objects[g.otmp->otyp].oc_material == METAL))
-                     && mdef->mhp > 1
-                     && !mdef->mcan) {
+                     && mdef->mhp > 1 && !mdef->mcan) {
                      struct monst *mclone;
                      if ((mclone = clone_mon(mdef, 0, 0)) != 0) {
 -                        if (vis && canspotmon(mdef)) {
 +                        if (g.vis && canspotmon(mdef)) {
                              char buf[BUFSZ];
  
                              Strcpy(buf, Monnam(mdef));
              break;
  
          case AT_ENGL:
 -                if (vis)
+             if (mdef->data == &mons[PM_SHADE]) { /* no silver teeth... */
++                if (g.vis)
+                     pline("%s attempt to engulf %s is futile.",
+                           s_suffix(Monnam(magr)), mon_nam(mdef));
+                 strike = 0;
+                 break;
+             }
              if (u.usteed && mdef == u.usteed) {
                  strike = 0;
                  break;
@@@ -501,7 -538,30 +527,30 @@@ hitmm(magr, mdef, mattk
  register struct monst *magr, *mdef;
  struct attack *mattk;
  {
 -                          || (mattk->aatyp == AT_CLAW && otmp))),
 -            silverhit = (weaponhit && otmp
 -                         && objects[otmp->otyp].oc_material == SILVER),
+     boolean weaponhit = ((mattk->aatyp == AT_WEAP
 -        showit |= vis;
++                          || (mattk->aatyp == AT_CLAW && g.otmp))),
++            silverhit = (weaponhit && g.otmp
++                         && objects[g.otmp->otyp].oc_material == SILVER),
+             showit = FALSE;
+     /* unhiding or unmimicking happens even if hero can't see it
+        because the formerly concealed monster is now in action */
+     if (M_AP_TYPE(mdef)) {
+         seemimic(mdef);
 -        showit |= vis;
++        showit |= g.vis;
+     } else if (mdef->mundetected) {
+         mdef->mundetected = 0;
 -        showit |= vis;
++        showit |= g.vis;
+     }
+     if (M_AP_TYPE(magr)) {
+         seemimic(magr);
 -        showit |= vis;
++        showit |= g.vis;
+     } else if (magr->mundetected) {
+         magr->mundetected = 0;
 -    if (vis) {
++        showit |= g.vis;
+     }
 +    if (g.vis) {
          int compat;
          char buf[BUFSZ];
  
                      mdef->mcansee ? "smiles at" : "talks to");
              pline("%s %s %s.", buf, mon_nam(mdef),
                    compat == 2 ? "engagingly" : "seductively");
 -        } else if (shade_miss(magr, mdef, otmp, FALSE, TRUE)) {
++        } else if (shade_miss(magr, mdef, g.otmp, FALSE, TRUE)) {
+             return MM_MISS; /* bypass mdamagem() */
          } else {
              char magr_name[BUFSZ];
  
                  Sprintf(buf, "%s hits", magr_name);
              }
              pline("%s %s.", buf, mon_nam_too(mdef, magr));
 -                      simpleonames(otmp), mdef_name);
+             if (mon_hates_silver(mdef) && silverhit) {
+                 char *mdef_name = mon_nam_too(mdef, magr);
+                 /* note: mon_nam_too returns a modifiable buffer; so
+                    does s_suffix, but it returns a single static buffer
+                    and we might be calling it twice for this message */
+                 Strcpy(magr_name, s_suffix(magr_name));
+                 if (!noncorporeal(mdef->data) && !amorphous(mdef->data)) {
+                     if (mdef != magr) {
+                         mdef_name = s_suffix(mdef_name);
+                     } else {
+                         (void) strsubst(mdef_name, "himself", "his own");
+                         (void) strsubst(mdef_name, "herself", "her own");
+                         (void) strsubst(mdef_name, "itself", "its own");
+                     }
+                     Strcat(mdef_name, " flesh");
+                 }
+                 pline("%s %s sears %s!", magr_name, /*s_suffix(magr_name), */
++                      simpleonames(g.otmp), mdef_name);
+             }
          }
      } else
          noises(magr, mattk);
@@@ -882,16 -968,27 +957,27 @@@ register struct attack *mattk
      case AD_HEAL:
      case AD_PHYS:
   physical:
-         if (mattk->aatyp == AT_KICK && thick_skinned(pd)) {
+         /* this shade check is necessary in case any attacks which
+            dish out physical damage bypass hitmm() to get here */
 -        if ((mattk->aatyp == AT_WEAP || mattk->aatyp == AT_CLAW) && otmp)
 -            dmgwep = *otmp;
++        if ((mattk->aatyp == AT_WEAP || mattk->aatyp == AT_CLAW) && g.otmp)
++            dmgwep = *g.otmp;
+         else
 -            dmgwep = zeroobj;
++            dmgwep = cg.zeroobj;
+         if (shade_miss(magr, mdef, &dmgwep, FALSE, TRUE)) {
+             tmp = 0;
+         } else if (mattk->aatyp == AT_KICK && thick_skinned(pd)) {
              tmp = 0;
-         } else if (mattk->aatyp == AT_WEAP) {
+         } else if (mattk->aatyp == AT_WEAP
 -                   || (mattk->aatyp == AT_CLAW && otmp)) {
 -            if (otmp) {
++                   || (mattk->aatyp == AT_CLAW && g.otmp)) {
 +            if (g.otmp) {
                  struct obj *marmg;
  
 -                if (otmp->otyp == CORPSE
 -                    && touch_petrifies(&mons[otmp->corpsenm]))
 +                if (g.otmp->otyp == CORPSE
 +                    && touch_petrifies(&mons[g.otmp->corpsenm]))
                      goto do_stone;
 -                tmp += dmgval(otmp, mdef);
 +                tmp += dmgval(g.otmp, mdef);
                  if ((marmg = which_armor(magr, W_ARMG)) != 0
                      && marmg->otyp == GAUNTLETS_OF_POWER)
                      tmp += rn1(4, 3); /* 3..6 */
diff --cc src/mhitu.c
index b063ba367ca6404d5a173136ce61615d1c1eccf4,f14ddbb63eacacba83600432abfa93344a84f429..08970c23223ded7ef2d46343181f7ca803fb1bef
@@@ -1787,10 -1791,9 +1787,9 @@@ struct attack *mattk
      if (!u.uswallow) { /* swallows you */
          int omx = mtmp->mx, omy = mtmp->my;
  
 -        if (!engulf_target(mtmp, &youmonst))
 +        if (!engulf_target(mtmp, &g.youmonst))
              return 0;
-         if ((t && is_pit(t->ttyp))
-             && sobj_at(BOULDER, u.ux, u.uy))
+         if ((t && is_pit(t->ttyp)) && sobj_at(BOULDER, u.ux, u.uy))
              return 0;
  
          if (Punished)
diff --cc src/mthrowu.c
index 504cb533ad5f956cb48d24606c70b7741bfb05b2,7ecbbb2b2d804e5a163e77a00ea8d7bde16c2a83..a1b36476aca19c61a1e579d879a35bf531091d45
@@@ -376,10 -388,19 +380,19 @@@ boolean verbose;    /* give message(s) 
          }
          if (objects[otmp->otyp].oc_material == SILVER
              && mon_hates_silver(mtmp)) {
-             if (vis)
-                 pline_The("silver sears %s flesh!", s_suffix(mon_nam(mtmp)));
-             else if (verbose && !g.mtarget)
-                 pline("Its flesh is seared!");
+             boolean flesh = (!noncorporeal(mtmp->data)
+                              && !amorphous(mtmp->data));
+             /* note: extra silver damage is handled by dmgval() */
+             if (vis) {
+                 char *m_name = mon_nam(mtmp);
+                 if (flesh) /* s_suffix returns a modifiable buffer */
+                     m_name = strcat(s_suffix(m_name), " flesh");
+                 pline_The("silver sears %s!", m_name);
 -            } else if (verbose && !target) {
++            } else if (verbose && !g.mtarget) {
+                 pline("%s is seared!", flesh ? "Its flesh" : "It");
+             }
          }
          if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx, mtmp->my)) {
              if (resists_acid(mtmp)) {
@@@ -529,13 -550,18 +542,18 @@@ struct obj *obj;         /* missile (o
      if (sym)
          tmp_at(DISP_FLASH, obj_to_glyph(singleobj, rn2_on_display_rng));
      while (range-- > 0) { /* Actually the loop is always exited by break */
 -        bhitpos.x += dx;
 -        bhitpos.y += dy;
 -        mtmp = m_at(bhitpos.x, bhitpos.y);
 +        g.bhitpos.x += dx;
 +        g.bhitpos.y += dy;
-         if ((mtmp = m_at(g.bhitpos.x, g.bhitpos.y)) != 0) {
++        mtmp = m_at(g.bhitpos.x, g.bhitpos.y);
+         if (mtmp && shade_miss(mon, mtmp, singleobj, TRUE, TRUE)) {
+             /* if mtmp is a shade and missile passes harmlessly through it,
+                give message and skip it in order to keep going */
+             mtmp = (struct monst *) 0;
+         } else if (mtmp) {
              if (ohitmon(mtmp, singleobj, range, TRUE))
                  break;
 -        } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
 -            if (multi)
 +        } else if (g.bhitpos.x == u.ux && g.bhitpos.y == u.uy) {
 +            if (g.multi)
                  nomul(0);
  
              if (singleobj->oclass == GEM_CLASS
diff --cc src/uhitm.c
index 0848d95136e6083c88942b073d0a7add257e67e2,2eedb184fecc007a337d4879e594cb30fb1cae37..9f2b1236a6683c52dc1759d0965623c46a7dcb5e
@@@ -1138,21 -1140,14 +1135,14 @@@ int dieroll
              poiskilled = TRUE;
      }
      if (tmp < 1) {
+         boolean mon_is_shade = (mon->data == &mons[PM_SHADE]);
          /* make sure that negative damage adjustment can't result
             in inadvertently boosting the victim's hit points */
-         tmp = 0;
-         if (mdat == &mons[PM_SHADE]) {
-             if (!hittxt) {
-                 const char *what = *unconventional ? unconventional : "attack";
-                 Your("%s %s harmlessly through %s.", what,
-                      vtense(what, "pass"), mon_nam(mon));
-                 hittxt = TRUE;
-             }
-         } else {
-             if (get_dmg_bonus)
-                 tmp = 1;
-         }
+         tmp = (get_dmg_bonus && !mon_is_shade) ? 1 : 0;
+         if (mon_is_shade && !hittxt
+             && thrown != HMON_THROWN && thrown != HMON_KICKED)
 -            hittxt = shade_miss(&youmonst, mon, obj, FALSE, TRUE);
++            hittxt = shade_miss(&g.youmonst, mon, obj, FALSE, TRUE);
      }
  
      if (jousting) {
@@@ -1362,9 -1357,47 +1352,47 @@@ struct obj *obj
      return FALSE;
  }
  
 -    boolean youagr = (magr == &youmonst), youdef = (mdef == &youmonst);
+ /* used for hero vs monster and monster vs monster; also handles
+    monster vs hero but that won't happen because hero can't be a shade */
+ boolean
+ shade_miss(magr, mdef, obj, thrown, verbose)
+ struct monst *magr, *mdef;
+ struct obj *obj;
+ boolean thrown, verbose;
+ {
+     const char *what, *whose, *target;
 -            || (magr == &youmonst && distu(mdef->mx, mdef->my) <= 2))) {
++    boolean youagr = (magr == &g.youmonst), youdef = (mdef == &g.youmonst);
+     /* we're using dmgval() for zero/not-zero, not for actual damage amount */
+     if (mdef->data != &mons[PM_SHADE] || (obj && dmgval(obj, mdef)))
+         return FALSE;
+     if (verbose
+         && ((youdef || cansee(mdef->mx, mdef->my) || sensemon(mdef))
++            || (magr == &g.youmonst && distu(mdef->mx, mdef->my) <= 2))) {
+         static const char harmlessly_thru[] = " harmlessly through ";
+         what = (!obj || shade_aware(obj)) ? "attack" : cxname(obj);
+         target = youdef ? "you" : mon_nam(mdef);
+         if (!thrown) {
+             whose = youagr ? "Your" : s_suffix(Monnam(magr));
+             pline("%s %s %s%s%s.", whose, what,
+                   vtense(what, "pass"), harmlessly_thru, target);
+         } else {
+             pline("%s %s%s%s.", The(what), /* note: not pline_The() */
+                   vtense(what, "pass"), harmlessly_thru, target);
+         }
+         if (!youdef && !canspotmon(mdef))
+             map_invisible(mdef->mx, mdef->my);
+     }
+     if (!youdef)
+         mdef->msleeping = 0;
+     return TRUE;
+ }
  /* check whether slippery clothing protects from hug or wrap attack */
  /* [currently assumes that you are the attacker] */
 -STATIC_OVL boolean
 +static boolean
  m_slips_free(mdef, mattk)
  struct monst *mdef;
  struct attack *mattk;
diff --cc src/zap.c
index 1151297b530b160bdc2eeecb8873f9e757664c25,1c7a5debb217e3047987e5ee9270f6de6b0ee0a6..a9adec79465d10392d42c2a8086bbb81f4541422
+++ b/src/zap.c
@@@ -3347,8 -3356,14 +3348,14 @@@ struct obj **pobj; /* object tossed/use
              }
          }
  
-         if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
+         /* if mtmp is a shade and missile passes harmlessly through it,
+            give message and skip it in order to keep going */
+         if (mtmp && (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
 -            && shade_miss(&youmonst, mtmp, obj, TRUE, TRUE))
++            && shade_miss(&g.youmonst, mtmp, obj, TRUE, TRUE))
+             mtmp = (struct monst *) 0;
+         if (mtmp) {
 -            notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
 +            g.notonhead = (g.bhitpos.x != mtmp->mx || g.bhitpos.y != mtmp->my);
              if (weapon == FLASHED_LIGHT) {
                  /* FLASHED_LIGHT hitting invisible monster should
                     pass through instead of stop so we call
Simple merge
Simple merge