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