From e8723df7788f382a1f2a81f652f0244a11cac01b Mon Sep 17 00:00:00 2001 From: PatR Date: Tue, 8 Aug 2017 18:58:25 -0700 Subject: [PATCH] grappling with water Reported directly to devteam: if applying a grappling hook towards a target past some water ended up pulling the hero toward the target, hero would drown without any chance of crawling out of the water. It used hurtle() to move, and hurtle assumed levitation so didn't check for entering pools of water except on the Plane of Water. --- doc/fixes36.1 | 2 ++ src/dothrow.c | 30 +++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/doc/fixes36.1 b/doc/fixes36.1 index d2fb9b2ca..72b2d2d81 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -407,6 +407,8 @@ fix the 'A' command to have the 'D' command's fix for C331-1 (quirk for eating 1 tin from stack of N (for N >= 2) on shop's floor forced hero to buy 2 using a cursed whistle in a vault will summon the guard immediately throne room's throne is occupied by a king +using a grappling hook and getting pulled toward the target into water would + drown hero without any chance to crawl out Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository diff --git a/src/dothrow.c b/src/dothrow.c index 769be9370..a6825fcc9 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dothrow.c $NHDT-Date: 1455140444 2016/02/10 21:40:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.118 $ */ +/* NetHack 3.6 dothrow.c $NHDT-Date: 1502243899 2017/08/09 01:58:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.125 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -448,7 +448,22 @@ genericptr_t arg; int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y; boolean keep_going = TRUE; - /* Use Bresenham's Line Algorithm to walk from src to dest */ + /* Use Bresenham's Line Algorithm to walk from src to dest. + * + * This should be replaced with a more versatile algorithm + * since it handles slanted moves in a suboptimal way. + * Going from 'x' to 'y' needs to pass through 'z', and will + * fail if there's an obstable there, but it could choose to + * pass through 'Z' instead if that way imposes no obstacle. + * ..y .Zy + * xz. vs x.. + * Perhaps we should check both paths and accept whichever + * one isn't blocked. But then multiple zigs and zags could + * potentially produce a meandering path rather than the best + * attempt at a straight line. And (*check_proc)() would + * need to work more like 'travel', distinguishing between + * testing a possible move and actually attempting that move. + */ dx = dest_cc->x - src_cc->x; dy = dest_cc->y - src_cc->y; prev_x = x = src_cc->x; @@ -640,9 +655,11 @@ int x, y; vision_recalc(1); /* update for new position */ flush_screen(1); - if (levl[x][y].typ == WATER && Is_waterlevel(&u.uz)) { - multi = 0; - drown(); + if (is_pool(x, y) && !u.uinwater + && ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER) + || !(Levitation || Flying || Wwalking))) { + multi = 0; /* can move, so drown() allows crawling out of water */ + (void) drown(); return FALSE; } @@ -768,8 +785,7 @@ boolean verbose; (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range); } -/* Move a monster through the air for a few squares. - */ +/* Move a monster through the air for a few squares. */ void mhurtle(mon, dx, dy, range) struct monst *mon; -- 2.40.0