Allow identifying stackable items by comparison to identical items
NetHack has historically had problems (both in terms of interface and in terms of gameplay exploits) caused by unidentified items not stacking with identified items. The 3.7 change to cause items picked up by monsters to become unidentified has exacerbated this, e.g. there's an undesirable strategy in which players give ammunition to hostile monsters in order to unidentify it, allowing it to stack with other unidentified ammunition so that the whole stack can be enchanted with a single scroll. This commit makes it possible to stack items with different identification statuses (unles Blind), in effect causing the unidentified items to be identified by comparing them to the identified items (this is consistent with the mechanic via which two stacks of unidentified items can be determined to be the same as each other). The hope is that this will prevent any gain from exploits involving intentionally unidentifying (or intentionally failing to identify) items, that it will prevent interface clutter caused by (e.g.) a Ranger's main projectiles becoming partially unidentified as a nymph picks them up and subsequently failing to stack, and that it will reduce the incentive to backtrack to an altar to merge, e.g., a stack of formally-known-uncursed and a stack of informally-known-uncursed food rations to stack.
This commit is contained in:
@@ -511,6 +511,8 @@ any blessed key was behaving as if was the rogue's Master Key when unlocking
|
||||
when an unseen non-pet picks up or uses an item, hero loses known/dknown/
|
||||
bknown/cknown/lknown memory of that item (so becomes unidentified; in
|
||||
particular, player won't be asked what to call unseen thrown potion)
|
||||
when picking up a stackable item, it can be identified by comparing it to
|
||||
another identical item that is already identified
|
||||
wishing for a partly eaten wraith corpse yielded "partly eaten food (1) more
|
||||
nutritious than untouched food (0)"
|
||||
if PREFIXES_IN_USE was defined (and VAR_PLAYGROUND forces it to be) when
|
||||
|
||||
43
src/invent.c
43
src/invent.c
@@ -707,6 +707,7 @@ int
|
||||
merged(struct obj **potmp, struct obj **pobj)
|
||||
{
|
||||
register struct obj *otmp = *potmp, *obj = *pobj;
|
||||
boolean discovered = FALSE;
|
||||
|
||||
if (mergable(otmp, obj)) {
|
||||
/* Approximate age: we do it this way because if we were to
|
||||
@@ -745,6 +746,29 @@ merged(struct obj **potmp, struct obj **pobj)
|
||||
if (obj->timed)
|
||||
obj_stop_timers(obj); /* follows lights */
|
||||
|
||||
/* objects can be identified by comparing them (unless Blind,
|
||||
but that is handled in mergable()); the object becomes
|
||||
identified in a particular dimension if either object was
|
||||
previously identified in that dimension, and if the
|
||||
identification states don't match, one of them must have
|
||||
previously been identified */
|
||||
if (obj->known != otmp->known) {
|
||||
otmp->known = TRUE;
|
||||
discovered = TRUE;
|
||||
}
|
||||
if (obj->rknown != otmp->rknown) {
|
||||
otmp->rknown = TRUE;
|
||||
if (otmp->oerodeproof) {
|
||||
discovered = TRUE;
|
||||
}
|
||||
}
|
||||
if (obj->bknown != otmp->bknown) {
|
||||
otmp->bknown = TRUE;
|
||||
if (!Role_if(PM_CLERIC)) {
|
||||
discovered = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* fixup for `#adjust' merging wielded darts, daggers, &c */
|
||||
if (obj->owornmask && carried(otmp)) {
|
||||
long wmask = otmp->owornmask | obj->owornmask;
|
||||
@@ -802,6 +826,15 @@ merged(struct obj **potmp, struct obj **pobj)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print a message if item comparison discovers more
|
||||
information about the items (with the exception of thrown
|
||||
items, where this would be too spammy as such items get
|
||||
unidentified by monsters very frequently). */
|
||||
if (discovered && otmp->where == OBJ_INVENT &&
|
||||
!obj->was_thrown && !otmp->was_thrown) {
|
||||
pline("You learn more about your items by comparing them.");
|
||||
}
|
||||
|
||||
obfree(obj, otmp); /* free(obj), bill->otmp */
|
||||
return 1;
|
||||
}
|
||||
@@ -4548,14 +4581,15 @@ mergable(
|
||||
return FALSE;
|
||||
|
||||
if (obj->dknown != otmp->dknown
|
||||
|| (obj->bknown != otmp->bknown && !Role_if(PM_CLERIC))
|
||||
|| (obj->bknown != otmp->bknown && !Role_if(PM_CLERIC) &&
|
||||
(Blind || Hallucination))
|
||||
|| obj->oeroded != otmp->oeroded || obj->oeroded2 != otmp->oeroded2
|
||||
|| obj->greased != otmp->greased)
|
||||
return FALSE;
|
||||
|
||||
if ((obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS)
|
||||
&& (obj->oerodeproof != otmp->oerodeproof
|
||||
|| obj->rknown != otmp->rknown))
|
||||
|| (obj->rknown != otmp->rknown && (Blind || Hallucination))))
|
||||
return FALSE;
|
||||
|
||||
if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
|
||||
@@ -4614,7 +4648,10 @@ mergable(
|
||||
if (obj->oartifact != otmp->oartifact)
|
||||
return FALSE;
|
||||
|
||||
return (obj->known == otmp->known) ? TRUE : FALSE;
|
||||
if (obj->known != otmp->known && (Blind || Hallucination))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* the #showgold command */
|
||||
|
||||
Reference in New Issue
Block a user