From d6cbaca654eba33dc08a53ae143bb41f6124bbb4 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Mon, 23 Mar 2026 11:42:51 +0200 Subject: [PATCH] Reorganize mcastu code Merge the two different enums, so all monster spells are in one list. This should have no functional difference, but cleans up the code a bit. --- src/mcastu.c | 350 +++++++++++++++++++++++---------------------------- 1 file changed, 155 insertions(+), 195 deletions(-) diff --git a/src/mcastu.c b/src/mcastu.c index bffe7d790..605fb1ab5 100644 --- a/src/mcastu.c +++ b/src/mcastu.c @@ -5,44 +5,40 @@ #include "hack.h" -/* monster mage spells */ -enum mcast_mage_spells { - MGC_PSI_BOLT = 0, - MGC_CURE_SELF, - MGC_HASTE_SELF, - MGC_STUN_YOU, - MGC_DISAPPEAR, - MGC_WEAKEN_YOU, - MGC_DESTRY_ARMR, - MGC_CURSE_ITEMS, - MGC_AGGRAVATION, - MGC_SUMMON_MONS, - MGC_CLONE_WIZ, - MGC_DEATH_TOUCH -}; +enum mcast_spells { + MCAST_PSI_BOLT = 0, + MCAST_OPEN_WOUNDS, + MCAST_LIGHTNING, + MCAST_FIRE_PILLAR, + MCAST_GEYSER, + MCAST_DEATH_TOUCH, -/* monster cleric spells */ -enum mcast_cleric_spells { - CLC_OPEN_WOUNDS = 0, - CLC_CURE_SELF, - CLC_CONFUSE_YOU, - CLC_PARALYZE, - CLC_BLIND_YOU, - CLC_INSECTS, - CLC_CURSE_ITEMS, - CLC_LIGHTNING, - CLC_FIRE_PILLAR, - CLC_GEYSER + MCAST_CURE_SELF, + MCAST_HASTE_SELF, + MCAST_DISAPPEAR, + + MCAST_AGGRAVATION, + MCAST_STUN_YOU, + MCAST_WEAKEN_YOU, + MCAST_CONFUSE_YOU, + MCAST_PARALYZE, + MCAST_BLIND_YOU, + + MCAST_DESTRY_ARMR, + MCAST_CURSE_ITEMS, + + MCAST_INSECTS, + MCAST_SUMMON_MONS, + MCAST_CLONE_WIZ }; staticfn void cursetxt(struct monst *, boolean); -staticfn int choose_magic_spell(int); -staticfn int choose_clerical_spell(int); +staticfn int choose_magic_spell(struct monst *); +staticfn int choose_clerical_spell(struct monst *); staticfn int m_cure_self(struct monst *, int); -staticfn void cast_wizard_spell(struct monst *, int, int); -staticfn void cast_cleric_spell(struct monst *, int, int); -staticfn boolean is_undirected_spell(unsigned int, int); -staticfn boolean spell_would_be_useless(struct monst *, unsigned int, int); +staticfn void mcast_spell(struct monst *, int, int); +staticfn boolean is_undirected_spell(int); +staticfn boolean spell_would_be_useless(struct monst *, int); /* feedback when frustrated monster couldn't cast a spell */ staticfn void @@ -73,8 +69,10 @@ cursetxt(struct monst *mtmp, boolean undirected) /* convert a level-based random selection into a specific mage spell; inappropriate choices will be screened out by spell_would_be_useless() */ staticfn int -choose_magic_spell(int spellval) +choose_magic_spell(struct monst *mtmp) { + int spellval = rn2(mtmp->m_lev); + /* for 3.4.3 and earlier, val greater than 22 selected default spell */ while (spellval > 24 && rn2(25)) spellval = rn2(spellval); @@ -83,52 +81,54 @@ choose_magic_spell(int spellval) case 24: case 23: if (Antimagic || Hallucination) - return MGC_PSI_BOLT; + return MCAST_PSI_BOLT; FALLTHROUGH; /*FALLTHRU*/ case 22: case 21: case 20: - return MGC_DEATH_TOUCH; + return MCAST_DEATH_TOUCH; case 19: case 18: - return MGC_CLONE_WIZ; + return MCAST_CLONE_WIZ; case 17: case 16: case 15: - return MGC_SUMMON_MONS; + return MCAST_SUMMON_MONS; case 14: case 13: - return MGC_AGGRAVATION; + return MCAST_AGGRAVATION; case 12: case 11: case 10: - return MGC_CURSE_ITEMS; + return MCAST_CURSE_ITEMS; case 9: case 8: - return MGC_DESTRY_ARMR; + return MCAST_DESTRY_ARMR; case 7: case 6: - return MGC_WEAKEN_YOU; + return MCAST_WEAKEN_YOU; case 5: case 4: - return MGC_DISAPPEAR; + return MCAST_DISAPPEAR; case 3: - return MGC_STUN_YOU; + return MCAST_STUN_YOU; case 2: - return MGC_HASTE_SELF; + return MCAST_HASTE_SELF; case 1: - return MGC_CURE_SELF; + return MCAST_CURE_SELF; case 0: default: - return MGC_PSI_BOLT; + return MCAST_PSI_BOLT; } } /* convert a level-based random selection into a specific cleric spell */ staticfn int -choose_clerical_spell(int spellnum) +choose_clerical_spell(struct monst *mtmp) { + int spellnum = rn2(mtmp->m_lev); + /* for 3.4.3 and earlier, num greater than 13 selected the default spell */ while (spellnum > 15 && rn2(16)) @@ -138,34 +138,34 @@ choose_clerical_spell(int spellnum) case 15: case 14: if (rn2(3)) - return CLC_OPEN_WOUNDS; + return MCAST_OPEN_WOUNDS; FALLTHROUGH; /*FALLTHRU*/ case 13: - return CLC_GEYSER; + return MCAST_GEYSER; case 12: - return CLC_FIRE_PILLAR; + return MCAST_FIRE_PILLAR; case 11: - return CLC_LIGHTNING; + return MCAST_LIGHTNING; case 10: case 9: - return CLC_CURSE_ITEMS; + return MCAST_CURSE_ITEMS; case 8: - return CLC_INSECTS; + return MCAST_INSECTS; case 7: case 6: - return CLC_BLIND_YOU; + return MCAST_BLIND_YOU; case 5: case 4: - return CLC_PARALYZE; + return MCAST_PARALYZE; case 3: case 2: - return CLC_CONFUSE_YOU; + return MCAST_CONFUSE_YOU; case 1: - return CLC_CURE_SELF; + return MCAST_CURE_SELF; case 0: default: - return CLC_OPEN_WOUNDS; + return MCAST_OPEN_WOUNDS; } } @@ -200,15 +200,14 @@ castmu( int cnt = 40; do { - spellnum = rn2(ml); if (mattk->adtyp == AD_SPEL) - spellnum = choose_magic_spell(spellnum); + spellnum = choose_magic_spell(mtmp); else - spellnum = choose_clerical_spell(spellnum); + spellnum = choose_clerical_spell(mtmp); /* not trying to attack? don't allow directed spells */ if (!thinks_it_foundyou) { - if (!is_undirected_spell(mattk->adtyp, spellnum) - || spell_would_be_useless(mtmp, mattk->adtyp, spellnum)) { + if (!is_undirected_spell(spellnum) + || spell_would_be_useless(mtmp, spellnum)) { if (foundyou) impossible( "spellcasting monster found you and doesn't know it?"); @@ -217,7 +216,7 @@ castmu( break; } } while (--cnt > 0 - && spell_would_be_useless(mtmp, mattk->adtyp, spellnum)); + && spell_would_be_useless(mtmp, spellnum)); if (cnt == 0) return M_ATTK_MISS; } @@ -225,10 +224,12 @@ castmu( /* monster unable to cast spells? */ if (mtmp->mcan || mtmp->mspec_used || !ml || m_seenres(mtmp, cvt_adtyp_to_mseenres(mattk->adtyp))) { - cursetxt(mtmp, is_undirected_spell(mattk->adtyp, spellnum)); + cursetxt(mtmp, is_undirected_spell(spellnum)); return M_ATTK_MISS; } + debugpline3("castmu:%s,lvl:%i,spell:%i", noit_Monnam(mtmp), ml, spellnum); + if (mattk->adtyp == AD_SPEL || mattk->adtyp == AD_CLRC) { /* monst->m_lev is unsigned (uchar), monst->mspec_used is int */ mtmp->mspec_used = (int) ((mtmp->m_lev < 8) ? (10 - mtmp->m_lev) : 2); @@ -245,7 +246,7 @@ castmu( * for fire mis-aimed at ice. */ if (!foundyou && thinks_it_foundyou - && !is_undirected_spell(mattk->adtyp, spellnum)) { + && !is_undirected_spell(spellnum)) { pline_mon(mtmp, "%s casts a spell at %s!", canseemon(mtmp) ? Monnam(mtmp) : "Something", is_waterwall(mtmp->mux, mtmp->muy) ? "empty water" @@ -262,10 +263,10 @@ castmu( } return M_ATTK_MISS; } - if (canspotmon(mtmp) || !is_undirected_spell(mattk->adtyp, spellnum)) { + if (canspotmon(mtmp) || !is_undirected_spell(spellnum)) { pline_mon(mtmp, "%s casts a spell%s!", canspotmon(mtmp) ? Monnam(mtmp) : "Something", - is_undirected_spell(mattk->adtyp, spellnum) ? "" + is_undirected_spell(spellnum) ? "" : (Invis && !perceives(mtmp->data) && !u_at(mtmp->mux, mtmp->muy)) ? " at a spot near you" @@ -344,10 +345,7 @@ castmu( break; case AD_SPEL: /* wizard spell */ case AD_CLRC: /* clerical spell */ - if (mattk->adtyp == AD_SPEL) - cast_wizard_spell(mtmp, dmg, spellnum); - else - cast_cleric_spell(mtmp, dmg, spellnum); + mcast_spell(mtmp, dmg, spellnum); dmg = 0; /* done by the spell casting functions */ break; } /* switch */ @@ -446,20 +444,22 @@ death_inflicted_by( and spell_would_be_useless(). */ staticfn void -cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) +mcast_spell(struct monst *mtmp, int dmg, int spellnum) { + int orig_dmg = 0; + if (dmg < 0) { - impossible("monster cast wizard spell (%d) with negative dmg (%d)?", + impossible("monster cast spell (%d) with negative dmg (%d)?", spellnum, dmg); return; } - if (dmg == 0 && !is_undirected_spell(AD_SPEL, spellnum)) { + if (dmg == 0 && !is_undirected_spell(spellnum)) { impossible("cast directed wizard spell (%d) with dmg=0?", spellnum); return; } switch (spellnum) { - case MGC_DEATH_TOUCH: + case MCAST_DEATH_TOUCH: pline("Oh no, %s's using the touch of death!", mhe(mtmp)); if (nonliving(gy.youmonst.data) || is_demon(gy.youmonst.data)) { You("seem no deader than before."); @@ -479,7 +479,7 @@ cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) } dmg = 0; break; - case MGC_CLONE_WIZ: + case MCAST_CLONE_WIZ: if (mtmp->iswiz && svc.context.no_of_wizards == 1) { pline("Double Trouble..."); clonewiz(); @@ -487,7 +487,7 @@ cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) } else impossible("bad wizard cloning?"); break; - case MGC_SUMMON_MONS: { + case MCAST_SUMMON_MONS: { int count = nasty(mtmp); if (!count) { @@ -515,17 +515,17 @@ cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) dmg = 0; break; } - case MGC_AGGRAVATION: + case MCAST_AGGRAVATION: You_feel("that monsters are aware of your presence."); aggravate(); dmg = 0; break; - case MGC_CURSE_ITEMS: + case MCAST_CURSE_ITEMS: You_feel("as if you need some help."); rndcurse(); dmg = 0; break; - case MGC_DESTRY_ARMR: + case MCAST_DESTRY_ARMR: if (Antimagic) { shieldeff(u.ux, u.uy); monstseesu(M_SEEN_MAGR); @@ -539,7 +539,7 @@ cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) } dmg = 0; break; - case MGC_WEAKEN_YOU: /* drain strength */ + case MCAST_WEAKEN_YOU: /* drain strength */ if (Antimagic) { shieldeff(u.ux, u.uy); monstseesu(M_SEEN_MAGR); @@ -561,7 +561,7 @@ cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) } dmg = 0; break; - case MGC_DISAPPEAR: /* makes self invisible */ + case MCAST_DISAPPEAR: /* makes self invisible */ if (!mtmp->minvis && !mtmp->invis_blkd) { if (canseemon(mtmp)) pline_mon(mtmp, "%s suddenly %s!", Monnam(mtmp), @@ -573,7 +573,7 @@ cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) } else impossible("no reason for monster to cast disappear spell?"); break; - case MGC_STUN_YOU: + case MCAST_STUN_YOU: if (Antimagic || Free_action) { shieldeff(u.ux, u.uy); monstseesu(M_SEEN_MAGR); @@ -590,14 +590,14 @@ cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) } dmg = 0; break; - case MGC_HASTE_SELF: + case MCAST_HASTE_SELF: mon_adjust_speed(mtmp, 1, (struct obj *) 0); dmg = 0; break; - case MGC_CURE_SELF: + case MCAST_CURE_SELF: dmg = m_cure_self(mtmp, dmg); break; - case MGC_PSI_BOLT: + case MCAST_PSI_BOLT: /* prior to 3.4.0 Antimagic was setting the damage to 1--this made the spell virtually harmless to players with magic res. */ if (Antimagic) { @@ -616,35 +616,7 @@ cast_wizard_spell(struct monst *mtmp, int dmg, int spellnum) else Your("%s suddenly aches very painfully!", body_part(HEAD)); break; - default: - impossible("mcastu: invalid magic spell (%d)", spellnum); - dmg = 0; - break; - } - - if (dmg) - mdamageu(mtmp, dmg); -} - -DISABLE_WARNING_FORMAT_NONLITERAL - -staticfn void -cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) -{ - int orig_dmg = 0; - - if (dmg < 0) { - impossible("monster cast cleric spell (%d) with negative dmg (%d)?", - spellnum, dmg); - return; - } - if (dmg == 0 && !is_undirected_spell(AD_CLRC, spellnum)) { - impossible("cast directed cleric spell (%d) with dmg=0?", spellnum); - return; - } - - switch (spellnum) { - case CLC_GEYSER: + case MCAST_GEYSER: /* this is physical damage (force not heat), * not magical damage or fire damage */ @@ -657,7 +629,7 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) water_damage_chain(level.objects[u.ux][u.uy], TRUE); #endif break; - case CLC_FIRE_PILLAR: + case MCAST_FIRE_PILLAR: pline("A pillar of fire strikes all around you!"); orig_dmg = dmg = d(8, 6); if (Fire_resistance) { @@ -677,7 +649,7 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) /* burn up flammable items on the floor, melt ice terrain */ mon_spell_hits_spot(mtmp, AD_FIRE, u.ux, u.uy); break; - case CLC_LIGHTNING: { + case MCAST_LIGHTNING: { boolean reflects; Soundeffect(se_bolt_of_lightning, 80); @@ -708,12 +680,7 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) (void) flashburn((long) rnd(100), TRUE); break; } - case CLC_CURSE_ITEMS: - You_feel("as if you need some help."); - rndcurse(); - dmg = 0; - break; - case CLC_INSECTS: { + case MCAST_INSECTS: { /* Try for insects, and if there are none left, go for (sticks to) snakes. -3. */ struct permonst *pm = mkclass(S_ANT, 0); @@ -788,13 +755,15 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) } else { fmt = "%s summons %s!"; } - if (fmt) + if (fmt) { + DISABLE_WARNING_FORMAT_NONLITERAL; pline_mon(mtmp, fmt, Monnam(mtmp), what); - + RESTORE_WARNING_FORMAT_NONLITERAL; + } dmg = 0; break; } - case CLC_BLIND_YOU: + case MCAST_BLIND_YOU: /* note: resists_blnd() doesn't apply here */ if (!Blinded) { int num_eyes = eyecount(gy.youmonst.data); @@ -809,7 +778,7 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) } else impossible("no reason for monster to cast blindness spell?"); break; - case CLC_PARALYZE: + case MCAST_PARALYZE: if (Antimagic || Free_action) { shieldeff(u.ux, u.uy); monstseesu(M_SEEN_MAGR); @@ -829,7 +798,7 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) gn.nomovemsg = 0; dmg = 0; break; - case CLC_CONFUSE_YOU: + case MCAST_CONFUSE_YOU: if (Antimagic) { shieldeff(u.ux, u.uy); monstseesu(M_SEEN_MAGR); @@ -849,10 +818,7 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) } dmg = 0; break; - case CLC_CURE_SELF: - dmg = m_cure_self(mtmp, dmg); - break; - case CLC_OPEN_WOUNDS: + case MCAST_OPEN_WOUNDS: if (Antimagic) { shieldeff(u.ux, u.uy); monstseesu(M_SEEN_MAGR); @@ -870,7 +836,7 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) Your("body is covered with painful wounds!"); break; default: - impossible("mcastu: invalid clerical spell (%d)", spellnum); + impossible("mcastu: invalid magic spell (%d)", spellnum); dmg = 0; break; } @@ -879,38 +845,27 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum) mdamageu(mtmp, dmg); } -RESTORE_WARNING_FORMAT_NONLITERAL - staticfn boolean -is_undirected_spell(unsigned int adtyp, int spellnum) +is_undirected_spell(int spellnum) { - if (adtyp == AD_SPEL) { - switch (spellnum) { - case MGC_CLONE_WIZ: - case MGC_SUMMON_MONS: - case MGC_AGGRAVATION: - case MGC_DISAPPEAR: - case MGC_HASTE_SELF: - case MGC_CURE_SELF: - return TRUE; - default: - break; - } - } else if (adtyp == AD_CLRC) { - switch (spellnum) { - case CLC_INSECTS: - case CLC_CURE_SELF: - return TRUE; - default: - break; - } + switch (spellnum) { + case MCAST_CLONE_WIZ: + case MCAST_SUMMON_MONS: + case MCAST_AGGRAVATION: + case MCAST_DISAPPEAR: + case MCAST_HASTE_SELF: + case MCAST_CURE_SELF: + case MCAST_INSECTS: + return TRUE; + default: + break; } return FALSE; } /* Some spells are useless under some circumstances. */ staticfn boolean -spell_would_be_useless(struct monst *mtmp, unsigned int adtyp, int spellnum) +spell_would_be_useless(struct monst *mtmp, int spellnum) { /* Some spells don't require the player to really be there and can be cast * by the monster when you're invisible, yet still shouldn't be cast when @@ -920,58 +875,63 @@ spell_would_be_useless(struct monst *mtmp, unsigned int adtyp, int spellnum) */ boolean mcouldseeu = couldsee(mtmp->mx, mtmp->my); - if (adtyp == AD_SPEL) { + switch (spellnum) { + case MCAST_CLONE_WIZ: + /* only the Wizard is allowed to clone himself */ + if (!mtmp->iswiz || svc.context.no_of_wizards > 1) + return TRUE; + if (!mcouldseeu) + return TRUE; + break; + case MCAST_SUMMON_MONS: + /* don't summon monsters if it doesn't think you're around */ + if (!mcouldseeu || mtmp->mpeaceful) + return TRUE; + break; + case MCAST_AGGRAVATION: /* aggravate monsters, etc. won't be cast by peaceful monsters */ - if (mtmp->mpeaceful - && (spellnum == MGC_AGGRAVATION || spellnum == MGC_SUMMON_MONS - || spellnum == MGC_CLONE_WIZ)) + if (!mcouldseeu || mtmp->mpeaceful) return TRUE; + /* aggravation (global wakeup) when everyone is already active */ + /* if nothing needs to be awakened then this spell is useless + but caster might not realize that [chance to pick it then + must be very small otherwise caller's many retry attempts + will eventually end up picking it too often] */ + if (!has_aggravatables(mtmp)) + return rn2(100) ? TRUE : FALSE; + break; + case MCAST_HASTE_SELF: /* haste self when already fast */ - if (mtmp->permspeed == MFAST && spellnum == MGC_HASTE_SELF) + if (mtmp->permspeed == MFAST) return TRUE; + break; + case MCAST_DISAPPEAR: /* invisibility when already invisible */ - if ((mtmp->minvis || mtmp->invis_blkd) && spellnum == MGC_DISAPPEAR) + if (mtmp->minvis || mtmp->invis_blkd) return TRUE; /* peaceful monster won't cast invisibility if you can't see invisible, same as when monsters drink potions of invisibility. This doesn't really make a lot of sense, but lets the player avoid hitting peaceful monsters by mistake */ - if (mtmp->mpeaceful && !See_invisible && spellnum == MGC_DISAPPEAR) + if (mtmp->mpeaceful && !See_invisible) return TRUE; + break; + case MCAST_CURE_SELF: /* healing when already healed */ - if (mtmp->mhp == mtmp->mhpmax && spellnum == MGC_CURE_SELF) + if (mtmp->mhp == mtmp->mhpmax) return TRUE; - /* don't summon monsters if it doesn't think you're around */ - if (!mcouldseeu && (spellnum == MGC_SUMMON_MONS - || (!mtmp->iswiz && spellnum == MGC_CLONE_WIZ))) + break; + case MCAST_INSECTS: + /* summon insects/sticks to snakes won't be cast by peaceful monsters */ + if (!mcouldseeu || mtmp->mpeaceful) return TRUE; - if ((!mtmp->iswiz || svc.context.no_of_wizards > 1) - && spellnum == MGC_CLONE_WIZ) - return TRUE; - /* aggravation (global wakeup) when everyone is already active */ - if (spellnum == MGC_AGGRAVATION) { - /* if nothing needs to be awakened then this spell is useless - but caster might not realize that [chance to pick it then - must be very small otherwise caller's many retry attempts - will eventually end up picking it too often] */ - if (!has_aggravatables(mtmp)) - return rn2(100) ? TRUE : FALSE; - } - } else if (adtyp == AD_CLRC) { - /* summon insects/sticks to snakes won't be cast by peaceful monsters - */ - if (mtmp->mpeaceful && spellnum == CLC_INSECTS) - return TRUE; - /* healing when already healed */ - if (mtmp->mhp == mtmp->mhpmax && spellnum == CLC_CURE_SELF) - return TRUE; - /* don't summon insects if it doesn't think you're around */ - if (!mcouldseeu && spellnum == CLC_INSECTS) - return TRUE; - /* blindness spell on blinded player */ - if (Blinded && spellnum == CLC_BLIND_YOU) + break; + case MCAST_BLIND_YOU: + if (Blinded) return TRUE; + break; + default: } return FALSE; }