diff --git a/src/pray.c b/src/pray.c index cc1a5d07a..034aa27eb 100644 --- a/src/pray.c +++ b/src/pray.c @@ -5,6 +5,7 @@ #include "hack.h" static int prayer_done(void); +static void maybe_turn_mon_iter(struct monst *); static struct obj *worst_cursed_item(void); static int in_trouble(void); static void fix_curse_trouble(struct obj *, const char *); @@ -101,6 +102,11 @@ static const char *const godvoices[] = { #define on_shrine() ((levl[u.ux][u.uy].altarmask & AM_SHRINE) != 0) #define a_align(x, y) ((aligntyp) Amask2align(levl[x][y].altarmask & AM_MASK)) +/* used by turn undead iteration function; always reinitialized + before iterating that, so don't need to be globals */ +static int turn_undead_range; +static int turn_undead_msg_cnt; + /* critically low hit points if hp <= 5 or hp <= maxhp/N for some N */ boolean critically_low_hp( @@ -2247,14 +2253,73 @@ prayer_done(void) /* M. Stephenson (1.0.3b) */ return 1; } +/* iterable for undead turning by priest/knight */ +static void +maybe_turn_mon_iter(struct monst *mtmp) +{ + /* 3.6.3: used to use cansee() here but the purpose is to prevent + #turn operating through walls, not to require that the hero be + able to see the target location */ + if (!couldsee(mtmp->mx, mtmp->my) + || mdistu(mtmp) > turn_undead_range) + return; + + if (!mtmp->mpeaceful + && (is_undead(mtmp->data) || is_vampshifter(mtmp) + || (is_demon(mtmp->data) && (u.ulevel > (MAXULEV / 2))))) { + mtmp->msleeping = 0; + if (Confusion) { + if (!turn_undead_msg_cnt++) + pline("Unfortunately, your voice falters."); + mtmp->mflee = 0; + mtmp->mfrozen = 0; + mtmp->mcanmove = 1; + } else if (!resist(mtmp, '\0', 0, TELL)) { + int xlev = 6; + + switch (mtmp->data->mlet) { + /* this is intentional, lichs are tougher + than zombies. */ + case S_LICH: + xlev += 2; + /*FALLTHRU*/ + case S_GHOST: + xlev += 2; + /*FALLTHRU*/ + case S_VAMPIRE: + xlev += 2; + /*FALLTHRU*/ + case S_WRAITH: + xlev += 2; + /*FALLTHRU*/ + case S_MUMMY: + xlev += 2; + /*FALLTHRU*/ + case S_ZOMBIE: + if (u.ulevel >= xlev && !resist(mtmp, '\0', 0, NOTELL)) { + if (u.ualign.type == A_CHAOTIC) { + mtmp->mpeaceful = 1; + set_malign(mtmp); + } else { /* damn them */ + killed(mtmp); + } + break; + } /* else flee */ + /*FALLTHRU*/ + default: + monflee(mtmp, 0, FALSE, TRUE); + break; + } + } + } +} + /* #turn command */ int doturn(void) { /* Knights & Priest(esse)s only please */ - struct monst *mtmp, *mtmp2; const char *Gname; - int once, range, xlev; if (!Role_if(PM_CLERIC) && !Role_if(PM_KNIGHT)) { /* Try to use the "turn undead" spell. */ @@ -2299,68 +2364,11 @@ doturn(void) exercise(A_WIS, TRUE); /* note: does not perform unturn_dead() on victims' inventories */ - range = BOLT_LIM + (u.ulevel / 5); /* 8 to 14 */ - range *= range; - once = 0; - for (mtmp = fmon; mtmp; mtmp = mtmp2) { - mtmp2 = mtmp->nmon; - if (DEADMONSTER(mtmp)) - continue; - /* 3.6.3: used to use cansee() here but the purpose is to prevent - #turn operating through walls, not to require that the hero be - able to see the target location */ - if (!couldsee(mtmp->mx, mtmp->my) - || mdistu(mtmp) > range) - continue; + turn_undead_range = BOLT_LIM + (u.ulevel / 5); /* 8 to 14 */ + turn_undead_range *= turn_undead_range; + turn_undead_msg_cnt = 0; - if (!mtmp->mpeaceful - && (is_undead(mtmp->data) || is_vampshifter(mtmp) - || (is_demon(mtmp->data) && (u.ulevel > (MAXULEV / 2))))) { - mtmp->msleeping = 0; - if (Confusion) { - if (!once++) - pline("Unfortunately, your voice falters."); - mtmp->mflee = 0; - mtmp->mfrozen = 0; - mtmp->mcanmove = 1; - } else if (!resist(mtmp, '\0', 0, TELL)) { - xlev = 6; - switch (mtmp->data->mlet) { - /* this is intentional, lichs are tougher - than zombies. */ - case S_LICH: - xlev += 2; - /*FALLTHRU*/ - case S_GHOST: - xlev += 2; - /*FALLTHRU*/ - case S_VAMPIRE: - xlev += 2; - /*FALLTHRU*/ - case S_WRAITH: - xlev += 2; - /*FALLTHRU*/ - case S_MUMMY: - xlev += 2; - /*FALLTHRU*/ - case S_ZOMBIE: - if (u.ulevel >= xlev && !resist(mtmp, '\0', 0, NOTELL)) { - if (u.ualign.type == A_CHAOTIC) { - mtmp->mpeaceful = 1; - set_malign(mtmp); - } else { /* damn them */ - killed(mtmp); - } - break; - } /* else flee */ - /*FALLTHRU*/ - default: - monflee(mtmp, 0, FALSE, TRUE); - break; - } - } - } - } + iter_mons(maybe_turn_mon_iter); /* * There is no detrimental effect on self for successful #turn