OSDN Git Service

upgrade to 3.6.1
[jnethack/source.git] / src / muse.c
index b7f7a70..2d74c03 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 muse.c  $NHDT-Date: 1447987786 2015/11/20 02:49:46 $  $NHDT-Branch: master $:$NHDT-Revision: 1.68 $ */
+/* NetHack 3.6 muse.c  $NHDT-Date: 1505181522 2017/09/12 01:58:42 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */
 /*      Copyright (C) 1990 by Ken Arromdee                         */
 /* NetHack may be freely redistributed.  See license for details.  */
 
@@ -28,6 +28,7 @@ STATIC_DCL int FDECL(precheck, (struct monst *, struct obj *));
 STATIC_DCL void FDECL(mzapmsg, (struct monst *, struct obj *, BOOLEAN_P));
 STATIC_DCL void FDECL(mreadmsg, (struct monst *, struct obj *));
 STATIC_DCL void FDECL(mquaffmsg, (struct monst *, struct obj *));
+STATIC_DCL boolean FDECL(m_use_healing, (struct monst *));
 STATIC_PTR int FDECL(mbhitm, (struct monst *, struct obj *));
 STATIC_DCL void FDECL(mbhit, (struct monst *, int,
                               int FDECL((*), (MONST_P, OBJ_P)),
@@ -39,7 +40,7 @@ STATIC_DCL boolean FDECL(cures_stoning, (struct monst *, struct obj *,
                                          BOOLEAN_P));
 STATIC_DCL boolean FDECL(mcould_eat_tin, (struct monst *));
 STATIC_DCL boolean FDECL(muse_unslime, (struct monst *, struct obj *,
-                                        BOOLEAN_P));
+                                        struct trap *, BOOLEAN_P));
 STATIC_DCL int FDECL(cures_sliming, (struct monst *, struct obj *));
 STATIC_DCL boolean FDECL(green_mon, (struct monst *));
 
@@ -178,27 +179,37 @@ struct obj *obj;
         && !rn2(WAND_BACKFIRE_CHANCE)) {
         int dam = d(obj->spe + 2, 6);
 
-        if (!Deaf) {
-            if (vis)
+        /* 3.6.1: no Deaf filter; 'if' message doesn't warrant it, 'else'
+           message doesn't need it since You_hear() has one of its own */
+        if (vis) {
+#if 0 /*JP:T*/
+            pline("%s zaps %s, which suddenly explodes!", Monnam(mon),
+                  an(xname(obj)));
+#else
+            pline("%s\82ª%s\82ð\82Ó\82è\82©\82´\82·\82Æ\81C\82»\82ê\82Í\93Ë\91R\94\9a\94­\82µ\82½\81I", Monnam(mon),
+                  an(xname(obj)));
+#endif
+        } else {
+            /* same near/far threshold as mzapmsg() */
+            int range = couldsee(mon->mx, mon->my) /* 9 or 5 */
+                           ? (BOLT_LIM + 1) : (BOLT_LIM - 3);
+
 #if 0 /*JP*/
-                pline("%s zaps %s, which suddenly explodes!", Monnam(mon),
-                      an(xname(obj)));
+            You_hear("a zap and an explosion %s.",
+                     (distu(mon->mx, mon->my) <= range * range)
+                        ? "nearby" : "in the distance");
 #else
-                pline("%s\82Í%s\82ð\82Ó\82è\82©\82´\82µ\82½\81C\82»\82ê\82Í\93Ë\91R\94\9a\94­\82µ\82½\81I", Monnam(mon),
-                      an(xname(obj)));
+            You_hear("%s\82­\82Ì\8fñ\82Ì\89¹\82Æ\94\9a\94­\89¹\82ð\95·\82¢\82½\81D",
+                     (distu(mon->mx, mon->my) <= range * range)
+                        ? "\8bß" : "\89\93");
 #endif
-            else
-/*JP
-                You_hear("a zap and an explosion in the distance.");
-*/
-                You_hear("\89\93\95û\82Ì\8fñ\82Ì\89¹\82Æ\94\9a\94­\89¹\82ð\95·\82¢\82½\81D");
         }
         m_useup(mon, obj);
-        if (mon->mhp <= dam) {
+        mon->mhp -= dam;
+        if (mon->mhp <= 0) {
             monkilled(mon, "", AD_RBRE);
             return 1;
-        } else
-            mon->mhp -= dam;
+        }
         m.has_defense = m.has_offense = m.has_misc = 0;
         /* Only one needed to be set to 0 but the others are harmless */
     }
@@ -212,17 +223,16 @@ struct obj *otmp;
 boolean self;
 {
     if (!canseemon(mtmp)) {
-        if (!Deaf)
+        int range = couldsee(mtmp->mx, mtmp->my) /* 9 or 5 */
+                       ? (BOLT_LIM + 1) : (BOLT_LIM - 3);
+
 #if 0 /*JP*/
-            You_hear("a %s zap.", (distu(mtmp->mx, mtmp->my)
-                                   <= (BOLT_LIM + 1) * (BOLT_LIM + 1))
-                                      ? "nearby"
-                                      : "distant");
+        You_hear("a %s zap.", (distu(mtmp->mx, mtmp->my) <= range * range)
+                                 ? "nearby" : "distant");
 #else
-            You_hear("%s\82­\82Å\8fñ\82Ì\89¹\82ð\95·\82¢\82½\81D", (distu(mtmp->mx, mtmp->my)
-                                   <= (BOLT_LIM + 1) * (BOLT_LIM + 1))
-                                      ? "\8bß"
-                                      : "\89\93");
+        You_hear("%s\82­\82Å\8fñ\82Ì\89¹\82ð\95·\82¢\82½\81D",
+                              (distu(mtmp->mx, mtmp->my) <= range * range)
+                                 ? "\8bß" : "\89\93");
 #endif
     } else if (self) {
 #if 0 /*JP*/
@@ -345,6 +355,29 @@ struct obj *otmp;
  * that if you polymorph into one you teleport at will.
  */
 
+STATIC_OVL boolean
+m_use_healing(mtmp)
+struct monst *mtmp;
+{
+    struct obj *obj = 0;
+    if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
+        m.defensive = obj;
+        m.has_defense = MUSE_POT_FULL_HEALING;
+        return TRUE;
+    }
+    if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
+        m.defensive = obj;
+        m.has_defense = MUSE_POT_EXTRA_HEALING;
+        return TRUE;
+    }
+    if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
+        m.defensive = obj;
+        m.has_defense = MUSE_POT_HEALING;
+        return TRUE;
+    }
+    return FALSE;
+}
+
 /* Select a defensive item/action for a monster.  Returns TRUE iff one is
    found. */
 boolean
