/*
 *  File:       spl-book.cc
 *  Summary:    Spellbook/Staff contents array and management functions
 *  Written by: Josh Fishman
 *
 *  Change History (most recent first):
 *
 *      24jun2000  jmf  Changes to many books; addition of Assassinations;
 *                      alteration of type-printout to match new bitfield.
 *  <1> 19mar2000  jmf  Created by taking stuff from dungeon.cc, spells0.cc,
 *                      spells.cc, shopping.cc
 */

#include "AppHdr.h"
#include "spl-book.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#ifdef DOS
#include <conio.h>
#endif

#include "externs.h"

#include "debug.h"
#include "delay.h"
#include "invent.h"
#include "itemname.h"
#include "items.h"
#include "it_use3.h"
#include "player.h"
#include "religion.h"
#include "spl-cast.h"
#include "spl-util.h"
#include "stuff.h"

static int spellbook_template_array[NUMBER_SPELLBOOKS][SPELLBOOK_SIZE] =
{
    // 0 - Minor Magic I
    {0,
     SPELL_MAGIC_DART,
     SPELL_SUMMON_SMALL_MAMMAL,
     SPELL_THROW_FLAME,
     SPELL_BLINK,
     SPELL_SLOW,
     SPELL_MEPHITIC_CLOUD,
     SPELL_CONJURE_FLAME,
     SPELL_NO_SPELL,
     },
    // 1 - Minor Magic II
    {0,
     SPELL_MAGIC_DART,
     SPELL_THROW_FROST,
     SPELL_BLINK,
     SPELL_STICKS_TO_SNAKES,
     SPELL_SLOW,
     SPELL_MEPHITIC_CLOUD,
     SPELL_OZOCUBUS_ARMOUR,
     SPELL_NO_SPELL,
     },
    // 2 - Minor Magic III
    {0,
     SPELL_MAGIC_DART,
     SPELL_SUMMON_SMALL_MAMMAL,
     SPELL_BLINK,
     SPELL_REPEL_MISSILES,
     SPELL_SLOW,
     SPELL_SUMMON_LARGE_MAMMAL,
     SPELL_MEPHITIC_CLOUD,
     SPELL_NO_SPELL,
     },
    // 3 - Book of Conjurations I - Fire and Earth
    {0,
     SPELL_MAGIC_DART,
     SPELL_THROW_FLAME,
     SPELL_STONE_ARROW,
     SPELL_CONJURE_FLAME,
     SPELL_BOLT_OF_MAGMA,
     SPELL_FIREBALL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 4 - Book of Conjurations II - Air and Ice
    {0,
     SPELL_MAGIC_DART,
     SPELL_THROW_FROST,
     SPELL_MEPHITIC_CLOUD,
     SPELL_DISCHARGE,
     SPELL_BOLT_OF_COLD,
     SPELL_FREEZING_CLOUD,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 5 - Book of Flames
    {0,
     SPELL_FLAME_TONGUE,
     SPELL_THROW_FLAME,
     SPELL_CONJURE_FLAME,
     SPELL_STICKY_FLAME,
     SPELL_BOLT_OF_FIRE,
     SPELL_FIREBALL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 6 - Book of Frost
    {0,
     SPELL_FREEZE,
     SPELL_THROW_FROST,
     SPELL_OZOCUBUS_ARMOUR,
     SPELL_ICE_BOLT,
     SPELL_SUMMON_ICE_BEAST,
     SPELL_FREEZING_CLOUD,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 7 - Book of Summonings
    {0,
     SPELL_ABJURATION_I,
     SPELL_RECALL,
     SPELL_SUMMON_LARGE_MAMMAL,
     SPELL_SHADOW_CREATURES,
     SPELL_SUMMON_WRAITHS,
     SPELL_SUMMON_HORRIBLE_THINGS,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 8 - Book of Fire
    {0,
     SPELL_EVAPORATE,
     SPELL_FIRE_BRAND,
     SPELL_SUMMON_ELEMENTAL,
     SPELL_BOLT_OF_MAGMA,
     SPELL_DELAYED_FIREBALL,
     SPELL_IGNITE_POISON,
     SPELL_RING_OF_FLAMES,
     SPELL_NO_SPELL,
     },
    // 9 - Book of Ice
    {0,
     SPELL_FREEZING_AURA,
     SPELL_SLEEP,
     SPELL_CONDENSATION_SHIELD,
     SPELL_BOLT_OF_COLD,
     SPELL_OZOCUBUS_REFRIGERATION,
     SPELL_MASS_SLEEP,
     SPELL_SIMULACRUM,
     SPELL_NO_SPELL,
     },

    // 10 - Book of Surveyances
    {0,
     SPELL_DETECT_SECRET_DOORS,
     SPELL_DETECT_TRAPS,
     SPELL_DETECT_ITEMS,
     SPELL_MAGIC_MAPPING,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL
     },
    // 11 - Book of Spatial Translocations
    {0,
     SPELL_APPORTATION,
     SPELL_BLINK,
     SPELL_RECALL,
     SPELL_TELEPORT_OTHER,
     SPELL_TELEPORT_SELF,
     SPELL_CONTROL_TELEPORT,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 12 - Book of Enchantments (fourth one)
    {0,
     SPELL_LEVITATION,
     SPELL_SELECTIVE_AMNESIA,
     SPELL_REMOVE_CURSE,
     SPELL_CAUSE_FEAR,
     SPELL_EXTENSION,
     SPELL_DEFLECT_MISSILES,
     SPELL_HASTE,
     SPELL_NO_SPELL,
     },
    // 13 - Young Poisoner's Handbook
    {0,
     SPELL_STING,
     SPELL_CURE_POISON_II,
     SPELL_MEPHITIC_CLOUD,
     SPELL_POISON_WEAPON,
     SPELL_VENOM_BOLT,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 14 - Book of the Tempests
    {0,
     SPELL_DISCHARGE,
     SPELL_LIGHTNING_BOLT,
     SPELL_FIREBALL,
     SPELL_SHATTER,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 15 - Book of Death
    {0,
     SPELL_CORPSE_ROT,
     SPELL_BONE_SHARDS,
     SPELL_LETHAL_INFUSION,
     SPELL_AGONY,
     SPELL_BOLT_OF_DRAINING,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 16 - Book of Hinderance
    {0,
     SPELL_CONFUSING_TOUCH,
     SPELL_SLOW,
     SPELL_CONFUSE,
     SPELL_PARALYZE,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 17 - Book of Changes
    {0,
     SPELL_FULSOME_DISTILLATION,
     SPELL_STICKS_TO_SNAKES,
     SPELL_EVAPORATE,
     SPELL_SPIDER_FORM,
     SPELL_ICE_FORM,
     SPELL_DIG,
     SPELL_BLADE_HANDS,
     SPELL_NO_SPELL,
     },
    // 18 - Book of Transfigurations
    {0,
     SPELL_SANDBLAST,
     SPELL_POLYMORPH_OTHER,
     SPELL_STATUE_FORM,
     SPELL_ALTER_SELF,
     SPELL_DRAGON_FORM,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 19 - Book of Practical Magic
    {0,
     SPELL_PROJECTED_NOISE,
     SPELL_SELECTIVE_AMNESIA,
     SPELL_DETECT_CURSE,
     SPELL_DIG,
     SPELL_REMOVE_CURSE,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },

    // 20 - Book of War Chants
    {0,
     SPELL_FIRE_BRAND,
     SPELL_FREEZING_AURA,
     SPELL_REPEL_MISSILES,
     SPELL_BERSERKER_RAGE,
     SPELL_REGENERATION,
     SPELL_HASTE,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 21 - Book of Clouds
    {0,
     SPELL_EVAPORATE,
     SPELL_MEPHITIC_CLOUD,
     SPELL_CONJURE_FLAME,
     SPELL_POISONOUS_CLOUD,
     SPELL_FREEZING_CLOUD,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 22 - Book of Healing
    {0,
     SPELL_CURE_POISON_I,
     SPELL_LESSER_HEALING,
     SPELL_GREATER_HEALING,
     SPELL_PURIFICATION,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 23 - Book of Necromancy
    {0,
     SPELL_PAIN,
     SPELL_ANIMATE_SKELETON,
     SPELL_VAMPIRIC_DRAINING,
     SPELL_REGENERATION,
     SPELL_DISPEL_UNDEAD,
     SPELL_ANIMATE_DEAD,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 24 - Necronomicon -- Kikubaaqudgha special
    {0,
     SPELL_SYMBOL_OF_TORMENT,
     SPELL_CONTROL_UNDEAD,
     SPELL_SUMMON_WRAITHS,
     SPELL_DEATHS_DOOR,
     SPELL_NECROMUTATION,
     SPELL_DEATH_CHANNEL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 25 - Book of Callings
    {0,
     SPELL_SUMMON_SMALL_MAMMAL,
     SPELL_STICKS_TO_SNAKES,
     SPELL_CALL_IMP,
     SPELL_SUMMON_ELEMENTAL,
     SPELL_SUMMON_SCORPIONS,
     SPELL_SUMMON_ICE_BEAST,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 26 - Book of Charms
    {0,
     SPELL_BACKLIGHT,
     SPELL_REPEL_MISSILES,
     SPELL_SLEEP,
#ifdef USE_SILENCE_CODE
     SPELL_SILENCE,
#endif
     SPELL_CONFUSE,
     SPELL_ENSLAVEMENT,
     SPELL_INVISIBILITY,
#ifndef USE_SILENCE_CODE
     SPELL_NO_SPELL,
#endif
     SPELL_NO_SPELL,
     },
    // 27 - Book of Demonology  -- Vehumet special
    {0,
     SPELL_ABJURATION_I,
     SPELL_RECALL,
     SPELL_CALL_IMP,
     SPELL_SUMMON_DEMON,
     SPELL_DEMONIC_HORDE,
     SPELL_SUMMON_GREATER_DEMON,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 28 - Book of Air
    {0,
     SPELL_SHOCK,
     SPELL_SWIFTNESS,
     SPELL_REPEL_MISSILES,
     SPELL_LEVITATION,
     SPELL_MEPHITIC_CLOUD,
     SPELL_DISCHARGE,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },

    // Removing Air Walk... it's currently broken in a number or ways:
    // - the AC/EV bonus probably means very little to any character
    //   capable of casting a level nine spell
    // - the penalty of dropping inventory is a bit harsh considering
    //   the above
    // - the fire/ice susceptibility doesn't work... the AC/EV bonus
    //   cancel it out (so you'd hardly be wary of them since they
    //   can't really do any damage).
    // - there is no need for another invulnerability spell (which is
    //   what this spell is trying to be), one is more than enough...
    //   let people use necromancy.
    // - there is no need for another air spell... air spells are
    //   already very common (ie. this level nine spell occured in
    //   two books!)

    // 29 - Book of the Sky
    {0,
#ifdef USE_SILENCE_CODE
     SPELL_SILENCE,
#endif
     SPELL_SUMMON_ELEMENTAL,
     SPELL_INSULATION,
     SPELL_AIRSTRIKE,
     SPELL_FLY,
     SPELL_DEFLECT_MISSILES,
     SPELL_LIGHTNING_BOLT,
     SPELL_CONJURE_BALL_LIGHTNING,
#ifndef USE_SILENCE_CODE
     SPELL_NO_SPELL,
#endif
     },

    // 30 - Book of Divinations
    {0,
     SPELL_DETECT_SECRET_DOORS,
     SPELL_DETECT_CREATURES,
     SPELL_DETECT_ITEMS,
     SPELL_DETECT_CURSE,
     SPELL_SEE_INVISIBLE,
     SPELL_FORESCRY,
     SPELL_IDENTIFY,
     SPELL_NO_SPELL,
     },
    // 31 - Book of the Warp
    {0,
     SPELL_CONTROLLED_BLINK,
     SPELL_BANISHMENT,
     SPELL_DISPERSAL,
     SPELL_PORTAL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 32 - Book of Envenomations
    {0,
     SPELL_SPIDER_FORM,
     SPELL_POISON_AMMUNITION,
     SPELL_SUMMON_SCORPIONS,
     SPELL_RESIST_POISON,
     SPELL_OLGREBS_TOXIC_RADIANCE,
     SPELL_POISONOUS_CLOUD,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 33 - Book of Annihilations -- Vehumet special
    {0,
     SPELL_ISKENDERUNS_MYSTIC_BLAST,
     SPELL_POISON_ARROW,
     SPELL_ORB_OF_ELECTROCUTION,        // XXX: chain lightning?
     SPELL_LEHUDIBS_CRYSTAL_SPEAR,
     SPELL_ICE_STORM,
     SPELL_FIRE_STORM,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 34 - Book of Unlife
    {0,
     SPELL_SUBLIMATION_OF_BLOOD,
     SPELL_ANIMATE_DEAD,
     SPELL_TWISTED_RESURRECTION,
     SPELL_BORGNJORS_REVIVIFICATION,
     SPELL_SIMULACRUM,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },

    // 35 - Tome of Destruction
    {0,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 36 - Book of Control
    {0,
     SPELL_ENSLAVEMENT,
     SPELL_TAME_BEASTS,
     SPELL_MASS_CONFUSION,
     SPELL_CONTROL_UNDEAD,
     SPELL_CONTROL_TELEPORT,
     SPELL_MASS_SLEEP,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 37 - Book of Mutations //jmf: now Morphology
    {0,
     SPELL_FRAGMENTATION,
     SPELL_POLYMORPH_OTHER,
     SPELL_ALTER_SELF,
     SPELL_CIGOTUVIS_DEGENERATION,
     // SPELL_IGNITE_POISON,    // moved to Fire which was a bit slim -- bwr
     SPELL_SHATTER,
     // SPELL_AIR_WALK,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 38 - Book of Tukima
    {0,
     SPELL_SURE_BLADE,
     SPELL_TUKIMAS_VORPAL_BLADE,
     SPELL_TUKIMAS_DANCE,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 39 - Book of Geomancy
    {0,
     SPELL_SANDBLAST,
     SPELL_STONESKIN,
     SPELL_PASSWALL,
     SPELL_STONE_ARROW,
     SPELL_SUMMON_ELEMENTAL,
     SPELL_FRAGMENTATION,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },

    // 40 - Book of Earth
    {0,
     SPELL_MAXWELLS_SILVER_HAMMER,
     SPELL_MAGIC_MAPPING,
     SPELL_DIG,
     SPELL_STATUE_FORM,
     SPELL_BOLT_OF_IRON,
     SPELL_TOMB_OF_DOROKLOHE,
     SPELL_SHATTER,
     SPELL_NO_SPELL,
     },
    // 41 - manuals of all kinds
    {0,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 42 - Book of Wizardry
    {0,
     SPELL_DETECT_CREATURES,
     SPELL_SUMMON_ELEMENTAL,
     SPELL_MAGIC_MAPPING,
     SPELL_TELEPORT_SELF,
     SPELL_FIREBALL,
     SPELL_IDENTIFY,
     SPELL_HASTE,
     SPELL_NO_SPELL,
     },
    // 43 - Book of Power
    {0,
     SPELL_ANIMATE_DEAD,
     SPELL_TELEPORT_OTHER,
     SPELL_VENOM_BOLT,
     SPELL_BOLT_OF_IRON,
     SPELL_INVISIBILITY,
     SPELL_MASS_CONFUSION,
     SPELL_POISONOUS_CLOUD,
     SPELL_NO_SPELL,
     },
    // 44 - Book of Cantrips      //jmf: added 04jan2000
    {0,
     SPELL_CONFUSING_TOUCH,
     SPELL_ANIMATE_SKELETON,
     SPELL_SUMMON_SMALL_MAMMAL,
     SPELL_DETECT_SECRET_DOORS,
     SPELL_APPORTATION,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },

    // 45 - Book of Party Tricks  //jmf: added 04jan2000
    {0,
     SPELL_SUMMON_BUTTERFLIES,
     SPELL_APPORTATION,
     SPELL_PROJECTED_NOISE,
     SPELL_BLINK,
     SPELL_LEVITATION,
     SPELL_INTOXICATE,
     SPELL_NO_SPELL,  //jmf: SPELL_ERINGYAS_SURPRISING_BOUQUET, when finished
     SPELL_NO_SPELL,
     },

    // 46 - Book of Beasts //jmf: added 19mar2000
    {0,
     SPELL_SUMMON_SMALL_MAMMAL,
     SPELL_STICKS_TO_SNAKES,
     SPELL_DETECT_CREATURES,
     SPELL_SUMMON_LARGE_MAMMAL,
     SPELL_TAME_BEASTS,
     SPELL_DRAGON_FORM,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },

    // 47 - Book of Stalking //jmf: 24jun2000
    {0,
     SPELL_STING,
     SPELL_SURE_BLADE,
     SPELL_PROJECTED_NOISE,
     SPELL_MEPHITIC_CLOUD,
     SPELL_POISON_WEAPON,
     SPELL_PARALYZE,
     SPELL_INVISIBILITY,
     SPELL_NO_SPELL,
     },

    // 48 -- unused
    {0,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },

    // 49 - unused
    {0,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },

    // 50 - Staff of Smiting //jmf: totally obsolete --- no longer looks here.
    {0,
     SPELL_SMITING,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 51 - Staff of Summoning
    {0,
     SPELL_ABJURATION_I,
     SPELL_RECALL,
     SPELL_SUMMON_ELEMENTAL,
     SPELL_SWARM,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 52 - Staff of Destruction
    {0,
     SPELL_THROW_FLAME,
     SPELL_BOLT_OF_FIRE,
     SPELL_FIREBALL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 53 - Staff of Destruction
    {0,
     SPELL_THROW_FROST,
     SPELL_ICE_BOLT,
     SPELL_FREEZING_CLOUD,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 54 - Staff of Destruction
    {0,
     SPELL_BOLT_OF_IRON,
     SPELL_FIREBALL,
     SPELL_LIGHTNING_BOLT,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 55 - Staff of Destruction
    {0,
     SPELL_BOLT_OF_INACCURACY,
     SPELL_BOLT_OF_MAGMA,
     SPELL_BOLT_OF_COLD,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 56 - Staff of Warding
    {0,
     SPELL_ABJURATION_I,
     SPELL_CONDENSATION_SHIELD,
     SPELL_CAUSE_FEAR,
     SPELL_DEFLECT_MISSILES,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 57 - Staff of Exploration
    {0,
     SPELL_DETECT_SECRET_DOORS,
     SPELL_DETECT_TRAPS,
     SPELL_DETECT_ITEMS,
     SPELL_MAGIC_MAPPING,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 58 - Staff of Demonology
    {0,
     SPELL_ABJURATION_I,
     SPELL_RECALL,
     SPELL_CALL_IMP,
     SPELL_SUMMON_DEMON,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
    // 59 - Staff of Striking -- unused like Smiting
    {0,
     SPELL_STRIKING,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     SPELL_NO_SPELL,
     },
};

static void spellbook_template( int sbook_type,
                         FixedVector < int, SPELLBOOK_SIZE > &sbtemplate_pass )
{
    ASSERT( sbook_type >= 0 );
    ASSERT( sbook_type < NUMBER_SPELLBOOKS );

    // no point doing anything if tome of destruction or a manual
    if (sbook_type == BOOK_DESTRUCTION || sbook_type == BOOK_MANUAL)
        return;

    for (int i = 0; i < SPELLBOOK_SIZE; i++)    //jmf: was i = 1
    {
        sbtemplate_pass[i] = spellbook_template_array[sbook_type][i];
    }
}                               // end spellbook_template()

int which_spell_in_book(int sbook_type, int spl)
{
    FixedVector < int, SPELLBOOK_SIZE > wsib_pass;      // was 10 {dlb}

    spellbook_template(sbook_type, wsib_pass);

    return (wsib_pass[ spl + 1 ]);
}                               // end which_spell_in_book()

static unsigned char spellbook_contents( item_def &book, int action )
{
    FixedVector<int, SPELLBOOK_SIZE> spell_types;    // was 10 {dlb}
    int spelcount = 0;
    int i, j;

    const int spell_levels = player_spell_levels();

    // special case for staves
    const int type = (book.base_type == OBJ_STAVES) ? book.sub_type + 40
                                                    : book.sub_type;

    bool spell_skills = false;

    for (i = SK_SPELLCASTING; i <= SK_POISON_MAGIC; i++)
    {
        if (you.skills[i])
        {
            spell_skills = true;
            break;
        }
    }

    set_ident_flags( book, ISFLAG_KNOW_TYPE );

#ifdef DOS_TERM
    char buffer[4800];
    gettext(1, 1, 80, 25, buffer);
    window(1, 1, 80, 25);
#endif

    spellbook_template( type, spell_types );

    clrscr();
    textcolor(LIGHTGREY);

    char str_pass[ ITEMNAME_SIZE ];
    item_name( book, DESC_CAP_THE, str_pass );
    cprintf( str_pass );

#ifdef JP
    cprintf( EOL EOL " 呪文                               系統                     レベル" EOL );
#else
    cprintf( EOL EOL " Spells                             Type                      Level" EOL );
#endif

    for (j = 1; j < SPELLBOOK_SIZE; j++)
    {
        if (spell_types[j] == SPELL_NO_SPELL)
            continue;

        cprintf(" ");

        bool knowsSpell = false;
        for (i = 0; i < 25 && !knowsSpell; i++)
        {
            knowsSpell = (you.spells[i] == spell_types[j]);
        }

        const int level_diff = spell_difficulty( spell_types[j] );
        const int levels_req = spell_levels_required( spell_types[j] );

        int colour = DARKGREY;
        if (action == RBOOK_USE_STAFF)
        {
            if (you.experience_level >= level_diff
                && you.magic_points >= level_diff)
            {
                colour = LIGHTGREY;
            }
        }
        else
        {
            if (knowsSpell)
                colour = LIGHTGREY;
            else if (you.experience_level >= level_diff
                        && spell_levels >= levels_req
                        && spell_skills)
            {
                colour = LIGHTBLUE;
            }
        }

        textcolor( colour );

        // Old:
        // textcolor(knowsSpell ? DARKGREY : LIGHTGREY);
        //              was: ? LIGHTGREY : LIGHTBLUE

        char strng[2];

        strng[0] = index_to_letter(spelcount);
        strng[1] = '\0';

        cprintf(strng);
        cprintf(" - ");

        cprintf( spell_title(spell_types[j]) );
        gotoxy( 35, wherey() );


        if (action == RBOOK_USE_STAFF)
#ifdef JP
            cprintf( "発動" );
#else
            cprintf( "Evocations" );
#endif
        else
        {
            bool already = false;

            for (i = 0; i <= SPTYP_LAST_EXPONENT; i++)
            {
                if (spell_typematch( spell_types[j], 1 << i ))
                {
                    if (already)
                        cprintf( "/" );

                    cprintf( spelltype_name( 1 << i ) );
                    already = true;
                }
            }
        }

        gotoxy( 65, wherey() );

        char sval[3];

        itoa( level_diff, sval, 10 );
        cprintf( sval );
        cprintf( EOL );
        spelcount++;
    }

    textcolor(LIGHTGREY);
    cprintf(EOL);

    switch (action)
    {
    case RBOOK_USE_STAFF:
#ifdef JP
        cprintf( "唱える呪文を選択してください。" EOL );
#else
        cprintf( "Select a spell to cast." EOL );
#endif
        break;

    case RBOOK_MEMORIZE:
#ifdef JP
        cprintf( "覚える呪文を選択してください。(%dレベル分の記憶が可能)" EOL,
                 spell_levels );
#else
        cprintf( "Select a spell to memorise (%d level%s available)." EOL,
                 spell_levels, (spell_levels == 1) ? "" : "s" );
#endif
        break;

    case RBOOK_READ_SPELL:
#ifdef JP
        cprintf( "解説を読みたい呪文を選択してください。" EOL );
#else
        cprintf( "Select a spell to read its description." EOL );
#endif
        break;

    default:
        break;
    }

    unsigned char keyn = getch();

    if (keyn == 0)
        getch();

#ifdef DOS_TERM
    puttext(1, 1, 80, 25, buffer);
    window(1, 18, 80, 25);
#endif

    return (keyn);     // try to figure out that for which this is used {dlb}
}

//jmf: was in shopping.cc
char book_rarity(unsigned char which_book)
{
    switch (which_book)
    {
    case BOOK_MINOR_MAGIC_I:
    case BOOK_MINOR_MAGIC_II:
    case BOOK_MINOR_MAGIC_III:
    case BOOK_SURVEYANCES:
    case BOOK_HINDERANCE:
    case BOOK_CANTRIPS: //jmf: added 04jan2000
        return 1;

    case BOOK_CHANGES:
    case BOOK_CHARMS:
        return 2;

    case BOOK_CONJURATIONS_I:
    case BOOK_CONJURATIONS_II:
    case BOOK_PRACTICAL_MAGIC:
    case BOOK_NECROMANCY:
    case BOOK_CALLINGS:
    case BOOK_WIZARDRY:
        return 3;

    case BOOK_FLAMES:
    case BOOK_FROST:
    case BOOK_AIR:
    case BOOK_GEOMANCY:
        return 4;

    case BOOK_YOUNG_POISONERS:
    case BOOK_STALKING:    //jmf: added 24jun2000
    case BOOK_WAR_CHANTS:
        return 5;

    case BOOK_CLOUDS:
    case BOOK_POWER:
        return 6;

    case BOOK_ENCHANTMENTS:
    case BOOK_PARTY_TRICKS:     //jmf: added 04jan2000
        return 7;

    case BOOK_TRANSFIGURATIONS:
    case BOOK_DIVINATIONS:
        return 8;

    case BOOK_FIRE:
    case BOOK_ICE:
    case BOOK_SKY:
    case BOOK_EARTH:
    case BOOK_UNLIFE:
    case BOOK_CONTROL:
    case BOOK_SPATIAL_TRANSLOCATIONS:
        return 10;

    case BOOK_TEMPESTS:
    case BOOK_DEATH:
        return 11;

    case BOOK_MUTATIONS:
    case BOOK_BEASTS:           //jmf: added 23mar2000
        return 12;

    case BOOK_ENVENOMATIONS:
    case BOOK_WARP:
        return 15;

    case BOOK_TUKIMA:
        return 16;

    case BOOK_SUMMONINGS:
        return 18;

    case BOOK_ANNIHILATIONS: // Vehumet special
    case BOOK_DEMONOLOGY:    // Vehumet special
    case BOOK_NECRONOMICON:  // Kikubaaqudgha special
    case BOOK_MANUAL:
        return 20;

    case BOOK_DESTRUCTION:
        return 30;

    case BOOK_HEALING:
        return 100;

    default:
        return 1;
    }
}                               // end book_rarity()

bool is_valid_spell_in_book( unsigned int splbook, int spell )
{
    FixedVector< int, SPELLBOOK_SIZE >  spells;

    spellbook_template( you.inv[ splbook ].sub_type, spells );

    if (spells[ spell ] != SPELL_NO_SPELL)
        return true;

    return false;
}                               // end is_valid_spell_in_book()

static bool which_spellbook( int &book, int &spell )
{
    const int avail_levels = player_spell_levels();

    // Knowing delayed fireball will allow Fireball to be learned for free -bwr
    if (avail_levels < 1 && !player_has_spell(SPELL_DELAYED_FIREBALL))
    {
#ifdef JP
        mpr("あなたは今のところ呪文を覚えることはできない。");
#else
        mpr("You can't memorise any more spells yet.");
#endif
        return (false);
    }
    else if (inv_count() < 1)
    {
        canned_msg(MSG_NOTHING_CARRIED);
        return (false);
    }

#ifdef JP
    snprintf( info, INFO_SIZE, "あなたは%dレベル分の呪文を覚えることができる。",
             avail_levels );
#else
    snprintf( info, INFO_SIZE, "You can memorise %d more level%s of spells.",
             avail_levels, (avail_levels > 1) ? "s" : "" );
#endif

    mpr( info );

#ifdef JP
    book = prompt_invent_item( "どの呪文書から覚えますか？", OBJ_BOOKS );
#else
    book = prompt_invent_item( "Memorise from which spellbook?", OBJ_BOOKS );
#endif
    if (book == PROMPT_ABORT)
    {
        canned_msg( MSG_OK );
        return (false);
    }

    if (you.inv[book].base_type != OBJ_BOOKS
        || you.inv[book].sub_type == BOOK_MANUAL)
    {
#ifdef JP
        mpr("それは呪文書ではない！");
#else
        mpr("That isn't a spellbook!");
#endif
        return (false);
    }

    if (you.inv[book].sub_type == BOOK_DESTRUCTION)
    {
        tome_of_power( book );
        return (false);
    }

    spell = read_book( you.inv[book], RBOOK_MEMORIZE );
#ifndef USE_MULTIWIN
    clrscr();
#endif

    return (true);
}                               // end which_spellbook()

// Returns false if the player cannot read/memorize from the book,
// and true otherwise. -- bwr
static bool player_can_read_spellbook( const item_def &book )
{
    if (book.base_type != OBJ_BOOKS)
        return (true);

    if ((book.sub_type == BOOK_ANNIHILATIONS
            && you.religion != GOD_VEHUMET
            && (you.skills[SK_CONJURATIONS] < 10
                || you.skills[SK_SPELLCASTING] < 10))
        || (book.sub_type == BOOK_DEMONOLOGY
            && you.religion != GOD_VEHUMET
            && (you.skills[SK_SUMMONINGS] < 10
                || you.skills[SK_SPELLCASTING] < 10))
        || (book.sub_type == BOOK_NECRONOMICON
            && you.religion != GOD_KIKUBAAQUDGHA
            && (you.skills[SK_NECROMANCY] < 10
                || you.skills[SK_SPELLCASTING] < 10)))
    {
        return (false);
    }

    return (true);
}

unsigned char read_book( item_def &book, int action )
{
    unsigned char key2 = 0;

    if (book.base_type == OBJ_BOOKS && !player_can_read_spellbook( book ))
    {
#ifdef JP
        mpr( "この本の内容は現在のあなたの理解力を遥かに越えている。" );
#else
        mpr( "This book is beyond your current level of understanding." );
#endif
        more();
        return (0);
    }

    // remember that this function is called from staff spells as well:
    key2 = spellbook_contents( book, action );

    if (book.base_type == OBJ_BOOKS)
    {
        you.had_book[ book.sub_type ] = 1;

        if ( book.sub_type == BOOK_MINOR_MAGIC_I
            || book.sub_type == BOOK_MINOR_MAGIC_II
            || book.sub_type == BOOK_MINOR_MAGIC_III)
        {
            you.had_book[BOOK_MINOR_MAGIC_I] = 1;
            you.had_book[BOOK_MINOR_MAGIC_II] = 1;
            you.had_book[BOOK_MINOR_MAGIC_III] = 1;
        }
        else if (book.sub_type == BOOK_CONJURATIONS_I
             || book.sub_type == BOOK_CONJURATIONS_II)
        {
            you.had_book[BOOK_CONJURATIONS_I] = 1;
            you.had_book[BOOK_CONJURATIONS_II] = 1;
        }
    }

    redraw_screen();

    /* Put special book effects in another function which can be called from
       memorise as well */

    // reading spell descriptions doesn't take time:
    if (action != RBOOK_READ_SPELL)
        you.turn_is_over = 1;

    set_ident_flags( book, ISFLAG_KNOW_TYPE );

    return (key2);
}                               // end read_book()

// recoded to answer whether an UNDEAD_STATE is
// barred from a particular spell passed to the
// function - note that the function can be expanded
// to prevent memorisation of certain spells by
// the living by setting up an US_ALIVE case returning
// a value of false for a set of spells ... might be
// an idea worth further consideration - 12mar2000 {dlb}
bool undead_cannot_memorise(unsigned char spell, unsigned char being)
{
    switch (being)
    {
    case US_HUNGRY_DEAD:
        switch (spell)
        {
        //case SPELL_REGENERATION:
        case SPELL_BORGNJORS_REVIVIFICATION:
        case SPELL_CURE_POISON_II:
        case SPELL_DEATHS_DOOR:
        case SPELL_NECROMUTATION:
        case SPELL_RESIST_POISON:
        case SPELL_SYMBOL_OF_TORMENT:
        case SPELL_TAME_BEASTS:
        case SPELL_BERSERKER_RAGE:
            return true;
        }
        break;

    case US_UNDEAD:
        switch (spell)
        {
        case SPELL_AIR_WALK:
        case SPELL_ALTER_SELF:
        case SPELL_BLADE_HANDS:
        case SPELL_BORGNJORS_REVIVIFICATION:
        case SPELL_CURE_POISON_II:
        case SPELL_DEATHS_DOOR:
        case SPELL_DRAGON_FORM:
        case SPELL_GLAMOUR:
        case SPELL_ICE_FORM:
        case SPELL_INTOXICATE:
        case SPELL_NECROMUTATION:
        case SPELL_PASSWALL:
        case SPELL_REGENERATION:
        case SPELL_RESIST_POISON:
        case SPELL_SPIDER_FORM:
        case SPELL_STATUE_FORM:
        case SPELL_SUMMON_HORRIBLE_THINGS:
        case SPELL_SYMBOL_OF_TORMENT:
        case SPELL_TAME_BEASTS:
        case SPELL_BERSERKER_RAGE:
            return true;
        }
        break;
    }

    return false;
}                               // end undead_cannot_memorise()

bool learn_spell(void)
{
    int chance = 0;
    int levels_needed = 0;
    unsigned char keyin;
    int book, spell;
    int index;

    int i;
    int j = 0;

    for (i = SK_SPELLCASTING; i <= SK_POISON_MAGIC; i++)
    {
        if (you.skills[i])
            j++;
    }

    if (j == 0)
    {
#ifdef JP
        mpr("あなたは魔法書など読めない！現在のところ巻物のみ読むことができる。");
#else
        mpr("You can't use spell magic! I'm afraid it's scrolls only for now.");
#endif
        return (false);
    }

    if (!which_spellbook( book, spell ))
        return (false);

    if (spell < 'A' || (spell > 'Z' && spell < 'a') || spell > 'z')
    {
      whatt:
        redraw_screen();
#ifdef JP
        mpr("なんでしょうか？");
#else
        mpr("What?");
#endif
        return (false);
    }

    index = letter_to_index( spell );

    if (index >= SPELLBOOK_SIZE)
        goto whatt;

    if (!is_valid_spell_in_book( book, index ))
        goto whatt;

    unsigned int specspell = which_spell_in_book(you.inv[book].sub_type,index);

    if (specspell == SPELL_NO_SPELL)
        goto whatt;

    // You can always memorise selective amnesia:
    if (you.spell_no == 21 && specspell != SPELL_SELECTIVE_AMNESIA)
    {
        redraw_screen();
#ifdef JP
        mpr("あなたの頭はすでに呪文でいっぱいだ！");
#else
        mpr("Your head is already too full of spells!");
#endif
        return (false);
    }

    if (you.is_undead && spell_typematch(specspell, SPTYP_HOLY))
    {
        redraw_screen();
#ifdef JP
        mpr("あなたはこの系統の魔法を使うことはできない！");
#else
        mpr("You cannot use this type of magic!");
#endif
        return (false);
    }

    if (undead_cannot_memorise(specspell, you.is_undead))
    {
        redraw_screen();
#ifdef JP
        mpr("あなたはこの呪文を使うことはできない。");
#else
        mpr("You cannot use this spell.");
#endif
        return (false);
    }

    for (i = 0; i < 25; i++)
    {
        if (you.spells[i] == specspell)
        {
            redraw_screen();
#ifdef JP
            mpr("あなたはその呪文を既に知っている！");
#else
            mpr("You already know that spell!");
#endif
            you.turn_is_over = 1;
            return (false);
        }
    }

    levels_needed = spell_levels_required( specspell );

    if (player_spell_levels() < levels_needed)
    {
        redraw_screen();
#ifdef JP
        mpr("あなたはまだそのような高レベルの魔法は覚えられない！");
#else
        mpr("You can't memorise that many levels of magic yet!");
#endif
        you.turn_is_over = 1;
        return (false);
    }

    if (you.experience_level < spell_difficulty(specspell))
    {
        redraw_screen();
#ifdef JP
        mpr("あなたはその呪文を習得するにはあまりに経験不足だ！");
#else
        mpr("You're too inexperienced to learn that spell!");
#endif
        you.turn_is_over = 1;
        return (false);
    }

    redraw_screen();

    chance = spell_fail(specspell);

    int temp_rand = random2(3);

#ifdef JP
    strcpy(info, "その呪文を");

    temp_rand = random2(4);
    strcat(info, (temp_rand == 0) ? "覚える" :
                 (temp_rand == 1) ? "記憶する" :
                 (temp_rand == 2) ? "身につける" :
                 (temp_rand == 3) ? "理解する"
                                  : "");
    temp_rand = random2(3);
    strcat(info, (temp_rand == 0) ? "難しさは" :
                 (temp_rand == 1) ? "厄介さは" :
                 (temp_rand == 2) ? "大変さは"
                                  : "");

    strcat(info, (chance >= 80) ? "とてつもない" :
                 (chance >= 60) ? "非常なものだ" :
                 (chance >= 45) ? "なかなかのものだ" :
                 (chance >= 30) ? "そこそこのものだ"
                                : "大した事がない");

    strcat(info, "。");
#else
    strcpy(info, "This spell is ");

    strcat(info, (chance >= 80) ? "very" :
                 (chance >= 60) ? "quite" :
                 (chance >= 45) ? "rather" :
                 (chance >= 30) ? "somewhat"
                                : "not that");

    strcat(info, " ");

    strcat(info, (temp_rand == 0) ? "difficult" :
                 (temp_rand == 1) ? "tricky" :
                 (temp_rand == 2) ? "challenging"
                                  : "");

    strcat(info, " to ");

    temp_rand = random2(4);

    strcat(info, (temp_rand == 0) ? "memorise" :
                 (temp_rand == 1) ? "commit to memory" :
                 (temp_rand == 2) ? "learn" :
                 (temp_rand == 3) ? "absorb"
                                  : "");

    strcat(info, ".");
#endif

    mpr(info);

#ifdef JP
    strcpy(info, "");
#else
    strcpy(info, "Memorise ");
#endif
    strcat(info, spell_title(specspell));
#ifdef JP
    strcat(info, "を覚えますか？");
#else
    strcat(info, "?");
#endif
    mpr(info);

    for (;;)
    {
        keyin = getch();

        if (keyin == 'n' || keyin == 'N')
        {
            redraw_screen();
            return (false);
        }

        if (keyin == 'y' || keyin == 'Y')
            break;
    }

    mesclr( true );

    if (you.mutation[MUT_BLURRY_VISION] > 0
                && random2(4) < you.mutation[MUT_BLURRY_VISION])
    {
#ifdef JP
        mpr("文字が不可解なちんぷんかんぷんに霞んだ。");
#else
        mpr("The writing blurs into unreadable gibberish.");
#endif
        you.turn_is_over = 1;
        return (false);
    }

    if (random2(40) + random2(40) + random2(40) < chance)
    {
        redraw_screen();
#ifdef JP
        mpr("あなたは呪文を覚えるのに失敗した。");
#else
        mpr("You fail to memorise the spell.");
#endif
        you.turn_is_over = 1;

        if (you.inv[ book ].sub_type == BOOK_NECRONOMICON)
        {
#ifdef JP
            mpr("ネクロノミコンのページが暗黒の憎悪に輝いた……。");
            miscast_effect( SPTYP_NECROMANCY, 8, random2avg(88, 3), 100,
                            "ネクロノミコンの閲覧" );
#else
            mpr("The pages of the Necronomicon glow with a dark malevolence...");
            miscast_effect( SPTYP_NECROMANCY, 8, random2avg(88, 3), 100,
                            "reading the Necronomicon" );
#endif
        }
        else if (you.inv[ book ].sub_type == BOOK_DEMONOLOGY)
        {
#ifdef JP
            mpr("この本はあなたの愚行に煩わされることを喜ばない！");
            miscast_effect( SPTYP_SUMMONING, 7, random2avg(88, 3), 100,
                            "悪魔術の魔法書の閲覧" );
#else
            mpr("This book does not appreciate being disturbed by one of your ineptitude!");
            miscast_effect( SPTYP_SUMMONING, 7, random2avg(88, 3), 100,
                            "reading the book of Demonology" );
#endif
        }
        else if (you.inv[ book ].sub_type == BOOK_ANNIHILATIONS)
        {
#ifdef JP
            mpr("この本はあなたの愚行に煩わされることを喜ばない！");
            miscast_effect( SPTYP_CONJURATION, 8, random2avg(88, 3), 100,
                            "殲滅の魔法書の閲覧" );
#else
            mpr("This book does not appreciate being disturbed by one of your ineptitude!");
            miscast_effect( SPTYP_CONJURATION, 8, random2avg(88, 3), 100,
                            "reading the book of Annihilations" );
#endif
        }

#ifdef WIZARD
        if (!you.wizard)
            return (false);
#ifdef JP
        else if (!yesno("どうしても覚えますか？"))
#else
        else if (!yesno("Memorize anyway?"))
#endif
            return (false);
#else
        return (false);
#endif
    }

    start_delay( DELAY_MEMORIZE, spell_difficulty( specspell ), specspell );

    you.turn_is_over = 1;
    redraw_screen();

    naughty( NAUGHTY_SPELLCASTING, 2 + random2(5) );

    return (true);
}                               // end which_spell()

int staff_spell( int staff )
{
    int spell;
    unsigned char specspell;
    int mana, diff;
    FixedVector< int, SPELLBOOK_SIZE >  spell_list;

    // converting sub_type into book index type
    const int type = you.inv[staff].sub_type + 40;

    // Spell staves are mostly for the benefit of non-spellcasters, so we're
    // not going to involve INT or Spellcasting skills for power. -- bwr
    const int powc = 5 + you.skills[SK_EVOCATIONS]
                       + roll_dice( 2, you.skills[SK_EVOCATIONS] );

    if (you.inv[staff].sub_type < STAFF_SMITING
        || you.inv[staff].sub_type >= STAFF_AIR)
    {
        //mpr("That staff has no spells in it.");
        canned_msg(MSG_NOTHING_HAPPENS);
        return (0);
    }

    if (item_not_ident( you.inv[staff], ISFLAG_KNOW_TYPE ))
    {
        set_ident_flags( you.inv[staff], ISFLAG_KNOW_TYPE );
        you.wield_change = true;
    }

    spellbook_template( type, spell_list );

    unsigned char num_spells;
    for (num_spells = 0; num_spells < SPELLBOOK_SIZE - 1; num_spells++)
    {
        if (spell_list[ num_spells + 1 ] == SPELL_NO_SPELL)
            break;
    }

    if (num_spells == 0)
    {
        canned_msg(MSG_NOTHING_HAPPENS);  // shouldn't happen
        return (0);
    }
    else if (num_spells == 1)
        spell = 'a';  // automatically selected if its the only option
    else
    {
        snprintf( info, INFO_SIZE,
#ifdef JP
                  "ロッドからどの呪文を発動しますか？([a-%c]呪文 [*][?]一覧) ",
#else
                  "Evoke which spell from the rod ([a-%c] spell [?*] list)? ",
#endif
                  'a' + num_spells - 1 );

        mpr( info, MSGCH_PROMPT );
        spell = get_ch();

        if (spell == '?' || spell == '*')
            spell = read_book( you.inv[staff], RBOOK_USE_STAFF );
    }

    if (spell < 'A' || (spell > 'Z' && spell < 'a') || spell > 'z')
    {
        goto whattt;
    }

    spell = letter_to_index( spell );

    if (spell >= SPELLBOOK_SIZE)
        goto whattt;

    if (!is_valid_spell_in_book( staff, spell ))
        goto whattt;

    specspell = which_spell_in_book( type,  spell );

    if (specspell == SPELL_NO_SPELL)
        goto whattt;

    mana = spell_mana( specspell );
    diff = spell_difficulty( specspell );

    if (you.magic_points < mana || you.experience_level < diff)
    {
#ifdef JP
        mpr("あなたの脳髄は傷ついた！");
#else
        mpr("Your brain hurts!");
#endif
        confuse_player( 2 + random2(4) );
        you.turn_is_over = 1;
        return (0);
    }

    // Exercising the spell skills doesn't make very much sense given
    // that spell staves are largely intended to supply spells to
    // non-spellcasters, and they don't use spell skills to determine
    // power in the same way that spellcasting does. -- bwr
    //
    // exercise_spell(specspell, true, true);

    your_spells(specspell, powc, false);

    dec_mp(spell_mana(specspell));

    you.turn_is_over = 1;

    return (roll_dice( 1, 1 + spell_difficulty(specspell) / 2 ));

  whattt:
#ifdef JP
    mpr("何でしょう？");
#else
    mpr("What?");
#endif

    return (0);
}                               // end staff_spell()
