From: PatR Date: Thu, 26 Mar 2020 08:31:46 +0000 (-0700) Subject: teleds() vs ball&chain X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dbb133ece94ab3c585339072a04aeeab7dd13ce0;p=nethack teleds() vs ball&chain I think this should fix #K672 but without a test case I can't be sure. The ball and chain handling in teleds() was a bit convoluted and this streamlines it a bit. There is still the situation that one place uses 'can't drag ball if dist > 1' and another uses 'no need to move ball if dist <= 2'. That seems contradictory but I want to prevent my head from spinning so haven't tried to puzzle it out. Instead of relying on multiple flag variables to decide whether to call placebc(), the ball and chain (or just chain when ball is carried) will be replaced if they were on the map before moving the hero and aren't there after assigning hero's new location --- diff --git a/src/teleport.c b/src/teleport.c index ba931b51e..84a9706dd 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 teleport.c $NHDT-Date: 1583881126 2020/03/10 22:58:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.116 $ */ +/* NetHack 3.6 teleport.c $NHDT-Date: 1585211492 2020/03/26 08:31:32 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.118 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -301,10 +301,9 @@ teleds(nux, nuy, teleds_flags) int nux, nuy; int teleds_flags; { - boolean ball_active, ball_still_in_range; - boolean allow_drag = ((teleds_flags & TELEDS_ALLOW_DRAG) != 0 - && near_capacity() <= SLT_ENCUMBER); - boolean is_teleport = (teleds_flags & TELEDS_TELEPORT) != 0; + boolean ball_active, ball_still_in_range = FALSE, + allow_drag = (teleds_flags & TELEDS_ALLOW_DRAG) != 0, + is_teleport = (teleds_flags & TELEDS_TELEPORT) != 0; struct monst *vault_guard = vault_occupied(u.urooms) ? findgd() : 0; if (u.utraptype == TT_BURIEDBALL) { @@ -312,7 +311,10 @@ int teleds_flags; buried_ball_to_punishment(); } ball_active = (Punished && uball->where != OBJ_FREE); - ball_still_in_range = FALSE; + if (!ball_active + || near_capacity() > SLT_ENCUMBER + || distmin(u.ux, u.uy, nux, nuy) > 1) + allow_drag = FALSE; /* If they have to move the ball, then drag if allow_drag is true; * otherwise they are teleporting, so unplacebc(). @@ -330,18 +332,10 @@ int teleds_flags; * rock in the way), in which case it teleports the ball on its own. */ if (ball_active) { - if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2) { + if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2) ball_still_in_range = TRUE; /* don't have to move the ball */ - } else { - /* have to move the ball */ - if (!allow_drag || distmin(u.ux, u.uy, nux, nuy) > 1) { - /* we should not have dist > 1 and allow_drag at the same - * time, but just in case, we must then revert to teleport. - */ - allow_drag = FALSE; - unplacebc(); - } - } + else if (!allow_drag) + unplacebc(); /* have to move the ball */ } reset_utrap(FALSE); set_ustuck((struct monst *) 0); @@ -354,29 +348,24 @@ int teleds_flags; } if (u.uswallow) { + /* subset of unstuck() */ u.uswldtim = u.uswallow = 0; - if (Punished && !ball_active) { - /* ensure ball placement, like unstuck */ - ball_active = TRUE; - allow_drag = FALSE; + if (Punished) { /* ball&chain are off map while swallowed */ + ball_active = TRUE; /* to put chain and non-carried ball on map */ + ball_still_in_range = allow_drag = FALSE; /* (redundant) */ } docrt(); } - if (ball_active) { - if (ball_still_in_range || allow_drag) { - int bc_control; - xchar ballx, bally, chainx, chainy; - boolean cause_delay; - - if (drag_ball(nux, nuy, &bc_control, &ballx, &bally, &chainx, - &chainy, &cause_delay, allow_drag)) { - move_bc(0, bc_control, ballx, bally, chainx, chainy); - } else { - /* dragging fails if hero is encumbered beyond 'burdened' */ - allow_drag = FALSE; /* teleport b&c to hero's new spot */ - unplacebc(); /* to match placebc() below */ - } - } + if (ball_active && (ball_still_in_range || allow_drag)) { + int bc_control; + xchar ballx, bally, chainx, chainy; + boolean cause_delay; + + if (drag_ball(nux, nuy, &bc_control, &ballx, &bally, &chainx, + &chainy, &cause_delay, allow_drag)) + move_bc(0, bc_control, ballx, bally, chainx, chainy); + else /* dragging fails if hero is encumbered beyond 'burdened' */ + unplacebc(); /* to match placebc() below */ } if (is_teleport && flags.verbose) @@ -387,10 +376,8 @@ int teleds_flags; the old position if allow_drag is true... */ u_on_newpos(nux, nuy); /* set u., usteed->; cliparound() */ fill_pit(u.ux0, u.uy0); - if (ball_active) { - if (!ball_still_in_range && !allow_drag) - placebc(); - } + if (ball_active && uchain->where == OBJ_FREE) + placebc(); /* put back the ball&chain if they were taken off map */ initrack(); /* teleports mess up tracking monsters without this */ update_player_regions(); /*