OSDN Git Service

upgrade to 3.6.1
[jnethack/source.git] / src / apply.c
index 0ab5920..c6f0000 100644 (file)
@@ -1,5 +1,6 @@
-/* NetHack 3.6 apply.c $NHDT-Date: 1446808436 2015/11/06 11:13:56 $  $NHDT-Branch: master $:$NHDT-Revision: 1.210 $ */
+/* NetHack 3.6 apply.c $NHDT-Date: 1519598527 2018/02/25 22:42:07 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.243 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /* JNetHack Copyright */
@@ -17,13 +18,13 @@ STATIC_DCL boolean FDECL(its_dead, (int, int, int *));
 STATIC_DCL int FDECL(use_stethoscope, (struct obj *));
 STATIC_DCL void FDECL(use_whistle, (struct obj *));
 STATIC_DCL void FDECL(use_magic_whistle, (struct obj *));
-STATIC_DCL void FDECL(use_leash, (struct obj *));
+STATIC_DCL int FDECL(use_leash, (struct obj *));
 STATIC_DCL int FDECL(use_mirror, (struct obj *));
 STATIC_DCL void FDECL(use_bell, (struct obj **));
 STATIC_DCL void FDECL(use_candelabrum, (struct obj *));
 STATIC_DCL void FDECL(use_candle, (struct obj **));
 STATIC_DCL void FDECL(use_lamp, (struct obj *));
-STATIC_DCL void FDECL(light_cocktail, (struct obj *));
+STATIC_DCL void FDECL(light_cocktail, (struct obj **));
 STATIC_PTR void FDECL(display_jump_positions, (int));
 STATIC_DCL void FDECL(use_tinning_kit, (struct obj *));
 STATIC_DCL void FDECL(use_figurine, (struct obj **));
@@ -41,7 +42,10 @@ STATIC_DCL boolean FDECL(figurine_location_checks, (struct obj *,
                                                     coord *, BOOLEAN_P));
 STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
 STATIC_DCL void FDECL(setapplyclasses, (char *));
+STATIC_PTR boolean FDECL(check_jump, (genericptr_t, int, int));
 STATIC_DCL boolean FDECL(is_valid_jump_pos, (int, int, int, BOOLEAN_P));
+STATIC_DCL boolean FDECL(get_valid_jump_position, (int, int));
+STATIC_DCL boolean FDECL(get_valid_polearm_position, (int, int));
 STATIC_DCL boolean FDECL(find_poleable_mon, (coord *, int, int));
 
 #ifdef AMIGA
