From: Pasi Kallinen Date: Sun, 20 Feb 2022 19:12:23 +0000 (+0200) Subject: Clean up some spell-related code X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=038ae7f984741ab1a6939b538bca9a0b6f8bb14d;p=nethack Clean up some spell-related code Add two helper functions and use those outside of spell.c, instead of iterating through all the spells. --- diff --git a/include/extern.h b/include/extern.h index 1a29793c5..a8327b1bf 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2536,6 +2536,8 @@ extern int tport_spell(int); extern void losespells(void); extern int dovspell(void); extern void initialspell(struct obj *); +extern boolean known_spell(short); +extern int spell_idx(short); /* ### steal.c ### */ diff --git a/src/apply.c b/src/apply.c index 4ef076110..ef73be941 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1761,15 +1761,8 @@ jump(int magic) /* 0=Physical, otherwise skill level */ coord cc; /* attempt "jumping" spell if hero has no innate jumping ability */ - if (!magic && !Jumping) { - int sp_no; - - for (sp_no = 0; sp_no < MAXSPELL; ++sp_no) - if (g.spl_book[sp_no].sp_id == NO_SPELL) - break; - else if (g.spl_book[sp_no].sp_id == SPE_JUMPING) - return spelleffects(sp_no, FALSE); - } + if (!magic && !Jumping && known_spell(SPE_JUMPING)) + return spelleffects(spell_idx(SPE_JUMPING), FALSE); if (!magic && (nolimbs(g.youmonst.data) || slithy(g.youmonst.data))) { /* normally (nolimbs || slithy) implies !Jumping, diff --git a/src/pray.c b/src/pray.c index 061b9f7b2..9eb97f36a 100644 --- a/src/pray.c +++ b/src/pray.c @@ -760,7 +760,6 @@ gcrownu(void) struct obj *obj; boolean already_exists, in_hand; short class_gift; - int sp_no; #define ok_wep(o) ((o) && ((o)->oclass == WEAPON_CLASS || is_weptool(o))) HSee_invisible |= FROMOUTSIDE; @@ -829,12 +828,8 @@ gcrownu(void) u.ugifts++; /* when getting a new book for known spell, enhance currently wielded weapon rather than the book */ - for (sp_no = 0; sp_no < MAXSPELL; sp_no++) - if (g.spl_book[sp_no].sp_id == class_gift) { - if (ok_wep(uwep)) - obj = uwep; /* to be blessed,&c */ - break; - } + if (known_spell(class_gift) && ok_wep(uwep)) + obj = uwep; /* to be blessed,&c */ } switch (u.ualign.type) { @@ -1189,17 +1184,14 @@ pleased(aligntyp g_align) /*FALLTHRU*/ case 6: { struct obj *otmp; - int sp_no, trycnt = u.ulevel + 1; + int trycnt = u.ulevel + 1; /* not yet known spells given preference over already known ones; also, try to grant a spell for which there is a skill slot */ otmp = mkobj(SPBOOK_no_NOVEL, TRUE); while (--trycnt > 0) { if (otmp->otyp != SPE_BLANK_PAPER) { - for (sp_no = 0; sp_no < MAXSPELL; sp_no++) - if (g.spl_book[sp_no].sp_id == otmp->otyp) - break; - if (sp_no == MAXSPELL + if (!known_spell(otmp->otyp) && !P_RESTRICTED(spell_skilltype(otmp->otyp))) break; /* usable, but not yet known */ } else { @@ -2007,21 +1999,9 @@ doturn(void) int once, range, xlev; if (!Role_if(PM_CLERIC) && !Role_if(PM_KNIGHT)) { - /* Try to use the "turn undead" spell. - * - * This used to be based on whether hero knows the name of the - * turn undead spellbook, but it's possible to know--and be able - * to cast--the spell while having lost the book ID to amnesia. - * (It also used to tell spelleffects() to cast at self?) - */ - int sp_no; - - for (sp_no = 0; sp_no < MAXSPELL; ++sp_no) { - if (g.spl_book[sp_no].sp_id == NO_SPELL) - break; - else if (g.spl_book[sp_no].sp_id == SPE_TURN_UNDEAD) - return spelleffects(sp_no, FALSE); - } + /* Try to use the "turn undead" spell. */ + if (known_spell(SPE_TURN_UNDEAD)) + return spelleffects(spell_idx(SPE_TURN_UNDEAD), FALSE); You("don't know how to turn undead!"); return ECMD_OK; } diff --git a/src/spell.c b/src/spell.c index 607d16597..6f05278ae 100644 --- a/src/spell.c +++ b/src/spell.c @@ -915,7 +915,7 @@ spelleffects(int spell, boolean atme) * (There's no duplication of messages; when the rejection takes * place in getspell(), we don't get called.) */ - if (rejectcasting()) { + if ((spell < 0) || rejectcasting()) { return ECMD_OK; /* no time elapses */ } @@ -1923,4 +1923,28 @@ initialspell(struct obj* obj) return; } +/* return TRUE if hero knows spell otyp, FALSE otherwise */ +boolean +known_spell(short otyp) +{ + int i; + + for (i = 0; (i < MAXSPELL) && (spellid(i) != NO_SPELL); i++) + if (spellid(i) == otyp) + return TRUE; + return FALSE; +} + +/* return index for spell otyp, or -1 if not found */ +int +spell_idx(short otyp) +{ + int i; + + for (i = 0; (i < MAXSPELL) && (spellid(i) != NO_SPELL); i++) + if (spellid(i) == otyp) + return i; + return -1; +} + /*spell.c*/ diff --git a/src/teleport.c b/src/teleport.c index 0aa28a82b..a01a09fcb 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -701,19 +701,18 @@ dotele( } if (!trap && !break_the_rules) { boolean castit = FALSE; - register int sp_no = 0, energy = 0; + int energy = 0; if (!Teleportation || (u.ulevel < (Role_if(PM_WIZARD) ? 8 : 12) && !can_teleport(g.youmonst.data))) { /* Try to use teleport away spell. */ - for (sp_no = 0; sp_no < MAXSPELL; sp_no++) - if (g.spl_book[sp_no].sp_id == SPE_TELEPORT_AWAY) - break; + boolean knownsp = known_spell(SPE_TELEPORT_AWAY); + /* casting isn't inhibited by being Stunned (...it ought to be) */ - castit = (sp_no < MAXSPELL && !Confusion); + castit = (knownsp && !Confusion); if (!castit && !break_the_rules) { You("%s.", - !Teleportation ? ((sp_no < MAXSPELL) + !Teleportation ? (knownsp ? "can't cast that spell" : "don't know that spell") : "are not able to teleport at will"); @@ -764,7 +763,7 @@ dotele( if (castit) { /* energy cost is deducted in spelleffects() */ exercise(A_WIS, TRUE); - if ((spelleffects(sp_no, TRUE) & ECMD_TIME)) + if ((spelleffects(spell_idx(SPE_TELEPORT_AWAY), TRUE) & ECMD_TIME)) return 1; else if (!break_the_rules) return 0;