From c98133ac8081edc9a81b6b0b457d8909cf2c6696 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sat, 23 Jul 2011 03:57:09 +0000 Subject: [PATCH] calculating shop price adjustments (trunk only) Fix the second of a couple of minor things I noticed when viewing that guy's ttyrec about a hidden inventory item which turned out to be scrolls of scare monster on the used-up items section of his shop bill. He had a lot of scroll prices which started as $X00 and were changed to $Y99 due to integer division roundoff when being hit with a 1/3 price increase for unID'd items followed by 1/2 price increase for low charisma: 100 -> 133 -> 199 200 -> 266 -> 399 Forcing things to round up instead of truncate would help in some cases but yield $Z01 in others. Rather than doing that, this accumulates the adjustment factors and then uses them to make one calculation which gives a better result: 100 -> 200 200 -> 400 Other values and/or other adjustments might not work out so well, but I don't think they'll ever become prices which look worse than before. For a single increase of 1/3, 100 still yields 133 but 200 now gives 267 (so ends up differing from the combined price for two 100->133 items). --- doc/fixes35.0 | 1 + src/shk.c | 89 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 27 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index cec8f59a2..fd9801b09 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -373,6 +373,7 @@ for poly'd hero hiding on ceiling, attack by sea monsters won't move them into hero's position unless it is over water or they're already on land for poly'd hero hiding on ceiling, attack by long worm might fill hero's destination with worm's tail, so double check and maybe choose again +when shop prices are adjusted, handle roundoff (integer truncation) better Platform- and/or Interface-Specific Fixes diff --git a/src/shk.c b/src/shk.c index d6992b666..6d423b440 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1843,7 +1843,10 @@ get_cost(obj, shkp) register struct obj *obj; register struct monst *shkp; /* if angry, impose a surcharge */ { - register long tmp = getprice(obj, FALSE); + long tmp = getprice(obj, FALSE), + /* used to perform a single calculation even when multiple + adjustments (unID'd, dunce/tourist, charisma) are made */ + multiplier = 1L, divisor = 1L; if (!tmp) tmp = 5L; /* shopkeeper may notice if the player isn't very knowledgeable - @@ -1891,27 +1894,44 @@ register struct monst *shkp; /* if angry, impose a surcharge */ break; } tmp = (long) objects[i].oc_cost; - } else if (!(obj->o_id % 4)) /* arbitrarily impose surcharge */ - tmp += tmp / 3L; + } else if (!(obj->o_id % 4)) { + /* unid'd, arbitrarily impose surcharge: tmp *= 4/3 */ + multiplier *= 4L; + divisor *= 3L; + } } + if (uarmh && uarmh->otyp == DUNCE_CAP) + multiplier *= 4L, divisor *= 3L; #ifdef TOURIST - if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2)) - || (uarmu && !uarm && !uarmc)) /* touristy shirt visible */ - tmp += tmp / 3L; - else + else if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2)) || + (uarmu && !uarm && !uarmc)) /* touristy shirt visible */ + multiplier *= 4L, divisor *= 3L; #endif - if (uarmh && uarmh->otyp == DUNCE_CAP) - tmp += tmp / 3L; - - if (ACURR(A_CHA) > 18) tmp /= 2L; - else if (ACURR(A_CHA) > 17) tmp -= tmp / 3L; - else if (ACURR(A_CHA) > 15) tmp -= tmp / 4L; - else if (ACURR(A_CHA) < 6) tmp *= 2L; - else if (ACURR(A_CHA) < 8) tmp += tmp / 2L; - else if (ACURR(A_CHA) < 11) tmp += tmp / 3L; + + if (ACURR(A_CHA) > 18) divisor *= 2L; + else if (ACURR(A_CHA) == 18) multiplier *= 2L, divisor *= 3L; + else if (ACURR(A_CHA) >= 16) multiplier *= 3L, divisor *= 4L; + else if (ACURR(A_CHA) <= 5) multiplier *= 2L; + else if (ACURR(A_CHA) <= 7) multiplier *= 3L, divisor *= 2L; + else if (ACURR(A_CHA) <= 10) multiplier *= 4L, divisor *= 3L; + + /* tmp = (tmp * multiplier) / divisor [with roundoff tweak] */ + tmp *= multiplier; + if (divisor > 1L) { + /* tmp = (((tmp * 10) / divisor) + 5) / 10 */ + tmp *= 10L; + tmp /= divisor; + tmp += 5L; + tmp /= 10L; + } + if (tmp <= 0L) tmp = 1L; - else if (obj->oartifact) tmp *= 4L; - /* anger surcharge should match rile_shk's */ + /* the artifact prices in artilist[] are also used as a score bonus; + inflate their shop price here without affecting score calculation */ + if (obj->oartifact) tmp *= 4L; + + /* anger surcharge should match rile_shk's, so we do it separately + from the multiplier/divisor calculation */ if (shkp && ESHK(shkp)->surcharge) tmp += (tmp + 2L) / 3L; return tmp; } @@ -2042,18 +2062,18 @@ set_cost(obj, shkp) register struct obj *obj; register struct monst *shkp; { - long tmp = getprice(obj, TRUE) * obj->quan; + long tmp = getprice(obj, TRUE) * obj->quan, + multiplier = 1L, divisor = 1L; + if (uarmh && uarmh->otyp == DUNCE_CAP) + divisor *= 3L; #ifdef TOURIST - if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2)) - || (uarmu && !uarm && !uarmc)) /* touristy shirt visible */ - tmp /= 3L; - else + else if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2)) || + (uarmu && !uarm && !uarmc)) /* touristy shirt visible */ + divisor *= 3L; #endif - if (uarmh && uarmh->otyp == DUNCE_CAP) - tmp /= 3L; else - tmp /= 2L; + divisor *= 2L; /* shopkeeper may notice if the player isn't very knowledgeable - especially when gem prices are concerned */ @@ -2066,8 +2086,23 @@ register struct monst *shkp; tmp = (tmp + 3) * obj->quan; } } else if (tmp > 1L && !rn2(4)) - tmp -= tmp / 4L; + multiplier *= 3L, divisor *= 4L; } + + if (tmp >= 1L) { + /* [see get_cost()] */ + tmp *= multiplier; + if (divisor > 1L) { + tmp *= 10L; + tmp /= divisor; + tmp += 5L; + tmp /= 10L; + } + /* avoid adjusting nonzero to zero */ + if (tmp < 1L) tmp = 1L; + } + + /* (no adjustment for angry shk here) */ return tmp; } -- 2.50.1