@@ -314,6 +318,13 @@ int rx, ry, *resp;
     } else if (corpse) {
         boolean here = (rx == u.ux && ry == u.uy),
                 one = (corpse->quan == 1L && !more_corpses), reviver = FALSE;
+        int visglyph, corpseglyph;
+
+        visglyph = glyph_at(rx, ry);
+        corpseglyph = obj_to_glyph(corpse);
+
+        if (Blind && (visglyph != corpseglyph))
+            map_object(corpse, TRUE);
 
         if (Role_if(PM_HEALER)) {
             /* ok to reset `corpse' here; we're done with it */
@@ -432,6 +443,8 @@ register struct obj *obj;
     context.stethoscope_move = moves;
     context.stethoscope_movement = youmonst.movement;
 
+    bhitpos.x = u.ux, bhitpos.y = u.uy; /* tentative, reset below */
+    notonhead = u.uswallow;
     if (u.usteed && u.dz > 0) {
         if (interference) {
 /*JP
@@ -499,6 +512,10 @@ register struct obj *obj;
         const char *mnm = x_monnam(mtmp, ARTICLE_A, (const char *) 0,
                                    SUPPRESS_IT | SUPPRESS_INVISIBLE, FALSE);
 
+        /* bhitpos needed by mstatusline() iff mtmp is a long worm */
+        bhitpos.x = rx, bhitpos.y = ry;
+        notonhead = (mtmp->mx != rx || mtmp->my != ry);
+
         if (mtmp->mundetected) {
             if (!canspotmon(mtmp))
 /*JP
@@ -523,7 +540,7 @@ register struct obj *obj;
             }
             seemimic(mtmp);
 /*JP
-            pline("That %s is really %s", what, mnm);
+            pline("That %s is really %s.", what, mnm);
 */
             pline("\82±\82Ì%s\82Í\8eÀ\8dÛ\82É\82Í%s\81D", what, mnm);
         } else if (flags.verbose && !canspotmon(mtmp)) {
@@ -532,19 +549,18 @@ register struct obj *obj;
 */
             pline("\82±\82±\82É\82Í%s\82ª\82¢\82é\81D", mnm);
         }
+
         mstatusline(mtmp);
         if (!canspotmon(mtmp))
             map_invisible(rx, ry);
         return res;
     }
-    if (glyph_is_invisible(levl[rx][ry].glyph)) {
-        unmap_object(rx, ry);
-        newsym(rx, ry);
+    if (unmap_invisible(rx,ry))
 /*JP
         pline_The("invisible monster must have moved.");
 */
         pline_The("\8c©\82¦\82È\82¢\89ö\95¨\82Í\88Ú\93®\82µ\82Ä\82µ\82Ü\82Á\82½\82æ\82¤\82¾\81D");
-    }
+
     lev = &levl[rx][ry];
     switch (lev->typ) {
     case SDOOR:
@@ -595,11 +611,17 @@ struct obj *obj;
 */
         You("%s\82ð\92Ê\82µ\82Ä\96A\82ð\8fo\82µ\82½\81D", xname(obj));
     } else {
+        if (Deaf)
+            You_feel("rushing air tickle your %s.",
+                        body_part(NOSE));
+        else
 /*JP
         You(whistle_str, obj->cursed ? "shrill" : "high");
 */
         You(whistle_str, obj->cursed ? "\95s\8bC\96¡\82È" : "\82©\82ñ\8d\82\82¢");
         wake_nearby();
+        if (obj->cursed)
+            vault_summon_gd();
     }
 }
 
@@ -744,6 +766,10 @@ unleash_all()
 
 #define MAXLEASHED 2
 
+/* TODO:
+ *  This ought to exclude various other things, such as lights and gas
+ *  spore, is_whirly() critters, ethereal creatures, possibly others.
+ */
 static boolean
 leashable(mtmp)
 struct monst *mtmp;
@@ -752,26 +778,40 @@ struct monst *mtmp;
 }
 
 /* ARGSUSED */
-STATIC_OVL void
+STATIC_OVL int
 use_leash(obj)
 struct obj *obj;
 {
     coord cc;
-    register struct monst *mtmp;
+    struct monst *mtmp;
     int spotmon;
 
+    if (u.uswallow) {
+        /* if the leash isn't in use, assume we're trying to leash
+           the engulfer; if it is use, distinguish between removing
+           it from the engulfer versus from some other creature
+           (note: the two in-use cases can't actually occur; all
+           leashes are released when the hero gets engulfed) */
+        You_cant((!obj->leashmon
+                  ? "leash %s from inside."
+                  : (obj->leashmon == (int) u.ustuck->m_id)
+                    ? "unleash %s from inside."
+                    : "unleash anything from inside %s."),
+                 noit_mon_nam(u.ustuck));
+        return 0;
+    }
     if (!obj->leashmon && number_leashed() >= MAXLEASHED) {
 /*JP
         You("cannot leash any more pets.");
 */
         You("\82±\82ê\88È\8fã\83y\83b\83g\82É\95R\82ð\82©\82¯\82ç\82ê\82È\82¢\81D");
-        return;
+        return 0;
     }
 
     if (!get_adjacent_loc((char *) 0, (char *) 0, u.ux, u.uy, &cc))
-        return;
+        return 0;
 
-    if ((cc.x == u.ux) && (cc.y == u.uy)) {
+    if (cc.x == u.ux && cc.y == u.uy) {
         if (u.usteed && u.dz > 0) {
             mtmp = u.usteed;
             spotmon = 1;
@@ -781,48 +821,51 @@ struct obj *obj;
         pline("Leash yourself?  Very funny...");
 */
         pline("\8e©\95ª\82ð\94\9b\82é\81H\95Ï\82È\82Ì\81D\81D\81D");
-        return;
+        return 0;
     }
 
+    /*
+     * From here on out, return value is 1 == a move is used.
+     */
+
     if (!(mtmp = m_at(cc.x, cc.y))) {
 /*JP
         There("is no creature there.");
 */
         pline("\82»\82±\82É\82Í\90\82«\95¨\82Í\82¢\82È\82¢\81D");
-        return;
+        (void) unmap_invisible(cc.x, cc.y);
+        return 1;
     }
 
     spotmon = canspotmon(mtmp);
-got_target:
-
-    if (!mtmp->mtame) {
-        if (!spotmon)
-/*JP
-            There("is no creature there.");
-*/
-            pline("\82»\82±\82É\82Í\90\82«\95¨\82Í\82¢\82È\82¢\81D");
-        else
+ got_target:
+
+    if (!spotmon && !glyph_is_invisible(levl[cc.x][cc.y].glyph)) {
+        /* for the unleash case, we don't verify whether this unseen
+           monster is the creature attached to the current leash */
+        You("fail to %sleash something.", obj->leashmon ? "un" : "");
+        /* trying again will work provided the monster is tame
+           (and also that it doesn't change location by retry time) */
+        map_invisible(cc.x, cc.y);
+    } else if (!mtmp->mtame) {
 #if 0 /*JP*/
-            pline("%s %s leashed!", Monnam(mtmp),
-                  (!obj->leashmon) ? "cannot be" : "is not");
+        pline("%s %s leashed!", Monnam(mtmp),
+              (!obj->leashmon) ? "cannot be" : "is not");
 #else
-          pline("%s\82Í\95R\82Å%s\81I", Monnam(mtmp),
-                  (!obj->leashmon) ? "\8c\8b\82×\82È\82¢" : "\8c\8b\82Î\82ê\82Ä\82¢\82È\82¢");
+        pline("%s\82Í\95R\82Å%s\81I", Monnam(mtmp),
+              (!obj->leashmon) ? "\8c\8b\82×\82È\82¢" : "\8c\8b\82Î\82ê\82Ä\82¢\82È\82¢");
 #endif
-        return;
-    }
-    if (!obj->leashmon) {
+    } else if (!obj->leashmon) {
+        /* applying a leash which isn't currently in use */
         if (mtmp->mleashed) {
 #if 0 /*JP*/
             pline("This %s is already leashed.",
-                  spotmon ? l_monnam(mtmp) : "monster");
+                  spotmon ? l_monnam(mtmp) : "creature");
 #else
             pline("%s\82Í\82·\82Å\82É\8c\8b\82Ñ\82Â\82¯\82ç\82ê\82Ä\82¢\82é\81D",
                   spotmon ? l_monnam(mtmp) : "\89ö\95¨");
 #endif
-            return;
-        }
-        if (!leashable(mtmp)) {
+        } else if (!leashable(mtmp)) {
 #if 0 /*JP*/
             pline("The leash won't fit onto %s%s.", spotmon ? "your " : "",
                   l_monnam(mtmp));
@@ -830,47 +873,44 @@ got_target:
             pline("\95R\82Í%s\82É\8d\87\82í\82È\82¢\81D",
                   l_monnam(mtmp));
 #endif
-            return;
-        }
-
+        } else {
 #if 0 /*JP*/
-        You("slip the leash around %s%s.", spotmon ? "your " : "",
-            l_monnam(mtmp));
+            You("slip the leash around %s%s.", spotmon ? "your " : "",
+                l_monnam(mtmp));
 #else
-        You("%s\82ð\95R\82Å\8c\8b\82Ñ\82Â\82¯\82½\81D",
-            l_monnam(mtmp));
+            You("%s\82ð\95R\82Å\8c\8b\82Ñ\82Â\82¯\82½\81D",
+                l_monnam(mtmp));
 #endif
-        mtmp->mleashed = 1;
-        obj->leashmon = (int) mtmp->m_id;
-        mtmp->msleeping = 0;
-        return;
-    }
-    if (obj->leashmon != (int) mtmp->m_id) {
+            mtmp->mleashed = 1;
+            obj->leashmon = (int) mtmp->m_id;
+            mtmp->msleeping = 0;
+        }
+    } else {
+        /* applying a leash which is currently in use */
+        if (obj->leashmon != (int) mtmp->m_id) {
 /*JP
         pline("This leash is not attached to that creature.");
 */
         pline("\82±\82Ì\95R\82Í\82»\82ê\82É\82Í\8c\8b\82Î\82ê\82Ä\82¢\82È\82¢\81D");
-        return;
-    } else {
-        if (obj->cursed) {
+        } else if (obj->cursed) {
 /*JP
             pline_The("leash would not come off!");
 */
             pline("\95R\82ª\82Í\82¸\82ê\82È\82¢\81I");
-            obj->bknown = TRUE;
-            return;
-        }
-        mtmp->mleashed = 0;
-        obj->leashmon = 0;
+            obj->bknown = 1;
+        } else {
+            mtmp->mleashed = 0;
+            obj->leashmon = 0;
 #if 0 /*JP*/
-        You("remove the leash from %s%s.", spotmon ? "your " : "",
-            l_monnam(mtmp));
+            You("remove the leash from %s%s.",
+                spotmon ? "your " : "", l_monnam(mtmp));
 #else
-        You("%s\82©\82ç\95R\82ð\82Í\82¸\82µ\82½\81D",
-            l_monnam(mtmp));
+            You("%s\82©\82ç\95R\82ð\82Í\82¸\82µ\82½\81D",
+                l_monnam(mtmp));
 #endif
+        }
     }
-    return;
+    return 1;
 }
 
 /* assuming mtmp->mleashed has been checked */
@@ -963,7 +1003,7 @@ register xchar x, y;
                        that's the result of his actions; gain experience,
                        lose pacifism, take alignment and luck hit, make
                        corpse less likely to remain tame after revival */
-                    xkilled(mtmp, 0); /* no "you kill it" message */
+                    xkilled(mtmp, XKILL_NOMSG);
                     /* life-saving doesn't ordinarily reset this */
                     if (mtmp->mhp > 0)
                         u.uconduct.killer = save_pacifism;
@@ -1023,8 +1063,6 @@ beautiful()
 #endif
 }
 
-#define WEAK 3 /* from eat.c */
-
 /*JP
 static const char look_str[] = "look %s.";
 */
@@ -1640,6 +1678,9 @@ struct obj **optr;
             end_burn(obj, TRUE);
         /* candles are now gone */
         useupall(obj);
+        /* candelabrum's weight is changing */
+        otmp->owt = weight(otmp);
+        update_inventory();
     }
 }
 
