OSDN Git Service

update year to 2020
[jnethack/source.git] / src / dokick.c
index de71b5f..bbf0934 100644 (file)
@@ -1,10 +1,10 @@
-/* NetHack 3.6 dokick.c        $NHDT-Date: 1446955295 2015/11/08 04:01:35 $  $NHDT-Branch: master $:$NHDT-Revision: 1.104 $ */
+/* 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-2016            */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020            */
 /* JNetHack may be freely redistributed.  See license for details. */
 
 #include "hack.h"
@@ -25,9 +25,9 @@ STATIC_DCL void FDECL(kickdmg, (struct monst *, BOOLEAN_P));
 STATIC_DCL boolean FDECL(maybe_kick_monster, (struct monst *,
                                               XCHAR_P, XCHAR_P));
 STATIC_DCL void FDECL(kick_monster, (struct monst *, XCHAR_P, XCHAR_P));
-STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P));
+STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P, char *));
 STATIC_DCL int FDECL(really_kick_object, (XCHAR_P, XCHAR_P));
-STATIC_DCL char *FDECL(kickstr, (char *));
+STATIC_DCL char *FDECL(kickstr, (char *, const char *));
 STATIC_DCL void FDECL(otransit_msg, (struct obj *, BOOLEAN_P, long));
 STATIC_DCL void FDECL(drop_to, (coord *, SCHAR_P));
 
@@ -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, 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 */
@@ -170,7 +167,7 @@ xchar x, y;
     int i, j;
 
     /* anger target even if wild miss will occur */
-    setmangry(mon);
+    setmangry(mon, TRUE);
 
     if (Levitation && !rn2(3) && verysmall(mon->data)
         && !is_flyer(mon->data)) {
@@ -179,23 +176,28 @@ xchar x, y;
 */
         pline("\8bó\92\86\82É\95\82\82¢\82Ä\82¢\82é\82Ì\82Å\81C\91å\82«\82­\8aO\82µ\82½\81I");
         exercise(A_DEX, FALSE);
-        (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+        (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
         return;
     }
 
     /* 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:T*/
         There("is %s here.",
               canspotmon(mon) ? a_monnam(mon) : "something hidden");
+#else
+        There("%s\82ª\82¢\82é\81D",
+              canspotmon(mon) ? a_monnam(mon) : "\89½\82©\89B\82ê\82Ä\82¢\82é\82à\82Ì");
+#endif
     }
 
     /* Kick attacks by kicking monsters are normal attacks, not special.
@@ -206,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);
@@ -222,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
@@ -230,19 +234,19 @@ 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);
-                (void) passive(mon, (boolean) (sum > 0), (sum != 2), AT_KICK,
-                               FALSE);
+                sum = damageum(mon, uattk, specialdmg);
+                (void) passive(mon, uarmf, (boolean) (sum > 0),
+                               (sum != 2), AT_KICK, FALSE);
                 if (sum == 2)
                     break; /* Defender died */
             } else {
                 missum(mon, uattk, (tmp + armorpenalty > kickdieroll));
-                (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+                (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
             }
         }
         return;
@@ -259,7 +263,7 @@ xchar x, y;
             Your("clumsy kick does no damage.");
 */
             Your("\95s\8aí\97p\82È\8fR\82è\82Å\83_\83\81\81[\83W\82ð\97^\82¦\82ç\82ê\82È\82©\82Á\82½\81D");
-            (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+            (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
             return;
         }
         if (i < j / 10)
@@ -273,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));
 */
@@ -291,16 +295,13 @@ doit:
             pline("%s\82Í\82 \82È\82½\82Ì%s\8fR\82è\82ð\96h\82¢\82¾\81D", Monnam(mon),
                   clumsy ? "\95s\8aí\97p\82È" : "");
 #endif
