OSDN Git Service

fix #48255
[jnethack/source.git] / src / dokick.c
index c730ccf..e436310 100644 (file)
@@ -1,10 +1,10 @@
-/* NetHack 3.6 dokick.c        $NHDT-Date: 1517128663 2018/01/28 08:37:43 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.113 $ */
+/* NetHack 3.6 dokick.c        $NHDT-Date: 1575245057 2019/12/02 00:04:17 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.136 $ */
 /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000  */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019            */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2023            */
 /* JNetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -36,15 +36,15 @@ static const char kick_passes_thru[] = "kick passes harmlessly through";
 */
 static const char kick_passes_thru[] = "\8fR\82è\82Í\83_\83\81\81[\83W\82ð\97^\82¦\82¸\82É\82·\82è\94²\82¯\82½";
 
+/* kicking damage when not poly'd into a form with a kick attack */
 STATIC_OVL void
 kickdmg(mon, clumsy)
-register struct monst *mon;
-register boolean clumsy;
+struct monst *mon;
+boolean clumsy;
 {
-    register int mdx, mdy;
-    register int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
-    int kick_skill = P_NONE;
-    int blessed_foot_damage = 0;
+    int mdx, mdy;
+    int dmg = (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 15;
+    int specialdmg, kick_skill = P_NONE;
     boolean trapkilled = FALSE;
 
     if (uarmf && uarmf->otyp == KICKING_BOOTS)
@@ -58,15 +58,13 @@ register boolean clumsy;
     if (thick_skinned(mon->data))
         dmg = 0;
 
-    /* attacking a shade is useless */
+    /* attacking a shade is normally useless */
     if (mon->data == &mons[PM_SHADE])
         dmg = 0;
 
-    if ((is_undead(mon->data) || is_demon(mon->data) || is_vampshifter(mon))
-        && uarmf && uarmf->blessed)
-        blessed_foot_damage = 1;
+    specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
 
-    if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) {
+    if (mon->data == &mons[PM_SHADE] && !specialdmg) {
 /*JP
         pline_The("%s.", kick_passes_thru);
 */
@@ -76,7 +74,7 @@ register boolean clumsy;
         return;
     }
 
-    if (mon->m_ap_type)
+    if (M_AP_TYPE(mon))
         seemimic(mon);
 
     check_caitiff(mon);
@@ -101,14 +99,13 @@ register boolean clumsy;
         /* a good kick exercises your dex */
         exercise(A_DEX, TRUE);
     }
-    if (blessed_foot_damage)
-        dmg += rnd(4);
+    dmg += specialdmg; /* for blessed (or hypothetically, silver) boots */
     if (uarmf)
         dmg += uarmf->spe;
     dmg += u.udaminc; /* add ring(s) of increase damage */
     if (dmg > 0)
         mon->mhp -= dmg;
-    if (mon->mhp > 0 && martial() && !bigmonst(mon->data) && !rn2(3)
+    if (!DEADMONSTER(mon) && martial() && !bigmonst(mon->data) && !rn2(3)
         && mon->mcanmove && mon != u.ustuck && !mon->mtrapped) {
         /* see if the monster has a place to move into */
         mdx = mon->mx + u.dx;
@@ -130,8 +127,8 @@ register boolean clumsy;
         }
     }
 
-    (void) passive(mon, uarmf, TRUE, mon->mhp > 0, AT_KICK, FALSE);
-    if (mon->mhp <= 0 && !trapkilled)
+    (void) passive(mon, uarmf, TRUE, !DEADMONSTER(mon), AT_KICK, FALSE);
+    if (DEADMONSTER(mon) && !trapkilled)
         killed(mon);
 
     /* may bring up a dialog, so put this after all messages */
@@ -186,15 +183,15 @@ xchar x, y;
     /* reveal hidden target even if kick ends up missing (note: being
        hidden doesn't affect chance to hit so neither does this reveal) */
     if (mon->mundetected
-        || (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER)) {
-        if (mon->m_ap_type)
+        || (M_AP_TYPE(mon) && M_AP_TYPE(mon) != M_AP_MONSTER)) {
+        if (M_AP_TYPE(mon))
             seemimic(mon);
         mon->mundetected = 0;
         if (!canspotmon(mon))
             map_invisible(x, y);
         else
             newsym(x, y);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         There("is %s here.",
               canspotmon(mon) ? a_monnam(mon) : "something hidden");
 #else
@@ -211,7 +208,7 @@ xchar x, y;
      */
     if (Upolyd && attacktype(youmonst.data, AT_KICK)) {
         struct attack *uattk;
-        int sum, kickdieroll, armorpenalty,
+        int sum, kickdieroll, armorpenalty, specialdmg,
             attknum = 0,
             tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum,
                                    &armorpenalty);
@@ -227,7 +224,9 @@ xchar x, y;
             if (uattk->aatyp != AT_KICK)
                 continue;
 
-            if (mon->data == &mons[PM_SHADE] && (!uarmf || !uarmf->blessed)) {
+            kickdieroll = rnd(20);
+            specialdmg = special_dmgval(&youmonst, mon, W_ARMF, (long *) 0);
+            if (mon->data == &mons[PM_SHADE] && !specialdmg) {
                 /* doesn't matter whether it would have hit or missed,
                    and shades have no passive counterattack */
 /*JP
@@ -235,12 +234,12 @@ xchar x, y;
 */
                 You("%s\82ð\8fR\82Á\82½\82ª\81C%s\81D", mon_nam(mon), kick_passes_thru);
                 break; /* skip any additional kicks */
-            } else if (tmp > (kickdieroll = rnd(20))) {
+            } else if (tmp > kickdieroll) {
 /*JP
                 You("kick %s.", mon_nam(mon));
 */
                 You("%s\82ð\8fR\82Á\82½\81D", mon_nam(mon));
-                sum = damageum(mon, uattk);
+                sum = damageum(mon, uattk, specialdmg);
                 (void) passive(mon, uarmf, (boolean) (sum > 0),
                                (sum != 2), AT_KICK, FALSE);
                 if (sum == 2)
@@ -278,7 +277,7 @@ xchar x, y;
 
     else if (uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25))
         clumsy = TRUE;
-doit:
+ doit:
 /*JP
     You("kick %s.", mon_nam(mon));
 */
@@ -383,7 +382,7 @@ register struct obj *gold;
                 robbed -= value;
                 if (robbed < 0L)
                     robbed = 0L;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline_The("amount %scovers %s recent losses.",
                           !robbed ? "" : "partially ", mhis(mtmp));
 #else
@@ -396,7 +395,7 @@ register struct obj *gold;
             } else {
                 if (mtmp->mpeaceful) {
                     ESHK(mtmp)->credit += value;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                     You("have %ld %s in credit.", ESHK(mtmp)->credit,
                         currency(ESHK(mtmp)->credit));
 #else
@@ -427,7 +426,7 @@ register struct obj *gold;
                out of the vault.  If he did do that, player
                could try fighting, then weasle out of being
                killed by throwing his/her gold when losing. */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             verbalize(
                 umoney
                     ? "Drop the rest and follow me."
@@ -561,7 +560,7 @@ xchar x, y; /* coordinates where object was before the impact, not after */
             You("%ld%s\95ª\82Ì\91¹\8aQ\82ð\82Ð\82«\82¨\82±\82µ\82½\81I", loss, currency(loss));
             make_angry_shk(shkp, x, y);
         } else {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             You("owe %s %ld %s for objects destroyed.", mon_nam(shkp), loss,
                 currency(loss));
 #else
@@ -609,14 +608,14 @@ xchar x, y;
         return 0;
 
     if ((trap = t_at(x, y)) != 0) {
-        if (((trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) && !Passes_walls)
-            || trap->ttyp == WEB) {
+        if ((is_pit(trap->ttyp) && !Passes_walls) || trap->ttyp == WEB) {
             if (!trap->tseen)
                 find_trap(trap);
 #if 0 /*JP:T*/
             You_cant("kick %s that's in a %s!", something,
-                     Hallucination ? "tizzy" :
-                     (trap->ttyp == WEB) ? "web" : "pit");
+                     Hallucination ? "tizzy"
+                         : (trap->ttyp == WEB) ? "web"
+                             : "pit");
 #else
             You("%s\82Å\82Í%s\82ð\8fR\82é\82±\82Æ\82ª\82Å\82«\82È\82¢\81I",
                 Hallucination ? "\8d¬\97\90\82µ\82½\8fó\91Ô" :
@@ -641,7 +640,7 @@ xchar x, y;
 
     if (!uarmf && kickedobj->otyp == CORPSE
         && touch_petrifies(&mons[kickedobj->corpsenm]) && !Stone_resistance) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         You("kick %s with your bare %s.",
             corpse_xname(kickedobj, (const char *) 0, CXN_PFX_THE),
             makeplural(body_part(FOOT)));
@@ -663,9 +662,25 @@ xchar x, y;
         }
     }
 
-    /* range < 2 means the object will not move.  */
-    /* maybe dexterity should also figure here.   */
-    range = (int) ((ACURRSTR) / 2 - kickedobj->owt / 40);
+    isgold = (kickedobj->oclass == COIN_CLASS);
+    {
+        int k_owt = (int) kickedobj->owt;
+
+        /* for non-gold stack, 1 item will be split off below (unless an
+           early return occurs, so we aren't moving the split to here);
+           calculate the range for that 1 rather than for the whole stack */
+        if (kickedobj->quan > 1L && !isgold) {
+            long save_quan = kickedobj->quan;
+
+            kickedobj->quan = 1L;
+            k_owt = weight(kickedobj);
+            kickedobj->quan = save_quan;
+        }
+
+        /* range < 2 means the object will not move
+           (maybe dexterity should also figure here) */
+        range = ((int) ACURRSTR) / 2 - k_owt / 40;
+    }
 
     if (martial())
         range += rnd(3);
@@ -695,7 +710,6 @@ xchar x, y;
     costly = (!(kickedobj->no_charge && !Has_contents(kickedobj))
               && (shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0
               && costly_spot(x, y));
-    isgold = (kickedobj->oclass == COIN_CLASS);
 
     if (IS_ROCK(levl[x][y].typ) || closed_door(x, y)) {
         if ((!martial() && rn2(20) > ACURR(A_DEX))
@@ -706,7 +720,7 @@ xchar x, y;
 */
                 pline("\82Ñ\82­\82Æ\82à\82µ\82È\82¢\81D");
             else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline("%s %sn't come loose.",
                       The(distant_name(kickedobj, xname)),
                       otense(kickedobj, "do"));
@@ -722,7 +736,7 @@ xchar x, y;
 */
             pline("\89½\82©\82ª\8aÉ\82ñ\82Å\82Æ\82ê\82½\81D");
         else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             pline("%s %s loose.", The(distant_name(kickedobj, xname)),
                   otense(kickedobj, "come"));
 #else
@@ -804,7 +818,7 @@ xchar x, y;
             kickedobj = splitobj(kickedobj, 1L);
         } else {
             if (rn2(20)) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 static NEARDATA const char *const flyingcoinmsg[] = {
                     "scatter the coins", "knock coins all over the place",
                     "send coins flying in all directions",
@@ -840,7 +854,7 @@ xchar x, y;
     }
 
     if (slide && !Blind)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         pline("Whee!  %s %s across the %s.", Doname2(kickedobj),
               otense(kickedobj, "slide"), surface(x, y));
 #else
@@ -1034,7 +1048,7 @@ dokick()
 
         if (wl == BOTH_SIDES)
             bp = makeplural(bp);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
         Your("%s%s %s in no shape for kicking.",
              (wl == LEFT_SIDE) ? "left " : (wl == RIGHT_SIDE) ? "right " : "",
              bp, (wl == BOTH_SIDES) ? "are" : "is");
@@ -1199,7 +1213,7 @@ dokick()
         kick_monster(mtmp, x, y);
         glyph = glyph_at(x, y);
         /* see comment in attack_checks() */
-        if (mtmp->mhp <= 0) { /* DEADMONSTER() */
+        if (DEADMONSTER(mtmp)) { /* DEADMONSTER() */
             /* if we mapped an invisible monster and immediately
                killed it, we don't want to forget what we thought
                was there before the kick */
@@ -1235,7 +1249,7 @@ dokick()
 /*JP
         You("splash some %s around.", hliquid("water"));
 */
-        You("%s\82ð\89ñ\82è\82É\82Ü\82«\82¿\82ç\82µ\82½\81D", hliquid("water"));
+        You("%s\82ð\89ñ\82è\82É\82Ü\82«\82¿\82ç\82µ\82½\81D", hliquid("\90\85"));
         return 1;
     }
 
@@ -1253,7 +1267,7 @@ dokick()
         if (maploc->typ == SDOOR) {
             if (!Levitation && rn2(30) < avrg_attrib) {
                 cvt_sdoor_to_door(maploc); /* ->typ = DOOR */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline("Crash!  %s a secret door!",
                       /* don't "kick open" when it's locked
                          unless it also happens to be trapped */
@@ -1346,7 +1360,7 @@ dokick()
                 return 1;
             } else if (!rn2(4)) {
                 if (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)) {
-                    fall_through(FALSE);
+                    fall_through(FALSE, 0);
                     return 1;
                 } else
                     goto ouch;
@@ -1360,9 +1374,9 @@ dokick()
             You("kick %s.", (Blind ? something : "the altar"));
 */
             You("%s\82ð\8fR\82Á\82½\81D", (Blind ? "\89½\82©" : "\8dÕ\92d"));
+            altar_wrath(x, y);
             if (!rn2(3))
                 goto ouch;
-            altar_wrath(x, y);
             exercise(A_DEX, TRUE);
             return 1;
         }
@@ -1405,7 +1419,7 @@ dokick()
             (void) mksobj_at(ROCK, x, y, TRUE, FALSE);
             del_engr_at(x, y);
             if (Blind)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                 pline("Crack!  %s broke!", Something);
 #else
                 pline("\83S\83c\83\93\81I\89½\82©\82ª\89ó\82ê\82½\81I");
@@ -1427,7 +1441,7 @@ dokick()
             /* nothing, fruit or trouble? 75:23.5:1.5% */
             if (rn2(3)) {
                 if (!rn2(6) && !(mvitals[PM_KILLER_BEE].mvflags & G_GONE))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                     You_hear("a low buzzing."); /* a warning */
 #else
                     You_hear("\82Ô\81[\82ñ\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D"); /* a warning */
@@ -1457,7 +1471,7 @@ dokick()
                      * may not refer to the correct object */
                     treefruit = mksobj(frtype, TRUE, FALSE);
                     treefruit->quan = nfruit - nfall;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
                     pline("%ld %s got caught in the branches.",
                           nfruit - nfall, xname(treefruit));
 #else
@@ -1551,14 +1565,25 @@ dokick()
                 exercise(A_DEX, TRUE);
                 return 1;
             } else if (!rn2(3)) {
-#if 0 /*JP*/
-                pline("Flupp!  %s.",
-                      (Blind ? "You hear a sloshing sound"
-                             : "Muddy waste pops up from the drain"));
+                if (Blind && Deaf)
+                    Sprintf(buf, " %s", body_part(FACE));
+                else
+                    buf[0] = '\0';
+#if 0 /*JP:T*/
+                pline("%s%s%s.", !Deaf ? "Flupp! " : "",
+                      !Blind
+                          ? "Muddy waste pops up from the drain"
+                          : !Deaf
+                              ? "You hear a sloshing sound"  /* Deaf-aware */
+                              : "Something splashes you in the", buf);
 #else
-                pline("\82¤\82í\81I%s\81D",
-                      (Blind ? "\82 \82È\82½\82Í\81C\83o\83`\83\83\83o\83`\83\83\82·\82é\89¹\82ð\95·\82¢\82½"
-                             : "\94r\90\85\8cû\82©\82ç\82Ç\82ë\82Ç\82ë\82Ì\94p\8aü\95¨\82ª\8fo\82Ä\82­\82é"));
+                /*JP:TODO:\81u\8aç\82É\82©\82©\82Á\82½\81v\82Ì\8cê\8f\87\92²\90® */
+                pline("%s%s\81D", !Deaf ? "\82¤\82í\81I" : "",
+                      !Blind
+                          ? "\94r\90\85\8cû\82©\82ç\82Ç\82ë\82Ç\82ë\82Ì\94p\8aü\95¨\82ª\8fo\82Ä\82­\82é"
+                          : !Deaf
+                              ? "\82 \82È\82½\82Í\81C\83o\83`\83\83\83o\83`\83\83\82·\82é\89¹\82ð\95·\82¢\82½"  /* Deaf-aware */
+                              : "\89½\82©\82ª\82 \82È\82½\82É\82©\82©\82Á\82½");
 #endif
                 if (!(maploc->looted & S_LRING)) { /* once per sink */
                     if (!Blind)
@@ -1580,7 +1605,7 @@ dokick()
             || IS_STWALL(maploc->typ)) {
             if (!IS_STWALL(maploc->typ) && maploc->ladder == LA_DOWN)
                 goto dumb;
       ouch:
+ ouch:
 /*JP
             pline("Ouch!  That hurts!");
 */
@@ -1613,7 +1638,7 @@ dokick()
 
     if (maploc->doormask == D_ISOPEN || maploc->doormask == D_BROKEN
         || maploc->doormask == D_NODOOR) {
   dumb:
+ dumb:
         exercise(A_DEX, FALSE);
         if (martial() || ACURR(A_DEX) >= 16 || rn2(3)) {
 /*JP
@@ -1828,10 +1853,11 @@ xchar dlev;          /* if !0 send to dlev near player */
         obj_extract_self(obj);
 
         if (costly) {
-            price += stolen_value(
-                obj, x, y, (costly_spot(u.ux, u.uy)
-                            && index(u.urooms, *in_rooms(x, y, SHOPBASE))),
-                TRUE);
+            price += stolen_value(obj, x, y,
+                                  (costly_spot(u.ux, u.uy)
+                                   && index(u.urooms,
+                                            *in_rooms(x, y, SHOPBASE))),
+                                  TRUE);
             /* set obj->no_charge to 0 */
             if (Has_contents(obj))
                 picked_container(obj); /* does the right thing */
@@ -1869,7 +1895,7 @@ xchar dlev;          /* if !0 send to dlev near player */
             pline("\8bß\82­\82É\82 \82Á\82½%s\82ª%s\97\8e\82¿\82½\81D", what, gate_str);
 #endif
         else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             pline("%s adjacent %s %s.",
                   dct == 1L ? "One of the" : "Some of the",
                   dct == 1L ? "objects falls" : what, gate_str);
@@ -1911,7 +1937,7 @@ xchar dlev;          /* if !0 send to dlev near player */
         }
         if (ESHK(shkp)->debit > debit) {
             long amt = (ESHK(shkp)->debit - debit);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
             You("owe %s %ld %s for goods lost.", Monnam(shkp), amt,
                 currency(amt));
 #else
@@ -1966,7 +1992,7 @@ boolean shop_floor_obj;
     /* boulders never fall through trap doors, but they might knock
        other things down before plugging the hole */
     if (otmp->otyp == BOULDER && ((t = t_at(x, y)) != 0)
-        && (t->ttyp == TRAPDOOR || t->ttyp == HOLE)) {
+        && is_hole(t->ttyp)) {
         if (impact)
             impact_drop(otmp, x, y, 0);
         return FALSE; /* let caller finish the drop */
@@ -2072,6 +2098,9 @@ boolean near_hero;
             continue;
 
         where = (int) (otmp->owornmask & 0x7fffL); /* destination code */
+        if ((where & MIGR_TO_SPECIES) != 0)
+            continue;
+
         nobreak = (where & MIGR_NOBREAK) != 0;
         noscatter = (where & MIGR_WITH_HERO) != 0;
         where &= ~(MIGR_NOBREAK | MIGR_NOSCATTER);
@@ -2115,6 +2144,8 @@ boolean near_hero;
             stackobj(otmp);
             if (!noscatter)
                 (void) scatter(nx, ny, rnd(2), 0, otmp);
+            else
+                newsym(nx, ny);
         } else { /* random location */
             /* set dummy coordinates because there's no
                current position for rloco() to update */
@@ -2127,40 +2158,100 @@ boolean near_hero;
     }
 }
 
+void
+deliver_obj_to_mon(mtmp, cnt, deliverflags)
+int cnt;
+struct monst *mtmp;
+unsigned long deliverflags;
+{
+    struct obj *otmp, *otmp2;
+    int where, maxobj = 1;
+    boolean at_crime_scene = In_mines(&u.uz);
+
+    if ((deliverflags & DF_RANDOM) && cnt > 1)
+        maxobj = rnd(cnt);
+    else if (deliverflags & DF_ALL)
+        maxobj = 0;
+    else
+        maxobj = 1;
+
+    cnt = 0;
+    for (otmp = migrating_objs; otmp; otmp = otmp2) {
+        otmp2 = otmp->nobj;
+        where = (int) (otmp->owornmask & 0x7fffL); /* destination code */
+        if ((where & MIGR_TO_SPECIES) == 0)
+            continue;
+
+        if ((mtmp->data->mflags2 & otmp->corpsenm) != 0) {
+            obj_extract_self(otmp);
+            otmp->owornmask = 0L;
+            otmp->ox = otmp->oy = 0;
+
+            /* special treatment for orcs and their kind */
+            if ((otmp->corpsenm & M2_ORC) != 0 && has_oname(otmp)) {
+                if (!has_mname(mtmp)) {
+                    if (at_crime_scene || !rn2(2))
+                        mtmp = christen_orc(mtmp,
+                                            at_crime_scene ? ONAME(otmp)
+                                                           : (char *) 0,
+                                            /* bought the stolen goods */
+                                            " the Fence");
+                }
+                free_oname(otmp);
+            }
+            otmp->corpsenm = 0;
+            (void) add_to_minv(mtmp, otmp);
+            cnt++;
+            if (maxobj && cnt >= maxobj)
+                break;
+            /* getting here implies DF_ALL */
+        }
+    }
+}
+
 STATIC_OVL void
 otransit_msg(otmp, nodrop, num)
 register struct obj *otmp;
 register boolean nodrop;
 long num;
 {
-    char obuf[BUFSZ];
+#if 0 /*JP*/
+    char *optr = 0, obuf[BUFSZ], xbuf[BUFSZ];
+#else
+    char obuf[BUFSZ], xbuf[BUFSZ];
+#endif
 
 #if 0 /*JP*/
-    Sprintf(obuf, "%s%s",
-            (otmp->otyp == CORPSE && type_is_pname(&mons[otmp->corpsenm]))
-                ? ""
-                : "The ",
-            cxname(otmp));
+    if (otmp->otyp == CORPSE) {
+        /* Tobjnam() calls xname() and would yield "The corpse";
+           we want more specific "The newt corpse" or "Medusa's corpse" */
+        optr = upstart(corpse_xname(otmp, (char *) 0, CXN_PFX_THE));
+    } else {
+        optr = Tobjnam(otmp, (char *) 0);
+    }
+    Strcpy(obuf, optr);
 #else
     Sprintf(obuf, "%s\82Í", xname(otmp));
 #endif
 
     if (num) { /* means: other objects are impacted */
+        /* As of 3.6.2: use a separate buffer for the suffix to avoid risk of
+           overrunning obuf[] (let pline() handle truncation if necessary) */
 #if 0 /*JP*/
-        Sprintf(eos(obuf), " %s %s object%s", otense(otmp, "hit"),
-                num == 1L ? "another" : "other", num > 1L ? "s" : "");
+        Sprintf(xbuf, " %s %s object%s", otense(otmp, "hit"),
+                (num == 1L) ? "another" : "other", (num > 1L) ? "s" : "");
         if (nodrop)
-            Sprintf(eos(obuf), ".");
+            Sprintf(eos(xbuf), ".");
         else
-            Sprintf(eos(obuf), " and %s %s.", otense(otmp, "fall"), gate_str);
+            Sprintf(eos(xbuf), " and %s %s.", otense(otmp, "fall"), gate_str);
 #else
-        Sprintf(eos(obuf), "\91¼\82Ì\95¨\91Ì\82É\96½\92\86\82µ\82Ä");
+        Sprintf(xbuf, "\91¼\82Ì\95¨\91Ì\82É\96½\92\86\82µ\82Ä");
         if(nodrop)
-            Sprintf(eos(obuf), "\8e~\82Ü\82Á\82½\81D");
+            Sprintf(eos(xbuf), "\8e~\82Ü\82Á\82½\81D");
         else
-            Sprintf(eos(obuf), "%s\97\8e\82¿\82½\81D", gate_str);
+            Sprintf(eos(xbuf), "%s\97\8e\82¿\82½\81D", gate_str);
 #endif
-        pline1(obuf);
+        pline("%s%s", obuf, xbuf);
     } else if (!nodrop)
 /*JP
         pline("%s %s %s.", obuf, otense(otmp, "fall"), gate_str);
@@ -2198,8 +2289,8 @@ xchar x, y;
     }
 
     if (((ttmp = t_at(x, y)) != 0 && ttmp->tseen)
-        && (ttmp->ttyp == TRAPDOOR || ttmp->ttyp == HOLE)) {
-#if 0 /*JP*/
+        && is_hole(ttmp->ttyp)) {
+#if 0 /*JP:T*/
         gate_str = (ttmp->ttyp == TRAPDOOR) ? "through the trap door"
                                             : "through the hole";
 #else