From 9a42d70901a48cb977513e963a7058359bce99ce Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 3 Nov 2024 09:03:04 -0500 Subject: [PATCH] ranged attack in repertoire might not be used Commit 22884522, ported (from Sporkhack, Evilhack), added the ability for monsters to maintain awareness of player resistances that they observed. Since they will refrain from using a ranged attack that they deem futile, take the specific monster's seen_resistance field into consideration when choosing code paths based on the availability of ranged attacks. Resolves #1307 --- include/extern.h | 5 +++++ src/mhitu.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ src/monmove.c | 5 +++-- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/include/extern.h b/include/extern.h index 7eaa68e65..8422224f4 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1485,6 +1485,11 @@ extern int gazemu(struct monst *, struct attack *) NONNULLARG12; extern void mdamageu(struct monst *, int) NONNULLARG1; extern int could_seduce(struct monst *, struct monst *, struct attack *) NONNULLARG12; extern int doseduce(struct monst *) NONNULLARG1; +extern boolean mon_avoiding_this_attack(struct monst *, int) NONNULLARG1; +/* extern boolean ranged_attk_assessed(struct monst *mtmp, + boolean (*assessfunct)(struct monst *, int)) NONNULLARG1; +*/ +extern boolean ranged_attk_available(struct monst *mtmp) NONNULLARG1; /* ### minion.c ### */ diff --git a/src/mhitu.c b/src/mhitu.c index 14b453147..8a442faa1 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -2305,6 +2305,62 @@ assess_dmg(struct monst *mtmp, int tmp) return M_ATTK_HIT; } +#if 0 +/* returns True if monster has a range attack in its repertoire + that it will actually utilize. Caller provides the assessment + callback (optional). Callback returns 0 if the attack is + active */ + +boolean ranged_attk_assessed( +struct monst *mtmp, +boolean (*assessfunc)(struct monst *, int)) +{ + int i; + struct permonst *ptr = mtmp->data; + + for (i = 0; i < NATTK; i++) + if (DISTANCE_ATTK_TYPE(ptr->mattk[i].aatyp)) { + if (!assessfunc || (*assessfunc)(mtmp, i) == 0) + return TRUE; + } + return FALSE; +} +#endif + +/* can be used as ranged_attk_assessed() callback. + Returns TRUE if monster is avoiding use of this attack */ +boolean +mon_avoiding_this_attack(struct monst *mtmp, int attkidx) +{ + struct permonst *ptr = mtmp->data; + int typ = -1; + + if (attkidx >= 0 + && (typ = get_atkdam_type(ptr->mattk[attkidx].adtyp)) >= 0 + && m_seenres(mtmp, cvt_adtyp_to_mseenres(typ))) + return TRUE; + return FALSE; +} + +/* + * This would be equivalent to: + * ranged_attk_assessed(mtmp, mon_avoiding_this_attack) + * but without the added assessment function call overhead. + */ +boolean ranged_attk_available(struct monst *mtmp) +{ + int i, typ = -1; + struct permonst *ptr = mtmp->data; + + for (i = 0; i < NATTK; i++) { + if (DISTANCE_ATTK_TYPE(ptr->mattk[i].aatyp) + && (typ = get_atkdam_type(ptr->mattk[i].adtyp)) >= 0 + && m_seenres(mtmp, cvt_adtyp_to_mseenres(typ)) == 0) + return TRUE; + } + return FALSE; +} + /* FIXME: * sequencing issue: a monster's attack might cause poly'd hero * to revert to normal form. The messages for passive counterattack diff --git a/src/monmove.c b/src/monmove.c index a56b14fba..dc343d333 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -910,7 +910,8 @@ dochug(struct monst *mtmp) return 0; /* Monsters can move and then shoot on same turn; our hero can't. Is that fair? */ - if (!nearby && (ranged_attk(mdat) + if (!nearby + && (ranged_attk_available(mtmp) || attacktype(mdat, AT_WEAP) || find_offensive(mtmp))) break; @@ -1159,7 +1160,7 @@ m_balks_at_approaching(struct monst *mtmp) return TRUE; /* can attack from distance, and hp loss or attack not used */ - if (ranged_attk(mtmp->data) + if (ranged_attk_available(mtmp) && ((mtmp->mhp < (mtmp->mhpmax+1) / 3) || !mtmp->mspec_used)) return TRUE;