]> granicus.if.org Git - nethack/commitdiff
shopkeeper inheriting hero's possessions (trunk only)
authornethack.rankin <nethack.rankin>
Sun, 28 Aug 2011 02:11:12 +0000 (02:11 +0000)
committernethack.rankin <nethack.rankin>
Sun, 28 Aug 2011 02:11:12 +0000 (02:11 +0000)
     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
src/shk.c

index 2fc5541cb94402dd4ac1333677fe7d815c7bb2e9..655a643fcbe986ba57fa340bd75b2f0cd27b966f 100644 (file)
@@ -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 "<mon> 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
index 6d423b4400b7bc0d14750900b5fce1afd7c0ef33..59701b45f7bf39b070b9bf8f5f01c89edb1705a6 100644 (file)
--- 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