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