@@ -1834,9 +1875,10 @@ struct obj *obj;
 }
 
 STATIC_OVL void
-light_cocktail(obj)
-struct obj *obj; /* obj is a potion of oil */
+light_cocktail(optr)
+struct obj **optr;
 {
+    struct obj *obj = *optr; /* obj is a potion of oil */
     char buf[BUFSZ];
     boolean split1off;
 
@@ -1857,7 +1899,7 @@ struct obj *obj; /* obj is a potion of oil */
          * but its easy.
          */
         freeinv(obj);
-        (void) addinv(obj);
+        *optr = addinv(obj);
         return;
     } else if (Underwater) {
 /*JP
@@ -1904,6 +1946,7 @@ struct obj *obj; /* obj is a potion of oil */
         if (obj)
             obj->nomerge = 0;
     }
+    *optr = obj;
 }
 
 static NEARDATA const char cuddly[] = { TOOL_CLASS, GEM_CLASS, 0 };
@@ -1975,7 +2018,48 @@ dojump()
     return jump(0);
 }
 
-boolean
+enum jump_trajectory {
+    jAny  = 0, /* any direction => magical jump */
+    jHorz = 1,
+    jVert = 2,
+    jDiag = 3  /* jHorz|jVert */
+};
+
+/* callback routine for walk_path() */
+STATIC_PTR boolean
+check_jump(arg, x, y)
+genericptr arg;
+int x, y;
+{
+    int traj = *(int *) arg;
+    struct rm *lev = &levl[x][y];
+
+    if (Passes_walls)
+        return TRUE;
+    if (IS_STWALL(lev->typ))
+        return FALSE;
+    if (IS_DOOR(lev->typ)) {
+        if (closed_door(x, y))
+            return FALSE;
+        if ((lev->doormask & D_ISOPEN) != 0 && traj != jAny
+            /* reject diagonal jump into or out-of or through open door */
+            && (traj == jDiag
+                /* reject horizontal jump through horizontal open door
+                   and non-horizontal (ie, vertical) jump through
+                   non-horizontal (vertical) open door */
+                || ((traj & jHorz) != 0) == (lev->horizontal != 0)))
+            return FALSE;
+        /* empty doorways aren't restricted */
+    }
+    /* let giants jump over boulders (what about Flying?
+       and is there really enough head room for giants to jump
+       at all, let alone over something tall?) */
+    if (sobj_at(BOULDER, x, y) && !throws_rocks(youmonst.data))
+        return FALSE;
+    return TRUE;
+}
+
+STATIC_OVL boolean
 is_valid_jump_pos(x, y, magic, showmsg)
 int x, y, magic;
 boolean showmsg;
