ring discovery (trunk only)

Picking up and putting on a +1 ring of protection while blind
resulted in having a "+1 ring (on {left|right} hand)" in inventory and
having ring of protection show up in the discoveries list.  The problem
is the same as the one for wands which has been previously addressed
(but not 100% fixed...):  when using an item whose effect is observable,
the item's type became discovered based upon that observation even if the
item itself had never been seen.

     The code for removing ring of protection lacked its break statement
and fell into the case for removing ring of protection from shapechangers,
but didn't cause any noticeable problem.
This commit is contained in:
nethack.rankin
2008-01-29 04:17:03 +00:00
parent 89a86618d0
commit d8a45a57b5
4 changed files with 97 additions and 33 deletions

View File

@@ -114,6 +114,7 @@ fix monsndx panic which happened after currently moving monster expelled
no longer replaces monster
reduced message verbosity when re-entering a temple
reduced message verbosity when monster with multiple attacks missed wildly
putting on a never seen ring while blinded won't make the ring a discovery
zapping a never seen wand while blinded won't make the wand a discovery
zapping an unID'd wand of teleportation at self will discover it (usually)
zapping unlocking magic at self while punished will remove attached chain

View File

@@ -108,6 +108,7 @@ E void FDECL(adjabil, (int,int));
E int NDECL(newhp);
E schar FDECL(acurr, (int));
E schar NDECL(acurrstr);
E boolean FDECL(extremeattr, (int));
E void FDECL(adjalign, (int));
E int FDECL(is_innate, (int));
E char *FDECL(from_what, (int));

View File

@@ -900,6 +900,34 @@ acurrstr()
else return((schar)(str - 100));
}
/* when wearing (or taking off) an unID'd item, this routine is used
to distinguish between observable +0 result and no-visible-effect
due to an attribute not being able to exceed maximum or minimun */
boolean
extremeattr(attrindx) /* does attrindx's value match its max or min? */
int attrindx;
{
/* Fixed_abil and racial MINATTR/MAXATTR aren't relevant here */
int lolimit = 3, hilimit = 25, curval = ACURR(attrindx);
/* upper limit for Str is 25 but its value is encoded differently */
if (attrindx == A_STR) {
hilimit = STR19(25); /* 125 */
/* lower limit for Str can also be 25 */
if (uarmg && uarmg->otyp == GAUNTLETS_OF_POWER)
lolimit = hilimit;
}
/* this exception is hypothetical; the only other worn item affecting
Int or Wis is another helmet so can't be in use at the same time */
if (attrindx == A_INT || attrindx == A_WIS) {
if (uarmh && uarmh->otyp == DUNCE_CAP)
hilimit = lolimit = 6;
}
/* are we currently at either limit? */
return (curval == lolimit || curval == hilimit) ? TRUE : FALSE;
}
/* avoid possible problems with alignment overflow, and provide a centralized
* location for any future alignment limits
*/

View File

