]> granicus.if.org Git - nethack/commitdiff
H216 - ball and chain movement
authorcohrs <cohrs>
Sun, 24 Sep 2006 22:31:22 +0000 (22:31 +0000)
committercohrs <cohrs>
Sun, 24 Sep 2006 22:31:22 +0000 (22:31 +0000)
<Someone> reported the longstanding behavior that when dragging, the chain
does not always remain directly between the player and the ball.  This occurs
when the player zigzags.  Added a check to the simple drag code to try to
keep the chain directly between the player and the ball.  But, don't do this
if the player is walking thru rock or if it would move the chain into rock.

doc/fixes34.4
src/ball.c

index 5a33792b9c8ef5b58d2eb73f8a7941cb734206e3..58335f4fc1f0f02e18c8b1e5ba7d5f756e15c36e 100644 (file)
@@ -259,6 +259,7 @@ fix region timeout detection, caused strange display of stinking cloud
        while wearing the Eyes of the Overworld
 try to keep migrating monsters from escaping the wizard tower
 affected monsters should always respect "Elbereth"
+try harder to keep dragged chain between ball and hero
 
 
 Platform- and/or Interface-Specific Fixes
index c1b5dec2a4523f3fe7a3bb279e944795dbb5c032..7bc7b743b4e99ebb64fa7adb12a74b35b698b7f2 100644 (file)
@@ -395,9 +395,9 @@ boolean allow_drag;
                return TRUE;
            }
 #define CHAIN_IN_MIDDLE(chx, chy) \
-(distmin(x, y, chx, chy) <= 1 && distmin(chx, chy, uball->ox, uball->oy) <= 1)
+ (distmin(x, y, chx, chy) <= 1 && distmin(chx, chy, uball->ox, uball->oy) <= 1)
 #define IS_CHAIN_ROCK(x,y) \
-(IS_ROCK(levl[x][y].typ) || (IS_DOOR(levl[x][y].typ) && \
+ (IS_ROCK(levl[x][y].typ) || (IS_DOOR(levl[x][y].typ) && \
       (levl[x][y].doormask & (D_CLOSED|D_LOCKED))))
 /* Don't ever move the chain into solid rock.  If we have to, then instead
  * undo the move_bc() and jump to the drag ball code.  Note that this also
@@ -548,7 +548,6 @@ boolean allow_drag;
                    break;
            }
 #undef SKIP_TO_DRAG
-#undef IS_CHAIN_ROCK
 #undef CHAIN_IN_MIDDLE
            return TRUE;
        }
@@ -622,11 +621,32 @@ drag:
            *ballx = *chainx = x;
            *bally = *chainy = y;
        } else {
+           xchar newchainx = u.ux, newchainy = u.uy;
+
+           /*
+            * Generally, chain moves to hero's previous location and ball
+            * moves to chain's previous location, except that we try to
+            * keep the chain directly between the hero and the ball.  But,
+            * take the simple approach if the hero's previous location or
+            * the potential between location is inaccessible.
+            */
+           if (dist2(x, y, uchain->ox, uchain->oy) == 4 &&
+               !IS_CHAIN_ROCK(newchainx, newchainy)) {
+               newchainx = (x + uchain->ox)/2;
+               newchainy = (y + uchain->oy)/2;
+               if (IS_CHAIN_ROCK(newchainx, newchainy)) {
+                   /* don't let chain move to inaccessible location */
+                   newchainx = u.ux;
+                   newchainy = u.uy;
+               }
+           }
+
            *ballx  = uchain->ox;
            *bally  = uchain->oy;
-           *chainx = u.ux;
-           *chainy = u.uy;
+           *chainx = newchainx;
+           *chainy = newchainy;
        }
+#undef IS_CHAIN_ROCK
        *cause_delay = TRUE;
        return TRUE;
 }