From 9e0d94596147254e2c150e0d84da1f07a15a6b26 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 27 Dec 2018 15:01:15 -0800 Subject: [PATCH 1/3] stack splitting vs shop prices I misread part of the original code and the revision introduced a bug based on that. obj->o_id price variations are used for all types of non-IDed items, not just non-glass gems. --- src/mkobj.c | 6 +++--- src/shk.c | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/mkobj.c b/src/mkobj.c index c1bce84a8..cab7c6344 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkobj.c $NHDT-Date: 1545948759 2018/12/27 22:12:39 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.138 $ */ +/* NetHack 3.6 mkobj.c $NHDT-Date: 1545951660 2018/12/27 23:01:00 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.139 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -465,8 +465,8 @@ long num; return otmp; } -/* when splitting a stack that has o_id-based shop prices (non-glass gems), - pick an o_id value for the new stack that will maintain the same price */ +/* when splitting a stack that has o_id-based shop prices, pick an + o_id value for the new stack that will maintain the same price */ STATIC_OVL unsigned nextoid(oldobj, newobj) struct obj *oldobj, *newobj; diff --git a/src/shk.c b/src/shk.c index 746afb522..1031c1606 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 shk.c $NHDT-Date: 1545948761 2018/12/27 22:12:41 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.148 $ */ +/* NetHack 3.6 shk.c $NHDT-Date: 1545951668 2018/12/27 23:01:08 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.149 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1993,10 +1993,8 @@ unsigned oid; { int res = 0, otyp = obj->otyp; - /* currently only used for non-glass gems */ - if (obj->oclass == GEM_CLASS && otyp != ROCK - && !(obj->dknown && objects[otyp].oc_name_known) - && objects[otyp].oc_material != GLASS) { + if (!(obj->dknown && objects[otyp].oc_name_known) + && (obj->oclass != GEM_CLASS || objects[otyp].oc_material != GLASS)) { res = ((oid % 4) == 0); /* id%4 ==0 -> +1, ==1..3 -> 0 */ } return res; From 96eaca731af2b2a0438a8826af61f2c4838ad700 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 27 Dec 2018 15:37:06 -0800 Subject: [PATCH 2/3] stack merging vs shop pricing When merging one stack into another and they have different obj->o_id price adjustments, keep the o_id of whichever one commands the higher shop price. --- doc/fixes36.2 | 5 ++++- src/shk.c | 13 ++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index ffc70c885..d4fb99cec 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -312,8 +312,11 @@ looking into an applied container with ':' showed prices of unpaid items but prevent achievement luckstone from merging with other luckstones if kicked or dropped by monster (not applicable for dropped by player; achievement would have been recorded and luckstone reverted to normal if picked up) -when splitting a stack of gems where internal ID is used to make adjustment to +when splitting a stack where internal ID is used to make adjustment to shop prices, pick an ID for new stack that yields same prices as old +when merging a stack where internal ID is used to adjust shop prices, always + keep the ID which induces the higher price (only matters when buying + from shop, not when selling; doesn't affect items already on bill) Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/shk.c b/src/shk.c index 1031c1606..ae2e1860a 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 shk.c $NHDT-Date: 1545951668 2018/12/27 23:01:08 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.149 $ */ +/* NetHack 3.6 shk.c $NHDT-Date: 1545953813 2018/12/27 23:36:53 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.150 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -958,6 +958,17 @@ register struct obj *obj, *merge; *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct]; #endif } + } else { + /* not on bill; if the item is being merged away rather than + just deleted and has a higher price adjustment than the stack + being merged into, give the latter the former's obj->o_id so + that the merged stack takes on higher price; matters if hero + eventually buys them from a shop, but doesn't matter if hero + owns them and intends to sell (unless he subsequently buys + them back) or if no shopping activity ever involves them */ + if (merge && (oid_price_adjustment(obj, obj->o_id) + > oid_price_adjustment(merge, merge->o_id))) + merge->o_id = obj->o_id; } if (obj->owornmask) { impossible("obfree: deleting worn obj (%d: %ld)", obj->otyp, From c056ca1b359097fc27c8bf3def07065993e4bdfa Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 27 Dec 2018 18:36:26 -0800 Subject: [PATCH 3/3] fix github issue #170 - stacks of non-missiles Fixes #170 Monsters never throw athames or scalpels but some fake player monsters on the Astral Plane are given those. Since they're stackable the quantity usually gets boosted but there's no point in having more than one if they won't be thrown. This could have been fixed by letting monsters throw those two items, but I prevented the quantity from being boosted instead. --- doc/fixes36.2 | 2 ++ include/extern.h | 3 ++- src/mplayer.c | 5 +++-- src/weapon.c | 16 +++++++++++++++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index d4fb99cec..fed918d0f 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -317,6 +317,8 @@ when splitting a stack where internal ID is used to make adjustment to when merging a stack where internal ID is used to adjust shop prices, always keep the ID which induces the higher price (only matters when buying from shop, not when selling; doesn't affect items already on bill) +since knives became stackable in 3.6.0, fake player monsters could be given + multi-quantity stacks for weapons (scalpel, athame) they never throw Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 28f671b1d..991070194 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1545948751 2018/12/27 22:12:31 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.677 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1545964581 2018/12/28 02:36:21 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.678 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2730,6 +2730,7 @@ E const char *FDECL(weapon_descr, (struct obj *)); E int FDECL(hitval, (struct obj *, struct monst *)); E int FDECL(dmgval, (struct obj *, struct monst *)); E struct obj *FDECL(select_rwep, (struct monst *)); +E boolean FDECL(monmightthrowwep, (struct obj *)); E struct obj *FDECL(select_hwep, (struct monst *)); E void FDECL(possibly_unwield, (struct monst *, BOOLEAN_P)); E void FDECL(mwepgone, (struct monst *)); diff --git a/src/mplayer.c b/src/mplayer.c index dfb97ab85..e0526be6a 100644 --- a/src/mplayer.c +++ b/src/mplayer.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mplayer.c $NHDT-Date: 1458949461 2016/03/25 23:44:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.21 $ */ +/* NetHack 3.6 mplayer.c $NHDT-Date: 1545964576 2018/12/28 02:36:16 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.25 $ */ /* Copyright (c) Izchak Miller, 1992. */ /* NetHack may be freely redistributed. See license for details. */ @@ -270,7 +270,8 @@ register boolean special; if (special && rn2(2)) otmp = mk_artifact(otmp, A_NONE); /* usually increase stack size if stackable weapon */ - if (objects[otmp->otyp].oc_merge && !otmp->oartifact) + if (objects[otmp->otyp].oc_merge && !otmp->oartifact + && monmightthrowwep(otmp)) otmp->quan += (long) rn2(is_spear(otmp) ? 4 : 8); /* mplayers knew better than to overenchant Magicbane */ if (otmp->oartifact == ART_MAGICBANE) diff --git a/src/weapon.c b/src/weapon.c index a590366bb..567aa9578 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 weapon.c $NHDT-Date: 1541145518 2018/11/02 07:58:38 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.60 $ */ +/* NetHack 3.6 weapon.c $NHDT-Date: 1545964580 2018/12/28 02:36:20 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.67 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -373,6 +373,7 @@ int x; return (struct obj *) 0; } +/* TODO: have monsters use aklys' throw-and-return */ static NEARDATA const int rwep[] = { DWARVISH_SPEAR, SILVER_SPEAR, ELVEN_SPEAR, SPEAR, ORCISH_SPEAR, JAVELIN, SHURIKEN, YA, SILVER_ARROW, ELVEN_ARROW, ARROW, ORCISH_ARROW, @@ -510,6 +511,19 @@ register struct monst *mtmp; return (struct obj *) 0; } +/* is 'obj' a type of weapon that any monster knows how to throw? */ +boolean +monmightthrowwep(obj) +struct obj *obj; +{ + short idx; + + for (idx = 0; idx < SIZE(rwep); ++idx) + if (obj->otyp == rwep[idx]) + return TRUE; + return FALSE; +} + /* Weapons in order of preference */ static const NEARDATA short hwep[] = { CORPSE, /* cockatrice corpse */