@@ -1997,26 +2081,75 @@ boolean showmsg;
 */
             pline("\89\93\82·\82¬\82é\81I");
         return FALSE;
-    } else if (!cansee(x, y)) {
+    } else if (!isok(x, y)) {
         if (showmsg)
 /*JP
-            You("cannot see where to land!");
+            You("cannot jump there!");
 */
-            You("\92\85\92n\93_\82ª\8c©\82¦\82È\82¢\81I");
+            You("\82»\82±\82É\82Í\94ò\82×\82È\82¢\81I");
         return FALSE;
-    } else if (!isok(x, y)) {
+    } else if (!cansee(x, y)) {
         if (showmsg)
 /*JP
-            You("cannot jump there!");
+            You("cannot see where to land!");
 */
-            You("\82»\82±\82É\82Í\94ò\82×\82È\82¢\81I");
+            You("\92\85\92n\93_\82ª\8c©\82¦\82È\82¢\81I");
         return FALSE;
+    } else {
+        coord uc, tc;
+        struct rm *lev = &levl[u.ux][u.uy];
+        /* we want to categorize trajectory for use in determining
+           passage through doorways: horizonal, vertical, or diagonal;
+           since knight's jump and other irregular directions are
+           possible, we flatten those out to simplify door checks */
+        int diag, traj,
+            dx = x - u.ux, dy = y - u.uy,
+            ax = abs(dx), ay = abs(dy);
+
+        /* diag: any non-orthogonal destination classifed as diagonal */
+        diag = (magic || Passes_walls || (!dx && !dy)) ? jAny
+               : !dy ? jHorz : !dx ? jVert : jDiag;
+        /* traj: flatten out the trajectory => some diagonals re-classified */
+        if (ax >= 2 * ay)
+            ay = 0;
+        else if (ay >= 2 * ax)
+            ax = 0;
+        traj = (magic || Passes_walls || (!ax && !ay)) ? jAny
+               : !ay ? jHorz : !ax ? jVert : jDiag;
+        /* walk_path doesn't process the starting spot;
+           this is iffy:  if you're starting on a closed door spot,
+           you _can_ jump diagonally from doorway (without needing
+           Passes_walls); that's intentional but is it correct? */
+        if (diag == jDiag && IS_DOOR(lev->typ)
+            && (lev->doormask & D_ISOPEN) != 0
+            && (traj == jDiag
+                || ((traj & jHorz) != 0) == (lev->horizontal != 0))) {
+            if (showmsg)
+                You_cant("jump diagonally out of a doorway.");
+            return FALSE;
+        }
+        uc.x = u.ux, uc.y = u.uy;
+        tc.x = x, tc.y = y; /* target */
+        if (!walk_path(&uc, &tc, check_jump, (genericptr_t) &traj)) {
+            if (showmsg)
+                There("is an obstacle preventing that jump.");
+            return FALSE;
+        }
     }
     return TRUE;
 }
 
 static int jumping_is_magic;
 
