From 8fa38ec8fb2b9c26cc3b95c46ae7748f60f14540 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 4 Oct 2019 15:16:51 -0700 Subject: [PATCH 1/5] fix 'b&c distance' sanity check warning when attempting to crawl out of water fails and hero is life-saved or wizard-/explore-mode player declines to die. If the hero is saved by positioning him/her one step further away from ball and chain, teleds() tries to drag them, but if 'emergency disrobe' left the hero stressed or worse, dragging fails. Ball and chain were being left where they were, with chain no longer being adjacent to hero. If drag_ball() fails, have teleds() teleport ball and chain to hero's new spot, same as when that isn't within range of a one step drag. --- doc/fixes36.3 | 9 +++++++-- src/teleport.c | 13 +++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index 4c3bd945e..ea0ebba13 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.121 $ $NHDT-Date: 1570142734 2019/10/03 22:45:34 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.122 $ $NHDT-Date: 1570227405 2019/10/04 22:16:45 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -163,6 +163,11 @@ query_category() and whatdoes_help() had early returns which could each leave the query one couldn't happen unless there is a coding error for object classes somewhere and the help one couldn't happen unless the installed data files left 'keyhelp' missing] +ball and chain could end up too far from punished hero (triggering b&c warning + for wizard mode with sanity checking active) when crawling out of + water failed because dropping stuff left hero overly encumbered and + hero was life saved--or player declined to die--if the hero got + teleported one step further from ball and chain's current location Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository @@ -170,7 +175,7 @@ Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository elemental_clog() loop needed to guard against obliteration of the monster that was trying to be placed using ^G to create "hidden mimic" shouldn't have marked it as undetected since - mimics 'hide' be appearing to be something else; honor "hidden" for + mimics 'hide' by appearing to be something else; honor "hidden" for 'hides_under' creatures if/when created at location with object(s), also for eels and other fish if/when created at water location for wizard mode 'wizweight' option, glob weight wasn't shown unless glob had diff --git a/src/teleport.c b/src/teleport.c index 9c2bd66f5..1e51ab1be 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 teleport.c $NHDT-Date: 1564771880 2019/08/02 18:51:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.92 $ */ +/* NetHack 3.6 teleport.c $NHDT-Date: 1570227405 2019/10/04 22:16:45 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.93 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -305,9 +305,9 @@ boolean allow_drag; * 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 { + } 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 @@ -344,8 +344,13 @@ boolean allow_drag; boolean cause_delay; if (drag_ball(nux, nuy, &bc_control, &ballx, &bally, &chainx, - &chainy, &cause_delay, allow_drag)) + &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 */ + } } } /* must set u.ux, u.uy after drag_ball(), which may need to know From f3bc5e5c78b67064551137091f5c41703aa4fb03 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 4 Oct 2019 16:12:08 -0700 Subject: [PATCH 2/5] fix #H9272 - "object lost" panic when polymorph causes loss of levitation boots or water walking boots while over water. If discarding stuff while trying to crawl out got rid of the taken-off boots, they wouldn't be in inventory any more when break_armor() tried to drop them after taking them off. --- doc/fixes36.3 | 5 ++++- src/polyself.c | 52 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index ea0ebba13..d39eff5c6 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.122 $ $NHDT-Date: 1570227405 2019/10/04 22:16:45 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.123 $ $NHDT-Date: 1570230710 2019/10/04 23:11:50 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -168,6 +168,9 @@ ball and chain could end up too far from punished hero (triggering b&c warning water failed because dropping stuff left hero overly encumbered and hero was life saved--or player declined to die--if the hero got teleported one step further from ball and chain's current location +avoid 'object lost' panic when polymorph causes loss of levitation boots or + water walking boots which dumps hero into water where emergency + disrobing/dropping in order to crawl out chooses to drop those boots Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/polyself.c b/src/polyself.c index 3f33c8e9b..ab84a7e18 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 polyself.c $NHDT-Date: 1559664952 2019/06/04 16:15:52 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.133 $ */ +/* NetHack 3.6 polyself.c $NHDT-Date: 1570230710 2019/10/04 23:11:50 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.134 $ */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -23,6 +23,7 @@ STATIC_DCL void FDECL(check_strangling, (BOOLEAN_P)); STATIC_DCL void FDECL(polyman, (const char *, const char *)); +STATIC_DCL void FDECL(dropp, (struct obj *)); STATIC_DCL void NDECL(break_armor); STATIC_DCL void FDECL(drop_weapon, (int)); STATIC_DCL int FDECL(armor_to_dragon, (int)); @@ -858,6 +859,33 @@ int mntmp; return 1; } +/* dropx() jacket for break_armor() */ +STATIC_OVL void +dropp(obj) +struct obj *obj; +{ + struct obj *otmp; + + /* + * Dropping worn armor while polymorphing might put hero into water + * (loss of levitation boots or water walking boots that the new + * form can't wear), where emergency_disrobe() could remove it from + * inventory. Without this, dropx() could trigger an 'object lost' + * panic. Right now, boots are the only armor which might encounter + * this situation, but handle it for all armor. + * + * Hypothetically, 'obj' could have merged with something (not + * applicable for armor) and no longer be a valid pointer, so scan + * inventory for it instead of trusting obj->where. + */ + for (otmp = invent; otmp; otmp = otmp->nobj) { + if (otmp == obj) { + dropx(obj); + break; + } + } +} + STATIC_OVL void break_armor() { @@ -876,7 +904,7 @@ break_armor() if (otmp->oartifact) { Your("%s falls off!", cloak_simple_name(otmp)); (void) Cloak_off(); - dropx(otmp); + dropp(otmp); } else { Your("%s tears apart!", cloak_simple_name(otmp)); (void) Cloak_off(); @@ -893,7 +921,7 @@ break_armor() cancel_don(); Your("armor falls around you!"); (void) Armor_gone(); - dropx(otmp); + dropp(otmp); } if ((otmp = uarmc) != 0) { if (is_whirly(youmonst.data)) @@ -901,7 +929,7 @@ break_armor() else You("shrink out of your %s!", cloak_simple_name(otmp)); (void) Cloak_off(); - dropx(otmp); + dropp(otmp); } if ((otmp = uarmu) != 0) { if (is_whirly(youmonst.data)) @@ -909,7 +937,7 @@ break_armor() else You("become much too small for your shirt!"); setworn((struct obj *) 0, otmp->owornmask & W_ARMU); - dropx(otmp); + dropp(otmp); } } if (has_horns(youmonst.data)) { @@ -927,7 +955,7 @@ break_armor() Your("%s falls to the %s!", helm_simple_name(otmp), surface(u.ux, u.uy)); (void) Helmet_off(); - dropx(otmp); + dropp(otmp); } } } @@ -939,12 +967,12 @@ break_armor() You("drop your gloves%s!", uwep ? " and weapon" : ""); drop_weapon(0); (void) Gloves_off(); - dropx(otmp); + dropp(otmp); } if ((otmp = uarms) != 0) { You("can no longer hold your shield!"); (void) Shield_off(); - dropx(otmp); + dropp(otmp); } if ((otmp = uarmh) != 0) { if (donning(otmp)) @@ -952,7 +980,7 @@ break_armor() Your("%s falls to the %s!", helm_simple_name(otmp), surface(u.ux, u.uy)); (void) Helmet_off(); - dropx(otmp); + dropp(otmp); } } if (nohands(youmonst.data) || verysmall(youmonst.data) @@ -966,7 +994,7 @@ break_armor() Your("boots %s off your feet!", verysmall(youmonst.data) ? "slide" : "are pushed"); (void) Boots_off(); - dropx(otmp); + dropp(otmp); } } } @@ -1019,6 +1047,10 @@ int alone; updateinv = FALSE; else if (candropwep) dropx(otmp); + /* [note: dropp vs dropx -- if heart of ahriman is wielded, we + might be losing levitation by dropping it; but that won't + happen until the drop, unlike Boots_off() dumping hero into + water and triggering emergency_disrobe() before dropx()] */ if (updateinv) update_inventory(); From f11f4de057d0aca3c843825e55a1d783c90705c2 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 4 Oct 2019 16:37:14 -0700 Subject: [PATCH 3/5] sortloot of tools Fix the first part of github issue 229. sortloot_classify() tries to group musical instruments separately from other tools, but missing 'break' in a 'switch' prevented that from happening--they were mixed together. Since that grouping isn't documented anywhere, only source divers would ever notice that it wasn't working as intended. --- doc/fixes36.3 | 4 +++- src/invent.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.3 b/doc/fixes36.3 index d39eff5c6..5ea4594cc 100644 --- a/doc/fixes36.3 +++ b/doc/fixes36.3 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.123 $ $NHDT-Date: 1570230710 2019/10/04 23:11:50 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.124 $ $NHDT-Date: 1570232224 2019/10/04 23:37:04 $ This fixes36.3 file is here to capture information about updates in the 3.6.x lineage following the release of 3.6.2 in May 2019. Please note, however, @@ -171,6 +171,8 @@ ball and chain could end up too far from punished hero (triggering b&c warning avoid 'object lost' panic when polymorph causes loss of levitation boots or water walking boots which dumps hero into water where emergency disrobing/dropping in order to crawl out chooses to drop those boots +'sortloot's attempt to group musical instruments separately from other tools + didn't work as intended due to missing 'break' in sortloot_classify() Fixes to Post-3.6.2 Problems that Were Exposed Via git Repository diff --git a/src/invent.c b/src/invent.c index 1f8bae8c4..01c252b89 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 invent.c $NHDT-Date: 1567213892 2019/08/31 01:11:32 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.262 $ */ +/* NetHack 3.6 invent.c $NHDT-Date: 1570232224 2019/10/04 23:37:04 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.263 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -141,8 +141,10 @@ struct obj *obj; case DRUM_OF_EARTHQUAKE: case HORN_OF_PLENTY: /* not a musical instrument */ k = 3; /* instrument or unknown horn of plenty */ + break; default: k = 4; /* 'other' tool */ + break; } break; case FOOD_CLASS: From c6b7540712edfde8495bd3a41b018aa0d8a1eecc Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 4 Oct 2019 17:28:32 -0700 Subject: [PATCH 4/5] potion mixing - healing vs "bad" potions Another part of github issue 229, mixtype() didn't have either 'break' or '/*FALLTHRU*/' separating healing from extra healing, extra healing from full healing, and full healing from unicorn horn. So dipping "bad" potions (sickness, confusion, blindness, hallucination) into healing/extra healing/full healing or vice versa operated the same as dipping a unicorn horn into the bad potion (producing fruit juice for sickness and water for the others). It wasn't clear from the code whether or not that was intentional. It actually seems reasonable (albeit suboptimal use of {plain, extra, full} healing), so continue to allow it and make the code clear that it's intentional. --- src/potion.c | 54 ++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/src/potion.c b/src/potion.c index 18c6b584f..728fdc9e4 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 potion.c $NHDT-Date: 1560850774 2019/06/18 09:39:34 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.162 $ */ +/* NetHack 3.6 potion.c $NHDT-Date: 1570235292 2019/10/05 00:28:12 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.163 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1769,41 +1769,33 @@ STATIC_OVL short mixtype(o1, o2) register struct obj *o1, *o2; { + int o1typ = o1->otyp, o2typ = o2->otyp; + /* cut down on the number of cases below */ if (o1->oclass == POTION_CLASS - && (o2->otyp == POT_GAIN_LEVEL || o2->otyp == POT_GAIN_ENERGY - || o2->otyp == POT_HEALING || o2->otyp == POT_EXTRA_HEALING - || o2->otyp == POT_FULL_HEALING || o2->otyp == POT_ENLIGHTENMENT - || o2->otyp == POT_FRUIT_JUICE)) { - struct obj *swp; - - swp = o1; - o1 = o2; - o2 = swp; + && (o2typ == POT_GAIN_LEVEL || o2typ == POT_GAIN_ENERGY + || o2typ == POT_HEALING || o2typ == POT_EXTRA_HEALING + || o2typ == POT_FULL_HEALING || o2typ == POT_ENLIGHTENMENT + || o2typ == POT_FRUIT_JUICE)) { + /* swap o1 and o2 */ + o1typ = o2->otyp; + o2typ = o1->otyp; } - switch (o1->otyp) { + switch (o1typ) { case POT_HEALING: - switch (o2->otyp) { - case POT_SPEED: - case POT_GAIN_LEVEL: - case POT_GAIN_ENERGY: + if (o2typ == POT_SPEED) return POT_EXTRA_HEALING; - } + /*FALLTHRU*/ case POT_EXTRA_HEALING: - switch (o2->otyp) { - case POT_GAIN_LEVEL: - case POT_GAIN_ENERGY: - return POT_FULL_HEALING; - } case POT_FULL_HEALING: - switch (o2->otyp) { - case POT_GAIN_LEVEL: - case POT_GAIN_ENERGY: - return POT_GAIN_ABILITY; - } + if (o2typ == POT_GAIN_LEVEL || o2typ == POT_GAIN_ENERGY) + return (o1typ == POT_HEALING) ? POT_EXTRA_HEALING + : (o1typ == POT_EXTRA_HEALING) ? POT_FULL_HEALING + : POT_GAIN_ABILITY; + /*FALLTHRU*/ case UNICORN_HORN: - switch (o2->otyp) { + switch (o2typ) { case POT_SICKNESS: return POT_FRUIT_JUICE; case POT_HALLUCINATION: @@ -1813,12 +1805,12 @@ register struct obj *o1, *o2; } break; case AMETHYST: /* "a-methyst" == "not intoxicated" */ - if (o2->otyp == POT_BOOZE) + if (o2typ == POT_BOOZE) return POT_FRUIT_JUICE; break; case POT_GAIN_LEVEL: case POT_GAIN_ENERGY: - switch (o2->otyp) { + switch (o2typ) { case POT_CONFUSION: return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT); case POT_HEALING: @@ -1834,7 +1826,7 @@ register struct obj *o1, *o2; } break; case POT_FRUIT_JUICE: - switch (o2->otyp) { + switch (o2typ) { case POT_SICKNESS: return POT_SICKNESS; case POT_ENLIGHTENMENT: @@ -1846,7 +1838,7 @@ register struct obj *o1, *o2; } break; case POT_ENLIGHTENMENT: - switch (o2->otyp) { + switch (o2typ) { case POT_LEVITATION: if (rn2(3)) return POT_GAIN_LEVEL; From 8443f73265c296c551ae26610c5e61ac794021e6 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 4 Oct 2019 17:53:01 -0700 Subject: [PATCH 5/5] glob pricing get_pricing_units() returns a long, so use long for intermediate steps of the calculation. Part of github issue 229, about mixing signed and unsigned. --- src/shk.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shk.c b/src/shk.c index f5c42bacd..5fcc70c99 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 shk.c $NHDT-Date: 1558124088 2019/05/17 20:14:48 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.163 $ */ +/* NetHack 3.6 shk.c $NHDT-Date: 1570236762 2019/10/05 00:52:42 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.168 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2035,11 +2035,11 @@ struct obj *obj; if (obj->globby) { /* globs must be sold by weight not by volume */ - int unit_weight = (int) objects[obj->otyp].oc_weight, - wt = (obj->owt > 0) ? obj->owt : weight(obj); + long unit_weight = (long) objects[obj->otyp].oc_weight, + wt = (obj->owt > 0) ? (long) obj->owt : (long) weight(obj); if (unit_weight) - units = wt / unit_weight; + units = (wt + unit_weight - 1L) / unit_weight; } return units; }