]> granicus.if.org Git - nethack/commitdiff
fix #K376 - tipping cap
authorPatR <rankin@nethack.org>
Tue, 18 Feb 2020 11:14:22 +0000 (03:14 -0800)
committerPatR <rankin@nethack.org>
Tue, 18 Feb 2020 11:14:22 +0000 (03:14 -0800)
Allow #tip to do something if you pick your worn helmet instead of
a container.  It's mostly just a variation of #chat but probably adds
several new bugs....

doc/fixes37.0
include/extern.h
src/pickup.c
src/sounds.c

index 95f64cd4452d517ac3f2ec84d55568b0254baa84..ad4974740b2b8d1d8c0296495999e8a0cd9694fb 100644 (file)
@@ -1,4 +1,4 @@
-$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.102 $ $NHDT-Date: 1581810078 2020/02/15 23:41:18 $
+$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.103 $ $NHDT-Date: 1582020640 2020/02/18 10:10:40 $
 
 General Fixes and Modified Features
 -----------------------------------
@@ -160,6 +160,7 @@ new glyph GLYPH_NOTHING was added so !dark_room has something to be set to
        now that stone could be mapped to an entirely different symbol
 added several new status conditions all of which are opt-in except
        the new cond_grab and cond_lava which are opt-out
+tipping your cap might get a response
 
 
 Platform- and/or Interface-Specific New Features
index 6a344c9fd836d0b9489076ba90abce0fff5ab4bf..7fdfeb039c14e06336c1611f5b107f72bcb006bb 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1581886855 2020/02/16 21:00:55 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.797 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1581985538 2020/02/18 00:25:38 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.798 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -2449,6 +2449,7 @@ E void FDECL(yelp, (struct monst *));
 E void FDECL(whimper, (struct monst *));
 E void FDECL(beg, (struct monst *));
 E int NDECL(dotalk);
+E int NDECL(tiphat);
 #ifdef USER_SOUNDS
 E int FDECL(add_sound_mapping, (const char *));
 E void FDECL(play_sound_for_message, (const char *));
index 8cb4f68dec4d53ccc415ba3a0f82cd19e34948c4..e86ec2d77b4652ed1b3661525e1291c1fa9c0f7b 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 pickup.c        $NHDT-Date: 1578297247 2020/01/06 07:54:07 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.258 $ */
+/* NetHack 3.6 pickup.c        $NHDT-Date: 1581985559 2020/02/18 00:25:59 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.261 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /*-Copyright (c) Robert Patrick Rankin, 2012. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -3171,6 +3171,8 @@ dotip()
     /* anything not covered yet */
     if (cobj->oclass == POTION_CLASS) /* can't pour potions... */
         pline_The("%s %s securely sealed.", xname(cobj), otense(cobj, "are"));
+    else if (uarmh && cobj == uarmh)
+        return tiphat();
     else if (cobj->otyp == STATUE)
         pline("Nothing interesting happens.");
     else
index b72003440d58d8831c88478060a1f324ca3cee55..0e3b7df89d7fbd65c5fa4abff02cdf41f1ee932f 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 sounds.c        $NHDT-Date: 1570844005 2019/10/12 01:33:25 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.83 $ */
+/* NetHack 3.6 sounds.c        $NHDT-Date: 1582024315 2020/02/18 11:11:55 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.95 $ */
 /*      Copyright (c) 1989 Janet Walz, Mike Threepoint */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -7,6 +7,7 @@
 static boolean FDECL(mon_is_gecko, (struct monst *));
 static int FDECL(domonnoise, (struct monst *));
 static int NDECL(dochat);
+static struct monst *FDECL(responsive_mon_at, (int, int));
 static int FDECL(mon_in_room, (struct monst *, int));
 
 /* this easily could be a macro, but it might overtax dumb compilers */
@@ -926,15 +927,14 @@ register struct monst *mtmp;
         break;
     case MS_SOLDIER: {
         static const char
-            *const soldier_foe_msg[3] =
-                {
-                  "Resistance is useless!", "You're dog meat!", "Surrender!",
-                },
-                   *const soldier_pax_msg[3] = {
-                       "What lousy pay we're getting here!",
-                       "The food's not fit for Orcs!",
-                       "My feet hurt, I've been on them all day!",
-                   };
+            *const soldier_foe_msg[3] = {
+                "Resistance is useless!", "You're dog meat!", "Surrender!",
+            },
+            *const soldier_pax_msg[3] = {
+                "What lousy pay we're getting here!",
+                "The food's not fit for Orcs!",
+                "My feet hurt, I've been on them all day!",
+            };
         verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
                                     : soldier_foe_msg[rn2(3)];
         break;
@@ -1115,6 +1115,135 @@ dochat()
     return domonnoise(mtmp);
 }
 
