]> granicus.if.org Git - nethack/commitdiff
fix #H4105 - credit cloning
authorPatR <rankin@nethack.org>
Sun, 20 Dec 2015 09:44:19 +0000 (01:44 -0800)
committerPatR <rankin@nethack.org>
Sun, 20 Dec 2015 09:44:19 +0000 (01:44 -0800)
Putting gold into a hero-owned container on a shop's floot gave credit
for the amount of the gold but also set the gold object no_charge, so
it could be taken out without taking away the credit.  Then put back
in and taken out as many times as the player liked, doubling the gold
each time until the shopkeeper was out of cash.

I think the proper fix would be to avoid giving credit instead of not
marking the gold no_charge, but that would require multiple additional
changes so I took the easy way out.

Most of the changes to pickup.c are reformatting that it escaped prior
to release.  The changes to shk.c are cosmetic and not part of the fix.

doc/fixes36.1
src/pickup.c
src/shk.c

index c49d68dcaac4fb9f7e9a7f87685121f3fc2688e2..c8a25f2ac3e15e029aa86c984e7280cb0f217d42 100644 (file)
@@ -47,6 +47,7 @@ make corpse visible if stethoscope told you about it being there
 sceptre of might database entry word change
 avoid "spellbook of novel" on discoveries list after object ID of novel
 add novel to discoveries list after reading one
+putting gold into hero-owned container on shop floor gave free credit
 
 
 Platform- and/or Interface-Specific Fixes
index 0fa4e65cccdf0ca39baa18487a0784021d3747c8..34fcf59e6186aa7b16dbe8492851cf5680b9f42c 100644 (file)
@@ -1,9 +1,9 @@
-/* NetHack 3.6 pickup.c        $NHDT-Date: 1445556881 2015/10/22 23:34:41 $  $NHDT-Branch: master $:$NHDT-Revision: 1.162 $ */
+/* NetHack 3.6 pickup.c        $NHDT-Date: 1450604648 2015/12/20 09:44:08 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.167 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
 /*
- *     Contains code for picking objects up, and container use.
+ *      Contains code for picking objects up, and container use.
  */
 
 #include "hack.h"
@@ -25,8 +25,8 @@ STATIC_DCL int FDECL(autopick, (struct obj *, int, menu_item **));
 STATIC_DCL int FDECL(count_categories, (struct obj *, int));
 STATIC_DCL long FDECL(carry_count, (struct obj *, struct obj *, long,
                                     BOOLEAN_P, int *, int *));
-STATIC_DCL int FDECL(lift_object,
-                     (struct obj *, struct obj *, long *, BOOLEAN_P));
+STATIC_DCL int FDECL(lift_object, (struct obj *, struct obj *, long *,
+                                   BOOLEAN_P));
 STATIC_DCL boolean FDECL(mbag_explodes, (struct obj *, int));
 STATIC_PTR int FDECL(in_container, (struct obj *));
 STATIC_PTR int FDECL(out_container, (struct obj *));
@@ -63,13 +63,14 @@ STATIC_DCL void FDECL(tipcontainer, (struct obj *));
 
 /* A variable set in use_container(), to be used by the callback routines  */
 /* in_container() and out_container() from askchain() and use_container(). */
-/* Also used by menu_loot() and container_gone().                         */
+/* Also used by menu_loot() and container_gone().                          */
 static NEARDATA struct obj *current_container;
 #define Icebox (current_container->otyp == ICE_BOX)
 
-static const char moderateloadmsg[] = "You have a little trouble lifting";
-static const char nearloadmsg[] = "You have much trouble lifting";
-static const char overloadmsg[] = "You have extreme difficulty lifting";
+static const char
+        moderateloadmsg[] = "You have a little trouble lifting",
+        nearloadmsg[] = "You have much trouble lifting",
+        overloadmsg[] = "You have extreme difficulty lifting";
 
 /* BUG: this lets you look at cockatrice corpses while blind without
    touching them */
