]> granicus.if.org Git - nethack/commitdiff
forcefight against edge of map
authorPatR <rankin@nethack.org>
Thu, 28 Apr 2022 09:21:46 +0000 (02:21 -0700)
committerPatR <rankin@nethack.org>
Thu, 28 Apr 2022 09:21:46 +0000 (02:21 -0700)
Noticed when testing the forcefight against obscured furniture fix:
if you attempted forcefight against the edge of the map, you got
feedback about having already moved as far in <direction> as possible
rather than about forcefight failing to attack anything.  Have the
can't move out bounds test check for forcefight before deciding to
give to its normal feedback.

doc/fixes3-7-0.txt
src/hack.c

index 9969714246408775e6c0091d91b24ead3bf674aa..64e9bbcb9464e0c50041b53fe0404c77dbd76572 100644 (file)
@@ -896,6 +896,8 @@ with two-weapon combat or Cleaver attacking multiple targets, hero kept going
        with next attack after being paralyzed by passive counter-attack
 trap detection could falsely find trapped secret doors; those can't be trapped
        due to details of how they use overlaid fields in the rm structure
+for force-fight against edge of level, report "you harmlessly attack unknown
+       obstacle" rather than "you have moved as far <direction> as possible"
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 04a2b7f2cf4fba17704cb319414dc0b7def638a7..5ec41191e5eb7115890b35d7745f4355ea296071 100644 (file)
@@ -1839,7 +1839,14 @@ domove_swap_with_pet(struct monst *mtmp, xchar x, xchar y)
 static boolean
 domove_fight_empty(xchar x, xchar y)
 {
-    int glyph = glyph_at(x, y);
+    static const char unknown_obstacle[] = "an unknown obstacle";
+    boolean off_edge = !isok(x, y);
+    int glyph = !off_edge ? glyph_at(x, y) : GLYPH_UNEXPLORED;
+
+    if (off_edge)
+        x = y = 0; /* for forcefight against the edge of the map; make
+                    * sure 'bad' coordinates are within array bounds in
+                    * case a bounds check gets overlooked */
 
     /* specifying 'F' with no monster wastes a turn */
     if (g.context.forcefight
@@ -1847,9 +1854,16 @@ domove_fight_empty(xchar x, xchar y)
         || (glyph_is_invisible(glyph) && !g.context.nopick)) {
         struct obj *boulder = 0;
         boolean explo = (Upolyd && attacktype(g.youmonst.data, AT_EXPL)),
-                solid = (!accessible(x, y) || IS_FURNITURE(levl[x][y].typ));
+                solid = (off_edge || (!accessible(x, y)
+                                      || IS_FURNITURE(levl[x][y].typ)));
         char buf[BUFSZ];
 
+        if (off_edge) {
+            /* treat as if solid rock, even on planes' levels */
+            Strcpy(buf, unknown_obstacle);
+            goto futile;
+        }
+
         if (!Underwater) {
             boulder = sobj_at(BOULDER, x, y);
             /* if a statue is displayed at the target location,
@@ -1900,7 +1914,7 @@ domove_fight_empty(xchar x, xchar y)
                 glyph = back_to_glyph(x, y);
                 Strcpy(buf, the(defsyms[glyph_to_cmap(glyph)].explanation));
             } else {
-                Strcpy(buf, "an unknown obstacle");
+                Strcpy(buf, unknown_obstacle);
             }
             /* note: 'solid' is misleadingly named and catches pools
                of water and lava as well as rock and walls;
@@ -1908,16 +1922,20 @@ domove_fight_empty(xchar x, xchar y)
         } else {
             Strcpy(buf, "thin air");
         }
+
+ futile:
         You("%s%s %s.",
             !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
             explo ? "explode at" : "attack", buf);
 
         nomul(0);
         if (explo) {
-            struct attack *attk;
+            struct attack *attk
+                        = attacktype_fordmg(g.youmonst.data, AT_EXPL, AD_ANY);
+
             /* no monster has been attacked so we have bypassed explum() */
             wake_nearto(u.ux, u.uy, 7 * 7); /* same radius as explum() */
-            if ((attk = attacktype_fordmg(g.youmonst.data, AT_EXPL, AD_ANY)))
+            if (attk)
                 explum((struct monst *) 0, attk);
             u.mh = -1; /* dead in the current form */
             rehumanize();
@@ -2079,6 +2097,9 @@ static boolean
 move_out_of_bounds(xchar x, xchar y)
 {
     if (!isok(x, y)) {
+        if (g.context.forcefight)
+            return domove_fight_empty(x, y);
+
         if (flags.mention_walls) {
             int dx = u.dx, dy = u.dy;
 
@@ -2236,7 +2257,7 @@ domove_core(void)
         if (water_turbulence(&x, &y))
             return;
 
-        if (move_out_of_bounds(x,y))
+        if (move_out_of_bounds(x, y))
             return;
 
         if (avoid_running_into_trap_or_liquid(x, y))