-            (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+            (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
             return;
         } else {
             maybe_mnexto(mon);
             if (mon->mx != x || mon->my != y) {
-                if (glyph_is_invisible(levl[x][y].glyph)) {
-                    unmap_object(x, y);
-                    newsym(x, y);
-                }
-#if 0 /*JP*/
+                (void) unmap_invisible(x, y);
+#if 0 /*JP:T*/
                 pline("%s %s, %s evading your %skick.", Monnam(mon),
                       (!level.flags.noteleport && can_teleport(mon->data))
                           ? "teleports"
@@ -316,7 +317,8 @@ doit:
                 pline("%s\82Í%s\81C%s\82 \82È\82½\82Ì%s\8fR\82è\82ð\82½\82­\82Ý\82É\94ð\82¯\82½\81D", Monnam(mon),
                       (!level.flags.noteleport && can_teleport(mon->data))
                           ? "\8fu\8aÔ\88Ú\93®\82µ"
-                          : is_floater(mon->data) ? "\95\82\82«"
+                          : is_floater(mon->data)
+                                ? "\95\82\82«"
                                 : is_flyer(mon->data) ? "\82Í\82Î\82½\82«"
                                                       : (nolimbs(mon->data)
                                                          || slithy(mon->data))
@@ -324,7 +326,7 @@ doit:
                                                             : "\92µ\82Ë",
                       clumsy ? "\8ay\81X\82Æ" : "\91f\91\81\82­", clumsy ? "\95s\8aí\97p\82È" : "");
 #endif
-                (void) passive(mon, FALSE, 1, AT_KICK, FALSE);
+                (void) passive(mon, uarmf, FALSE, 1, AT_KICK, FALSE);
                 return;
             }
         }
@@ -345,7 +347,7 @@ register struct obj *gold;
 
     if (!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
         && !mtmp->isgd && !is_mercenary(mtmp->data)) {
-        wakeup(mtmp);
+        wakeup(mtmp, TRUE);
     } else if (!mtmp->mcanmove) {
         /* too light to do real damage */
         if (canseemon(mtmp)) {
@@ -364,7 +366,7 @@ register struct obj *gold;
         mtmp->msleeping = 0;
         finish_meating(mtmp);
         if (!mtmp->isgd && !rn2(4)) /* not always pleasing */
-            setmangry(mtmp);
+            setmangry(mtmp, TRUE);
         /* greedy monsters catch gold */
         if (cansee(mtmp->mx, mtmp->my))
 /*JP
@@ -380,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
@@ -393,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
@@ -424,6 +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:T*/
             verbalize(
                 umoney
                     ? "Drop the rest and follow me."
@@ -432,6 +435,16 @@ register struct obj *gold;
                           : mtmp->mpeaceful
                                 ? "I'll take care of that; please move along."
                                 : "I'll take that; now get moving.");
+#else
+            verbalize(
+                umoney
+                    ? "\8ec\82è\82ð\92u\82¢\82Ä\82Â\82¢\82Ä\82«\82È\82³\82¢\81D"
+                    : hidden_gold()
+                          ? "\82Ü\82¾\8bà\82ð\89B\82µ\82Ä\82¢\82é\82È\81D\92u\82«\82È\82³\82¢\81D"
+                          : mtmp->mpeaceful
+                                ? "\82»\82ê\82Í\8e\84\82ª\8fE\82Á\82Ä\82¨\82«\82Ü\82·\82©\82ç\82Â\82¢\82Ä\82«\82Ä\82­\82¾\82³\82¢\81D"
+                                : "\82»\82ê\82Í\8fE\82Á\82Ä\82¨\82­\81D\97\88\82È\82³\82¢\81D");
+#endif
         } else if (is_mercenary(mtmp->data)) {
             long goldreqd = 0L;
 
@@ -547,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
@@ -560,15 +573,18 @@ xchar x, y; /* coordinates where object was before the impact, not after */
 
 /* jacket around really_kick_object */
 STATIC_OVL int
-kick_object(x, y)
+kick_object(x, y, kickobjnam)
 xchar x, y;
+char *kickobjnam;
 {
     int res = 0;
 
+    *kickobjnam = '\0';
     /* if a pile, the "top" object gets kicked */
     kickedobj = level.objects[x][y];
     if (kickedobj) {
         /* kick object; if doing is fatal, done() will clean up kickedobj */
+        Strcpy(kickobjnam, killer_xname(kickedobj)); /* matters iff res==0 */
         res = really_kick_object(x, y);
         kickedobj = (struct obj *) 0;
     }
@@ -591,23 +607,27 @@ xchar x, y;
         || kickedobj == uchain)
         return 0;
 
-    if ((trap = t_at(x, y)) != 0
-        && (((trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) && !Passes_walls)
-            || trap->ttyp == WEB)) {
-        if (!trap->tseen)
-            find_trap(trap);
-#if 0 /*JP*/
-        You_cant("kick %s that's in a %s!", something,
-                 Hallucination ? "tizzy" : (trap->ttyp == WEB) ? "web"
-                                                               : "pit");
+    if ((trap = t_at(x, y)) != 0) {
+        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");
 #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Ô"
-                          : trap->ttyp == WEB
-                             ? "\82­\82à\82Ì\91\83\82Ì\92\86" : "\97\8e\82µ\8c\8a\82Ì\92\86",
-            something);
+            You("%s\82Å\82Í%s\82ð\8fR\82é\82±\82Æ\82ª\82Å\82«\82È\82¢\81I",
+                Hallucination ? "\8d¬\97\90\82µ\82½\8fó\91Ô" :
+                (trap->ttyp == WEB) ? "\82­\82à\82Ì\91\83\82Ì\92\86" : "\97\8e\82µ\8c\8a\82Ì\92\86",
+                something);
 #endif
-        return 1;
+            return 1;
+        }
+        if (trap->ttyp == STATUE_TRAP) {
+            activate_statue_trap(trap, x,y, FALSE);
+            return 1;
+        }
     }
 
     if (Fumbling && !rn2(3)) {
@@ -620,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)));
@@ -642,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);
@@ -674,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))
@@ -685,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"));
@@ -701,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
@@ -783,27 +818,43 @@ xchar x, y;
             kickedobj = splitobj(kickedobj, 1L);
         } else {
             if (rn2(20)) {
+#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",
                 };
+#else
+                static NEARDATA const char *const flyingcoinmsg[] = {
+                    "\8bà\89Ý\82ð\82Ü\82«\8eU\82ç\82µ\82½", "\8bà\89Ý\82ð\82Î\82ç\82Ü\82¢\82½",
+                    "\8bà\89Ý\82ð\82 \82¿\82±\82¿\82É\94ò\82Î\82µ\82½",
+                };
+#endif
 
+/*JP
                 pline("Thwwpingg!");
+*/
+                pline("\83K\83V\83\83\81[\83\93\81I");
+/*JP
                 You("%s!", flyingcoinmsg[rn2(SIZE(flyingcoinmsg))]);
+*/
+                You("%s\81I", flyingcoinmsg[rn2(SIZE(flyingcoinmsg))]);
                 (void) scatter(x, y, rn2(3) + 1, VIS_EFFECTS | MAY_HIT,
                                kickedobj);
                 newsym(x, y);
                 return 1;
             }
             if (kickedobj->quan > 300L) {
+/*JP
                 pline("Thump!");
+*/
+                pline("\83S\83c\83\93\81I");
                 return (!rn2(3) || martial());
             }
         }
     }
 
     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