@@ -41,6 +41,7 @@ STATIC_PTR int NDECL(Shield_on);
STATIC_PTR int NDECL(Shirt_on);
#endif
STATIC_DCL void NDECL(Amulet_on);
STATIC_DCL void FDECL(learnring, (struct obj *,BOOLEAN_P));
STATIC_DCL void FDECL(Ring_off_or_gone, (struct obj *, BOOLEAN_P));
STATIC_PTR int FDECL(select_off, (struct obj *));
STATIC_DCL struct obj *NDECL(do_takeoff);
@@ -699,12 +700,45 @@ Amulet_off()
return;
}
/* handle ring discovery; comparable to learnwand() */
STATIC_OVL void
learnring(ring, observed)
struct obj *ring;
boolean observed;
{
int ringtype = ring->otyp;
/* if effect was observeable then we usually discover the type */
if (observed) {
/* if we already know the ring type which accomplishes this
effect (assumes there is at most one type for each effect),
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;
else if (ring->dknown)
makeknown(ringtype);
#if 0 /* see learnwand() */
else
ring->eknown = 1;
#endif
}
/* make enchantment of charged ring known (might be +0) and update
perm invent window if we've seen this ring and know its type */
if (ring->dknown && objects[ringtype].oc_name_known) {
if (objects[ringtype].oc_charged) ring->known = 1;
update_inventory();
}
}
void
Ring_on(obj)
register struct obj *obj;
{
long oldprop = u.uprops[objects[obj->otyp].oc_oprop].extrinsic;
int old_attrib, which;
boolean observable;
/* make sure ring isn't wielded; can't use remove_worn_item()
here because it has already been set worn in a ring slot */
@@ -751,12 +785,12 @@ register struct obj *obj;
!perceives(youmonst.data) && !Blind) {
newsym(u.ux,u.uy);
pline("Suddenly you are transparent, but there!");
makeknown(RIN_SEE_INVISIBLE);
learnring(obj, TRUE);
}
break;
case RIN_INVISIBILITY:
if (!oldprop && !HInvis && !BInvis && !Blind) {
makeknown(RIN_INVISIBILITY);
learnring(obj, TRUE);
newsym(u.ux,u.uy);
self_invis_message();
}
@@ -764,7 +798,7 @@ register struct obj *obj;
case RIN_LEVITATION:
if (!oldprop && !HLevitation) {
float_up();
makeknown(RIN_LEVITATION);
learnring(obj, TRUE);
spoteffects(FALSE); /* for sinks */
}
break;
@@ -779,14 +813,15 @@ register struct obj *obj;
adjust_attrib:
old_attrib = ACURR(which);
ABON(which) += obj->spe;
if (ACURR(which) != old_attrib ||
(objects[obj->otyp].oc_name_known &&
old_attrib != 25 && old_attrib != 3)) {
context.botl = 1;
makeknown(obj->otyp);
obj->known = 1;
update_inventory();
}
observable = (old_attrib != ACURR(which));
/* if didn't change, usually means ring is +0 but might
be because nonzero couldn't go below min or above max;
learn +0 enchantment if attribute value is not stuck
at a limit [and ring has been seen and its type is
already discovered, both handled by learnring()] */
if (observable || !extremeattr(which))
learnring(obj, observable);
context.botl = 1;
break;
case RIN_INCREASE_ACCURACY: /* KMH */
u.uhitinc += obj->spe;
@@ -798,12 +833,12 @@ register struct obj *obj;
rescham();
break;
case RIN_PROTECTION:
if (obj->spe || objects[RIN_PROTECTION].oc_name_known) {
context.botl = 1;
makeknown(RIN_PROTECTION);
obj->known = 1;
update_inventory();
}
/* usually learn enchantment and discover type;
won't happen if ring is unseen or if it's +0
and the type hasn't been discovered yet */
observable = (obj->spe != 0);
learnring(obj, observable);
if (obj->spe) find_ac(); /* updates botl */
break;
}
}
@@ -815,6 +850,7 @@ boolean gone;
{
long mask = (obj->owornmask & W_RING);
int old_attrib, which;
boolean observable;
context.takeoff.mask &= ~mask;
if(!(u.uprops[objects[obj->otyp].oc_oprop].extrinsic & mask))
@@ -858,7 +894,7 @@ boolean gone;
if (Invisible && !Blind) {
newsym(u.ux,u.uy);
pline("Suddenly you cannot see yourself.");
makeknown(RIN_SEE_INVISIBLE);
learnring(obj, TRUE);
}
break;
case RIN_INVISIBILITY:
@@ -866,12 +902,12 @@ boolean gone;
newsym(u.ux,u.uy);
Your("body seems to unfade%s.",
See_invisible ? " completely" : "..");
makeknown(RIN_INVISIBILITY);
learnring(obj, TRUE);
}
break;
case RIN_LEVITATION:
(void) float_down(0L, 0L);
if (!Levitation) makeknown(RIN_LEVITATION);
if (!Levitation) learnring(obj, TRUE);
break;
case RIN_GAIN_STRENGTH:
which = A_STR;
@@ -884,12 +920,11 @@ boolean gone;
adjust_attrib:
old_attrib = ACURR(which);
ABON(which) -= obj->spe;
if (ACURR(which) != old_attrib) {
context.botl = 1;
makeknown(obj->otyp);
obj->known = 1;
update_inventory();
}
observable = (old_attrib != ACURR(which));
/* same criteria as Ring_on() */
if (observable || !extremeattr(which))
learnring(obj, observable);
context.botl = 1;
break;
case RIN_INCREASE_ACCURACY: /* KMH */
u.uhitinc -= obj->spe;
@@ -898,13 +933,12 @@ boolean gone;
u.udaminc -= obj->spe;
break;
case RIN_PROTECTION:
/* might have forgotten it due to amnesia */
if (obj->spe) {
context.botl = 1;
makeknown(RIN_PROTECTION);
obj->known = 1;
update_inventory();
}
/* might have been put on while blind and we can now see
or perhaps been forgotten due to amnesia */
observable = (obj->spe != 0);
learnring(obj, observable);
if (obj->spe) find_ac(); /* updates botl */
break;
case RIN_PROTECTION_FROM_SHAPE_CHAN:
/* If you're no longer protected, let the chameleons
* change shape again -dgk