+STATIC_OVL boolean
+get_valid_jump_position(x,y)
+int x,y;
+{
+    return (isok(x, y)
+            && (ACCESSIBLE(levl[x][y].typ) || Passes_walls)
+            && is_valid_jump_pos(x, y, jumping_is_magic, FALSE));
+}
+
 void
 display_jump_positions(state)
 int state;
@@ -2030,8 +2163,7 @@ int state;
             for (dy = -4; dy <= 4; dy++) {
                 x = dx + (int) u.ux;
                 y = dy + (int) u.uy;
-                if (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
-                    && is_valid_jump_pos(x, y, jumping_is_magic, FALSE))
+                if (get_valid_jump_position(x, y))
                     tmp_at(x, y);
             }
     } else {
@@ -2045,6 +2177,17 @@ int magic; /* 0=Physical, otherwise skill level */
 {
     coord cc;
 
+    /* attempt "jumping" spell if hero has no innate jumping ability */
+    if (!magic && !Jumping) {
+        int sp_no;
+
+        for (sp_no = 0; sp_no < MAXSPELL; ++sp_no)
+            if (spl_book[sp_no].sp_id == NO_SPELL)
+                break;
+            else if (spl_book[sp_no].sp_id == SPE_JUMPING)
+                return spelleffects(sp_no, FALSE);
+    }
+
     if (!magic && (nolimbs(youmonst.data) || slithy(youmonst.data))) {
         /* normally (nolimbs || slithy) implies !Jumping,
            but that isn't necessarily the case for knights */
@@ -2173,7 +2316,7 @@ int magic; /* 0=Physical, otherwise skill level */
     cc.x = u.ux;
     cc.y = u.uy;
     jumping_is_magic = magic;
-    getpos_sethilite(display_jump_positions);
+    getpos_sethilite(display_jump_positions, get_valid_jump_position);
 /*JP
     if (getpos(&cc, TRUE, "the desired position") < 0)
 */
@@ -2217,9 +2360,9 @@ int magic; /* 0=Physical, otherwise skill level */
                 break;
             case TT_LAVA:
 /*JP
-                You("pull yourself above the lava!");
+                You("pull yourself above the %s!", hliquid("lava"));
 */
-                You("\97n\8aâ\82©\82ç\94ò\82Ñ\8fo\82½\81I");
+                You("%s\82©\82ç\94ò\82Ñ\8fo\82½\81I", hliquid("\97n\8aâ"));
                 u.utrap = 0;
                 return 1;
             case TT_BURIEDBALL:
@@ -2258,8 +2401,12 @@ int magic; /* 0=Physical, otherwise skill level */
             temp = -temp;
         if (range < temp)
             range = temp;
-        (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range);
-        teleds(cc.x, cc.y, TRUE);
+        (void) walk_path(&uc, &cc, hurtle_jump, (genericptr_t) &range);
+        /* hurtle_jump -> hurtle_step results in <u.ux,u.uy> == <cc.x,cc.y>
+         * and usually moves the ball if punished, but does not handle all
+         * the effects of landing on the final position.
+         */
+        teleds(cc.x, cc.y, FALSE);
         sokoban_guilt();
         nomul(-1);
 /*JP
@@ -2385,11 +2532,13 @@ struct obj *obj;
                 verbalize(you_buy_it);
             useupf(corpse, 1L);
         }
-/*JP
-        can = hold_another_object(can, "You make, but cannot pick up, %s.",
-*/
-        can = hold_another_object(can, "\8aÊ\8bl\82É\82Å\82«\82½\82ª\81C%s\82ð\8e\9d\82Â\82±\82Æ\82ª\82Å\82«\82È\82¢\81D",
-                                  doname(can), (const char *) 0);
+#if 0 /*JP*/
+        (void) hold_another_object(can, "You make, but cannot pick up, %s.",
+                                   doname(can), (const char *) 0);
+#else
+        (void) hold_another_object(can, "\8aÊ\8bl\82É\82Å\82«\82½\82ª\81C%s\82ð\8e\9d\82Â\82±\82Æ\82ª\82Å\82«\82È\82¢\81D",
+                                   doname(can), (const char *) 0);
+#endif
     } else
         impossible("Tinning failed.");
 }
@@ -2444,6 +2593,7 @@ struct obj *obj;
 */
                 pline("\89½\82à\8bN\82«\82È\82©\82Á\82½\82æ\82¤\82¾\81D");
             make_deaf((HDeaf & TIMEOUT) + lcount, TRUE);
+            context.botl = TRUE;
             break;
         }
         return;