+/* is there a monster at <x,y> that can see the hero and react? */
+static struct monst *
+responsive_mon_at(x, y)
+int x, y;
+{
+    struct monst *mtmp = isok(x, y) ? m_at(x, y) : 0;
+
+    if (mtmp && (!mtmp->mcanmove || mtmp->msleeping /* immobilized monst */
+                 || !mtmp->mcansee || !haseyes(mtmp->data) /* blind monst */
+                 || (Invis && !perceives(mtmp->data)) /* unseen hero */
+                 || (x != mtmp->mx || y != mtmp->my))) /* worm tail */
+        mtmp = (struct monst *) 0;
+    return mtmp;
+}
+
+/* player chose 'uarmh' for #tip (pickup.c); visual #chat, sort of... */
+int
+tiphat()
+{
+    struct monst *mtmp;
+    struct obj *otmp;
+    int x, y, range, glyph, vismon, unseen, statue, res;
+
+    if (!uarmh) /* can't get here from there */
+        return 0;
+
+    res = uarmh->bknown ? 0 : 1;
+    if (cursed(uarmh)) /* "You can't.  It is cursed." */
+        return res; /* if learned of curse, use a move */
+
+    /* might choose a position, but dealing with direct lines is simpler */
+    if (!getdir("At whom? (in what direction)")) /* bail on ESC */
+        return res; /* iffy; now know it's not cursed for sure (since we got
+                     * past prior test) but might have already known that */
+    res = 1; /* physical action is going to take place */
+
+    /* most helmets have a short wear/take-off delay and we could set
+       'multi' to account for that, but we'll pretend that no extra time
+       beyond the current move is necessary */
+    You("briefly doff your %s.", helm_simple_name(uarmh));
+
+    if (!u.dx && !u.dy) {
+        if (u.usteed && u.dz > 0) {
+            if (!u.usteed->mcanmove || u.usteed->msleeping)
+                pline("%s doesn't notice.", Monnam(u.usteed));
+            else
+                (void) domonnoise(u.usteed);
+        } else if (u.dz) {
+            pline("There's no one %s there.", (u.dz < 0) ? "up" : "down");
+        } else {
+            pline_The("lout here doesn't acknowledge you...");
+        }
+        return res;
+    }
+
+    mtmp = (struct monst *) 0;
+    vismon = unseen = statue = 0, glyph = GLYPH_MON_OFF;
+    x = u.ux, y = u.uy;
+    for (range = 1; range <= BOLT_LIM + 1; ++range) {
+        x += u.dx, y += u.dy;
+        if (!isok(x, y) || (range > 1 && !couldsee(x, y))) {
+            /* switch back to coordinates for previous interation's 'mtmp' */
+            x -= u.dx, y -= u.dy;
+            break;
+        }
+        mtmp = m_at(x, y);
+        vismon = (mtmp && canseemon(mtmp));
+        glyph = glyph_at(x, y);
+        unseen = glyph_is_invisible(glyph);
+        statue = (glyph_is_statue(glyph) /* mimic or hallucinatory statue */
+                  || (!vismon && !unseen && (otmp = vobj_at(x, y)) != 0
+                      && otmp->otyp == STATUE)); /* or actual statue */
+        if (vismon && (M_AP_TYPE(mtmp) == M_AP_FURNITURE
+                       || M_AP_TYPE(mtmp) == M_AP_OBJECT))
+            vismon = 0, mtmp = (struct monst *) 0;
+        if (vismon || unseen || (statue && Hallucination)
+            /* unseen adjacent monster will respond if able */
+            || (range == 1 && mtmp && responsive_mon_at(x, y)
+                && mtmp->data->msound != MS_SILENT)
+            /* we check accessible() after m_at() in case there's a
+               visible monster phazing through a wall here */
+            || !(accessible(x, y) || levl[x][y].typ == IRONBARS))
+            break;
+    }
+
+    if (unseen || (statue && Hallucination)) {
+        pline("That %screature is ignoring you!", unseen ? "unseen " : "");
+    } else if (!mtmp || !responsive_mon_at(x, y)) {
+        if (vismon) /* 'vismon' is only True when 'mtmp' is non-Null */
+            pline("%s seems not to notice you.", Monnam(mtmp));
+        else
+            goto nada;
+    } else { /* 'mtmp' is guaranteed to be non-Null if we get here */
+        /* if this monster is waiting for something, prod it into action */
+        mtmp->mstrategy &= ~STRAT_WAITMASK;
+
+        if (vismon && mtmp->mpeaceful && humanoid(mtmp->data)) {
+            if ((otmp = which_armor(mtmp, W_ARMH)) == 0) {
+                pline("%s waves.", Monnam(mtmp));
+            } else if (otmp->cursed) {
+                pline("%s grasps %s %s but can't remove it.", Monnam(mtmp),
+                      mhis(mtmp), helm_simple_name(otmp));
+                otmp->bknown = 1;
+            } else {
+                pline("%s tips %s %s in response.", Monnam(mtmp),
+                      mhis(mtmp), helm_simple_name(otmp));
+            }
+        } else if (vismon && humanoid(mtmp->data)) {
+            static const char *const reaction[3] = {
+                "curses", "gestures rudely", "gestures offensively",
+            };
+            int which = !Deaf ? rn2(3) : rn1(2, 1),
+                twice = (Deaf || which > 0 || rn2(3)) ? 0 : rn1(2, 1);
+
+            pline("%s %s%s%s at you...", Monnam(mtmp), reaction[which],
+                  twice ? " and " : "", twice ? reaction[twice] : "");
+        } else if (distu(x, y) <= 2 && !Deaf && domonnoise(mtmp)) {
+            if (!vismon)
+                map_invisible(x, y);
+        } else if (vismon) {
+            pline("%s doesn't respond.", Monnam(mtmp));
+        } else {
+ nada:
+            pline("%s", nothing_happens);
+        }
+    }
+    return res;
+}
+
 #ifdef USER_SOUNDS
 
 extern void FDECL(play_usersound, (const char *, int));