summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-29 11:11:32 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-29 11:11:32 +0000
commit7fcfce7d250e09f85bc09f9e720dda5cf723e68e (patch)
treef70f14cb977e44bcded985b8527e7cd01ad50663 /crawl-ref
parent10a49dc866d7cb5b0d5fe0400ae02f30e8be4d85 (diff)
downloadcrawl-ref-7fcfce7d250e09f85bc09f9e720dda5cf723e68e.tar.gz
crawl-ref-7fcfce7d250e09f85bc09f9e720dda5cf723e68e.zip
* Dump spells contained in randart spellbooks, marking memorised spells
with an asterisk. * Sif Muna no longer gifts the books specific to Kiku and Vehumet (Necronomicon, Annihilations, Demonology) though the spells contained there-in may crop up in randart books. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8011 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/chardump.cc23
-rw-r--r--crawl-ref/source/command.cc54
-rw-r--r--crawl-ref/source/describe.cc81
-rw-r--r--crawl-ref/source/describe.h2
-rw-r--r--crawl-ref/source/effects.cc64
-rw-r--r--crawl-ref/source/initfile.cc14
-rw-r--r--crawl-ref/source/items.cc12
-rw-r--r--crawl-ref/source/makeitem.cc10
-rw-r--r--crawl-ref/source/randart.cc4
-rw-r--r--crawl-ref/source/religion.cc2
-rw-r--r--crawl-ref/source/spl-book.cc26
-rw-r--r--crawl-ref/source/spl-book.h1
12 files changed, 164 insertions, 129 deletions
diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc
index 6f50aa8146..1e614e9b74 100644
--- a/crawl-ref/source/chardump.cc
+++ b/crawl-ref/source/chardump.cc
@@ -653,7 +653,7 @@ static void _sdump_religion(dump_params &par)
}
}
-static bool dump_item_origin(const item_def &item, int value)
+static bool _dump_item_origin(const item_def &item, int value)
{
#define fs(x) (flags & (x))
const int flags = Options.dump_item_origins;
@@ -661,10 +661,11 @@ static bool dump_item_origin(const item_def &item, int value)
return (true);
if (fs(IODS_ARTEFACTS)
- && (is_random_artefact(item) || is_fixed_artefact(item))
- && item_ident(item, ISFLAG_KNOW_PROPERTIES))
+ && (is_random_artefact(item) || is_fixed_artefact(item))
+ && item_ident(item, ISFLAG_KNOW_PROPERTIES))
+ {
return (true);
-
+ }
if (fs(IODS_EGO_ARMOUR) && item.base_type == OBJ_ARMOUR
&& item_type_known( item ))
{
@@ -682,16 +683,22 @@ static bool dump_item_origin(const item_def &item, int value)
return (true);
if (fs(IODS_RUNES) && item.base_type == OBJ_MISCELLANY
- && item.sub_type == MISC_RUNE_OF_ZOT)
+ && item.sub_type == MISC_RUNE_OF_ZOT)
+ {
return (true);
+ }
if (fs(IODS_RODS) && item.base_type == OBJ_STAVES
- && item_is_rod(item))
+ && item_is_rod(item))
+ {
return (true);
+ }
if (fs(IODS_STAVES) && item.base_type == OBJ_STAVES
- && !item_is_rod(item))
+ && !item_is_rod(item))
+ {
return (true);
+ }
if (fs(IODS_BOOKS) && item.base_type == OBJ_BOOKS)
return (true);
@@ -790,7 +797,7 @@ static void _sdump_inventory(dump_params &par)
}
if (origin_describable(you.inv[j])
- && dump_item_origin(you.inv[j], ival))
+ && _dump_item_origin(you.inv[j], ival))
{
text += "\n" " (" + origin_desc(you.inv[j]) + ")";
}
diff --git a/crawl-ref/source/command.cc b/crawl-ref/source/command.cc
index 1fbab5fdfe..7751761b85 100644
--- a/crawl-ref/source/command.cc
+++ b/crawl-ref/source/command.cc
@@ -1247,58 +1247,6 @@ static bool _append_books(std::string &desc, item_def &item, std::string key)
return (true);
}
-// Adds a list of all spells contained in a book or rod to its
-// description string.
-static void _append_spells(std::string &desc, const item_def &item)
-{
- if (!item.has_spells())
- return;
-
- desc += "$$Spells Type Level$";
-
- for (int j = 0; j < 8; j++)
- {
- spell_type stype = which_spell_in_book(item, j);
- if (stype == SPELL_NO_SPELL)
- continue;
-
- std::string name = spell_title(stype);
- desc += name;
- for (unsigned int i = 0; i < 35 - name.length(); i++)
- desc += " ";
-
- name = "";
- if (item.base_type == OBJ_STAVES)
- name += "Evocations";
- else
- {
- bool already = false;
-
- for (int i = 0; i <= SPTYP_LAST_EXPONENT; i++)
- {
- if (spell_typematch( stype, 1 << i ))
- {
- if (already)
- name += "/" ;
-
- name += spelltype_name( 1 << i );
- already = true;
- }
- }
- }
- desc += name;
-
- for (unsigned int i = 36; i < 65 - name.length(); i++)
- desc += " ";
-
- char sval[3];
- itoa( spell_difficulty( stype ), sval, 10 );
- desc += sval;
- desc += "$";
- }
-
-}
-
static bool _do_description(std::string key, std::string type,
std::string footer = "")
{
@@ -1411,7 +1359,7 @@ static bool _do_description(std::string key, std::string type,
|| get_item_by_name(&mitm[thing_created], name, OBJ_STAVES))
{
if (!_append_books(desc, mitm[thing_created], key))
- _append_spells(desc, mitm[thing_created]);
+ append_spells(desc, mitm[thing_created]);
}
else
_append_non_item(desc, key);
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 42bf6aa797..25a95d3f45 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -1625,6 +1625,58 @@ static std::string _describe_deck( const item_def &item )
return (description);
}
+// Adds a list of all spells contained in a book or rod to its
+// description string.
+void append_spells(std::string &desc, const item_def &item)
+{
+ if (!item.has_spells())
+ return;
+
+ desc += "$$Spells Type Level$";
+
+ for (int j = 0; j < 8; j++)
+ {
+ spell_type stype = which_spell_in_book(item, j);
+ if (stype == SPELL_NO_SPELL)
+ continue;
+
+ std::string name = (is_memorised(stype)) ? "*" : "";
+ name += spell_title(stype);
+ desc += name;
+ for (unsigned int i = 0; i < 35 - name.length(); i++)
+ desc += " ";
+
+ name = "";
+ if (item.base_type == OBJ_STAVES)
+ name += "Evocations";
+ else
+ {
+ bool already = false;
+
+ for (int i = 0; i <= SPTYP_LAST_EXPONENT; i++)
+ {
+ if (spell_typematch( stype, 1 << i ))
+ {
+ if (already)
+ name += "/" ;
+
+ name += spelltype_name( 1 << i );
+ already = true;
+ }
+ }
+ }
+ desc += name;
+
+ for (unsigned int i = 36; i < 65 - name.length(); i++)
+ desc += " ";
+
+ char sval[3];
+ itoa( spell_difficulty( stype ), sval, 10 );
+ desc += sval;
+ desc += "$";
+ }
+}
+
// ========================================================================
// Public Functions
// ========================================================================
@@ -1714,7 +1766,8 @@ std::string get_item_description( const item_def &item, bool verbose,
description << ".$";
}
else if (verbose || (item.base_type != OBJ_WEAPONS
- && item.base_type != OBJ_ARMOUR))
+ && item.base_type != OBJ_ARMOUR
+ && item.base_type != OBJ_BOOKS))
{
description << "$$";
@@ -1779,7 +1832,7 @@ std::string get_item_description( const item_def &item, bool verbose,
std::string desc;
switch (item.base_type)
{
- // Weapons, armour, jewellery might be artefacts.
+ // Weapons, armour, jewellery, books might be artefacts.
case OBJ_WEAPONS:
desc = _describe_weapon( item, verbose );
if (desc.empty())
@@ -1804,6 +1857,22 @@ std::string get_item_description( const item_def &item, bool verbose,
description << desc;
break;
+ case OBJ_BOOKS:
+ if (!player_can_read_spellbook( item ))
+ {
+ description << "$This book is beyond your current level of "
+ "understanding.";
+ }
+ else if (!verbose && is_random_artefact( item ))
+ {
+ append_spells( desc, item );
+ if (desc.empty())
+ need_extra_line = false;
+ else
+ description << desc;
+ }
+ break;
+
case OBJ_MISSILES:
description << _describe_ammo( item );
break;
@@ -1905,14 +1974,6 @@ std::string get_item_description( const item_def &item, bool verbose,
description << _describe_deck( item );
break;
- case OBJ_BOOKS:
- if (!player_can_read_spellbook( item ))
- {
- description << "$This book is beyond your current level of "
- "understanding.";
- }
- break;
-
case OBJ_POTIONS:
#ifdef DEBUG_BLOOD_POTIONS
// List content of timer vector for blood potions.
diff --git a/crawl-ref/source/describe.h b/crawl-ref/source/describe.h
index 1b938b6740..ab661c919c 100644
--- a/crawl-ref/source/describe.h
+++ b/crawl-ref/source/describe.h
@@ -27,6 +27,8 @@ enum item_description_type
NUM_IDESC
};
+void append_spells(std::string &desc, const item_def &item);
+
// last updated 12may2000 {dlb}
/* ***********************************************************************
* called from: chardump - spells4
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index 9b34adb9de..72de9af7fd 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -1186,8 +1186,7 @@ static int _find_acquirement_subtype(object_class_type class_wanted,
// much too good (most spells, lots of books here,
// id wand charges, gives magic resistance),
// something will eventually have to be done. -- bwr
- if (best_any >= SK_FIGHTING
- && best_any <= SK_STAVES)
+ if (best_any >= SK_FIGHTING && best_any <= SK_STAVES)
{
// Fighter mages get the fighting enchantment books
if (!you.had_book[BOOK_WAR_CHANTS])
@@ -1275,7 +1274,7 @@ static int _find_acquirement_subtype(object_class_type class_wanted,
}
// If the book is invalid find any valid one.
- while (book_rarity(type_wanted) == 100)
+ while (type_wanted == BOOK_HEALING)
type_wanted = random2(NUM_NORMAL_BOOKS);
break;
@@ -1423,8 +1422,8 @@ static void _do_book_acquirement(item_def &book, int agent)
// items() shouldn't make book a randart for acquirement items.
ASSERT(!is_random_artefact(book));
- // Non-normal books are rare enough without turning them into
- // randart books.
+ // Non-normal books (i.e. manuals/book of destruction) are rare enough
+ // without turning them into randart books.
if (book.sub_type > MAX_NORMAL_BOOK)
return;
@@ -1445,36 +1444,35 @@ static void _do_book_acquirement(item_def &book, int agent)
std::vector<int> vec;
for (int i = 1; i <= 9 && (vec.empty() || i <= max_level); i++)
- {
if (!(seen_levels & (1 << i)))
vec.push_back(i);
- }
+
if (vec.size() > 0)
level = vec[random2(vec.size())];
else
level = -1;
}
- int choice_weights[4] = {
- 55, // fixed themed
- 24, // leave alone
- level == -1 ? 0 : 12, // fixed level
- agent == GOD_XOM ? 0 : 6, // manual (too useful for Xom)
- };
+ int choice = random_choose_weighted(
+ 55, BOOK_RANDART_THEME,
+ 24, book.sub_type,
+ level == -1 ? 0 : 12, BOOK_RANDART_LEVEL,
+ agent == GOD_XOM ? 0 : 6, BOOK_MANUAL, // too useful for Xom
+ 0);
+
+ // No changes.
+ if (choice == book.sub_type)
+ return;
- int choice = choose_random_weighted(choice_weights, choice_weights + 4);
+ book.sub_type = choice;
- switch(choice)
+ switch (choice)
{
- case 0:
+ case BOOK_RANDART_THEME:
make_book_theme_randart(book, 0, 0, 7, 22);
break;
- case 1:
- // Leave alone
- break;
-
- case 2:
+ case BOOK_RANDART_LEVEL:
{
int num_spells = 7 - (level + 1) / 2 + random_range(1, 2);
make_book_level_randart(book, level, num_spells);
@@ -1482,7 +1480,7 @@ static void _do_book_acquirement(item_def &book, int agent)
}
// Spell discipline manual
- case 3:
+ case BOOK_MANUAL:
{
int weights[SK_POISON_MAGIC - SK_CONJURATIONS + 1];
int total_weights = 0;
@@ -1559,15 +1557,13 @@ bool acquirement(object_class_type class_wanted, int agent,
}
}
- const bool god_agent = agent > GOD_NO_GOD && agent < NUM_GODS;
-
if (grid_destroys_items(grd(you.pos())))
{
// How sad (and stupid).
if (!silenced(you.pos()) && !quiet)
mprf(MSGCH_SOUND, grid_item_destruction_message(grd(you.pos())));
- if (god_agent)
+ if (agent > GOD_NO_GOD && agent < NUM_GODS)
{
if (agent == GOD_XOM)
simple_god_message(" snickers.", GOD_XOM);
@@ -1596,7 +1592,7 @@ bool acquirement(object_class_type class_wanted, int agent,
// Don't generate randart books in items(), we do that
// ourselves.
- int want_arts = class_wanted == OBJ_BOOKS ? 0 : 1;
+ int want_arts = (class_wanted == OBJ_BOOKS ? 0 : 1);
thing_created = items( want_arts, class_wanted, type_wanted, true,
MAKE_GOOD_ITEM, MAKE_ITEM_RANDOM_RACE,
@@ -1661,6 +1657,20 @@ bool acquirement(object_class_type class_wanted, int agent,
continue;
}
}
+
+ // Sif Muna shouldn't gift Vehumet or Kiku's special books.
+ // (The spells therein are still fair game for randart books.)
+ if (agent == GOD_SIF_MUNA
+ && doodad.sub_type >= MIN_GOD_ONLY_BOOK
+ && doodad.sub_type <= MAX_GOD_ONLY_BOOK)
+ {
+ ASSERT(doodad.base_type == OBJ_BOOKS);
+
+ // Try again.
+ destroy_item(thing_created);
+ thing_created = NON_ITEM;
+ continue;
+ }
break;
}
@@ -1822,7 +1832,7 @@ bool acquirement(object_class_type class_wanted, int agent,
if (is_random_artefact(thing))
{
if (!is_unrandom_artefact(thing)
- && !thing.base_type == OBJ_BOOKS)
+ && thing.base_type != OBJ_BOOKS)
{
// Give another name that takes god gift into account;
// artefact books already do that.
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 14e9e69f57..bbd6dcdc4f 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -2832,15 +2832,21 @@ void game_options::read_option_line(const std::string &str, bool runscript)
{
const std::string &ch = choices[i];
if (ch == "artefacts" || ch == "artifacts"
- || ch == "artefact" || ch == "artifact")
+ || ch == "artefact" || ch == "artifact")
+ {
dump_item_origins |= IODS_ARTEFACTS;
+ }
else if (ch == "ego_arm" || ch == "ego armour"
- || ch == "ego_armour")
+ || ch == "ego_armour")
+ {
dump_item_origins |= IODS_EGO_ARMOUR;
+ }
else if (ch == "ego_weap" || ch == "ego weapon"
- || ch == "ego_weapon" || ch == "ego weapons"
- || ch == "ego_weapons")
+ || ch == "ego_weapon" || ch == "ego weapons"
+ || ch == "ego_weapons")
+ {
dump_item_origins |= IODS_EGO_WEAPON;
+ }
else if (ch == "jewellery" || ch == "jewelry")
dump_item_origins |= IODS_JEWELLERY;
else if (ch == "runes")
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index 990dd46204..49c376408e 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -1061,7 +1061,7 @@ bool origin_is_god_gift(const item_def& item, god_type *god)
if (iorig > GOD_NO_GOD && iorig < NUM_GODS)
{
*god = static_cast<god_type>(iorig);
- return(true);
+ return (true);
}
return (false);
@@ -2570,16 +2570,16 @@ bool item_is_equipped(const item_def &item, bool quiver_too)
bool item_def::has_spells() const
{
return ((base_type == OBJ_BOOKS && item_type_known(*this)
- && sub_type != BOOK_DESTRUCTION
- && sub_type != BOOK_MANUAL)
+ && sub_type != BOOK_DESTRUCTION
+ && sub_type != BOOK_MANUAL)
|| count_staff_spells(*this, true) > 1);
}
int item_def::book_number() const
{
- return (base_type == OBJ_BOOKS? sub_type :
- base_type == OBJ_STAVES? sub_type + NUM_BOOKS - STAFF_SMITING :
- -1);
+ return (base_type == OBJ_BOOKS ? sub_type :
+ base_type == OBJ_STAVES ? sub_type + NUM_BOOKS - STAFF_SMITING
+ : -1);
}
bool item_def::cursed() const
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index bd98b43d61..bd4ee4a76d 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -2424,7 +2424,7 @@ static void _generate_book_item(item_def& item, int allow_uniques,
continue;
}
}
- while (book_rarity(item.sub_type) == 100);
+ while (item.sub_type == BOOK_HEALING);
// Tome of destruction: rare!
if (item_level > 10 && x_chance_in_y(21 + item_level, 7000))
@@ -2664,7 +2664,7 @@ static void _generate_misc_item(item_def& item, int force_type, int item_race)
// Returns item slot or NON_ITEM if it fails.
int items( int allow_uniques, // not just true-false,
- // because of BCR acquirement hack
+ // because of BCR acquirement hack
object_class_type force_class, // desired OBJECTS class {dlb}
int force_type, // desired SUBTYPE - enum varies by OBJ
bool dont_place, // don't randomly place item on level
@@ -2681,9 +2681,9 @@ int items( int allow_uniques, // not just true-false,
// force_ego = SPWPN_VORPAL, and a random weapon of a type
// appropriate for the vorpal brand will be chosen.
ASSERT(force_ego <= 0
- || (force_class == OBJ_WEAPONS || force_class == OBJ_ARMOUR
- || force_class == OBJ_MISSILES)
- && force_type != OBJ_RANDOM);
+ || force_type != OBJ_RANDOM
+ && (force_class == OBJ_WEAPONS || force_class == OBJ_ARMOUR
+ || force_class == OBJ_MISSILES));
// Find an empty slot for the item (with culling if required).
int p = get_item_slot(10);
diff --git a/crawl-ref/source/randart.cc b/crawl-ref/source/randart.cc
index 482d732e12..0ba286f991 100644
--- a/crawl-ref/source/randart.cc
+++ b/crawl-ref/source/randart.cc
@@ -1153,7 +1153,7 @@ static bool _init_randart_book(item_def &book)
ASSERT(book.plus != 0);
god_type god;
- bool redo = !origin_is_god_gift(book, &god) || god != GOD_XOM;
+ bool redo = (!origin_is_god_gift(book, &god) || god != GOD_XOM);
// Plus and plus2 contain paramaters to make_book_foo_randart()
// which might get changed after the book has been made into a
@@ -2110,7 +2110,7 @@ bool make_item_randart( item_def &item )
}
}
- // This already is a randart.
+ // This item already is a randart.
if (item.flags & ISFLAG_RANDART)
return (true);
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index d3bc89da58..2ca8d4d9b4 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -1987,7 +1987,7 @@ static void _do_god_gift(bool prayed_for)
}
if (gift != NUM_BOOKS
- && !(grid_destroys_items(grd(you.pos()))))
+ && !grid_destroys_items(grd(you.pos())))
{
if (gift == OBJ_RANDOM)
success = acquirement(OBJ_BOOKS, you.religion);
diff --git a/crawl-ref/source/spl-book.cc b/crawl-ref/source/spl-book.cc
index dad9800e5d..b8ecd5d7c0 100644
--- a/crawl-ref/source/spl-book.cc
+++ b/crawl-ref/source/spl-book.cc
@@ -1137,8 +1137,8 @@ void mark_had_book(const item_def &book)
int level = book.plus;
ASSERT(level > 0 && level <= 9);
- if (origin_is_acquirement(book) ||
- origin_is_god_gift(book, &god) && god == GOD_SIF_MUNA)
+ if (origin_is_acquirement(book)
+ || origin_is_god_gift(book, &god) && god == GOD_SIF_MUNA)
{
you.attribute[ATTR_RND_LVL_BOOKS] |= (1 << level);
}
@@ -1191,6 +1191,7 @@ int read_book( item_def &book, read_book_action_type action )
// from memorise as well.
set_ident_flags( book, ISFLAG_KNOW_TYPE );
+ set_ident_flags( book, ISFLAG_IDENT_MASK);
return (keyin);
}
@@ -1714,13 +1715,11 @@ static bool _compare_spells(spell_type a, spell_type b)
return (strcmp(spell_title(a), spell_title(b)));
}
-static bool _is_memorised(spell_type spell)
+bool is_memorised(spell_type spell)
{
for (int i = 0; i < 25; i++)
- {
if (you.spells[i] == spell)
return (true);
- }
return (false);
}
@@ -1802,8 +1801,7 @@ static void _get_spell_list(std::vector<spell_type> &spell_list, int level,
}
-bool make_book_level_randart(item_def &book, int level,
- int num_spells)
+bool make_book_level_randart(item_def &book, int level, int num_spells)
{
ASSERT(book.base_type == OBJ_BOOKS);
@@ -1815,7 +1813,7 @@ bool make_book_level_randart(item_def &book, int level,
if (!is_random_artefact(book))
{
- // Stuf parameters into book.plus and book.plus2, then call
+ // Stuff parameters into book.plus and book.plus2, then call
// make_item_randart(), which will call us back.
if (level == -1)
{
@@ -1922,7 +1920,7 @@ bool make_book_level_randart(item_def &book, int level,
spell_type spell = spell_list[spell_pos];
ASSERT(spell != SPELL_NO_SPELL);
- if (avoid_memorised[spell_pos] && _is_memorised(spell))
+ if (avoid_memorised[spell_pos] && is_memorised(spell))
{
// Only once.
avoid_memorised[spell_pos] = false;
@@ -2044,12 +2042,14 @@ static bool _get_weighted_discs(bool completely_random, god_type god,
}
}
- do {
+ do
+ {
disc1 = ok_discs[choose_random_weighted(skill_weights,
skill_weights + num_discs)];
disc2 = ok_discs[choose_random_weighted(apt_weights,
apt_weights + num_discs)];
- } while(disciplines_conflict(disc1, disc2));
+ }
+ while(disciplines_conflict(disc1, disc2));
return (true);
}
@@ -2093,7 +2093,7 @@ static void _get_weighted_spells(bool completely_random, god_type god,
int c = 1;
if (!you.seen_spell[spell])
c = 4;
- else if (!_is_memorised(spell))
+ else if (!is_memorised(spell))
c = 2;
int total_skill = 0;
@@ -2124,7 +2124,7 @@ static void _get_weighted_spells(bool completely_random, god_type god,
int book_pos = 0;
int spells_left = spell_list.size();
- while(book_pos < num_spells && max_levels > 0 && spells_left > 0)
+ while (book_pos < num_spells && max_levels > 0 && spells_left > 0)
{
spell_type spell =
(spell_type) choose_random_weighted(spell_weights,
diff --git a/crawl-ref/source/spl-book.h b/crawl-ref/source/spl-book.h
index 41abf8a158..b43aeddf53 100644
--- a/crawl-ref/source/spl-book.h
+++ b/crawl-ref/source/spl-book.h
@@ -59,6 +59,7 @@ spell_type which_spell_in_book(int sbook_type, int spl);
// returns amount practised (or -1 for abort)
int staff_spell( int zap_device_2 );
+bool is_memorised(spell_type spell);
bool undead_cannot_memorise(spell_type spell, char being);