From 2111abdc2993f813b4b67f269fbd5baa6d9c1400 Mon Sep 17 00:00:00 2001 From: PatR Date: Sat, 3 Mar 2018 15:26:49 -0800 Subject: [PATCH] buried_ball() Noticed when I was looking at float_up()/float_down() vs being trapped. (I have a substantial patch for that but it involves infrastructure changes so will have to go into master instead of the 3.6.0 branch.) buried_ball() was using nested loops as a very convoluted way to test if (otmp->ox >= cc->x - 2 && otmp->ox <= cc->x + 2 && otmp->oy >= cc->y - 2 && otmp->oy <= cc->y + 2) I think this revised version is closer to what was intended. There are issues. buried_ball() finds the buried iron ball nearest to the specified location--which is always the hero's current location-- rather than the one which was 'uball' before being buried. A player can spot that since iron balls aren't necessarily identical. Also, it searches within a radius of two steps but a tethered hero is only allowed to move one step away from buried ball, so something is off. --- src/dig.c | 62 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/src/dig.c b/src/dig.c index 0886ed477..d1a557648 100644 --- a/src/dig.c +++ b/src/dig.c @@ -1714,36 +1714,47 @@ struct obj * buried_ball(cc) coord *cc; { - xchar check_x, check_y; - struct obj *otmp, *otmp2; + int odist, bdist = COLNO; + struct obj *otmp, *ball = 0; - if (u.utraptype == TT_BURIEDBALL) - for (otmp = level.buriedobjlist; otmp; otmp = otmp2) { - otmp2 = otmp->nobj; + /* FIXME: + * This is just approximate; if multiple buried balls meet the + * criterium (within 2 steps of tethered hero's present location) + * it will find an arbitrary one rather than the one which used + * to be uball. Once 3.6.{0,1} save file compatibility is broken, + * we should add context.buriedball_oid and then we can find the + * actual former uball, which might be extra heavy or christened + * or not the one buried directly underneath the target spot. + * + * [Why does this search within a radius of two when trapmove() + * only lets hero get one step away from the buried ball?] + */ + + if (u.utrap && u.utraptype == TT_BURIEDBALL) + for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) { if (otmp->otyp != HEAVY_IRON_BALL) continue; - /* try the exact location first */ + /* if found at the target spot, we're done */ if (otmp->ox == cc->x && otmp->oy == cc->y) return otmp; - /* Now try the vicinity */ - /* - * (x-2,y-2) (x+2,y-2) - * (x,y) - * (x-2,y+2) (x+2,y+2) + /* find nearest within allowable vicinity: +/-2 + * 4 5 8 + * 1 2 5 + * 0 1 4 */ - for (check_x = cc->x - 2; check_x <= cc->x + 2; ++check_x) - for (check_y = cc->y - 2; check_y <= cc->y + 2; ++check_y) { - if (check_x == cc->x && check_y == cc->y) - continue; - if (isok(check_x, check_y) - && (otmp->ox == check_x && otmp->oy == check_y)) { - cc->x = check_x; - cc->y = check_y; - return otmp; - } - } + odist = dist2(otmp->ox, otmp->oy, cc->x, cc->y); + if (odist <= 8 && (!ball || odist < bdist)) { + /* remember nearest buried ball but keep checking others */ + ball = otmp; + bdist = odist; + } } - return (struct obj *) 0; + if (ball) { + /* found, but not at < cc->x, cc->y > */ + cc->x = ball->ox; + cc->y = ball->oy; + } + return ball; } void @@ -1751,6 +1762,7 @@ buried_ball_to_punishment() { coord cc; struct obj *ball; + cc.x = u.ux; cc.y = u.uy; ball = buried_ball(&cc); @@ -1774,6 +1786,7 @@ buried_ball_to_freedom() { coord cc; struct obj *ball; + cc.x = u.ux; cc.y = u.uy; ball = buried_ball(&cc); @@ -1913,7 +1926,8 @@ int x, y; for (otmp = level.buriedobjlist; otmp; otmp = otmp2) { otmp2 = otmp->nobj; if (otmp->ox == x && otmp->oy == y) { - if (bball && otmp == bball && u.utraptype == TT_BURIEDBALL) { + if (bball && otmp == bball + && u.utrap && u.utraptype == TT_BURIEDBALL) { buried_ball_to_punishment(); } else { obj_extract_self(otmp);