]> granicus.if.org Git - nethack/commitdiff
new container flags
authornethack.allison <nethack.allison>
Wed, 15 Dec 2004 23:50:18 +0000 (23:50 +0000)
committernethack.allison <nethack.allison>
Wed, 15 Dec 2004 23:50:18 +0000 (23:50 +0000)
[Attention: This patch increments EDITLEVEL in patchlevel.h, rendering all
 previous save and bones files obsolete.]

Here's the first cut at the two recommended flags lknown and cknown.
I've attempted to stay close to Pat's recommendations:
   "Containers ought to have two new flags:  lknown for lock status known,
    and cknown for contents known (ie, `secret').  Formatted box and chest
    descriptions should include locked/unlocked/broken when that is known
    and empty/nonempty (or something like "holds N items") when contents
    are known. The contents indicator would also apply to nonlockable
    containers."

I probably overlooked a place where a flag should be adjusted, but this
should give us a good starting point.

I wasn't sure what to do with the case of the auditory feedback for
magical locking "Click" and "Clunk". The question that came to my mind
was: Should those reveal the locked or unlocked status of a box?
I suppose if you knew the type of wand you were zapping or the spell
you were casting, you could argue that they should.

In the end, I opted for setting lknown right off the zap/cast effect
for anyone playing a Wizard role, and not setting it for anyone else,
thus advancing class differentiation a little bit too.

I haven't checked the cknown results under all flags.menu_style options
at this point, only MENU_FULL.

doc/fixes35.0
include/obj.h
include/patchlevel.h
src/dokick.c
src/invent.c
src/lock.c
src/mkobj.c
src/objnam.c
src/pickup.c
src/zap.c

index 097d798ec6ec67c324886cb80de9eecd1ce4ca02..ca413c19de0caf8273f3cdf3d8df347529b6ab70 100644 (file)
@@ -115,6 +115,8 @@ vampires can now shapeshift into bats and fog clouds; the latter can be done at
        will to slip through locked doors
 shapeshifted vampire will transform back to vampire form after you defeat it and
        continue to fight in its native form
+container lknown flag for locked/unlocked/broken awareness
+container cknown flag for container content awareness
 
 
 Platform- and/or Interface-Specific New Features
index 477fa8b1cad1289ff7a8fd3205a45d21a5e92069..d47a09eb2657604afc28378764128f0d1929a92d 100644 (file)
@@ -92,7 +92,9 @@ struct obj {
 
        Bitfield(in_use,1);     /* for magic items before useup items */
        Bitfield(bypass,1);     /* mark this as an object to be skipped by bhito() */
-       /* 6 free bits */
+       Bitfield(cknown,1);     /* contents of container assumed to be known */
+       Bitfield(lknown,1);     /* locked/unlocked status is known */
+       /* 4 free bits */
 
        int     corpsenm;       /* type of corpse is mons[corpsenm] */
 #define leashmon  corpsenm     /* gets m_id of attached pet */
index fefd12b97f3fed8dc814c0d1d2eb37d4537ecdf7..3ab6a90d5ba5e574f4428bc2405e05fbd22ac484 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)patchlevel.h       3.4     2004/06/12      */
+/*     SCCS Id: @(#)patchlevel.h       3.4     2004/12/15      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -13,7 +13,7 @@
  * Incrementing EDITLEVEL can be used to force invalidation of old bones
  * and save files.
  */
-#define EDITLEVEL      14
+#define EDITLEVEL      15
 
 #define COPYRIGHT_BANNER_A \
 "NetHack, Copyright 1985-2004"
index d40df0543ef75abc55cc349e1646cc63d9303dd5..b363cce7a6d6d100b5a9ec827c6909a25cff5912 100644 (file)
@@ -516,12 +516,14 @@ xchar x, y;
                        You("break open the lock!");
                        kickobj->olocked = 0;
                        kickobj->obroken = 1;
+                       kickobj->lknown = 1;
                        if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
                        return(1);
                    }
                } else {
                    if (!rn2(3) || (martial() && !rn2(2))) {
                        pline_The("lid slams open, then falls shut.");
+                       kickobj->lknown = 1;
                        if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
                        return(1);
                    }
index d8b01f111534d832f6c2e5cc0b7524bc0ff96f1d..0b1974d81e02e1fb49ca1b9f4ba70be438d31d06 100644 (file)
@@ -1917,15 +1917,27 @@ dounpaid()
         */
        for (otmp = invent; otmp; otmp = otmp->nobj) {
            if (Has_contents(otmp)) {
+               long contcost = 0L;
                marker = (struct obj *) 0;      /* haven't found any */
                while (find_unpaid(otmp->cobj, &marker)) {
                    totcost += cost = unpaid_cost(marker);
-                   save_unpaid = marker->unpaid;
-                   marker->unpaid = 0;    /* suppress "(unpaid)" suffix */
-                   putstr(win, 0,
+                   contcost += cost;
+                   if (otmp->cknown) {
+                       save_unpaid = marker->unpaid;
+                       marker->unpaid = 0;    /* suppress "(unpaid)" suffix */
+                       putstr(win, 0,
                           xprname(marker, distant_name(marker, doname),
                                   CONTAINED_SYM, TRUE, cost, 0L));
-                   marker->unpaid = save_unpaid;
+                       marker->unpaid = save_unpaid;
+                   }
+               }
+               if (!otmp->cknown) {
+                       char contbuf[BUFSZ];
+                       /* Shopkeeper knows what to charge for contents */
+                       Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
+                       putstr(win, 0,
+                               xprname((struct obj *)0, contbuf,
+                               CONTAINED_SYM, TRUE, contcost, 0L));
                }
            }
        }
@@ -2937,6 +2949,7 @@ register struct obj *obj;
            free((genericptr_t)selected);
        } else
            ret = (struct obj *) 0;
+       obj->cknown = 1;
        return ret;
 }
 
index 4b4542e17bce39df6c8707e91786d68633cbd86d..1a0ab0292eaa2db78f3055f64dce8dafac2be2f5 100644 (file)
@@ -117,6 +117,7 @@ picklock()  /* try to open/close a lock */
            else xlock.door->doormask = D_LOCKED;
        } else {
            xlock.box->olocked = !xlock.box->olocked;
+           xlock.box->lknown = 1;
            if(xlock.box->otrapped)     
                (void) chest_trap(xlock.box, FINGER, FALSE);
        }
@@ -163,6 +164,7 @@ forcelock() /* try to force a locked chest */
        You("succeed in forcing the lock.");
        xlock.box->olocked = 0;
        xlock.box->obroken = 1;
+       xlock.box->lknown = 1;
        if(!xlock.picktyp && !rn2(3)) {
            struct monst *shkp;
            boolean costly;
@@ -301,6 +303,7 @@ pick_lock(pick) /* pick a lock with a given object */
                            safe_qbuf("", sizeof("There is  here, unlock its lock?"),
                                doname(otmp), an(simple_typename(otmp->otyp)), "a box"),
                            verb, it ? "it" : "its lock");
+                   otmp->lknown = 1;
 
                    c = ynq(qbuf);
                    if(c == 'q') return(0);
@@ -461,12 +464,14 @@ doforce()         /* try to force a chest with your weapon */
                if (otmp->obroken || !otmp->olocked) {
                    There("is %s here, but its lock is already %s.",
                          doname(otmp), otmp->obroken ? "broken" : "unlocked");
+                   otmp->lknown = 1;
                    continue;
                }
                Sprintf(qbuf,"There is %s here, force its lock?",
                        safe_qbuf("", sizeof("There is  here, force its lock?"),
                                doname(otmp), an(simple_typename(otmp->otyp)),
                                "a box"));
+               otmp->lknown = 1;
 
                c = ynq(qbuf);
                if(c == 'q') return(0);
@@ -702,6 +707,7 @@ register struct obj *obj, *otmp;    /* obj *is* a box */
                pline("Klunk!");
                obj->olocked = 1;
                obj->obroken = 0;
+               if (Role_if(PM_WIZARD)) obj->lknown = 1;
                res = 1;
            } /* else already closed and locked */
            break;
@@ -711,6 +717,7 @@ register struct obj *obj, *otmp;    /* obj *is* a box */
                pline("Klick!");
                obj->olocked = 0;
                res = 1;
+               if (Role_if(PM_WIZARD)) obj->lknown = 1;
            } else                      /* silently fix if broken */
                obj->obroken = 0;
            break;
index d067deb0a3de8d22d210d6bf3d394aaa4db87a5a..a8144aac03a595afc3943677df6fc2b14e558c60 100644 (file)
@@ -377,6 +377,8 @@ boolean artif;
                otmp->dknown = 0;
        if (!objects[otmp->otyp].oc_uses_known)
                otmp->known = 1;
+       otmp->lknown = 0;
+       otmp->cknown = 0;
 #ifdef INVISIBLE_OBJECTS
        otmp->oinvis = !rn2(1250);
 #endif
index aacd1dd14ea1ced6db65ad2fcc71a636b5ba8628..ad090c21cd7ef5db52261e30fc2ece6c2a5d3e6a 100644 (file)
@@ -569,6 +569,11 @@ register struct obj *obj;
        if (obj->oinvis) Strcat(prefix,"invisible ");
 #endif
 
+       /* "empty" goes at the beginning, but item count goes at the end */
+       if (obj->cknown &&
+           (Is_container(obj) || obj->otyp == STATUE) && !Has_contents(obj))
+               Strcat(prefix, "empty ");
+
        if (obj->bknown &&
            obj->oclass != COIN_CLASS &&
            (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
@@ -602,8 +607,28 @@ register struct obj *obj;
                Strcat(prefix, "uncursed ");
        }
 
+       if (obj->lknown && Is_box(obj)) {
+           if (obj->obroken)
+               Strcat(prefix, "unlockable ");
+           else if (obj->olocked)
+               Strcat(prefix, "locked ");
+           else
+               Strcat(prefix, "unlocked ");
+       }
+
        if (obj->greased) Strcat(prefix, "greased ");
 
+       if (obj->cknown && Has_contents(obj)) {
+           struct obj *curr;
+           long itemcount = 0L;
+
+           /* 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));
+       }
+
        switch(obj->oclass) {
        case AMULET_CLASS:
                if(obj->owornmask & W_AMUL)
index 429d2f4da4a0d2e7519cf5fac5ea156cc2321a17..cda4f94c4b4d6a3f200890e6f28de7f3d8940774 100644 (file)
@@ -1544,8 +1544,11 @@ lootcont:
 
                if (cobj->olocked) {
                    pline("Hmmm, it seems to be locked.");
+                   cobj->lknown = 1;
                    continue;
                }
+               cobj->lknown = 1;
+
                if (cobj->otyp == BAG_OF_TRICKS) {
                    int tmp;
                    You("carefully open the bag...");
@@ -2091,9 +2094,11 @@ register int held;
        if (obj->olocked) {
            pline("%s to be locked.", Tobjnam(obj, "seem"));
            if (held) You("must put it down to unlock.");
+           obj->lknown = 1;
            return 0;
        } else if (obj->otrapped) {
            if (held) You("open %s...", the(xname(obj)));
+           obj->lknown = 1;
            (void) chest_trap(obj, HAND, FALSE);
            /* even if the trap fails, you've used up this turn */
            if (multi >= 0) {   /* in case we didn't become paralyzed */
@@ -2102,6 +2107,7 @@ register int held;
            }
            return 1;
        }
+       obj->lknown = 1;
        current_container = obj;        /* for use by in/out_container */
 
        if (obj->spe == 1) {
@@ -2147,6 +2153,7 @@ register int held;
                    if (!outokay && !inokay) {
                        pline("%s", emptymsg);
                        You("don't have anything to put in.");
+                       if (used) obj->cknown = 1;
                        return used;
                    }
                    menuprompt[0] = '\0';
@@ -2201,6 +2208,7 @@ ask_again2:
                    break;
                case 'q':
                default:
+                   if (used) obj->cknown = 1;
                    return used;
                }
            }
@@ -2215,6 +2223,7 @@ ask_again2:
 #endif
            /* nothing to put in, but some feedback is necessary */
            You("don't have anything to put in.");
+           if (used) obj->cknown = 1;
            return used;
        }
        if (flags.menu_style != MENU_FULL) {
@@ -2235,6 +2244,7 @@ ask_again2:
                    break;
                case 'q':
                default:
+                   if (used) obj->cknown = 1;
                    return used;
            }
        }
@@ -2330,6 +2340,7 @@ boolean put_in;
     }
 
     if (loot_everything) {
+       container->cknown = 1;
        for (otmp = container->cobj; otmp; otmp = otmp2) {
            otmp2 = otmp->nobj;
            res = out_container(otmp);
@@ -2338,6 +2349,7 @@ boolean put_in;
     } else {
        mflags = INVORDER_SORT;
        if (put_in && flags.invlet_constant) mflags |= USE_INVLET;
+       if (takeout) container->cknown = 1;
        Sprintf(buf,"%s what?", put_in ? putin : takeout);
        n = query_objlist(buf, put_in ? invent : container->cobj,
                          mflags, &pick_list, PICK_ANY,
@@ -2446,7 +2458,7 @@ dotip()
                c = ynq(buf);
                if (c == 'q') return 0;
                if (c == 'n') continue;
-
+               
                tipcontainer(cobj);
                return 1;
            }   /* next cobj */
@@ -2511,6 +2523,7 @@ struct obj *box;  /* or bag */
 {
     boolean empty_it = FALSE;
 
+    box->lknown = 1;
     if (box->olocked) {
        pline("It's locked.");
     } else if (box->otrapped) {
@@ -2524,16 +2537,19 @@ struct obj *box;        /* or bag */
     } else if (box->otyp == BAG_OF_TRICKS && box->spe > 0) {
        /* apply (not loot) this bag; uses up one charge */
        bagotricks(box);
+       box->cknown = 1;
     } else if (box->spe) {
        char yourbuf[BUFSZ];
 
        observe_quantum_cat(box);
+       box->cknown = 1;
        if (!Has_contents(box)) /* evidently a live cat came out */
            /* container type of "large box" is inferred */
            pline("%sbox is now empty.", Shk_Your(yourbuf, box));
        else                    /* holds cat corpse or other random stuff */
            empty_it = TRUE;
     } else if (!Has_contents(box)) {
+       box->cknown = 1;
        pline("It's empty.");
     } else {
        empty_it = TRUE;
@@ -2548,6 +2564,7 @@ struct obj *box;  /* or bag */
        int held = carried(box);
        long loss = 0L;
 
+       box->cknown = 1;
        pline("%s out%c",
              box->cobj->nobj ? "Objects spill" : "An object spills",
              !(highdrop || altarizing) ? ':' : '.');  
index c8ce7624fc8ceefecbc8d51b7f5f5cd70180b5ad..08599b17efb2007d28221d611fc5d31e1bd58a6a 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -1561,6 +1561,7 @@ struct obj *obj, *otmp;
                            o->dknown = 1;      /* "seen", even if blind */
                        (void) display_cinventory(obj);
                    }
+                   obj->cknown = 1;
                    res = 1;
                }
                if (res) makeknown(WAN_PROBING);