@@ -415,21 +448,8 @@ struct monst *mtmp;
      */
     if (!mtmp->mcansee && !nohands(mtmp->data)
         && mtmp->data != &mons[PM_PESTILENCE]) {
-        if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
-            m.defensive = obj;
-            m.has_defense = MUSE_POT_FULL_HEALING;
+        if (m_use_healing(mtmp))
             return TRUE;
-        }
-        if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
-            m.defensive = obj;
-            m.has_defense = MUSE_POT_EXTRA_HEALING;
-            return TRUE;
-        }
-        if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
-            m.defensive = obj;
-            m.has_defense = MUSE_POT_HEALING;
-            return TRUE;
-        }
     }
 
     fraction = u.ulevel < 10 ? 5 : u.ulevel < 14 ? 4 : 3;
@@ -439,21 +459,8 @@ struct monst *mtmp;
 
     if (mtmp->mpeaceful) {
         if (!nohands(mtmp->data)) {
-            if ((obj = m_carrying(mtmp, POT_FULL_HEALING)) != 0) {
-                m.defensive = obj;
-                m.has_defense = MUSE_POT_FULL_HEALING;
-                return TRUE;
-            }
-            if ((obj = m_carrying(mtmp, POT_EXTRA_HEALING)) != 0) {
-                m.defensive = obj;
-                m.has_defense = MUSE_POT_EXTRA_HEALING;
-                return TRUE;
-            }
-            if ((obj = m_carrying(mtmp, POT_HEALING)) != 0) {
-                m.defensive = obj;
-                m.has_defense = MUSE_POT_HEALING;
+            if (m_use_healing(mtmp))
                 return TRUE;
-            }
         }
         return FALSE;
     }