@@ -2485,9 +2635,8 @@ struct obj *obj;
         if (ABASE(idx) >= AMAX(idx))
             continue;
         val_limit = AMAX(idx);
-        /* don't recover strength lost from hunger */
-        if (idx == A_STR && u.uhs >= WEAK)
-            val_limit--;
+        /* this used to adjust 'val_limit' for A_STR when u.uhs was
+           WEAK or worse, but that's handled via ATEMP(A_STR) now */
         if (Fixed_abil) {
             /* potion/spell of restore ability override sustain ability
                intrinsic but unicorn horn usage doesn't */
@@ -2635,8 +2784,9 @@ long timeout;
     if (mtmp) {
         char and_vanish[BUFSZ];
         struct obj *mshelter = level.objects[mtmp->mx][mtmp->my];
-        Sprintf(monnambuf, "%s", an(m_monnam(mtmp)));
 
+        /* [m_monnam() yields accurate mon type, overriding hallucination] */
+        Sprintf(monnambuf, "%s", an(m_monnam(mtmp)));
         /*JP:TODO:and_vanish\82Í\96¢\8f\88\97\9d*/
         and_vanish[0] = '\0';
         if ((mtmp->minvis && !See_invisible)
@@ -2697,14 +2847,16 @@ long timeout;
         case OBJ_MINVENT:
             if (cansee_spot && !silent && !suppress_see) {
                 struct monst *mon;
+
                 mon = figurine->ocarry;
                 /* figurine carrying monster might be invisible */
-                if (canseemon(figurine->ocarry)) {
+                if (canseemon(figurine->ocarry)
+                    && (!mon->wormno || cansee(mon->mx, mon->my)))
 /*JP
                     Sprintf(carriedby, "%s pack", s_suffix(a_monnam(mon)));
 */
-                    Sprintf(carriedby, "%s\82Ì\8a\93", s_suffix(a_monnam(mon)));
-                else if (is_pool(mon->mx, mon->my))
+                    Sprintf(carriedby, "%s\82Ì\8a\93", a_monnam(mon));
+                else if (is_pool(mon->mx, mon->my))
 /*JP
                     Strcpy(carriedby, "empty water");
 */
@@ -2923,20 +3075,6 @@ struct obj *obj;
     update_inventory();
 }
 
-static struct trapinfo {
-    struct obj *tobj;
-    xchar tx, ty;
-    int time_needed;
-    boolean force_bungle;
-} trapinfo;
-
-void
-reset_trapset()
-{
-    trapinfo.tobj = 0;
-    trapinfo.force_bungle = 0;
-}
-
 /* touchstones - by Ken Arnold */
 STATIC_OVL void
 use_stone(tstone)
@@ -3128,6 +3266,20 @@ struct obj *tstone;
     return;
 }
 
+static struct trapinfo {
+    struct obj *tobj;
+    xchar tx, ty;
+    int time_needed;
+    boolean force_bungle;
+} trapinfo;
+
+void
+reset_trapset()
+{
+    trapinfo.tobj = 0;
+    trapinfo.force_bungle = 0;
+}
+
 /* Place a landmine/bear trap.  Helge Hafting */
 STATIC_OVL void
 use_trap(otmp)
@@ -3532,7 +3684,7 @@ struct obj *obj;
                 pline1(msg_slipsfree);
             }
             if (mtmp)
-                wakeup(mtmp);
+                wakeup(mtmp, TRUE);
         } else
             pline1(msg_snap);
 
@@ -3601,9 +3753,8 @@ struct obj *obj;
                         int hitu, hitvalu;
 
                         hitvalu = 8 + otmp->spe;
-                        hitu = thitu(hitvalu,
-                                     dmgval(otmp, &youmonst),
-                                     otmp, (char *)0);
+                        hitu = thitu(hitvalu, dmgval(otmp, &youmonst),
+                                     &otmp, (char *)0);
                         if (hitu) {
 /*JP
                             pline_The("%s hits you as you try to snatch it!",
@@ -3640,19 +3791,23 @@ struct obj *obj;
 #endif
                         instapetrify(kbuf);
                     }
-                    otmp = hold_another_object(
-/*JP
-                        otmp, "You drop %s!", doname(otmp), (const char *) 0);
-*/
-                        otmp, "%s\82ð\97\8e\82µ\82½\81I", doname(otmp), (const char *) 0);
+#if 0 /*JP:T*/
+                    (void) hold_another_object(otmp, "You drop %s!",
+                                               doname(otmp), (const char *) 0);
+#else
+                    (void) hold_another_object(otmp, "%s\82ð\97\8e\82µ\82½\81I",
+                                               doname(otmp), (const char *) 0);
+#endif
                     break;
                 default:
                     /* to floor beneath mon */
-/*JP
+#if 0 /*JP*/
                     You("yank %s from %s %s!", the(onambuf),
-*/
-                    You("%s\82ð%s\82Ì%s\82©\82ç\82Ð\82Á\82Ï\82Á\82½\81I", the(xname(otmp)),
                         s_suffix(mon_nam(mtmp)), mon_hand);
+#else
+                    You("%s\82ð%s\82Ì%s\82©\82ç\82Ð\82Á\82Ï\82Á\82½\81I", the(xname(otmp)),
+                        mon_nam(mtmp), mon_hand);
+#endif
                     obj_no_longer_held(otmp);
                     place_object(otmp, mtmp->mx, mtmp->my);
                     stackobj(otmp);
@@ -3661,7 +3816,7 @@ struct obj *obj;
             } else {
                 pline1(msg_slipsfree);
             }
-            wakeup(mtmp);
+            wakeup(mtmp, TRUE);
         } else {
             if (mtmp->m_ap_type && !Protection_from_shape_changers
                 && !sensemon(mtmp))
@@ -3738,6 +3893,15 @@ int min_range, max_range;
 static int polearm_range_min = -1;
 static int polearm_range_max = -1;
 
+STATIC_OVL boolean
+get_valid_polearm_position(x,y)
+int x,y;
+{
+    return (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
+            && distu(x, y) >= polearm_range_min
+            && distu(x, y) <= polearm_range_max);
+}
+
 void
 display_polearm_positions(state)
 int state;
@@ -3751,9 +3915,7 @@ int state;
             for (dy = -4; dy <= 4; dy++) {
                 x = dx + (int) u.ux;
                 y = dy + (int) u.uy;
-                if (isok(x, y) && ACCESSIBLE(levl[x][y].typ)
-                    && distu(x, y) >= polearm_range_min
-                    && distu(x, y) <= polearm_range_max) {
+                if (get_valid_polearm_position(x, y)) {
                     tmp_at(x, y);
                 }
             }
@@ -3823,7 +3985,7 @@ struct obj *obj;
         cc.x = hitm->mx;
         cc.y = hitm->my;
     }
-    getpos_sethilite(display_polearm_positions);
+    getpos_sethilite(display_polearm_positions, get_valid_polearm_position);
 /*JP
     if (getpos(&cc, TRUE, "the spot to hit") < 0)
 */
@@ -3885,11 +4047,7 @@ struct obj *obj;
         }
     } else {
         /* no monster here and no statue seen or remembered here */
-        if (glyph_is_invisible(glyph)) {
-            /* now you know that nothing is there... */
-            unmap_object(bhitpos.x, bhitpos.y);
-            newsym(bhitpos.x, bhitpos.y);
-        }
+        (void) unmap_invisible(bhitpos.x, bhitpos.y);
 /*JP
         You("miss; there is no one there to hit.");
 */
@@ -4189,11 +4347,13 @@ struct obj *obj;
         You("%s\82ð\89ó\82·\82¾\82¯\82Ì\97Í\82ª\82È\82¢\81I", xname(obj));
         return 0;
     }