@@ -862,13 +913,14 @@ xchar x, y;
 
 /* cause of death if kicking kills kicker */
 STATIC_OVL char *
-kickstr(buf)
+kickstr(buf, kickobjnam)
 char *buf;
+const char *kickobjnam;
 {
     const char *what;
 
-    if (kickedobj)
-        what = killer_xname(kickedobj);
+    if (*kickobjnam)
+        what = kickobjnam;
     else if (maploc == &nowhere)
 /*JP
         what = "nothing";
@@ -960,8 +1012,9 @@ dokick()
     int dmg = 0, glyph, oldglyph = -1;
     register struct monst *mtmp;
     boolean no_kick = FALSE;
-    char buf[BUFSZ];
+    char buf[BUFSZ], kickobjnam[BUFSZ];
 
+    kickobjnam[0] = '\0';
     if (nolimbs(youmonst.data) || slithy(youmonst.data)) {
 /*JP
         You("have no legs to kick with.");
@@ -995,9 +1048,15 @@ dokick()
 
         if (wl == BOTH_SIDES)
             bp = makeplural(bp);
+#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");
+#else
+        Your("%s%s\82Í\8fR\82è\82ª\82Å\82«\82é\8fó\91Ô\82\82á\82È\82¢\81D",
+             (wl == LEFT_SIDE) ? "\8d¶" : (wl == RIGHT_SIDE) ? "\89E" : "",
+             bp);
+#endif
         no_kick = TRUE;
     } else if (near_capacity() > SLT_ENCUMBER) {
 /*JP
@@ -1077,6 +1136,7 @@ dokick()
                 pline("%s\82Í\91å\82«\82È\83Q\83b\83v\82ð\82µ\82½\81D", Monnam(u.ustuck));
                 break;
             }
+            /*FALLTHRU*/
         default:
 /*JP
             Your("feeble kick has no effect.");
@@ -1153,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 */
@@ -1183,22 +1243,19 @@ dokick()
         }
         return 1;
     }
