From a6b432203449bcdba546730e69e5d1946d448e22 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 27 Dec 2018 14:12:48 -0800 Subject: [PATCH] fix #H7103 - shop pricing Player came across a stack of 2 gray stones in a shop and kicked one. That one ended up with a different (in his case, lower) price once it was separate. This behavior only applies to non-glass gems which add a price variation derived from internal ID (obj->o_id) number. Make splitting stacks always yield the same price per item in the new stack as was being charged in the old stack by choosing a similar o_id. Do it for all splits (that can vary price by ID, so just non-glass gems), not just ones performed inside shops. He picked up the lower priced one and dropped it back on the original higher priced one; the combined stack took on the lower price. That will no longer happen if they come from splitting a stack, but this fix doesn't address merging with different prices when they start out as separate stacks. (Unpaid items won't merge in inventory if prices are different, but shop-owned items will merge on floor.) --- doc/fixes36.2 | 2 ++ include/extern.h | 3 ++- src/mkobj.c | 27 +++++++++++++++++++++++---- src/shk.c | 22 ++++++++++++++++++++-- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 34da7b77b..ffc70c885 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -312,6 +312,8 @@ 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 + shop prices, pick an ID for new stack that yields same prices as old Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 7a239f127..28f671b1d 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1545597403 2018/12/23 20:36:43 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.676 $ */ +/* 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 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2248,6 +2248,7 @@ E void FDECL(check_unpaid_usage, (struct obj *, BOOLEAN_P)); E void FDECL(check_unpaid, (struct obj *)); E void FDECL(costly_gold, (XCHAR_P, XCHAR_P, long)); E long FDECL(get_cost_of_shop_item, (struct obj *)); +E int FDECL(oid_price_adjustment, (struct obj *, unsigned)); E boolean FDECL(block_door, (XCHAR_P, XCHAR_P)); E boolean FDECL(block_entry, (XCHAR_P, XCHAR_P)); E char *FDECL(shk_your, (char *, struct obj *)); diff --git a/src/mkobj.c b/src/mkobj.c index 50140fe1f..c1bce84a8 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mkobj.c $NHDT-Date: 1545597425 2018/12/23 20:37:05 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.137 $ */ +/* 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 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -6,6 +6,7 @@ #include "hack.h" STATIC_DCL void FDECL(mkbox_cnts, (struct obj *)); +STATIC_DCL unsigned FDECL(nextoid, (struct obj *, struct obj *)); STATIC_DCL void FDECL(maybe_adjust_light, (struct obj *, int)); STATIC_DCL void FDECL(obj_timer_checks, (struct obj *, XCHAR_P, XCHAR_P, int)); @@ -436,9 +437,7 @@ long num; otmp = newobj(); *otmp = *obj; /* copies whole structure */ otmp->oextra = (struct oextra *) 0; - otmp->o_id = context.ident++; - if (!otmp->o_id) - otmp->o_id = context.ident++; /* ident overflowed */ + otmp->o_id = nextoid(obj, otmp); otmp->timed = 0; /* not timed, yet */ otmp->lamplit = 0; /* ditto */ otmp->owornmask = 0L; /* new object isn't worn */ @@ -466,6 +465,26 @@ 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 */ +STATIC_OVL unsigned +nextoid(oldobj, newobj) +struct obj *oldobj, *newobj; +{ + int olddif, newdif, trylimit = 256; /* limit of 4 suffices at present */ + unsigned oid = context.ident - 1; /* loop increment will reverse -1 */ + + olddif = oid_price_adjustment(oldobj, oldobj->o_id); + do { + ++oid; + if (!oid) /* avoid using 0 (in case value wrapped) */ + ++oid; + newdif = oid_price_adjustment(newobj, oid); + } while (newdif != olddif && --trylimit >= 0); + context.ident = oid + 1; /* ready for next new object */ + return oid; +} + /* try to find the stack obj was split from, then merge them back together; returns the combined object if unsplit is successful, null otherwise */ struct obj * diff --git a/src/shk.c b/src/shk.c index 40c58adb5..746afb522 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 shk.c $NHDT-Date: 1545786461 2018/12/26 01:07:41 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.147 $ */ +/* 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 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1984,6 +1984,24 @@ register struct obj *obj; return cost; } +/* decide whether to apply a surcharge (or hypothetically, a discount) to obj + if it had ID number 'oid'; returns 1: increase, 0: normal, -1: decrease */ +int +oid_price_adjustment(obj, oid) +struct obj *obj; +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) { + res = ((oid % 4) == 0); /* id%4 ==0 -> +1, ==1..3 -> 0 */ + } + return res; +} + /* calculate the value that the shk will charge for [one of] an object */ STATIC_OVL long get_cost(obj, shkp) @@ -2043,7 +2061,7 @@ register struct monst *shkp; /* if angry, impose a surcharge */ break; } tmp = (long) objects[i].oc_cost; - } else if (!(obj->o_id % 4)) { + } else if (oid_price_adjustment(obj, obj->o_id) > 0) { /* unid'd, arbitrarily impose surcharge: tmp *= 4/3 */ multiplier *= 4L; divisor *= 3L; -- 2.40.0