From 67f3a26e5208d9bbda27ed9e6435dff89645d057 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sun, 28 Aug 2011 02:11:12 +0000 Subject: [PATCH] shopkeeper inheriting hero's possessions (trunk only) Fix one of the issues noticed while investigating the report of a shopkeeper sighing when a hero died without owing anything. If the death takes place outside of any shop on a level with multiple shopkeepers, the first one in the fmon list would be the one who had access to the dying hero's inventory, even if nothing was owed to that one and something was owed to another shopkeeper. Now the one who is owed gets first chance to take the hero's possessions. When dying inside a shop, the keeper of that shop takes control of the possessions regardless of whether he or anyone else is owed anything. That hasn't changed, except that if the hero is simutaneoulsy inside multiple shops (within a wall spot shared by two or more shops) and owes money to one of them, the one who is owed will take his inventory even if the other shk is found first. This doesn't include any changes to feedback given when the hero dies in the presence of shopkeepers. --- doc/fixes35.0 | 2 ++ src/shk.c | 72 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 2fc5541cb..655a643fc 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -379,6 +379,8 @@ for hero poly'd into a monster form that lacks a weapon attack but has a claw rename the SLEEPING property and Sleeping attribute to SLEEPY and Sleepy, resp. give alternate message for " turns to flee" when mon can't move all statues in a cockatrice nest were for giant ant if 'record' was empty +when dying outside all shops on a level with multiple shopkeepers and one takes + hero's stuff, choose one who is owed money over first one on fmon list Platform- and/or Interface-Specific Fixes diff --git a/src/shk.c b/src/shk.c index 6d423b440..59701b45f 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1577,9 +1577,11 @@ boolean paybill(croaked) int croaked; /* -1: escaped dungeon; 0: quit; 1: died */ { - register struct monst *mtmp, *mtmp2, *resident= (struct monst *)0; - register boolean taken = FALSE; - register int numsk = 0; + struct monst *mtmp, *mtmp2, *firstshk, + *resident, *creditor, *hostile, *localshk; + struct eshk *eshkp; + boolean taken = FALSE, local; + int numsk = 0; /* if we escaped from the dungeon, shopkeepers can't reach us; shops don't occur on level 1, but this could happen if hero @@ -1593,27 +1595,63 @@ int croaked; /* -1: escaped dungeon; 0: quit; 1: died */ repo.location.x = repo.location.y = 0; repo.shopkeeper = 0; - /* give shopkeeper first crack */ - if ((mtmp = shop_keeper(*u.ushops)) && inhishop(mtmp)) { + /* + * Scan all shopkeepres on the level, to prioritize them: + * 1) keeper of shop hero is inside and who is owed money, + * 2) keeper of shop hero is inside who isn't owed any money, + * 3) other shk who is owed money, 4) other shk who is angry, + * 5) any shk local to this level, and if none is found, + * 6) first shk on monster list (last resort; unlikely, since + * any nonlocal shk will probably be in the owed category + * and almost certainly be in the angry category). + */ + resident = creditor = hostile = localshk = (struct monst *)0; + for (mtmp = next_shkp(fmon, FALSE); + mtmp; mtmp = next_shkp(mtmp2, FALSE)) { + mtmp2 = mtmp->nmon; + eshkp = ESHK(mtmp); + local = on_level(&eshkp->shoplevel, &u.uz); + if (local && index(u.ushops, eshkp->shoproom)) { + /* inside this shk's shop [there might be more than one + resident shk if hero is standing in a breech of a shared + wall, so give priority to one who's also owed money] */ + if (!resident || + eshkp->billct || eshkp->debit || eshkp->robbed) + resident = mtmp; + } else if (eshkp->billct || eshkp->debit || eshkp->robbed) { + /* owe this shopkeeper money (might also owe others) */ + if (!creditor) creditor = mtmp; + } else if (eshkp->following || ANGRY(mtmp)) { + /* this shopkeeper is antagonistic (others might be too) */ + if (!hostile) hostile = mtmp; + } else if (local) { + /* this shopkeeper's shop is on current level */ + if (!localshk) localshk = mtmp; + } + } + + /* give highest priority shopkeeper first crack */ + firstshk = resident ? resident : creditor ? creditor : + hostile ? hostile : localshk; + if (firstshk) { numsk++; - resident = mtmp; - taken = inherits(resident, numsk, croaked); + taken = inherits(firstshk, numsk, croaked); } + + /* now handle the rest */ for (mtmp = next_shkp(fmon, FALSE); mtmp; mtmp = next_shkp(mtmp2, FALSE)) { mtmp2 = mtmp->nmon; - if (mtmp != resident) { - /* for bones: we don't want a shopless shk around */ - if(!on_level(&(ESHK(mtmp)->shoplevel), &u.uz)) - mongone(mtmp); - else { - numsk++; - taken |= inherits(mtmp, numsk, croaked); - } + eshkp = ESHK(mtmp); + local = on_level(&eshkp->shoplevel, &u.uz); + if (mtmp != firstshk) { + numsk++; + taken |= inherits(mtmp, numsk, croaked); } + /* for bones: we don't want a shopless shk around */ + if (!local) mongone(mtmp); } - if(numsk == 0) return(FALSE); - return(taken); + return taken; } STATIC_OVL boolean -- 2.50.1