]> granicus.if.org Git - nethack/commitdiff
revisit the forcefight crash fix
authorPatR <rankin@nethack.org>
Sun, 19 Apr 2015 03:02:40 +0000 (20:02 -0700)
committerPatR <rankin@nethack.org>
Sun, 19 Apr 2015 03:02:40 +0000 (20:02 -0700)
The previous fix prevents the crash from 'the()' when NO_GLYPH was
used as an index into the defsyms array, but it resulted in giving
feedback of "you attack thin air" regardless of what was at the
target location, reverting to the situation that the buggy code was
attempting to address in the first place.  Handle that differently
by removing the unseen monster glyph sooner.  Also, the underwater
handling wasn't working as intended.

I blamed Derek's pudding farming patch for introducing the problem,
but all that did was replace the offending line(s) with different
indentation.  The older post-3.4.3 patch which produced the problem
was mine.  Sorry, Derek.

src/hack.c

index c94363d913106c70aa1a552f7c282822eb0052cb..cde81937f32d3ca6714e9f94bc4a3a4ba026d917 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.5 hack.c  $NHDT-Date$  $NHDT-Branch$:$NHDT-Revision$ */
+/* NetHack 3.5 hack.c  $NHDT-Date: 1429412557 2015/04/19 03:02:37 $  $NHDT-Branch: master $:$NHDT-Revision: 1.143 $ */
 /* NetHack 3.5 hack.c  $Date: 2013/10/26 21:33:47 $  $Revision: 1.120 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
@@ -1336,49 +1336,67 @@ domove()
     if (context.forcefight ||
         /* remembered an 'I' && didn't use a move command */
         (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
-        struct obj *boulder = sobj_at(BOULDER, x, y);
+        struct obj *boulder = 0;
         boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
             solid = !accessible(x, y);
         int glyph = glyph_at(x, y);    /* might be monster */
         char buf[BUFSZ];
 
-        /* if a statue is displayed at the target location,
-           player is attempting to attack it [and boulder
-           handlng below is suitable for handling that] */
-        if (glyph_is_statue(glyph) ||
-            (Hallucination && glyph_is_monster(glyph)))
-            boulder = sobj_at(STATUE, x, y);
-
-        /* force fight at boulder/statue or wall/door while wielding
-           pick:  start digging to break the boulder or wall */
-        if (context.forcefight &&
-            /* can we dig? */
-            uwep && dig_typ(uwep, x, y) &&
-            /* should we dig? */
-            !glyph_is_invisible(glyph) &&
-            !glyph_is_monster(glyph)) {
-            (void)use_pick_axe2(uwep);
-            return;
-        }
+       if (!Underwater) {
+           boulder = sobj_at(BOULDER, x, y);
+           /* if a statue is displayed at the target location,
+              player is attempting to attack it [and boulder
+              handlng below is suitable for handling that] */
+           if (glyph_is_statue(glyph) ||
+               (Hallucination && glyph_is_monster(glyph)))
+               boulder = sobj_at(STATUE, x, y);
+
+           /* force fight at boulder/statue or wall/door while wielding
+              pick:  start digging to break the boulder or wall */
+           if (context.forcefight &&
+               /* can we dig? */
+               uwep && dig_typ(uwep, x, y) &&
+               /* should we dig? */
+               !glyph_is_invisible(glyph) &&
+               !glyph_is_monster(glyph)) {
+               (void)use_pick_axe2(uwep);
+               return;
+           }
+       }
+
+       /* about to become known empty -- remove 'I' if present */
+        unmap_object(x, y);
+        if (boulder) map_object(boulder, TRUE);
+        newsym(x, y);
+        glyph = glyph_at(x, y);                /* might have just changed */
 
         if (boulder)
             Strcpy(buf, ansimpleoname(boulder));
-        else if (solid && glyph_is_cmap(glyph))
-            Strcpy(buf, the(defsyms[glyph_to_cmap(glyph)].explanation));
-        else if (!Underwater)
-            Strcpy(buf, "thin air");
-        else if (is_pool(x, y))
-            Strcpy(buf, "empty water");
-        else   /* Underwater, targetting non-water */
-            Sprintf(buf, "a vacant spot on the %s", surface(x,y));
+        else if (Underwater && !is_pool(x, y))
+            /* Underwater, targetting non-water; the map just shows blank
+              because you don't see remembered terrain while underwater;
+              although the hero can attack an adjacent monster this way,
+              assume he can't reach out far enough to distinguish terrain */
+           Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR) ?
+                          "an air bubble" : "nothing");
+        else if (solid)
+           /* glyph might indicate unseen terrain if hero is blind;
+              unlike searching, this won't reveal what that terrain is
+              (except for solid rock, where the glyph would otherwise
+              yield ludicrous "dark part of a room") */
+            Strcpy(buf, (levl[x][y].typ == STONE) ? "solid rock" :
+                         glyph_is_cmap(glyph) ?
+                           the(defsyms[glyph_to_cmap(glyph)].explanation) :
+                             (const char *)"an unknown obstacle");
+           /* note: 'solid' is misleadingly named and catches pools
+              of water and lava as well as rock and walls */
+        else
+           Strcpy(buf, "thin air");
         You("%s%s %s.",
-            !(boulder || solid) ? "" :
-            !explo ? "harmlessly " : "futilely ",
+            !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
             explo ? "explode at" : "attack",
             buf);
-        unmap_object(x, y); /* known empty -- remove 'I' if present */
-        if (boulder) map_object(boulder, TRUE);
-        newsym(x, y);
+
         nomul(0);
         if (explo) {
             wake_nearby();