fix #H6338 - naming mimicked potion

Player tried to #name a potion on the floor and got prompted to call a
stream of fluid (sink feedback) instead of a potion.  A mimic posing
as an object is represented by a partially initialized object when
examining its map location.  #name for floor object uses the same data
as look_at.

obj->fromsink overloads obj->corpsenm which is set to NON_PM (-1) even
when creating a non-init'd object.  'fromsink' was only being forced to
0 when creating an init'd object (unlike leash which has its overload
of corpsenm set properly regardless of caller's request to init).  So
docall() treated a mimicked potion as a sink stream.

The fix is straightforward but has pointed out another bug which is
harder to fix.  Examining a floor object next to you sets that obj's
dknown flag as if you had seen it up close (a new feature in 3.6.0).
But a mimicked item is discarded as soon as it's been looked at, so
looking again from a non-adjacent spot will give different feedback
since the previously set dknown will be unset when replaced by a new
fake object.  So you can use '/' and ';' to recognize mimics without
provoking them into motion.  Best fix:  mimicking an object should use
a fully initialized one which is tracked via monst->mextra, but that
will break save file compatibility.  Possible hack:  change monst->
mappearance into a mask which uses N bits for object type (instead of
full 'int') and one of the other bits to track obj->dknown.  Examining
an adjacent object probably ought to set bknown for priests, so bknown
and blessed/uncursed/cursed would need to be tracked too.
This commit is contained in:
PatR
2017-10-28 01:18:25 -07:00
parent bf0223fd9f
commit 25c27cd4cf
3 changed files with 28 additions and 20 deletions

View File

@@ -195,7 +195,7 @@ struct obj **obj_p;
glyph among floor and buried objects; when !Blind, any buried
object's glyph will have been replaced by whatever is present
on the surface as soon as we moved next to its spot */
&& 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 */
&& !iflags.terrainmode) /* so don't set dknown when in terrain mode */
otmp->dknown = 1; /* if a pile, clearly see the top item only */