-    if (glyph_is_invisible(levl[x][y].glyph)) {
-        unmap_object(x, y);
-        newsym(x, y);
-    }
+    (void) unmap_invisible(x, y);
     if (is_pool(x, y) ^ !!u.uinwater) {
         /* objects normally can't be removed from water by kicking */
 /*JP
-        You("splash some water around.");
+        You("splash some %s around.", hliquid("water"));
 */
-        You("\90\85\82ð\89ñ\82è\82É\82Ü\82«\82¿\82ç\82µ\82½\81D");
+        You("%s\82ð\89ñ\82è\82É\82Ü\82«\82¿\82ç\82µ\82½\81D", hliquid("\90\85"));
         return 1;
     }
 
     if (OBJ_AT(x, y) && (!Levitation || Is_airlevel(&u.uz)
                          || Is_waterlevel(&u.uz) || sobj_at(BOULDER, x, y))) {
-        if (kick_object(x, y)) {
+        if (kick_object(x, y, kickobjnam)) {
             if (Is_airlevel(&u.uz))
                 hurtle(-u.dx, -u.dy, 1, TRUE); /* assume it's light */
             return 1;
@@ -1210,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 */
@@ -1303,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;
@@ -1317,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;
         }
@@ -1362,9 +1419,16 @@ dokick()
             (void) mksobj_at(ROCK, x, y, TRUE, FALSE);
             del_engr_at(x, y);
             if (Blind)
+#if 0 /*JP:T*/
                 pline("Crack!  %s broke!", Something);
+#else
+                pline("\83S\83c\83\93\81I\89½\82©\82ª\89ó\82ê\82½\81I");
+#endif
             else {
+/*JP
                 pline_The("headstone topples over and breaks!");
+*/
+                pline("\95æ\90Î\82Í\93|\82ê\82Ä\89ó\82ê\82½\81I");
                 newsym(x, y);
             }
             return 1;
@@ -1373,10 +1437,11 @@ dokick()
             goto ouch;
         if (IS_TREE(maploc->typ)) {
             struct obj *treefruit;
+
             /* 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 */
@@ -1387,7 +1452,9 @@ dokick()
                 && (treefruit = rnd_treefruit_at(x, y))) {
                 long nfruit = 8L - rnl(7), nfall;
                 short frtype = treefruit->otyp;
+
                 treefruit->quan = nfruit;
+                treefruit->owt = weight(treefruit);
                 if (is_plural(treefruit))
 /*JP
                     pline("Some %s fall from the tree!", xname(treefruit));
@@ -1404,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
@@ -1422,6 +1489,7 @@ dokick()
                 int cnt = rnl(4) + 2;
                 int made = 0;
                 coord mm;
+
                 mm.x = x;
                 mm.y = y;
                 while (cnt--) {
@@ -1497,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)
@@ -1526,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!");
 */
@@ -1549,7 +1628,7 @@ dokick()
             if (!rn2(3))
                 set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
             dmg = rnd(ACURR(A_CON) > 15 ? 3 : 5);
-            losehp(Maybe_Half_Phys(dmg), kickstr(buf), KILLED_BY);
+            losehp(Maybe_Half_Phys(dmg), kickstr(buf, kickobjnam), KILLED_BY);
             if (Is_airlevel(&u.uz) || Levitation)
                 hurtle(-u.dx, -u.dy, rn1(2, 4), TRUE); /* assume it's heavy */
             return 1;
@@ -1559,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
@@ -1620,7 +1699,7 @@ dokick()
         feel_newsym(x, y); /* we know we broke it */
         unblock_point(x, y); /* vision */
         if (shopdoor) {
-            add_damage(x, y, 400L);
+            add_damage(x, y, SHOP_DOOR_COST);
 /*JP
             pay_for_damage("break", FALSE);
 */
@@ -1690,7 +1769,8 @@ schar loc;
         } else if (In_endgame(&u.uz) || Is_botlevel(&u.uz)) {
             cc->y = cc->x = 0;
             break;
-        } /* else fall to the next cases */
+        }
+        /*FALLTHRU*/
     case MIGR_STAIRS_UP:
     case MIGR_LADDER_UP:
         cc->x = u.uz.dnum;
@@ -1773,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 */
@@ -1814,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);
@@ -1856,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
@@ -1911,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 */
@@ -2017,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);
@@ -2060,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 */
@@ -2072,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);
@@ -2143,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