Adjust seenres on visible gear removal

If a monster sees you remove some piece of gear that grants a
resistance, it will remove that resistance from its list of remembered
resistances and be willing to try attacking you with that adtyp again.
This avoids the situation where you put on a ring of cold, get hit with
one cold attack, and then can remove it because all the monsters nearby
will permanently remember you as being cold resistant (but even after
this change a wily hero could still step into a niche and do it without
any monsters seeing, so trick them into thinking she's still cold
resistant...).  The hero could still be resistant if there were multiple
sources to begin with, of course, but the monsters will test it and
learn that again if necessary.

It's a little weird that the monsters can recognize the intrinsic
granted by the item being removed, but they display knowledge of
unidentified (by the hero) objects in many other circumstances too, so I
hope it's forgivable in the pursuit of having them act more cleverly
about resuming previously-resisted attacks like this.  Another approach
that avoids the gear recognition, blanking seenres on any gear change,
can result in odd situations like orcs treating their own cloaks as
potential sources of many different resistances, which also seems silly.
This commit is contained in:
Michael Meyer
2023-08-25 14:21:06 -04:00
committed by Pasi Kallinen
parent 99683d94b4
commit 38cda5ad52
4 changed files with 42 additions and 1 deletions

View File

@@ -1694,7 +1694,9 @@ extern const char *msummon_environ(struct permonst *, const char **);
extern const struct permonst *raceptr(struct monst *);
extern boolean olfaction(struct permonst *);
unsigned long cvt_adtyp_to_mseenres(uchar);
unsigned long cvt_prop_to_mseenres(uchar);
extern void monstseesu(unsigned long);
extern void monstunseesu(unsigned long);
extern boolean resist_conflict(struct monst *);
extern boolean mon_knows_traps(struct monst *, int);
extern void mon_learns_traps(struct monst *, int);

View File

@@ -88,7 +88,9 @@ enum m_seen_resistance {
#define m_seenres(mon, mask) ((mon)->seen_resistance & (mask))
#define m_setseenres(mon, mask) ((mon)->seen_resistance |= (mask))
#define m_clearseenres(mon, mask) ((mon)->seen_resistance &= ~(mask))
#define monstseesu_ad(adtyp) monstseesu(cvt_adtyp_to_mseenres(adtyp))
#define monstunseesu_prop(prop) monstunseesu(cvt_prop_to_mseenres(prop))
struct monst {
struct monst *nmon;

View File

@@ -1450,7 +1450,25 @@ cvt_adtyp_to_mseenres(uchar adtyp)
}
}
/* Monsters remember hero resisting effect M_SEEN_foo */
/* Convert property resistance to M_SEEN_bar */
unsigned long
cvt_prop_to_mseenres(uchar prop)
{
switch (prop) {
case ANTIMAGIC: return M_SEEN_MAGR;
case FIRE_RES: return M_SEEN_FIRE;
case COLD_RES: return M_SEEN_COLD;
case SLEEP_RES: return M_SEEN_SLEEP;
case DISINT_RES: return M_SEEN_DISINT;
case POISON_RES: return M_SEEN_POISON;
case SHOCK_RES: return M_SEEN_ELEC;
case ACID_RES: return M_SEEN_ACID;
case REFLECTING: return M_SEEN_REFL;
default: return M_SEEN_NOTHING;
}
}
/* Monsters in line of sight remember hero resisting effect M_SEEN_foo */
void
monstseesu(unsigned long seenres)
{
@@ -1464,6 +1482,20 @@ monstseesu(unsigned long seenres)
m_setseenres(mtmp, seenres);
}
/* Monsters in line of sight forget hero resistance to M_SEEN_foo */
void
monstunseesu(unsigned long seenres)
{
struct monst *mtmp;
if (seenres == M_SEEN_NOTHING || u.uswallow)
return;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
if (!DEADMONSTER(mtmp) && m_canseeu(mtmp))
m_clearseenres(mtmp, seenres);
}
/* Can monster resist conflict caused by hero?
High-CHA heroes will be able to 'convince' monsters

View File

@@ -71,6 +71,10 @@ setworn(struct obj *obj, long mask)
p = objects[oobj->otyp].oc_oprop;
u.uprops[p].extrinsic =
u.uprops[p].extrinsic & ~wp->w_mask;
/* if the hero removed an extrinsic-granting item,
nearby monsters will notice and attempt attacks of
that type again */
monstunseesu_prop(p);
if ((p = w_blocks(oobj, mask)) != 0)
u.uprops[p].blocked &= ~wp->w_mask;
if (oobj->oartifact)
@@ -132,6 +136,7 @@ setnotworn(struct obj *obj)
*(wp->w_obj) = (struct obj *) 0;
p = objects[obj->otyp].oc_oprop;
u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;
monstunseesu_prop(p); /* remove this extrinsic from seenres */
obj->owornmask &= ~wp->w_mask;
if (obj->oartifact)
set_artifact_intrinsic(obj, 0, wp->w_mask);