Skip to content

Commit

Permalink
ring discovery (trunk only)
Browse files Browse the repository at this point in the history
     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.
  • Loading branch information
nethack.rankin committed Jan 29, 2008
1 parent 89a8661 commit d8a45a5
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 33 deletions.
1 change: 1 addition & 0 deletions doc/fixes35.0
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions include/extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
28 changes: 28 additions & 0 deletions src/attrib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
100 changes: 67 additions & 33 deletions src/do_wear.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -751,20 +785,20 @@ 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();
}
break;
case RIN_LEVITATION:
if (!oldprop && !HLevitation) {
float_up();
makeknown(RIN_LEVITATION);
learnring(obj, TRUE);
spoteffects(FALSE); /* for sinks */
}
break;
Expand All @@ -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;
Expand All @@ -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;
}
}
Expand All @@ -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))
Expand Down Expand Up @@ -858,20 +894,20 @@ 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:
if (!Invis && !BInvis && !Blind) {
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;
Expand All @@ -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;
Expand All @@ -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
Expand Down

0 comments on commit d8a45a5

Please sign in to comment.