]> granicus.if.org Git - nethack/commitdiff
shop feedback ("gold piecess") (trunk only)
authornethack.rankin <nethack.rankin>
Thu, 27 Oct 2011 02:24:54 +0000 (02:24 +0000)
committernethack.rankin <nethack.rankin>
Thu, 27 Oct 2011 02:24:54 +0000 (02:24 +0000)
     From a bug report, dropping and selling a container that had some things owned
by the hero and some already owned by the shop, you could get "You sold
some items inside <a container> for N gold piecess."  Shop handing for
containers has been changed significantly since 3.4.3, but the typo
"pieces" that then optionally gets plural "s" appended was still there.

     While testing the trivial fix, I noticed suboptional feedback in the
prompt about selling.  For a container owned by the shop, it said "items"
even when there was just one hero owned item inside.  Fortunately this
potentinal can of worns only seemed to have one tiny weeny worm in it....

     The revised version of count_buc() that I've had laying around for
a while is also included.

     The fixes entry is for "piecess", not escaped/captured/exterminated
worms, and goes into fixes34.4 despite this patch being labeled "trunk
only".  Separate patch for trunk to follow.

doc/fixes34.4
include/extern.h
src/invent.c
src/objnam.c
src/shk.c

index 9161a69d50282c5361325e2f2b8fedfd1c04cd80..f34526a89d5eda9f3cfb521c58f62061d1f98c2c 100644 (file)
@@ -412,6 +412,7 @@ temporary loss of Dex from wounded legs will become permanent if it occurs
 character escape sequence handling during options processing was vulernable
        to malformed escapes and could potentially be abused to clobber the
        stack and launch a buffer overrun attack
+fix message typo, "you sold some items inside <container> for N gold piecess"
 
 
 Platform- and/or Interface-Specific Fixes
index ed0cdb78b72ef77a753d869b32095aa0ac64bbff..0d7dfdedb771bf81b7dbfd8fcd3940466b656e22 100644 (file)
@@ -952,6 +952,7 @@ E void NDECL(reassign);
 E int NDECL(doorganize);
 E int FDECL(count_unpaid, (struct obj *));
 E int FDECL(count_buc, (struct obj *,int));
