Accurately track which items have been discovered, even if not #named

This fixes a couple of bugs: a long-standing bug in which writing a
scroll by label could fail even if you've already seen a scroll with
that label (due to the game not tracking whether or not you've seen a
scroll if it doesn't have a name); and a somewhat newer bug in which
spellbooks auto-identified by Wizard knowledge were marked as having
been encountered (rather than as known but not encountered).

Breaks save file compatibility, but not bones files.
This commit is contained in:
Alex Smith
2025-11-25 22:42:38 +00:00
parent 10a5e67478
commit 8c29b20010
38 changed files with 155 additions and 122 deletions
+1 -1
View File
@@ -2683,7 +2683,7 @@ use_stone(struct obj *tstone)
/* in case it was acquired while blinded */
if (!Blind)
tstone->dknown = 1;
observe_object(tstone);
known = (tstone->otyp == TOUCHSTONE && tstone->dknown
&& objects[TOUCHSTONE].oc_name_known);
Sprintf(stonebuf, "rub on the stone%s", plur(tstone->quan));
+4 -4
View File
@@ -1570,7 +1570,7 @@ artifact_hit(
}
*dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER;
pline("%s cuts %s in half!", wepdesc, mon_nam(mdef));
otmp->dknown = TRUE;
observe_object(otmp);
return TRUE;
} else {
if (bigmonst(gy.youmonst.data)) {
@@ -1587,7 +1587,7 @@ artifact_hit(
*/
*dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
pline("%s cuts you in half!", wepdesc);
otmp->dknown = TRUE;
observe_object(otmp);
return TRUE;
}
} else if (is_art(otmp, ART_VORPAL_BLADE)
@@ -1617,7 +1617,7 @@ artifact_hit(
mon_nam(mdef));
if (Hallucination && !flags.female)
pline("Good job Henry, but that wasn't Anne.");
otmp->dknown = TRUE;
observe_object(otmp);
return TRUE;
} else {
if (!has_head(gy.youmonst.data)) {
@@ -1634,7 +1634,7 @@ artifact_hit(
}
*dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER;
pline(ROLL_FROM(behead_msg), wepdesc, "you");
otmp->dknown = TRUE;
observe_object(otmp);
/* Should amulets fall off? */
return TRUE;
}
+10 -10
View File
@@ -26,7 +26,7 @@ staticfn void reconstrain_map(void);
staticfn void map_redisplay(void);
staticfn void browse_map(unsigned, const char *);
staticfn void map_monst(struct monst *, boolean);
staticfn void do_dknown_of(struct obj *);
staticfn void observe_recursively(struct obj *);
staticfn boolean check_map_spot(coordxy, coordxy, char, unsigned);
staticfn boolean clear_stale_map(char, unsigned);
staticfn void sense_trap(struct trap *, coordxy, coordxy, int);
@@ -246,14 +246,14 @@ o_material(struct obj *obj, unsigned material)
}
staticfn void
do_dknown_of(struct obj *obj)
observe_recursively(struct obj *obj)
{
struct obj *otmp;
obj->dknown = 1;
observe_object(obj);
if (Has_contents(obj)) {
for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
do_dknown_of(otmp);
observe_recursively(otmp);
}
}
@@ -638,7 +638,7 @@ object_detect(struct obj *detector, /* object doing the detecting */
if (do_dknown)
for (obj = gi.invent; obj; obj = obj->nobj)
do_dknown_of(obj);
observe_recursively(obj);
for (obj = fobj; obj; obj = obj->nobj) {
if ((!class && !boulder) || o_in(obj, class) || o_in(obj, boulder)) {
@@ -648,7 +648,7 @@ object_detect(struct obj *detector, /* object doing the detecting */
ct++;
}
if (do_dknown)
do_dknown_of(obj);
observe_recursively(obj);
}
for (obj = svl.level.buriedobjlist; obj; obj = obj->nobj) {
@@ -659,7 +659,7 @@ object_detect(struct obj *detector, /* object doing the detecting */
ct++;
}
if (do_dknown)
do_dknown_of(obj);
observe_recursively(obj);
}
if (u.usteed)
@@ -673,7 +673,7 @@ object_detect(struct obj *detector, /* object doing the detecting */
|| o_in(obj, boulder))
ct++;
if (do_dknown)
do_dknown_of(obj);
observe_recursively(obj);
}
if ((is_cursed && M_AP_TYPE(mtmp) == M_AP_OBJECT
&& (!class || class == objects[mtmp->mappearance].oc_class))
@@ -932,7 +932,7 @@ detect_obj_traps(
}
if (Is_box(otmp) && otmp->otrapped) {
otmp->tknown = 1;
otmp->dknown = 1;
observe_object(otmp);
result |= u_at(x, y) ? OTRAP_HERE : OTRAP_THERE;
if (ft) {
flash_glyph_at(x, y, trapglyph, FOUND_FLASH_COUNT);
@@ -1508,7 +1508,7 @@ do_vicinity_map(
unlike object detection, we don't notice buried items */
otmp = svl.level.objects[zx][zy];
if (extended)
otmp->dknown = 1;
observe_object(otmp);
map_object(otmp, TRUE);
newglyph = glyph_at(zx, zy);
/* if otmp is underwater, we'll need to redisplay the water */
+2 -2
View File
@@ -346,7 +346,7 @@ map_object(struct obj *obj, int show)
neardist = (r * r) * 2 - r; /* same as r*r + r*(r-1) */
if (distu(x, y) <= neardist) {
obj->dknown = 1;
observe_object(obj);
glyph = obj_to_glyph(obj, newsym_rn2);
}
}
@@ -1585,7 +1585,7 @@ see_nearby_objects(void)
if (!cansee(ix, iy) || distu(ix, iy) > neardist)
continue;
obj->dknown = 1; /* near enough to see it */
observe_object(obj);
/* operate on remembered glyph rather than current one */
glyph = levl[ix][iy].glyph;
if (glyph_is_generic_object(glyph))
+1 -1
View File
@@ -669,7 +669,7 @@ docall(struct obj *obj)
undiscover_object(obj->otyp);
} else {
*uname_p = dupstr(buf);
discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */
discover_object(obj->otyp, FALSE, TRUE, TRUE); /* possibly add to disco[] */
}
}
+2 -2
View File
@@ -1196,12 +1196,12 @@ learnring(struct obj *ring, boolean observed)
mark this ring as having been seen (no need for makeknown);
otherwise if we have seen this ring, discover its type */
if (objects[ringtype].oc_name_known)
ring->dknown = 1;
observe_object(ring);
else if (ring->dknown)
makeknown(ringtype);
#if 0 /* see learnwand() */
else
ring->eknown = 1;
observe_object(ring);
#endif
}
+12 -6
View File
@@ -1547,7 +1547,8 @@ consume_tin(const char *mesg)
mnum = tin->corpsenm;
if (mnum == NON_PM) {
pline("It turns out to be empty.");
tin->dknown = tin->known = 1;
observe_object(tin);
tin->known = 1;
tin = costly_tin(COST_OPEN);
use_up_tin(tin);
if (always_eat)
@@ -1579,8 +1580,10 @@ consume_tin(const char *mesg)
if (y_n("Eat it?") == 'n') {
if (flags.verbose)
You("discard the open tin.");
if (!Hallucination)
tin->dknown = tin->known = 1;
if (!Hallucination) {
observe_object(tin);
tin->known = 1;
}
tin = costly_tin(COST_OPEN);
use_up_tin(tin);
return;
@@ -1594,7 +1597,8 @@ consume_tin(const char *mesg)
eating_conducts(&mons[mnum]);
tin->dknown = tin->known = 1;
observe_object(tin);
tin->known = 1;
/* charge for one at pre-eating cost */
tin = svc.context.tin.tin = costly_tin(COST_OPEN);
@@ -1641,7 +1645,8 @@ consume_tin(const char *mesg)
Blind ? "" : " ", Blind ? "" : hcolor(NH_GREEN));
} else {
pline("It contains spinach.");
tin->dknown = tin->known = 1;
observe_object(tin);
tin->known = 1;
}
if (!always_eat && y_n("Eat it?") == 'n') {
@@ -2265,7 +2270,8 @@ eataccessory(struct obj *otmp)
if (u.uhp <= 0)
return; /* died from sink fall */
}
otmp->known = otmp->dknown = 1; /* by taste */
observe_object(otmp);
otmp->known = 1; /* by taste */
if (!rn2(otmp->oclass == RING_CLASS ? 3 : 5)) {
switch (otmp->otyp) {
default:
+10 -7
View File
@@ -921,7 +921,8 @@ artifact_score(
if (counting) {
u.urexp = nowrap_add(u.urexp, points);
} else {
discover_object(otmp->otyp, TRUE, FALSE);
discover_object(otmp->otyp, TRUE, TRUE, FALSE);
/* not observe_object; dead characters don't observe */
otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
/* assumes artifacts don't have quan > 1 */
Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)",
@@ -1254,7 +1255,8 @@ really_done(int how)
*/
for (obj = gi.invent; obj; obj = nextobj) {
nextobj = obj->nobj;
discover_object(obj->otyp, TRUE, FALSE);
discover_object(obj->otyp, TRUE, TRUE, FALSE);
/* observe_object not necessary after discover_object */
obj->known = obj->bknown = obj->dknown = obj->rknown = 1;
set_cknown_lknown(obj); /* set flags when applicable */
/* we resolve Schroedinger's cat now in case of both
@@ -1496,9 +1498,10 @@ really_done(int how)
if (objects[typ].oc_class != GEM_CLASS
|| typ <= LAST_REAL_GEM) {
otmp = mksobj(typ, FALSE, FALSE);
discover_object(otmp->otyp, TRUE, FALSE);
otmp->known = 1; /* for fake amulets */
discover_object(otmp->otyp, TRUE, TRUE, FALSE);
otmp->dknown = 1; /* seen it (blindness fix) */
/* observe_object not necessary after discover_object */
otmp->known = 1; /* for fake amulets */
if (has_oname(otmp))
free_oname(otmp);
otmp->quan = count;
@@ -1634,9 +1637,9 @@ container_contents(
(boolean (*)(OBJ_P)) 0);
for (srtc = sortedcobj; (obj = srtc->obj) != 0; ++srtc) {
if (identified) {
discover_object(obj->otyp, TRUE, FALSE);
obj->known = obj->bknown = obj->dknown
= obj->rknown = 1;
discover_object(obj->otyp, TRUE, TRUE, FALSE);
obj->dknown = 1; /* observe_object unnecessary */
obj->known = obj->bknown = obj->rknown = 1;
if (Is_container(obj) || obj->otyp == STATUE)
obj->cknown = obj->lknown = 1;
}
+1 -1
View File
@@ -2515,7 +2515,7 @@ wizkit_addinv(struct obj *obj)
return;
/* subset of starting inventory pre-ID */
obj->dknown = 1;
observe_object(obj);
if (Role_if(PM_CLERIC))
obj->bknown = 1; /* ok to bypass set_bknown() */
/* same criteria as lift_object()'s check for available inventory slot */
+2 -1
View File
@@ -641,7 +641,8 @@ drinksink(void)
otmp->cursed = otmp->blessed = 0;
pline("Some %s liquid flows from the faucet.",
Blind ? "odd" : hcolor(OBJ_DESCR(objects[otmp->otyp])));
otmp->dknown = !(Blind || Hallucination);
if(!(Blind || Hallucination))
observe_object(otmp);
otmp->quan++; /* Avoid panic upon useup() */
otmp->fromsink = 1; /* kludge for docall() */
(void) dopotion(otmp);
+5 -4
View File
@@ -178,7 +178,7 @@ loot_classify(Loot *sort_item, struct obj *obj)
* will put lower valued ones before higher valued ones.
*/
if (!Blind)
obj->dknown = 1; /* xname(obj) does this; we want it sooner */
observe_object(obj); /* xname(obj) does this; we want it sooner */
seen = obj->dknown ? TRUE : FALSE,
/* class order */
classorder = flags.sortpack ? flags.inv_order : def_srt_order;
@@ -1196,7 +1196,7 @@ hold_another_object(
char buf[BUFSZ];
if (!Blind)
obj->dknown = 1; /* maximize mergeability */
observe_object(obj); /* maximize mergeability */
if (obj->oartifact) {
/* place_object may change these */
boolean crysknife = (obj->otyp == CRYSKNIFE);
@@ -2546,7 +2546,8 @@ fully_identify_obj(struct obj *otmp)
makeknown(otmp->otyp);
if (otmp->oartifact)
discover_artifact((xint16) otmp->oartifact);
otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
observe_object(otmp);
otmp->known = otmp->bknown = otmp->rknown = 1;
set_cknown_lknown(otmp); /* set otmp->{cknown,lknown} if applicable */
if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
learn_egg_type(otmp->corpsenm);
@@ -6123,7 +6124,7 @@ display_binventory(coordxy x, coordxy y, boolean as_if_seen)
for (n = 0, obj = svl.level.buriedobjlist; obj; obj = obj->nobj)
if (obj->ox == x && obj->oy == y) {
if (as_if_seen)
obj->dknown = 1;
observe_object(obj);
n++;
}
+1 -1
View File
@@ -2128,7 +2128,7 @@ doseduce(struct monst *mon)
/* have her call your gloves by their correct
name, possibly revealing them to you */
if (yourgloves)
yourgloves->dknown = 1;
observe_object(yourgloves);
verbalize("Well, then you owe me %s%s!",
yourgloves ? yname(yourgloves)
: "twelve pairs of gloves",
+3
View File
@@ -834,6 +834,8 @@ static const char dknowns[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
void
clear_dknown(struct obj *obj)
{
/* note: this is an unobserving not an observing, so don't call
observe_object even if dknown is being set to 1 */
obj->dknown = strchr(dknowns, obj->oclass) ? 0 : 1;
if ((obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD)
|| obj->otyp == SHIELD_OF_REFLECTION
@@ -960,6 +962,7 @@ mksobj_init(struct obj **obj, boolean artif)
we initialize glob->owt explicitly so weight() doesn't
need to perform any fix up and returns glob->owt as-is */
otmp->owt = objects[otmp->otyp].oc_weight;
/* dknown, but not observed */
otmp->known = otmp->dknown = 1;
otmp->corpsenm = PM_GRAY_OOZE + (otmp->otyp - GLOB_OF_GRAY_OOZE);
start_glob_timeout(otmp, 0L);
+2 -2
View File
@@ -334,7 +334,7 @@ ohitmon(
ismimic = M_AP_TYPE(mtmp) && M_AP_TYPE(mtmp) != M_AP_MONSTER;
vis = cansee(gb.bhitpos.x, gb.bhitpos.y);
if (vis)
otmp->dknown = 1;
observe_object(otmp);
tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE);
/* High level monsters will be more likely to hit */
@@ -652,7 +652,7 @@ m_throw(
singleobj->ox = gb.bhitpos.x += dx;
singleobj->oy = gb.bhitpos.y += dy;
if (cansee(gb.bhitpos.x, gb.bhitpos.y))
singleobj->dknown = 1;
observe_object(singleobj);
mtmp = m_at(gb.bhitpos.x, gb.bhitpos.y);
if (mtmp && shade_miss(mon, mtmp, singleobj, TRUE, TRUE)) {
+6 -6
View File
@@ -207,7 +207,7 @@ mplayhorn(
? "nearby" : "in the distance");
unknow_object(otmp); /* hero loses info when unseen obj is used */
} else if (self) {
otmp->dknown = 1;
observe_object(otmp);
objnamp = xname(otmp);
if (strlen(objnamp) >= QBUFSZ)
objnamp = simpleonames(otmp);
@@ -216,7 +216,7 @@ mplayhorn(
pline("%s!", monverbself(mtmp, Monnam(mtmp), "play", objbuf));
makeknown(otmp->otyp); /* (wands handle this slightly differently) */
} else {
otmp->dknown = 1;
observe_object(otmp);
objnamp = xname(otmp);
if (strlen(objnamp) >= QBUFSZ)
objnamp = simpleonames(otmp);
@@ -242,7 +242,7 @@ mreadmsg(struct monst *mtmp, struct obj *otmp)
if (!vismon && Deaf)
return; /* no feedback */
otmp->dknown = 1; /* seeing or hearing scroll read reveals its label */
observe_object(otmp); /* seeing/hearing scroll read reveals its label */
Strcpy(onambuf, singular(otmp, vismon ? doname : ansimpleoname));
if (vismon) {
@@ -291,7 +291,7 @@ staticfn void
mquaffmsg(struct monst *mtmp, struct obj *otmp)
{
if (canseemon(mtmp)) {
otmp->dknown = 1;
observe_object(otmp);
pline_mon(mtmp, "%s drinks %s!", Monnam(mtmp), singular(otmp, doname));
} else if (!Deaf) {
Soundeffect(se_mon_chugging_potion, 25);
@@ -1967,7 +1967,7 @@ use_offensive(struct monst *mtmp)
* are not objects. Also set dknown in mthrowu.c.
*/
if (cansee(mtmp->mx, mtmp->my)) {
otmp->dknown = 1;
observe_object(otmp);
pline_mon(mtmp, "%s hurls %s!",
Monnam(mtmp), singular(otmp, doname));
}
@@ -3129,7 +3129,7 @@ muse_unslime(
vis |= canseemon(mon); /* burning potion may improve visibility */
if (vis) {
if (!Unaware)
obj->dknown = 1; /* hero is watching mon drink obj */
observe_object(obj); /* hero is watching mon drink obj */
pline("%s quaffs a burning %s",
saw_lit ? upstart(strcpy(Pronoun, mhe(mon))) : Monnam(mon),
simpleonames(obj));
+1 -1
View File
@@ -210,7 +210,7 @@ l_obj_objects_to_table(lua_State *L)
nhl_add_table_entry_int(L, "name_known", o->oc_name_known);
nhl_add_table_entry_int(L, "merge", o->oc_merge);
nhl_add_table_entry_int(L, "uses_known", o->oc_uses_known);
nhl_add_table_entry_int(L, "pre_discovered", o->oc_pre_discovered);
nhl_add_table_entry_int(L, "encountered", o->oc_encountered);
nhl_add_table_entry_int(L, "magic", o->oc_magic);
nhl_add_table_entry_int(L, "charged", o->oc_charged);
nhl_add_table_entry_int(L, "unique", o->oc_unique);
+32 -21
View File
@@ -377,7 +377,7 @@ savenames(NHFILE *nhfp)
unsigned int len;
if (update_file(nhfp)) {
for (i = 0; i < (MAXOCLASSES + 2); ++i) {
for (i = 0; i < (MAXOCLASSES + 2); ++i) {
Sfo_int(nhfp, &svb.bases[i], "names-bases");
}
for (i = 0; i < NUM_OBJECTS; ++i) {
@@ -436,41 +436,50 @@ restnames(NHFILE *nhfp)
}
#ifndef SFCTOOL
/* make the object dknown and mark it as encountered */
void
observe_object(struct obj *obj)
{
obj->dknown = 1;
discover_object(obj->otyp, FALSE, TRUE, FALSE);
}
void
discover_object(
int oindx,
boolean mark_as_known,
boolean mark_as_encountered,
boolean credit_hero)
{
if (!objects[oindx].oc_name_known
if ((!objects[oindx].oc_name_known && mark_as_known)
|| (!objects[oindx].oc_encountered && mark_as_encountered)
|| (Role_if(PM_SAMURAI)
&& Japanese_item_name(oindx, (const char *) 0))) {
int dindx, acls = objects[oindx].oc_class;
/* Loop thru disco[] 'til we find the target (which may have been
uname'd) or the next open slot; one or the other will be found
before we reach the next class...
*/
before we reach the next class... */
for (dindx = svb.bases[acls]; svd.disco[dindx] != 0; dindx++)
if (svd.disco[dindx] == oindx)
break;
svd.disco[dindx] = oindx;
/* if already known, we forced an item with a Japanese name into
disco[] but don't want to exercise wisdom or update perminv */
if (objects[oindx].oc_name_known)
return;
if (mark_as_encountered)
objects[oindx].oc_encountered = 1;
if (mark_as_known) {
if (!objects[oindx].oc_name_known && mark_as_known) {
objects[oindx].oc_name_known = 1;
if (credit_hero)
exercise(A_WIS, TRUE);
}
/* !in_moveloop => initial inventory, gameover => final disclosure */
if (program_state.in_moveloop && !program_state.gameover) {
if (objects[oindx].oc_class == GEM_CLASS)
gem_learned(oindx); /* could affect price of unpaid gems */
update_inventory();
/* !in_moveloop => initial inventory,
gameover => final disclosure */
if (program_state.in_moveloop && !program_state.gameover) {
if (objects[oindx].oc_class == GEM_CLASS)
gem_learned(oindx); /* could affect price of unpaid gems */
update_inventory();
}
}
}
}
@@ -514,9 +523,11 @@ interesting_to_discover(int i)
if (Role_if(PM_SAMURAI) && Japanese_item_name(i, (const char *) 0))
return TRUE;
/* Pre-discovered objects are now printed with a '*' */
/* Objects that were discovered without encountering them are now printed
with a '*' */
return (boolean) (objects[i].oc_uname != (char *) 0
|| (objects[i].oc_name_known
|| ((objects[i].oc_name_known
|| objects[i].oc_encountered)
&& OBJ_DESCR(objects[i]) != (char *) 0));
}
@@ -550,7 +561,7 @@ sortloot_descr(int otyp, char *outbuf)
o = cg.zeroobj;
o.otyp = otyp;
o.oclass = objects[otyp].oc_class;
o.dknown = 1;
o.dknown = 1; /* not observe_object, this isn't a real object */
o.known = (objects[otyp].oc_name_known || !objects[otyp].oc_uses_known)
? 1 : 0;
o.corpsenm = NON_PM; /* suppress statue and figurine details */
@@ -784,7 +795,7 @@ dodiscovered(void) /* free after Robert Viduya */
prev_class = oclass;
}
}
Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
Strcpy(buf, objects[dis].oc_encountered ? " " : "* ");
if (lootsort)
(void) sortloot_descr(dis, &buf[2]);
disco_append_typename(buf, dis);
@@ -1011,7 +1022,7 @@ doclassdisco(void)
++i) {
if ((dis = svd.disco[i]) != 0 && interesting_to_discover(dis)) {
++ct;
Strcpy(buf, objects[dis].oc_pre_discovered ? "* " : " ");
Strcpy(buf, objects[dis].oc_encountered ? " " : "* ");
if (lootsort)
(void) sortloot_descr(dis, &buf[2]);
disco_append_typename(buf, dis);
@@ -1113,7 +1124,7 @@ rename_disco(void)
odummy.oclass = objects[dis].oc_class;
odummy.quan = 1L;
odummy.known = !objects[dis].oc_uses_known;
odummy.dknown = 1;
odummy.dknown = 1; /* not observe_object: it isn't real */
docall(&odummy);
}
}
+5 -2
View File
@@ -625,7 +625,7 @@ xname_flags(
if (!nn && ocl->oc_uses_known && ocl->oc_unique)
obj->known = 0;
if (!Blind && !gd.distantname)
obj->dknown = 1;
observe_object(obj);
if (Role_if(PM_CLERIC))
obj->bknown = 1; /* avoid set_bknown() to bypass update_inventory() */
@@ -1057,6 +1057,8 @@ minimal_xname(struct obj *obj)
bareobj = cg.zeroobj;
bareobj.otyp = otyp;
bareobj.oclass = obj->oclass;
/* not observe_object, either the hero observed the object already or this
is overriding ID and shouldn't discover the object */
bareobj.dknown = (obj->dknown || iflags.override_ID) ? 1 : 0;
/* suppress known except for amulets (needed for fakes and real A-of-Y) */
bareobj.known = (obj->oclass == AMULET_CLASS)
@@ -1945,7 +1947,8 @@ killer_xname(struct obj *obj)
save_oname = ONAME(obj);
/* killer name should be more specific than general xname; however, exact
info like blessed/cursed and rustproof makes things be too verbose */
info like blessed/cursed and rustproof makes things be too verbose; set
dknown (not observe_object) because dead characters don't observe */
obj->known = obj->dknown = 1;
obj->bknown = obj->rknown = obj->greased = 0;
/* if character is a priest[ess], bknown will get toggled back on */
+2 -2
View File
@@ -366,11 +366,11 @@ object_from_map(
&& (fakeobj || otmp->where == OBJ_FLOOR) /* not buried */
/* terrain mode views what's already known, doesn't learn new stuff */
&& !iflags.terrainmode) /* so don't set dknown when in terrain mode */
otmp->dknown = 1; /* if a pile, clearly see the top item only */
observe_object(otmp); /* if a pile, clearly see the top item only */
if (fakeobj && mtmp && mimic_obj
&& (otmp->dknown || (M_AP_FLAG(mtmp) & M_AP_F_DKNOWN))) {
mtmp->m_ap_type |= M_AP_F_DKNOWN;
otmp->dknown = 1;
observe_object(otmp);
}
*obj_p = otmp;
return fakeobj; /* when True, caller needs to dealloc *obj_p */
+1 -1
View File
@@ -1816,7 +1816,7 @@ pickup_object(
/* In case of auto-pickup, where we haven't had a chance
to look at it yet; affects docall(SCR_SCARE_MONSTER). */
if (!Blind)
obj->dknown = 1;
observe_object(obj);
if (obj == uchain) { /* do not pick up attached chain */
return 0;
+2 -2
View File
@@ -646,7 +646,7 @@ polyself(int psflags)
re-converting scales to mail poses risk
of evaporation due to over enchanting */
uarm->otyp += GRAY_DRAGON_SCALES - GRAY_DRAGON_SCALE_MAIL;
uarm->dknown = 1;
observe_object(uarm);
disp.botl = TRUE; /* AC is changing */
}
uskin = uarm;
@@ -1371,7 +1371,7 @@ rehumanize(void)
return; /* don't rehumanize after all */
} else if (uamul && uamul->otyp == AMULET_OF_UNCHANGING) {
Your("%s %s!", simpleonames(uamul), otense(uamul, "fail"));
uamul->dknown = 1;
observe_object(uamul);
makeknown(AMULET_OF_UNCHANGING);
}
}
+5 -5
View File
@@ -2733,10 +2733,10 @@ potion_dip(struct obj *obj, struct obj *potion)
else
singlepotion->cursed = obj->cursed; /* odiluted left as-is */
singlepotion->bknown = FALSE;
if (Blind) {
singlepotion->dknown = FALSE;
} else {
singlepotion->dknown = !Hallucination;
singlepotion->dknown = FALSE; /* provisionally */
if (!Blind) {
if (!Hallucination)
observe_object(singlepotion);
*newbuf = '\0';
if (mixture == POT_WATER && singlepotion->dknown)
Sprintf(newbuf, "clears");
@@ -2756,7 +2756,7 @@ potion_dip(struct obj *obj, struct obj *potion)
struct obj fakeobj;
fakeobj = cg.zeroobj;
fakeobj.dknown = 1;
fakeobj.dknown = 1; /* no need to observe_object */
fakeobj.otyp = old_otyp;
fakeobj.oclass = POTION_CLASS;
docall(&fakeobj);
+6 -5
View File
@@ -879,7 +879,7 @@ gcrownu(void)
* even if hero doesn't know book */
bless(obj);
obj->bknown = 1; /* ok to skip set_bknown() */
obj->dknown = 1;
observe_object(obj);
at_your_feet(upstart(ansimpleoname(obj)));
dropy(obj);
u.ugifts++;
@@ -923,7 +923,7 @@ gcrownu(void)
; /* already got bonus above */
} else if (obj && in_hand) {
Your("%s goes snicker-snack!", xname(obj));
obj->dknown = 1;
observe_object(obj);
} else if (!already_exists) {
obj = mksobj(LONG_SWORD, FALSE, FALSE);
obj = oname(obj, artiname(ART_VORPAL_BLADE),
@@ -949,7 +949,7 @@ gcrownu(void)
; /* already got bonus above */
} else if (obj && in_hand) {
Your("%s hums ominously!", swordbuf);
obj->dknown = 1;
observe_object(obj);
} else if (!already_exists) {
obj = mksobj(RUNESWORD, FALSE, FALSE);
obj = oname(obj, artiname(ART_STORMBRINGER),
@@ -1052,7 +1052,8 @@ give_spell(void)
}
obfree(otmp, (struct obj *) 0); /* discard the book */
} else {
otmp->dknown = 1; /* not bknown */
observe_object(otmp);
/* don't set bknown */
/* discovering blank paper will make it less likely to
be given again; small chance to arbitrarily discover
some other book type without having to read it first */
@@ -1824,7 +1825,7 @@ bestow_artifact(uchar max_giftvalue)
/* make sure we can use this weapon */
unrestrict_weapon_skill(weapon_type(otmp));
if (!Hallucination && !Blind) {
otmp->dknown = 1;
observe_object(otmp);
makeknown(otmp->otyp);
discover_artifact(otmp->oartifact);
}
+1 -1
View File
@@ -127,7 +127,7 @@ artitouch(struct obj *obj)
if (!Qstat(touched_artifact)) {
/* in case we haven't seen the item yet (ie, currently blinded),
this quest message describes it by name so mark it as seen */
obj->dknown = 1;
observe_object(obj);
/* only give this message once */
Qstat(touched_artifact) = TRUE;
qt_pager("gotit");
+1 -1
View File
@@ -3360,7 +3360,7 @@ shk_names_obj(
char *obj_name, fmtbuf[BUFSZ];
boolean was_unknown = !obj->dknown;
obj->dknown = TRUE;
observe_object(obj);
/* Use real name for ordinary weapons/armor, and spell-less
* scrolls/books (that is, blank and mail), but only if the
* object is within the shk's area of interest/expertise.
+2 -1
View File
@@ -371,7 +371,8 @@ lay_an_egg(void)
uegg->owt = weight(uegg);
/* this sets hatch timers if appropriate */
set_corpsenm(uegg, egg_type_from_parent(u.umonnum, FALSE));
uegg->known = uegg->dknown = 1;
uegg->known = 1;
observe_object(uegg);
You("%s an egg.", eggs_in_water(gy.youmonst.data) ? "spawn" : "lay");
dropy(uegg);
stackobj(uegg);
+4 -3
View File
@@ -234,7 +234,7 @@ deadbook(struct obj *book2)
You("turn the pages of the Book of the Dead...");
makeknown(SPE_BOOK_OF_THE_DEAD);
book2->dknown = 1; /* in case blind now and hasn't been seen yet */
observe_object(book2); /* in case blind now and hasn't been seen yet */
/* KMH -- Need ->known to avoid "_a_ Book of the Dead" */
book2->known = 1;
if (invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
@@ -896,8 +896,9 @@ skill_based_spellbook_id(void)
}
if (objects[booktype].oc_level <= known_up_to_level)
/* makeknown(booktype) but don't exercise Wisdom */
discover_object(booktype, TRUE, FALSE);
/* makeknown(booktype) but don't exercise Wisdom or mark as
encountered */
discover_object(booktype, TRUE, FALSE, FALSE);
}
}
+4 -4
View File
@@ -1206,7 +1206,7 @@ trapeffect_arrow_trap(
} else {
place_object(otmp, u.ux, u.uy);
if (!Blind)
otmp->dknown = 1;
observe_object(otmp);
stackobj(otmp);
newsym(u.ux, u.uy);
}
@@ -1276,7 +1276,7 @@ trapeffect_dart_trap(
} else {
place_object(otmp, u.ux, u.uy);
if (!Blind)
otmp->dknown = 1;
observe_object(otmp);
stackobj(otmp);
newsym(u.ux, u.uy);
}
@@ -1352,7 +1352,7 @@ trapeffect_rocktrap(
harmless = TRUE;
}
if (!Blind)
otmp->dknown = 1;
observe_object(otmp);
stackobj(otmp);
newsym(u.ux, u.uy); /* map the rock */
@@ -5738,7 +5738,7 @@ untrap_box(
else
pline("There's a trap on %s.", the(xname(box)));
box->tknown = 1;
box->dknown = 1;
observe_object(box);
if (!confused)
exercise(A_WIS, TRUE);
+5 -4
View File
@@ -562,8 +562,8 @@ knows_object(int obj, boolean override_pauper)
{
if (u.uroleplay.pauper && !override_pauper)
return;
discover_object(obj, TRUE, FALSE);
objects[obj].oc_pre_discovered = 1; /* not a "discovery" */
/* mark as known, but not yet encountered */
discover_object(obj, TRUE, FALSE, FALSE);
}
/* Know ordinary (non-magical) objects of a certain class,
@@ -1207,6 +1207,7 @@ ini_inv_adjust_obj(struct trobj *trop, struct obj *obj)
} else {
if (objects[obj->otyp].oc_uses_known)
obj->known = 1;
/* not observe_object during startup, that's handled later */
obj->dknown = obj->bknown = obj->rknown = 1;
if (Is_container(obj) || obj->otyp == STATUE) {
obj->cknown = obj->lknown = 1;
@@ -1246,9 +1247,9 @@ ini_inv_use_obj(struct obj *obj)
{
/* Make the type known if necessary */
if (OBJ_DESCR(objects[obj->otyp]) && obj->known)
discover_object(obj->otyp, TRUE, FALSE);
discover_object(obj->otyp, TRUE, TRUE, FALSE);
if (obj->otyp == OIL_LAMP)
discover_object(POT_OIL, TRUE, FALSE);
discover_object(POT_OIL, TRUE, TRUE, FALSE);
if (obj->oclass == ARMOR_CLASS) {
if (is_shield(obj) && !uarms && !(uwep && bimanual(uwep))) {
+1 -1
View File
@@ -1133,7 +1133,7 @@ hmon_hitmon_misc_obj(
corpse_xname(obj, (const char *) 0,
obj->dknown ? CXN_PFX_THE
: CXN_ARTICLE));
obj->dknown = 1;
observe_object(obj);
if (!munstone(mon, TRUE))
minstapetrify(mon, TRUE);
if (resists_ston(mon))
+4 -9
View File
@@ -143,7 +143,7 @@ dowrite(struct obj *pen)
return ECMD_OK;
}
}
paper->dknown = 1;
observe_object(paper);
if (paper->otyp != SCR_BLANK_PAPER && paper->otyp != SPE_BLANK_PAPER) {
pline("That %s is not blank!", typeword);
exercise(A_WIS, FALSE);
@@ -326,13 +326,8 @@ dowrite(struct obj *pen)
*
* Writing by description requires that the hero knows the
* description (a scroll's label, that is, since books by_descr
* are rejected above). BUG: We can only do this for known
* scrolls and for the case where the player has assigned a
* name to put it onto the discoveries list; we lack a way to
* track other scrolls which have been seen closely enough to
* read the label without then being ID'd or named. The only
* exception is for currently carried inventory, where we can
* check for one [with its dknown bit set] of the same type.
* are rejected above). This is done by checking to see if a
* scroll with the same description has been encountered.
*
* Normal requirements can be overridden if hero is Lucky.
*/
@@ -345,7 +340,7 @@ dowrite(struct obj *pen)
/* if known, then either by-name or by-descr works */
if (!objects[new_obj->otyp].oc_name_known
/* else if named, then only by-descr works */
&& !(by_descr && label_known(new_obj->otyp, gi.invent))
&& !(by_descr && objects[new_obj->otyp].oc_encountered)
/* else fresh knowledge of the spell works */
&& spell_knowledge != spe_Fresh
/* and Luck might override after previous checks have failed */
+5 -5
View File
@@ -132,14 +132,14 @@ learnwand(struct obj *obj)
/* if type already discovered, treat this item has having been seen
even if hero is currently blinded (skips redundant makeknown) */
if (objects[obj->otyp].oc_name_known) {
obj->dknown = 1; /* will usually be set already */
observe_object(obj); /* will usually be dknown already */
/* otherwise discover it if item itself has been or can be seen */
} else {
/* in case it was picked up while blind and then zapped without
examining inventory after regaining sight (bypassing xname) */
if (!Blind)
obj->dknown = 1;
observe_object(obj);
/* make the discovery iff we know what we're manipulating */
if (obj->dknown)
makeknown(obj->otyp);
@@ -610,7 +610,7 @@ staticfn void
probe_objchain(struct obj *otmp)
{
for (; otmp; otmp = otmp->nobj) {
otmp->dknown = 1; /* treat as "seen" */
observe_object(otmp); /* treat as "seen" */
if (Is_container(otmp) || otmp->otyp == STATUE) {
otmp->lknown = 1;
if (!SchroedingersBox(otmp))
@@ -2220,7 +2220,7 @@ bhito(struct obj *obj, struct obj *otmp)
case WAN_PROBING:
res = !obj->dknown;
/* target object has now been "seen (up close)" */
obj->dknown = 1;
observe_object(obj);
if (Is_container(obj) || obj->otyp == STATUE) {
obj->cknown = obj->lknown = 1;
if (Is_box(obj) && !obj->tknown) {
@@ -2249,7 +2249,7 @@ bhito(struct obj *obj, struct obj *otmp)
/* view contents (not recursively) */
for (o = obj->cobj; o; o = o->nobj)
o->dknown = 1; /* "seen", even if blind */
observe_object(o); /* "seen", even if blind */
(void) display_cinventory(obj);
}
res = 1;