@@ -89,6 +90,7 @@ boolean here;     /* flag for type of obj list linkage */
         pline1(doname(otmp));
     } else {
         winid tmpwin = create_nhwindow(NHW_MENU);
+
         putstr(tmpwin, 0, "");
         do {
             putstr(tmpwin, 0, doname(otmp));
@@ -125,15 +127,15 @@ int *itemcount;
 
 /*
  * Suppose some '?' and '!' objects are present, but '/' objects aren't:
- *     "a" picks all items without further prompting;
- *     "A" steps through all items, asking one by one;
- *     "?" steps through '?' items, asking, and ignores '!' ones;
- *     "/" becomes 'A', since no '/' present;
- *     "?a" or "a?" picks all '?' without further prompting;
- *     "/a" or "a/" becomes 'A' since there aren't any '/'
- *         (bug fix:  3.1.0 thru 3.1.3 treated it as "a");
- *     "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
- *         (ie, treated as if it had just been "?a").
+ *      "a" picks all items without further prompting;
+ *      "A" steps through all items, asking one by one;
+ *      "?" steps through '?' items, asking, and ignores '!' ones;
+ *      "/" becomes 'A', since no '/' present;
+ *      "?a" or "a?" picks all '?' without further prompting;
+ *      "/a" or "a/" becomes 'A' since there aren't any '/'
+ *          (bug fix:  3.1.0 thru 3.1.3 treated it as "a");
+ *      "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/'
+ *          (ie, treated as if it had just been "?a").
  */
 STATIC_OVL boolean
 query_classes(oclasses, one_at_a_time, everything, action, objs, here,
@@ -168,7 +170,8 @@ int *menu_on_demand;
         }
     } else { /* more than one choice available */
         const char *where = 0;
-        register char sym, oc_of_sym, *p;
+        char sym, oc_of_sym, *p;
+
         /* additional choices */
         ilets[iletct++] = ' ';
         ilets[iletct++] = 'a';
@@ -189,8 +192,7 @@ int *menu_on_demand;
         if (*inbuf == '\033')
             return FALSE;
 
-        for (p = inbuf; (sym = *p++);) {
-            /* new A function (selective all) added by GAN 01/09/87 */
+        for (p = inbuf; (sym = *p++) != 0; ) {
             if (sym == ' ')
                 continue;
             else if (sym == 'A')
@@ -407,8 +409,8 @@ struct obj *obj;
     /* check for particular bless/curse state */
     if (bucx_filter) {
         /* first categorize this object's bless/curse state */
-        char bucx =
-            !obj->bknown ? 'X' : obj->blessed ? 'B' : obj->cursed ? 'C' : 'U';
+        char bucx = !obj->bknown ? 'X'
+                      : obj->blessed ? 'B' : obj->cursed ? 'C' : 'U';
 
         /* if its category is not in the list, reject */
         if (!index(valid_menu_classes, bucx))
@@ -425,11 +427,10 @@ allow_cat_no_uchain(obj)
 struct obj *obj;
 {
     if (obj != uchain
-       && ((index(valid_menu_classes,'u') && obj->unpaid)
+        && ((index(valid_menu_classes,'u') && obj->unpaid)
             || index(valid_menu_classes, obj->oclass)))
-       return TRUE;
-    else
-       return FALSE;
+        return TRUE;
+    return FALSE;
 }
 #endif
 
@@ -447,9 +448,9 @@ register struct obj *otmp;
  * or a monster's inventory if swallowed.
  *
  * Arg what:
- *     >0  autopickup
- *     =0  interactive
- *     <0  pickup count of something
+ *      >0  autopickup
+ *      =0  interactive
+ *      <0  pickup count of something
  *
  * Returns 1 if tried to pick something up, whether
  * or not it succeeded.
@@ -538,11 +539,12 @@ int what; /* should be a long */
     if (flags.menu_style != MENU_TRADITIONAL || iflags.menu_requested) {
         /* use menus exclusively */
         if (count) { /* looking for N of something */
-            char buf[QBUFSZ];
-            Sprintf(buf, "Pick %d of what?", count);
+            char qbuf[QBUFSZ];
+
+            Sprintf(qbuf, "Pick %d of what?", count);
             val_for_n_or_more = count; /* set up callback selector */
-            n = query_objlist(buf, objchain, traverse_how | AUTOSELECT_SINGLE
-                                                 | INVORDER_SORT,
+            n = query_objlist(qbuf, objchain, traverse_how | AUTOSELECT_SINGLE
+                                                  | INVORDER_SORT,
                               &pick_list, PICK_ONE, n_or_more);
             /* correct counts, if any given */
             for (i = 0; i < n; i++)
@@ -600,11 +602,12 @@ int what; /* should be a long */
                                traverse_how == BY_NEXTHERE, &via_menu)) {
                 if (!via_menu)
                     return 0;
-                n = query_objlist(
-                    "Pick up what?", objchain,
-                    traverse_how | (selective ? 0 : INVORDER_SORT),
-                    &pick_list, PICK_ANY,
-                    via_menu == -2 ? allow_all : allow_category);
+                n = query_objlist("Pick up what?", objchain,
+                                  traverse_how
+                                      | (selective ? 0 : INVORDER_SORT),
+                                  &pick_list, PICK_ANY,
+                                  (via_menu == -2) ? allow_all
+                                                   : allow_category);
                 goto menu_pickup;
             }
         }
@@ -657,7 +660,7 @@ int what; /* should be a long */
             n_picked += res;
         }
     end_query:
-        ; /* semicolon needed by brain-damaged compilers */
+        ; /* statement required after label */
     }
 
     if (!u.uswallow) {
@@ -684,9 +687,10 @@ boolean grab; /* forced pickup, rather than forced leave behind? */
      *  Does the text description of this match an exception?
      */
     char *objdesc = makesingular(doname(obj));
-    struct autopickup_exception *ape =
-        (grab) ? iflags.autopickup_exceptions[AP_GRAB]
-               : iflags.autopickup_exceptions[AP_LEAVE];
+    struct autopickup_exception
+        *ape = (grab) ? iflags.autopickup_exceptions[AP_GRAB]
+                      : iflags.autopickup_exceptions[AP_LEAVE];
+
     while (ape) {
         if (regex_match(objdesc, ape->regex))
             return TRUE;
@@ -732,7 +736,7 @@ menu_item **pick_list; /* list of objects and counts to pick up */
     }
 
     if (n) {
-        *pick_list = pi = (menu_item *) alloc(sizeof(menu_item) * n);
+        *pick_list = pi = (menu_item *) alloc(sizeof (menu_item) * n);
         for (n = 0, curr = olist; curr; curr = FOLLOW(curr, follow)) {
             pickit = (!*otypes || index(otypes, curr->oclass));
             if (!pickit)
@@ -759,15 +763,15 @@ menu_item **pick_list; /* list of objects and counts to pick up */
  * returned counts are guaranteed to be in bounds and non-zero.
  *
  * Query flags:
- *     BY_NEXTHERE       - Follow object list via nexthere instead of nobj.
- *     AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
- *                         use it.
- *     USE_INVLET        - Use object's invlet.
- *     INVORDER_SORT     - Use hero's pack order.
- *     INCLUDE_HERO      - Showing engulfer's invent; show hero too.
- *     SIGNAL_NOMENU     - Return -1 rather than 0 if nothing passes "allow".
- *     SIGNAL_ESCAPE     - Return -1 rather than 0 if player uses ESC to
- *                         pick nothing.
+ *      BY_NEXTHERE       - Follow object list via nexthere instead of nobj.
+ *      AUTOSELECT_SINGLE - Don't ask if only 1 object qualifies - just
+ *                          use it.
+ *      USE_INVLET        - Use object's invlet.
+ *      INVORDER_SORT     - Use hero's pack order.
+ *      INCLUDE_HERO      - Showing engulfer's invent; show hero too.
+ *      SIGNAL_NOMENU     - Return -1 rather than 0 if nothing passes "allow".
+ *      SIGNAL_ESCAPE     - Return -1 rather than 0 if player uses ESC to
+ *                          pick nothing.
  */
 int
 query_objlist(qstr, olist, qflags, pick_list, how, allow)
@@ -1202,7 +1206,7 @@ int *wt_before, *wt_after;
          * object and calling weight.
          *
          * This works for containers only because containers
-         * don't merge.                -dean
+         * don't merge.  -dean
          */
         for (qq = 1L; qq <= count; qq++) {
             obj->quan = qq;
@@ -1295,8 +1299,8 @@ boolean telekinesis;
         return -1;
     }
 
-    *cnt_p =
-        carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt);
+    *cnt_p = carry_count(obj, container, *cnt_p, telekinesis,
+                         &old_wt, &new_wt);
     if (*cnt_p < 1L) {
         result = -1; /* nothing lifted */
     } else if (obj->oclass != COIN_CLASS
@@ -1557,6 +1561,7 @@ mon_beside(x, y)
 int x, y;
 {
     int i, j, nx, ny;
+
     for (i = -1; i <= 1; i++)
         for (j = -1; j <= 1; j++) {
             nx = x + i;
@@ -1572,6 +1577,7 @@ do_loot_cont(cobjp)
 struct obj **cobjp;
 {
     struct obj *cobj = *cobjp;
+
     if (!cobj)
         return 0;
     if (cobj->olocked) {
@@ -1584,6 +1590,7 @@ struct obj **cobjp;
 
     if (cobj->otyp == BAG_OF_TRICKS) {
         int tmp;
+
         You("carefully open the bag...");
         pline("It develops a huge set of teeth and bites you!");
         tmp = rnd(10);
@@ -1645,7 +1652,7 @@ lootcont:
             int n, i;
             winid win;
             anything any;
-            menu_item *pick_list = NULL;
+            menu_item *pick_list = (menu_item *) 0;
 
             any.a_void = 0;
             win = create_nhwindow(NHW_MENU);
@@ -1846,9 +1853,9 @@ boolean *prev_loot;
     struct obj *otmp;
     char qbuf[QBUFSZ];
 
-    /* 3.3.1 introduced the ability to remove saddle from a steed */
-    /*         *passed_info is set to TRUE if a loot query was given. */
-    /* *prev_loot is set to TRUE if something was actually acquired in here.
+    /* 3.3.1 introduced the ability to remove saddle from a steed.
+     *  *passed_info is set to TRUE if a loot query was given.
+     *  *prev_loot is set to TRUE if something was actually acquired in here.
      */
     if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
         long unwornmask;
@@ -1884,10 +1891,11 @@ boolean *prev_loot;
             return 0;
         }
     }
-    /* 3.4.0 introduced the ability to pick things up from within swallower's
-     * stomach */
+    /* 3.4.0 introduced the ability to pick things up from within
+       swallower's stomach */
     if (u.uswallow) {
         int count = passed_info ? *passed_info : 0;
+
         timepassed = pickup(count);
     }
     return timepassed;
@@ -1966,16 +1974,16 @@ register struct obj *obj;
             return 0;
         }
         setuwep((struct obj *) 0);
+        /* This uwep check is obsolete.  It dates to 3.0 and earlier when
+         * unwielding Firebrand would be fatal in hell if hero had no other
+         * fire resistance.  Life-saving would force it to be re-wielded.
+         */
         if (uwep)
             return 0; /* unwielded, died, rewielded */
     } else if (obj == uswapwep) {
         setuswapwep((struct obj *) 0);
-        if (uswapwep)
-            return 0; /* unwielded, died, rewielded */
     } else if (obj == uquiver) {
         setuqwep((struct obj *) 0);
-        if (uquiver)
-            return 0; /* unwielded, died, rewielded */
     }
 
     if (fatal_corpse_mistake(obj, FALSE))
@@ -2001,12 +2009,13 @@ register struct obj *obj;
         (void) snuff_lit(obj);
 
     if (floor_container && costly_spot(u.ux, u.uy)) {
-        if (current_container->no_charge && !obj->unpaid) {
+        if (obj->oclass == COIN_CLASS) {
+            ; /* defer gold until after put-in message */
+        } else if (current_container->no_charge && !obj->unpaid) {
             /* don't sell when putting the item into your own container */
             obj->no_charge = 1;
-        } else if (obj->oclass != COIN_CLASS) {
-            /* sellobj() will take an unpaid item off the shop bill
-             * note: coins are handled later */
+        } else {
+            /* sellobj() will take an unpaid item off the shop bill */
             was_unpaid = obj->unpaid ? TRUE : FALSE;
             sellobj_state(SELL_DELIBERATE);
             sellobj(obj, u.ux, u.uy);
@@ -2018,6 +2027,7 @@ register struct obj *obj;
         /* stop any corpse timeouts when frozen */
         if (obj->otyp == CORPSE && obj->timed) {
             long rot_alarm = stop_timer(ROT_CORPSE, obj_to_any(obj));
+
             (void) stop_timer(REVIVE_MON, obj_to_any(obj));
             /* mark a non-reviving corpse as such */
             if (rot_alarm)
@@ -2058,7 +2068,6 @@ register struct obj *obj;
      * update status immediately.
      */
     bot();
-
     return (current_container ? 1 : -1);
 }
 
@@ -2121,10 +2130,10 @@ register struct obj *obj;
 
     otmp = addinv(obj);
     loadlev = near_capacity();
-    prinv(loadlev
-              ? (loadlev < MOD_ENCUMBER ? "You have a little trouble removing"
-                                        : "You have much trouble removing")
-              : (char *) 0,
+    prinv(loadlev ? ((loadlev < MOD_ENCUMBER)
+                        ? "You have a little trouble removing"
+                        : "You have much trouble removing")
+                  : (char *) 0,
           otmp, count);
 
     if (is_gold) {
@@ -2698,7 +2707,7 @@ dotip()
                 int n, i;
                 winid win;
                 anything any;
-                menu_item *pick_list = NULL;
+                menu_item *pick_list = (menu_item *) 0;
                 struct obj dummyobj, *otmp;
 
                 any = zeroany;
@@ -2838,7 +2847,7 @@ struct obj *box; /* or bag */
                treated the same as in the carried case.   We do so one
                item at a time instead of doing whole container at once
                to reduce the chance of exhausting shk's billing capacity. */
-        maybeshopgoods = !carried(box) && costly_spot(ox, oy);
+            maybeshopgoods = !carried(box) && costly_spot(ox, oy);
 
     /* caveat: this assumes that cknown, lknown, olocked, and otrapped
        fields haven't been overloaded to mean something special for the
index a0cf00e0d1c2ffe4625b19aaaf0c7d7039c57808..31ed6efbd202fc394d25f6fc6fc4de83163a58f7 100644 (file)
--- a/src/shk.c
+++ b/src/shk.c
@@ -1,4 +1,4 @@
-/* NetHack 3.6 shk.c   $NHDT-Date: 1446854234 2015/11/06 23:57:14 $  $NHDT-Branch: master $:$NHDT-Revision: 1.116 $ */
+/* NetHack 3.6 shk.c   $NHDT-Date: 1450604649 2015/12/20 09:44:09 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.117 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -383,9 +383,8 @@ register xchar x, y;
 
     rno = levl[x][y].roomno;
     if ((rno < ROOMOFFSET) || levl[x][y].edge || !IS_SHOP(rno - ROOMOFFSET))
-        return NO_ROOM;
-    else
-        return rno;
+        rno = NO_ROOM;
+    return rno;
 }
 
 void
@@ -773,21 +772,18 @@ register char rmno;
 
 boolean
 tended_shop(sroom)
-register struct mkroom *sroom;
+struct mkroom *sroom;
 {
-    register struct monst *mtmp = sroom->resident;
+    struct monst *mtmp = sroom->resident;
 
-    if (!mtmp)
-        return FALSE;
-    else
-        return (boolean) inhishop(mtmp);
+    return !mtmp ? FALSE : (boolean) inhishop(mtmp);
 }
 
 STATIC_OVL struct bill_x *
 onbill(obj, shkp, silent)
-register struct obj *obj;
-register struct monst *shkp;
-register boolean silent;
+struct obj *obj;
+struct monst *shkp;
+boolean silent;
 {
     if (shkp) {
         register struct bill_x *bp = ESHK(shkp)->bill_p;
@@ -1131,12 +1127,13 @@ register xchar ox, oy;
     hot_pursuit(shkp);
 }
 
-STATIC_VAR const char no_money[] = "Moreover, you%s have no money.";
-STATIC_VAR const char not_enough_money[] =
-    "Besides, you don't have enough to interest %s.";
+STATIC_VAR const char
+        no_money[] = "Moreover, you%s have no money.",
+        not_enough_money[] = "Besides, you don't have enough to interest %s.";
 
+/* delivers the cheapest item on the list */
 STATIC_OVL long
-cheapest_item(shkp) /* delivers the cheapest item on the list */
+cheapest_item(shkp)
 register struct monst *shkp;
 {
     register int ct = ESHK(shkp)->billct;
@@ -1348,6 +1345,7 @@ proceed:
         long dtmp = eshkp->debit;
         long loan = eshkp->loan;
         char sbuf[BUFSZ];
+
         umoney = money_cnt(invent);
         Sprintf(sbuf, "You owe %s %ld %s ", shkname(shkp), dtmp,
                 currency(dtmp));
@@ -1394,6 +1392,7 @@ proceed:
     if (eshkp->billct) {
         register boolean itemize;
         int iprompt;
+
         umoney = money_cnt(invent);
         if (!umoney && !eshkp->credit) {
             You("%shave no money or credit%s.",
@@ -2122,7 +2121,7 @@ boolean quietly;
                               (7 - obj->spe), (obj->spe > 0) ? " more" : "",
                               plur(7 - obj->spe));
                 /* [what if hero is already carrying enough candles?
-                   should Izchak explain how to attach them instead] */
+                   should Izchak explain how to attach them instead?] */
             } else {
                 verbalize("I won't stock that.  Take it out of here!");
             }