+E long FDECL(count_contents, (struct obj *,BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
 E void FDECL(carry_obj_effects, (struct obj *));
 E const char *FDECL(currency, (long));
 E void FDECL(silly_thing, (const char *,struct obj *));
index 9d2ca7dbd25c33cca013632cee9cb2b6eb0a697d..15f967f111ca3bdfcb88e8d108203972fd0d8543 100644 (file)
@@ -2056,6 +2056,9 @@ count_unpaid(list)
 /*
  * Returns the number of items with b/u/c/unknown within the given list.  
  * This does NOT include contained objects.
+ *
+ * Assumes that the hero sees or touches or otherwise senses the objects
+ * at some point:  bknown is forced for priest[ess], like in xname().
  */
 int
 count_buc(list, type)
@@ -2064,31 +2067,37 @@ count_buc(list, type)
 {
     int count = 0;
 
-    while (list) {
-       if (Role_if(PM_PRIEST)) list->bknown = TRUE;
-       switch(type) {
-           case BUC_BLESSED:
-               if (list->oclass != COIN_CLASS && list->bknown && list->blessed)
-                   count++;
-               break;
-           case BUC_CURSED:
-               if (list->oclass != COIN_CLASS && list->bknown && list->cursed)
-                   count++;
-               break;
-           case BUC_UNCURSED:
-               if (list->oclass != COIN_CLASS &&
-                       list->bknown && !list->blessed && !list->cursed)
-                   count++;
-               break;
-           case BUC_UNKNOWN:
-               if (list->oclass != COIN_CLASS && !list->bknown)
-                   count++;
-               break;
-           default:
-               impossible("need count of curse status %d?", type);
-               return 0;
-       }
-       list = list->nobj;
+    for ( ; list; list = list->nobj) {
+       /* coins are "none of the above" as far as BUCX filtering goes */
+       if (list->oclass == COIN_CLASS) continue;
+       /* priests always know bless/curse state */
+       if (Role_if(PM_PRIEST)) list->bknown = 1;
+
+       /* check whether this object matches the requested type */
+       if (!list->bknown ? (type == BUC_UNKNOWN) :
+             list->blessed ? (type == BUC_BLESSED) :
+               list->cursed ? (type == BUC_CURSED) :
+                 (type == BUC_UNCURSED))
+           ++count;
+    }
+    return count;
+}
+
+long
+count_contents(container, nested, quantity, everything)
+struct obj *container;
+boolean nested,                /* include contents of any nested containers */
+       quantity,       /* count all vs count separate stacks */
+       everything;     /* all objects vs only unpaid objects */
+{
+    struct obj *otmp;
+    long count = 0L;
+
+    for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
+       if (nested && Has_contents(otmp))
+           count += count_contents(otmp, nested, quantity, everything);
+       if (everything || otmp->unpaid)
+           count += quantity ? otmp->quan : 1L;
     }
     return count;
 }
index 7eec819e9781af3370ea60086ce4530ce7d76a11..ed3bab96794bf05ad12e7650d34e72f1784088ae 100644 (file)
@@ -736,14 +736,15 @@ register struct obj *obj;
        if (obj->greased) Strcat(prefix, "greased ");
 
        if (cknown && Has_contents(obj)) {
-           struct obj *curr;
-           long itemcount = 0L;
+           /* we count all objects (obj->quantity); perhaps we should
+              count seperate stacks instead (or even introduce a user
+              preference option to choose between the two alternatives)
+              since it's somewhat odd so see "containing 1002 items"
+              when there are 2 scrolls plus 1000 gold pieces */
+           long itemcount = count_contents(obj, FALSE, TRUE, TRUE);
 
-           /* Count the number of contained objects */
-           for (curr = obj->cobj; curr; curr = curr->nobj)
-               itemcount += curr->quan;
            Sprintf(eos(bp), " containing %ld item%s",
-                       itemcount, plur(itemcount));
+                   itemcount, plur(itemcount));
        }
 
        switch(obj->oclass) {
index 59701b45f7bf39b070b9bf8f5f01c89edb1705a6..2823935f83685286a21883bf9604966cb3778d43 100644 (file)
--- a/src/shk.c
+++ b/src/shk.c
@@ -2876,9 +2876,15 @@ xchar x, y;
 
                if (short_funds) offer = shkmoney;
                if (!sell_response) {
-                   only_partially_your_contents = (container &&
-                               contained_cost(obj, shkp, 0L, FALSE, FALSE) !=
-                               contained_cost(obj, shkp, 0L, FALSE, TRUE));
+                   long yourc = 0L, shksc;
+
+                   if (container) {
+                       /* number of items owned by shk */
+                       shksc = count_contents(obj, TRUE, TRUE, FALSE);
+                       /* number of items owned by you (total - shksc) */
+                       yourc = count_contents(obj, TRUE, TRUE, TRUE) - shksc;
+                       only_partially_your_contents = shksc && yourc;
+                   }
                    /*
                       "<shk> offers * for ..." query formatting.
                       Normal item(s):
@@ -2895,22 +2901,26 @@ xchar x, y;
                       Your container:
                        "... your <empty bag>.  Sell it?"
                        "... your <bag> and its contents.  Sell them?"
+                       "... your <bag> and item inside.  Sell them?"
                        "... your <bag> and items inside.  Sell them?"
                       Shk's container:
-                      (empty case won't happen--nothing to sell)
-                       "... the contents of the <bag>.  Sell them?"
+                       "... your item in the <bag>.  Sell it?"
                        "... your items in the <bag>.  Sell them?"
                     */
                    Sprintf(qbuf, "%s offers%s %ld gold piece%s for %s%s ",
                            shkname(shkp), short_funds ? " only" : "",
                            offer, plur(offer),
-                           (cltmp && !ltmp) ? (only_partially_your_contents ?
-                             "your items in " : the_contents_of) : "",
+                           (cltmp && !ltmp) ? 
+                             ((yourc == 1L) ? "your item in " :
+                                              "your items in ") : "",
                            obj->unpaid ? "the" : "your");
-                   one = (obj->quan == 1L && !cltmp);
+                   one = obj->unpaid ? (yourc == 1L) :
+                               (obj->quan == 1L && !cltmp);
                    Sprintf(qsfx, "%s.  Sell %s?",
                            (cltmp && ltmp) ? (only_partially_your_contents ?
-                             " and items inside" : and_its_contents) : "",
+                             ((yourc == 1L) ? " and item inside" :
+                                              " and items inside") :
+                             and_its_contents) : "",
                            one ? "it" : "them");
                    (void)safe_qbuf(qbuf, qbuf, qsfx,
                                    obj, xname, simpleonames,
@@ -2932,7 +2942,7 @@ xchar x, y;
                            pay(-offer, shkp);
                            shk_names_obj(shkp, obj, (sell_how != SELL_NORMAL) ?
                                    (!ltmp && cltmp && only_partially_your_contents) ?
-                                   "sold some items inside %s for %ld gold pieces%s.%s" :
+                                   "sold some items inside %s for %ld gold piece%s.%s" :
                                    "sold %s for %ld gold piece%s.%s" :
               "relinquish %s and receive %ld gold piece%s in compensation.%s",
                                    offer, "");