-/*JP
-    pline("Raising %s high above your %s, you break it in two!", yname(obj),
-*/
-    You("%s\82ð%s\82Ì\8fã\82É\8d\82\82­\8cf\82°\81C\93ñ\82Â\82É\82Ö\82µ\90Ü\82Á\82½\81I", xname(obj),
+#if 0 /*JP:T*/
+    pline("Raising %s high above your %s, you %s it in two!", yname(obj),
+          body_part(HEAD), is_fragile ? "snap" : "break");
+#else
+    pline("%s\82ð%s\82Ì\8fã\82É\8d\82\82­\8cf\82°\81C\93ñ\82Â\82É\82Ö\82µ\90Ü\82Á\82½\81I", yname(obj),
           body_part(HEAD));
+#endif
 
     /* [ALI] Do this first so that wand is removed from bill. Otherwise,
      * the freeinv() below also hides it from setpaid() which causes problems.
@@ -4242,10 +4402,12 @@ struct obj *obj;
         goto wanexpl;
     case WAN_FIRE:
         expltype = EXPL_FIERY;
+        /*FALLTHRU*/
     case WAN_COLD:
         if (expltype == EXPL_MAGICAL)
             expltype = EXPL_FROSTY;
         dmg *= 2;
+        /*FALLTHRU*/
     case WAN_MAGIC_MISSILE:
     wanexpl:
         explode(u.ux, u.uy, -(obj->otyp), dmg, WAND_CLASS, expltype);
@@ -4517,7 +4679,7 @@ doapply()
     case SACK:
     case BAG_OF_HOLDING:
     case OILSKIN_SACK:
-        res = use_container(&obj, 1);
+        res = use_container(&obj, 1, FALSE);
         break;
     case BAG_OF_TRICKS:
         (void) bagotricks(obj, FALSE, (int *) 0);
@@ -4538,7 +4700,7 @@ doapply()
         use_tinning_kit(obj);
         break;
     case LEASH:
-        use_leash(obj);
+        res = use_leash(obj);
         break;
     case SADDLE:
         res = use_saddle(obj);
@@ -4593,7 +4755,7 @@ doapply()
         use_lamp(obj);
         break;
     case POT_OIL:
-        light_cocktail(obj);
+        light_cocktail(&obj);
         break;
     case EXPENSIVE_CAMERA:
         res = use_camera(obj);
@@ -4608,30 +4770,8 @@ doapply()
         res = dowrite(obj);
         break;
     case TIN_OPENER:
-        if (!carrying(TIN)) {
-/*JP
-            You("have no tin to open.");
-*/
-            You("\8aÊ\82ð\8e\9d\82Á\82Ä\82¢\82È\82¢\81D");
-            goto xit;
-        }
-/*JP
-        You("cannot open a tin without eating or discarding its contents.");
-*/
-        pline("\92\86\90g\82ð\90H\82×\82é\82©\81C\8eÌ\82Ä\82é\82©\82µ\82È\82¢\82Æ\8aÊ\82ð\8aJ\82¯\82ç\82ê\82È\82¢\81D");
-        if (flags.verbose)
-/*JP
-            pline("In order to eat, use the 'e' command.");
-*/
-            pline("\90H\82×\82é\82É\82Í\81C'e'\83R\83}\83\93\83h\82ð\8eg\82¦\82Î\82æ\82¢\81D");
-        if (obj != uwep)
-            pline(
-/*JP
-          "Opening the tin will be much easier if you wield the tin opener.");
-*/
-          "\8aÊ\90Ø\82è\82ð\91\95\94õ\82µ\82Ä\82¢\82ê\82Î\81C\82¸\82Á\82Æ\8aÈ\92P\82É\8aJ\82¯\82é\82±\82Æ\82ª\82Å\82«\82é\81D");
-        goto xit;
-
+        res = use_tin_opener(obj);
+        break;
     case FIGURINE:
         use_figurine(&obj);
         break;
@@ -4676,7 +4816,6 @@ doapply()
         pline("Sorry, I don't know how to use that.");
 */
         pline("\82»\82ê\82ð\82Ç\82¤\82â\82Á\82Ä\8eg\82¤\82ñ\82¾\82¢\81H");
-    xit:
         nomul(0);
         return 0;
     }