@@ -465,9 +472,7 @@ struct monst *mtmp;
             if (!is_floater(mtmp->data))
                 m.has_defense = MUSE_DOWNSTAIRS;
         } else if (x == xupstair && y == yupstair) {
-            /* don't let monster leave the dungeon with the Amulet */
-            if (ledger_no(&u.uz) != 1)
-                m.has_defense = MUSE_UPSTAIRS;
+            m.has_defense = MUSE_UPSTAIRS;
         } else if (sstairs.sx && x == sstairs.sx && y == sstairs.sy) {
             if (sstairs.up || !is_floater(mtmp->data))
                 m.has_defense = MUSE_SSTAIRS;
@@ -683,10 +688,7 @@ struct monst *mtmp;
     int i, fleetim, how = 0;
     struct obj *otmp = m.defensive;
     boolean vis, vismon, oseen;
-/*JP
-    const char *mcsa = "%s can see again.";
-*/
-    const char *mcsa = "%s\82Í\82Ü\82½\8c©\82¦\82é\82æ\82¤\82É\82È\82Á\82½\81D";
+    const char *Mnam;
 
     if ((i = precheck(mtmp, otmp)) != 0)
         return i;
@@ -717,10 +719,7 @@ struct monst *mtmp;
                 pline("%s\82Ì\8ap\82Ì\90æ\92[\82ª\8bP\82¢\82½\81I", mon_nam(mtmp));
         }
         if (!mtmp->mcansee) {
-            mtmp->mcansee = 1;
-            mtmp->mblinded = 0;
-            if (vismon)
-                pline(mcsa, Monnam(mtmp));
+            mcureblindness(mtmp, vismon);
         } else if (mtmp->mconf || mtmp->mstun) {
             mtmp->mconf = mtmp->mstun = 0;
             if (vismon)
@@ -950,12 +949,13 @@ struct monst *mtmp;
         if (vis) {
             struct trap *t = t_at(trapx, trapy);
 
+            Mnam = Monnam(mtmp);
 #if 0 /*JP*/
-            pline("%s %s into a %s!", Monnam(mtmp),
-                  makeplural(locomotion(mtmp->data, "jump")),
-                  t->ttyp == TRAPDOOR ? "trap door" : "hole");
+            pline("%s %s into a %s!", Mnam,
+                  vtense(Mnam, locomotion(mtmp->data, "jump")),
+                  (t->ttyp == TRAPDOOR) ? "trap door" : "hole");
 #else
-            pline("%s\82Í%s\82É%s\93ü\82Á\82½\81I", Monnam(mtmp),
+            pline("%s\82Í%s\82É%s\93ü\82Á\82½\81I", Mnam,
                   t->ttyp == TRAPDOOR ? "\97\8e\82µ\94à" : "\8c\8a",
                   jconj(locomotion(mtmp->data, "\94ò\82Ô"), "\82Ä"));
 #endif
@@ -978,24 +978,9 @@ struct monst *mtmp;
                          (coord *) 0);
         return 2;
     case MUSE_UPSTAIRS:
-        /* Monsters without amulets escape the dungeon and are
-         * gone for good when they leave up the up stairs.
-         * Monsters with amulets would reach the endlevel,
-         * which we cannot allow since that would leave the
-         * player stranded.
-         */
-        if (ledger_no(&u.uz) == 1) {
-            if (mon_has_special(mtmp))
-                return 0;
-            if (vismon)
-/*JP
-                pline("%s escapes the dungeon!", Monnam(mtmp));
-*/
-                pline("%s\82Í\96À\8b{\82©\82ç\93¦\91\96\82µ\82½\81I", Monnam(mtmp));
-            mongone(mtmp);
-            return 2;
-        }
         m_flee(mtmp);
+        if (ledger_no(&u.uz) == 1)
+            goto escape; /* impossible; level 1 upstairs are SSTAIRS */
         if (Inhell && mon_has_amulet(mtmp) && !rn2(4)
             && (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz) - 3)) {
             if (vismon)
@@ -1056,6 +1041,25 @@ struct monst *mtmp;
         return 2;
     case MUSE_SSTAIRS:
         m_flee(mtmp);
+        if (ledger_no(&u.uz) == 1) {
+        escape:
+            /* Monsters without the Amulet escape the dungeon and
+             * are gone for good when they leave up the up stairs.
+             * A monster with the Amulet would leave it behind
+             * (mongone -> mdrop_special_objs) but we force any
+             * monster who manages to acquire it or the invocation
+             * tools to stick around instead of letting it escape.
+             */
+            if (mon_has_special(mtmp))
+                return 0;
+            if (vismon)
+/*JP
+                pline("%s escapes the dungeon!", Monnam(mtmp));
+*/
+                pline("%s\82Í\96À\8b{\82©\82ç\93¦\91\96\82µ\82½\81I", Monnam(mtmp));
+            mongone(mtmp);
+            return 2;
+        }
         if (vismon)
 #if 0 /*JP*/
             pline("%s escapes %sstairs!", Monnam(mtmp),
@@ -1074,11 +1078,12 @@ struct monst *mtmp;
     case MUSE_TELEPORT_TRAP:
         m_flee(mtmp);
         if (vis) {
-#if 0 /*JP*/
-            pline("%s %s onto a teleport trap!", Monnam(mtmp),
-                  makeplural(locomotion(mtmp->data, "jump")));
-#else
-            pline("%s\82Í\8fu\8aÔ\88Ú\93®\82Ìã©\82É\94ò\82Ñ\8d\9e\82ñ\82¾\81I", Monnam(mtmp));
+            Mnam = Monnam(mtmp);
+#if 0 /*JP:T*/
+            pline("%s %s onto a teleport trap!", Mnam,
+                  vtense(Mnam, locomotion(mtmp->data, "jump")));
+#else /* \93ú\96{\8cê\82Å\82Í\91S\82Ä\81u\94ò\82Ñ\8d\9e\82ñ\82¾\81v */
+            pline("%s\82Í\8fu\8aÔ\88Ú\93®\82Ìã©\82É\94ò\82Ñ\8d\9e\82ñ\82¾\81I", Mnam);
 #endif
             seetrap(t_at(trapx, trapy));
         }
@@ -1097,12 +1102,8 @@ struct monst *mtmp;
         mtmp->mhp += i;
         if (mtmp->mhp > mtmp->mhpmax)
             mtmp->mhp = ++mtmp->mhpmax;
-        if (!otmp->cursed && !mtmp->mcansee) {
-            mtmp->mcansee = 1;
-            mtmp->mblinded = 0;
-            if (vismon)
-                pline(mcsa, Monnam(mtmp));
-        }
+        if (!otmp->cursed && !mtmp->mcansee)
+            mcureblindness(mtmp, vismon);
         if (vismon)
 /*JP
             pline("%s looks better.", Monnam(mtmp));
@@ -1118,12 +1119,8 @@ struct monst *mtmp;
         mtmp->mhp += i;
         if (mtmp->mhp > mtmp->mhpmax)
             mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 5 : 2));
-        if (!mtmp->mcansee) {
-            mtmp->mcansee = 1;
-            mtmp->mblinded = 0;
-            if (vismon)
-                pline(mcsa, Monnam(mtmp));
-        }
+        if (!mtmp->mcansee)
+            mcureblindness(mtmp, vismon);
         if (vismon)
 /*JP
             pline("%s looks much better.", Monnam(mtmp));
@@ -1138,12 +1135,8 @@ struct monst *mtmp;
         if (otmp->otyp == POT_SICKNESS)
             unbless(otmp); /* Pestilence */
         mtmp->mhp = (mtmp->mhpmax += (otmp->blessed ? 8 : 4));
-        if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS) {
-            mtmp->mcansee = 1;
-            mtmp->mblinded = 0;
-            if (vismon)
-                pline(mcsa, Monnam(mtmp));
-        }
+        if (!mtmp->mcansee && otmp->otyp != POT_SICKNESS)
+            mcureblindness(mtmp, vismon);
         if (vismon)
 /*JP
             pline("%s looks completely healed.", Monnam(mtmp));
@@ -1187,7 +1180,7 @@ try_again:
             goto try_again;
         if (!rn2(3))
             return WAN_TELEPORTATION;
-    /* else FALLTHRU */
+        /*FALLTHRU*/
     case 0:
     case 1:
         return SCR_TELEPORTATION;
@@ -1195,7 +1188,7 @@ try_again:
     case 10:
         if (!rn2(3))
             return WAN_CREATE_MONSTER;
-    /* else FALLTHRU */
+        /*FALLTHRU*/
     case 2:
         return SCR_CREATE_MONSTER;
     case 3:
@@ -1281,7 +1274,7 @@ struct monst *mtmp;
                 m.has_offense = MUSE_WAN_FIRE;
             }
             nomore(MUSE_FIRE_HORN);
-            if (obj->otyp == FIRE_HORN && obj->spe > 0) {
+            if (obj->otyp == FIRE_HORN && obj->spe > 0 && can_blow(mtmp)) {
                 m.offensive = obj;
                 m.has_offense = MUSE_FIRE_HORN;
             }
@@ -1291,7 +1284,7 @@ struct monst *mtmp;
                 m.has_offense = MUSE_WAN_COLD;
             }
             nomore(MUSE_FROST_HORN);
-            if (obj->otyp == FROST_HORN && obj->spe > 0) {
+            if (obj->otyp == FROST_HORN && obj->spe > 0 && can_blow(mtmp)) {
                 m.offensive = obj;
                 m.has_offense = MUSE_FROST_HORN;
             }
@@ -1311,6 +1304,24 @@ struct monst *mtmp;
             m.offensive = obj;
             m.has_offense = MUSE_WAN_STRIKING;
         }
+#if 0   /* use_offensive() has had some code to support wand of teleportation
+         * for a long time, but find_offensive() never selected one;
+         * so for the time being, this is still disabled */
+        nomore(MUSE_WAN_TELEPORTATION);
+        if (obj->otyp == WAN_TELEPORTATION && obj->spe > 0
+            /* don't give controlled hero a free teleport */
+            && !Teleport_control
+            /* do try to move hero to a more vulnerable spot */
+            && (onscary(u.ux, u.uy, mtmp)
+                || (u.ux == xupstair && u.uy == yupstair)
+                || (u.ux == xdnstair && u.uy == ydnstair)
+                || (u.ux == sstairs.sx && u.uy == sstairs.sy)
+                || (u.ux == xupladder && u.uy == yupladder)
+                || (u.ux == xdnladder && u.uy == ydnladder))) {
+            m.offensive = obj;
+            m.has_offense = MUSE_WAN_TELEPORTATION;
+        }
+#endif
         nomore(MUSE_POT_PARALYSIS);
         if (obj->otyp == POT_PARALYSIS && multi >= 0) {
             m.offensive = obj;
@@ -1374,8 +1385,8 @@ register struct monst *mtmp;
 register struct obj *otmp;
 {
     int tmp;
-
     boolean reveal_invis = FALSE;
+
     if (mtmp != &youmonst) {
         mtmp->msleeping = 0;
         if (mtmp->m_ap_type)
@@ -1436,6 +1447,7 @@ register struct obj *otmp;
                 makeknown(WAN_STRIKING);
         }
         break;
+#if 0   /* disabled because find_offensive() never picks WAN_TELEPORTATION */
     case WAN_TELEPORTATION:
         if (mtmp == &youmonst) {
             if (zap_oseen)
@@ -1453,6 +1465,7 @@ register struct obj *otmp;
                 (void) rloc(mtmp, TRUE);
         }
         break;
+#endif
     case WAN_CANCELLATION:
     case SPE_CANCELLATION:
         (void) cancel_monst(mtmp, otmp, FALSE, TRUE, FALSE);
@@ -1720,10 +1733,13 @@ struct monst *mtmp;
 */
                 losehp(num, "\89\8a\82Ì\8aª\95¨\82Å", KILLED_BY_AN);
             for (mtmp2 = fmon; mtmp2; mtmp2 = mtmp2->nmon) {
-                if (DEADMONSTER(mtmp2)) continue;
-                if (mtmp == mtmp2) continue;
+                if (DEADMONSTER(mtmp2))
+                    continue;
+                if (mtmp == mtmp2)
+                    continue;
                 if (dist2(mtmp2->mx, mtmp2->my, mtmp->mx, mtmp->my) < 3) {
-                    if (resists_fire(mtmp2)) continue;
+                    if (resists_fire(mtmp2))
+                        continue;
                     mtmp2->mhp -= num;
                     if (resists_cold(mtmp2))
                         mtmp2->mhp -= 3 * num;
@@ -2052,8 +2068,8 @@ struct monst *mtmp;
         Strcpy(nambuf, mon_nam(mtmp));
         mon_set_minvis(mtmp);
         if (vismon && mtmp->minvis) { /* was seen, now invisible */
-            if (canspotmon(mtmp))
-#if 0 /*JP*/
+            if (canspotmon(mtmp)) {
+#if 0 /*JP:T*/
                 pline("%s body takes on a %s transparency.",
                       upstart(s_suffix(nambuf)),
                       Hallucination ? "normal" : "strange");
@@ -2062,11 +2078,14 @@ struct monst *mtmp;
                       Hallucination ? "\82 \82½\82è\82Ü\82¦\82È\82±\82Æ\82¾\82ª" : "\8aï\96­\82È\82±\82Æ\82É",
                       nambuf);
 #endif
-            else
+            } else {
 /*JP
                 pline("Suddenly you cannot see %s.", nambuf);
 */
                 pline("%s\82Í\93Ë\91R\8c©\82¦\82È\82­\82È\82Á\82½\81D", nambuf);
+                if (vis)
+                    map_invisible(mtmp->mx, mtmp->my);
+            }
             if (oseen)
                 makeknown(otmp->otyp);
         }
@@ -2110,13 +2129,16 @@ struct monst *mtmp;
         m_useup(mtmp, otmp);
         return 2;
     case MUSE_POLY_TRAP:
-        if (vismon)
-#if 0 /*JP*/
-            pline("%s deliberately %s onto a polymorph trap!", Monnam(mtmp),
-                  makeplural(locomotion(mtmp->data, "jump")));
+        if (vismon) {
+            const char *Mnam = Monnam(mtmp);
+
+#if 0 /*JP:T*/
+            pline("%s deliberately %s onto a polymorph trap!", Mnam,
+                  vtense(Mnam, locomotion(mtmp->data, "jump")));
 #else
-            pline("%s\82Í\82í\82´\82Æ\95Ï\89»\82Ìã©\82É\94ò\82Ñ\82±\82ñ\82¾\81I", Monnam(mtmp));
+            pline("%s\82Í\82í\82´\82Æ\95Ï\89»\82Ìã©\82É\94ò\82Ñ\82±\82ñ\82¾\81I", Mnam);
 #endif
+        }
         if (vis)
             seetrap(t_at(trapx, trapy));
 
@@ -2249,11 +2271,13 @@ STATIC_OVL void
 you_aggravate(mtmp)
 struct monst *mtmp;
 {
-/*JP
+#if 0 /*JP:T*/
     pline("For some reason, %s presence is known to you.",
-*/
-    pline("\82È\82º\82©\81C\82 \82È\82½\82Í%s\82Ì\91\8dÝ\82É\8bC\82ª\82Â\82¢\82½\81D",
           s_suffix(noit_mon_nam(mtmp)));
+#else
+    pline("\82È\82º\82©\81C\82 \82È\82½\82Í%s\82Ì\91\8dÝ\82É\8bC\82ª\82Â\82¢\82½\81D",
+          noit_mon_nam(mtmp));
+#endif
     cls();
 #ifdef CLIPPING
     cliparound(mtmp->mx, mtmp->my);
@@ -2369,7 +2393,7 @@ struct obj *obj;
         if (typ == UNICORN_HORN)
             return (boolean) (!obj->cursed && !is_unicorn(mon->data));
         if (typ == FROST_HORN || typ == FIRE_HORN)
-            return (obj->spe > 0);
+            return (obj->spe > 0 && can_blow(mon));
         break;
     case FOOD_CLASS:
         if (typ == CORPSE)
@@ -2496,6 +2520,23 @@ const char *fmt, *str;
     return FALSE;
 }
 
+/* cure mon's blindness (use_defensive, dog_eat, meatobj) */
+void
+mcureblindness(mon, verbos)
+struct monst *mon;
+boolean verbos;
+{
+    if (!mon->mcansee) {
+        mon->mcansee = 1;
+        mon->mblinded = 0;
+        if (verbos && haseyes(mon->data))
+/*JP
+            pline("%s can see again.", Monnam(mon));
+*/
+            pline("%s\82Í\82Ü\82½\8c©\82¦\82é\82æ\82¤\82É\82È\82Á\82½\81D", Monnam(mon));
+    }
+}
+
 /* TRUE if the monster ate something */
 boolean
 munstone(mon, by_you)
@@ -2526,7 +2567,7 @@ mon_consume_unstone(mon, obj, by_you, stoning)
 struct monst *mon;
 struct obj *obj;
 boolean by_you;
-boolean stoning;
+boolean stoning; /* True: stop petrification, False: cure stun && confusion */
 {
     boolean vis = canseemon(mon), tinned = obj->otyp == TIN,
             food = obj->otyp == CORPSE || tinned,
@@ -2585,7 +2626,10 @@ boolean stoning;
 */
             pline("%s\82Í\8e\80\82ñ\82¾\81I", Monnam(mon));
             if (by_you)
-                xkilled(mon, 0);
+                /* hero gets credit (experience) and blame (possible loss
+                   of alignment and/or luck and/or telepathy depending on
+                   mon) for the kill but does not break pacifism conduct */
+                xkilled(mon, XKILL_NOMSG | XKILL_NOCONDUCT);
             else
                 mondead(mon);
             return;
@@ -2681,6 +2725,7 @@ struct monst *mon;
 boolean by_you;
 {
     struct obj *obj, odummy;
+    struct permonst *mptr = mon->data;
 
     /*
      * muse_unslime() gives "mon starts turning green", "mon zaps
@@ -2689,7 +2734,7 @@ boolean by_you;
      * (via our caller) newcham()'s "mon turns into slime" feedback.
      */
 
-    if (slimeproof(mon->data))
+    if (slimeproof(mptr))
         return FALSE;
     if (mon->meating || !mon->mcanmove || mon->msleeping)
         return FALSE;
@@ -2701,29 +2746,63 @@ boolean by_you;
        [possible extension: monst capable of casting high level clerical
        spells could toss pillar of fire at self--probably too suicidal] */
     if (!mon->mcan && !mon->mspec_used
-        && attacktype_fordmg(mon->data, AT_BREA, AD_FIRE)) {
+        && attacktype_fordmg(mptr, AT_BREA, AD_FIRE)) {
         odummy = zeroobj; /* otyp == STRANGE_OBJECT */
-        return muse_unslime(mon, &odummy, by_you);
+        return muse_unslime(mon, &odummy, (struct trap *) 0, by_you);
     }
 
-    for (obj = mon->minvent; obj; obj = obj->nobj)
-        if (cures_sliming(mon, obj))
-            return muse_unslime(mon, obj, by_you);
+    /* same MUSE criteria as use_defensive() */
+    if (!is_animal(mptr) && !mindless(mptr)) {
+        struct trap *t;
 
-    /* TODO: check for and move onto an adjacent fire trap */
+        for (obj = mon->minvent; obj; obj = obj->nobj)
+            if (cures_sliming(mon, obj))
+                return muse_unslime(mon, obj, (struct trap *) 0, by_you);
+
+        if (((t = t_at(mon->mx, mon->my)) == 0 || t->ttyp != FIRE_TRAP)
+            && mptr->mmove && !mon->mtrapped) {
+            int xy[2][8], x, y, idx, ridx, nxy = 0;
+
+            for (x = mon->mx - 1; x <= mon->mx + 1; ++x)
+                for (y = mon->my - 1; y <= mon->my + 1; ++y)
+                    if (isok(x, y) && accessible(x, y)
+                        && !m_at(x, y) && (x != u.ux || y != u.uy)) {
+                        xy[0][nxy] = x, xy[1][nxy] = y;
+                        ++nxy;
+                    }
+            for (idx = 0; idx < nxy; ++idx) {
+                ridx = rn1(nxy - idx, idx);
+                if (ridx != idx) {
+                    x = xy[0][idx];
+                    xy[0][idx] = xy[0][ridx];
+                    xy[0][ridx] = x;
+                    y = xy[1][idx];
+                    xy[1][idx] = xy[1][ridx];
+                    xy[1][ridx] = y;
+                }
+                if ((t = t_at(xy[0][idx], xy[1][idx])) != 0
+                    && t->ttyp == FIRE_TRAP)
+                    break;
+            }
+        }
+        if (t && t->ttyp == FIRE_TRAP)
+            return muse_unslime(mon, &zeroobj, t, by_you);
+
+    } /* MUSE */
 
     return FALSE;
 }
 
 /* mon uses an item--selected by caller--to burn away incipient slime */
 STATIC_OVL boolean
-muse_unslime(mon, obj, by_you)
+muse_unslime(mon, obj, trap, by_you)
 struct monst *mon;
 struct obj *obj;
+struct trap *trap;
 boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
-{
+{               /* [by_you not honored if 'mon' triggers fire trap]. */
     struct obj *odummyp;
-    int otyp = obj->otyp, dmg;
+    int otyp = obj->otyp, dmg = 0;
     boolean vis = canseemon(mon), res = TRUE;
 
     if (vis)
@@ -2732,14 +2811,37 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
     /* -4 => sliming, causes quiet loss of enhanced speed */
     mon_adjust_speed(mon, -4, (struct obj *) 0);
 
-    if (otyp == STRANGE_OBJECT) {
+    if (trap) {
+        const char *Mnam = vis ? Monnam(mon) : 0;
+
+        if (mon->mx == trap->tx && mon->my == trap->ty) {
+            if (vis)
+                pline("%s triggers %s fire trap!", Mnam,
+                      trap->tseen ? "the" : "a");
+        } else {
+            remove_monster(mon->mx, mon->my);
+            newsym(mon->mx, mon->my);
+            place_monster(mon, trap->tx, trap->ty);
+            if (mon->wormno) /* won't happen; worms don't MUSE to unslime */
+                worm_move(mon);
+            newsym(mon->mx, mon->my);
+            if (vis)
+                pline("%s %s %s %s fire trap!", Mnam,
+                      vtense(Mnam, locomotion(mon->data, "move")),
+                      is_floater(mon->data) ? "over" : "onto",
+                      trap->tseen ? "the" : "a");
+        }
+        /* hack to avoid mintrap()'s chance of avoiding known trap */
+        mon->mtrapseen &= ~(1 << (FIRE_TRAP - 1));
+        mintrap(mon);
+    } else if (otyp == STRANGE_OBJECT) {
         /* monster is using fire breath on self */
         if (vis)
             pline("%s breathes fire on %sself.", Monnam(mon), mhim(mon));
         if (!rn2(3))
             mon->mspec_used = rn1(10, 5);
         /* -21 => monster's fire breath; 1 => # of damage dice */
-        (void) zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
+        dmg = zhitm(mon, by_you ? 21 : -21, 1, &odummyp);
     } else if (otyp == SCR_FIRE) {
         mreadmsg(mon, obj);
         if (mon->mconf) {
@@ -2758,17 +2860,43 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
             explode(mon->mx, mon->my, -11, dmg, SCROLL_CLASS,
                     /* by_you: override -11 for mon but not others */
                     by_you ? -EXPL_FIERY : EXPL_FIERY);
+            dmg = 0; /* damage has been applied by explode() */
         }
     } else { /* wand/horn of fire w/ positive charge count */
         mzapmsg(mon, obj, TRUE);
         obj->spe--;
         /* -1 => monster's wand of fire; 2 => # of damage dice */
-        (void) zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
+        dmg = zhitm(mon, by_you ? 1 : -1, 2, &odummyp);
     }
 
+    if (dmg) {
+        /* zhitm() applies damage but doesn't kill creature off;
+           for fire breath, dmg is going to be 0 (fire breathers are
+           immune to fire damage) but for wand of fire or fire horn,
+           'mon' could have taken damage so might die */
+        if (mon->mhp <= 0) {
+            if (by_you) {
+                /* mon killed self but hero gets credit and blame (except
+                   for pacifist conduct); xkilled()'s message would say
+                   "You killed/destroyed <mon>" so give our own message */
+                if (vis)
+                    pline("%s is %s by the fire!", Monnam(mon),
+                          nonliving(mon->data) ? "destroyed" : "killed");
+                xkilled(mon, XKILL_NOMSG | XKILL_NOCONDUCT);
+            } else
+                monkilled(mon, "fire", AD_FIRE);
+        } else {
+            /* non-fatal damage occurred */
+            if (vis)
+                pline("%s is burned%s", Monnam(mon), exclam(dmg));
+        }
+    }
     if (vis) {
         if (res && mon->mhp > 0)
+/*JP
             pline("%s slime is burned away!", s_suffix(Monnam(mon)));
+*/
+            pline("%s\82Ì\83X\83\89\83C\83\80\82Í\94R\82¦\82Â\82«\82½\81I", Monnam(mon));
         if (otyp != STRANGE_OBJECT)
             makeknown(otyp);
     }
@@ -2788,7 +2916,8 @@ struct obj *obj;
     if (obj->otyp == SCR_FIRE)
         return (haseyes(mon->data) && mon->mcansee);
     /* hero doesn't need hands or even limbs to zap, so mon doesn't either */
-    return ((obj->otyp == WAN_FIRE || obj->otyp == FIRE_HORN)
+    return ((obj->otyp == WAN_FIRE
+             || (obj->otyp == FIRE_HORN && can_blow(mon)))
             && obj->spe > 0);
 }