summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-04-11 11:23:33 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2008-04-11 11:23:33 +0000
commit7896dbd29bda379c2fb31feeb3b16bda57039c00 (patch)
treed7f820c06e503416aa61dee002c9358c24ade813 /crawl-ref/source
parent0fe8afdd2c0c0bcac82f6f1237181dc6fb1c58c2 (diff)
downloadcrawl-ref-7896dbd29bda379c2fb31feeb3b16bda57039c00.tar.gz
crawl-ref-7896dbd29bda379c2fb31feeb3b16bda57039c00.zip
Fix 1937869: Have weapon swapping respect spells the character knows
and allow wielding the appropriate items, e.g. arrows for Sticks to Snakes etc. Use the same rules for clicking on items in Tiles. Also add yet another minimap colour option, this time for plants (really zero xp monsters in general) since I became tired of plant-rich vaults showing up in bright red colours. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@4195 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/direct.cc18
-rw-r--r--crawl-ref/source/externs.h1
-rw-r--r--crawl-ref/source/initfile.cc6
-rw-r--r--crawl-ref/source/item_use.cc141
-rw-r--r--crawl-ref/source/libgui.cc112
-rw-r--r--crawl-ref/source/player.cc9
-rw-r--r--crawl-ref/source/player.h4
7 files changed, 218 insertions, 73 deletions
diff --git a/crawl-ref/source/direct.cc b/crawl-ref/source/direct.cc
index 3b89368585..ac34d64f0a 100644
--- a/crawl-ref/source/direct.cc
+++ b/crawl-ref/source/direct.cc
@@ -1098,9 +1098,9 @@ static void describe_oos_square(int x, int y)
bool in_vlos(int x, int y)
{
- return in_los_bounds(x, y)
- && (env.show(view2show(coord_def(x, y)))
- || coord_def(x, y) == grid2view(you.pos()));
+ return (in_los_bounds(x, y)
+ && (env.show(view2show(coord_def(x, y)))
+ || coord_def(x, y) == grid2view(you.pos())));
}
bool in_vlos(const coord_def &pos)
@@ -1115,28 +1115,30 @@ bool in_los(int x, int y)
static bool find_monster( int x, int y, int mode, int range = -1)
{
+ // target the player for friendly and general spells
if ((mode == TARG_FRIEND || mode == TARG_ANY)
&& x == you.x_pos && y == you.y_pos)
{
return (true);
}
-
+
// don't target out of range
if (!_is_target_in_range(x, y, range))
return (false);
-
+
const int targ_mon = mgrd[ x ][ y ];
-
+
// No monster or outside LOS.
if (targ_mon == NON_MONSTER || !in_los(x,y))
return (false);
-
+
// Unseen monsters in shallow water show a "strange disturbance"
// (unless flying!)
if (!player_monster_visible(&menv[targ_mon]))
{
// since you can't see the monster, assume it's not a friend
- return (mode != TARG_FRIEND && grd[x][y] == DNGN_SHALLOW_WATER
+ return (mode != TARG_FRIEND
+ && grd[x][y] == DNGN_SHALLOW_WATER
&& !mons_flies(&menv[targ_mon]));
}
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index dc11da94f0..7f3ff99de4 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1778,6 +1778,7 @@ public:
char tile_monster_col;
char tile_neutral_col;
char tile_friendly_col;
+ char tile_plant_col;
char tile_item_col;
char tile_unseen_col;
char tile_floor_col;
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index cf0edbb097..519f5feb15 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -813,6 +813,7 @@ void game_options::reset_options()
tile_monster_col = MAP_RED;
tile_neutral_col = MAP_RED;
tile_friendly_col = MAP_LTRED;
+ tile_plant_col = MAP_DKGREEN;
tile_item_col = MAP_GREEN;
tile_unseen_col = MAP_BLACK;
tile_floor_col = MAP_LTGREY;
@@ -2580,6 +2581,11 @@ void game_options::read_option_line(const std::string &str, bool runscript)
tile_friendly_col =
_str_to_tile_colour(field);
}
+ else if (key == "tile_plant_col")
+ {
+ tile_plant_col =
+ _str_to_tile_colour(field);
+ }
else if (key == "tile_item_col")
{
tile_item_col =
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 5070a8ad6c..80a7f25787 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -184,6 +184,51 @@ bool can_wield(const item_def *weapon, bool say_reason,
#undef SAY
}
+static bool _valid_weapon_swap(const item_def &item)
+{
+ // weapons and staves are valid weapons
+ if (item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES)
+ return true;
+
+ // misc. items need to be wielded to be evoked
+ if (item.base_type == OBJ_MISCELLANY && item.sub_type != MISC_RUNE_OF_ZOT)
+ return true;
+
+ // some missiles need to be wielded for spells
+ if (item.base_type == OBJ_MISSILES)
+ {
+ if (item.sub_type == MI_STONE)
+ return (player_knows_spell(SPELL_SANDBLAST));
+
+ if (item.sub_type == MI_ARROW)
+ return (player_knows_spell(SPELL_STICKS_TO_SNAKES));
+
+ return false;
+ }
+
+ // Boneshards
+ if (item.base_type == OBJ_CORPSES)
+ {
+ return (item.sub_type == CORPSE_SKELETON
+ && player_knows_spell(SPELL_BONE_SHARDS));
+ }
+
+ // Sublimation of Blood
+ if (!player_knows_spell(SPELL_SUBLIMATION_OF_BLOOD))
+ return false;
+
+ if (item.base_type == OBJ_FOOD)
+ return (item.sub_type == FOOD_CHUNK);
+
+ if (item.base_type == OBJ_POTIONS && item_type_known(item))
+ {
+ return (item.sub_type == POT_BLOOD
+ || item.sub_type == POT_BLOOD_COAGULATED);
+ }
+
+ return false;
+}
+
bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages)
{
if (inv_count() < 1)
@@ -210,21 +255,18 @@ bool wield_weapon(bool auto_wield, int slot, bool show_weff_messages)
// If the swap slot has a bad (but valid) item in it,
// the swap will be to bare hands.
- const bool good_swap = (item_slot == PROMPT_GOT_SPECIAL)
- || you.inv[item_slot].base_type == OBJ_WEAPONS
- || you.inv[item_slot].base_type == OBJ_STAVES
- || (you.inv[item_slot].base_type == OBJ_MISCELLANY
- && you.inv[item_slot].sub_type != MISC_RUNE_OF_ZOT);
+ const bool good_swap = (item_slot == PROMPT_GOT_SPECIAL
+ || _valid_weapon_swap(you.inv[item_slot]));
// Prompt if not using the auto swap command, or if the swap slot
// is empty.
- if (item_slot != PROMPT_GOT_SPECIAL &&
- (!auto_wield || !is_valid_item(you.inv[item_slot]) || !good_swap))
+ if (item_slot != PROMPT_GOT_SPECIAL
+ && (!auto_wield || !is_valid_item(you.inv[item_slot]) || !good_swap))
{
if (!auto_wield)
item_slot = prompt_invent_item(
"Wield which item (- for none, * to show all)?",
- MT_INVLIST, OSEL_WIELD,
+ MT_INVLIST, OSEL_WIELD,
true, true, true, '-', NULL, OPER_WIELD);
else
item_slot = PROMPT_GOT_SPECIAL;
@@ -4534,21 +4576,36 @@ void tile_use_item(int idx, InvAction act)
}
else if (act == INV_USE2) // secondary item use
{
- if (you.inv[idx].base_type == OBJ_WEAPONS
- && is_throwable(you.inv[idx], player_size(PSIZE_BODY)))
+ const item_def item = you.inv[idx];
+
+ if (item.base_type == OBJ_WEAPONS
+ && is_throwable(item, player_size(PSIZE_BODY)))
{
- fire_thing(idx); // fire weapons
+ if (check_warning_inscriptions(item, OPER_FIRE))
+ fire_thing(idx); // fire weapons
}
- else if (you.inv[idx].base_type == OBJ_MISCELLANY
- || you.inv[idx].base_type == OBJ_STAVES
- && item_is_rod(you.inv[idx])) // unwield rods/misc. items
+ else if (item.base_type == OBJ_MISCELLANY
+ || item.base_type == OBJ_STAVES
+ && item_is_rod(item)) // unwield rods/misc. items
{
if (you.equip[EQ_WEAPON] == idx
- && check_warning_inscriptions(you.inv[idx], OPER_WIELD))
+ && check_warning_inscriptions(item, OPER_WIELD))
{
wield_weapon(true, PROMPT_GOT_SPECIAL); // unwield
}
}
+ else if (you.equip[EQ_WEAPON] == idx
+ && check_warning_inscriptions(item, OPER_WIELD))
+ {
+ wield_weapon(true, PROMPT_GOT_SPECIAL); // unwield
+ }
+ else if (_valid_weapon_swap(item)
+ && check_warning_inscriptions(item, OPER_WIELD))
+ {
+ // secondary wield for several spells and such
+ wield_weapon(true, idx); // wield
+ }
+
return;
}
else if (act != INV_USE)
@@ -4557,7 +4614,7 @@ void tile_use_item(int idx, InvAction act)
// Equipped?
bool equipped = false;
bool equipped_weapon = false;
- for (unsigned int i=0; i< NUM_EQUIP;i++)
+ for (unsigned int i = 0; i < NUM_EQUIP; i++)
{
if (you.equip[i] == idx)
{
@@ -4569,16 +4626,17 @@ void tile_use_item(int idx, InvAction act)
}
TileMoveInvCursor(-1);
+ const item_def item = you.inv[idx];
// Special case for folks who are wielding something
// that they shouldn't be wielding.
// Note that this is only a problem for equipables
// (otherwise it would only waste a turn)
if (you.equip[EQ_WEAPON] == idx
- && (you.inv[idx].base_type == OBJ_ARMOUR
- || you.inv[idx].base_type == OBJ_JEWELLERY))
+ && (item.base_type == OBJ_ARMOUR
+ || item.base_type == OBJ_JEWELLERY))
{
- if (!check_warning_inscriptions(you.inv[idx], OPER_WIELD))
+ if (!check_warning_inscriptions(item, OPER_WIELD))
return;
wield_weapon(true, PROMPT_GOT_SPECIAL);
@@ -4586,7 +4644,7 @@ void tile_use_item(int idx, InvAction act)
}
// Use it
- const int type = you.inv[idx].base_type;
+ const int type = item.base_type;
switch (type)
{
case OBJ_WEAPONS:
@@ -4595,82 +4653,83 @@ void tile_use_item(int idx, InvAction act)
// wield any unwielded item of these types
if (!equipped)
{
- if (check_warning_inscriptions(you.inv[idx], OPER_WIELD))
+ if (check_warning_inscriptions(item, OPER_WIELD))
wield_weapon(true, idx);
return;
}
// evoke misc. items and rods
- if (type == OBJ_MISCELLANY || item_is_rod(you.inv[idx]))
+ if (type == OBJ_MISCELLANY || item_is_rod(item))
{
- if (check_warning_inscriptions(you.inv[idx], OPER_EVOKE))
+ if (check_warning_inscriptions(item, OPER_EVOKE))
evoke_wielded();
return;
}
// unwield staves or weapons
- if (check_warning_inscriptions(you.inv[idx], OPER_WIELD))
+ if (check_warning_inscriptions(item, OPER_WIELD))
wield_weapon(true, PROMPT_GOT_SPECIAL); // unwield
return;
-
+
case OBJ_MISSILES:
- fire_thing(idx);
+ if (check_warning_inscriptions(item, OPER_FIRE))
+ fire_thing(idx);
return;
case OBJ_ARMOUR:
if (equipped && !equipped_weapon)
{
- if (check_warning_inscriptions(you.inv[idx], OPER_TAKEOFF))
+ if (check_warning_inscriptions(item, OPER_TAKEOFF))
takeoff_armour(idx);
}
- else if (check_warning_inscriptions(you.inv[idx], OPER_WEAR))
+ else if (check_warning_inscriptions(item, OPER_WEAR))
wear_armour(idx);
return;
case OBJ_WANDS:
- if (check_warning_inscriptions(you.inv[idx], OPER_ZAP))
+ if (check_warning_inscriptions(item, OPER_ZAP))
zap_wand(idx);
return;
case OBJ_CORPSES:
if (you.species != SP_VAMPIRE
- || you.inv[idx].sub_type == CORPSE_SKELETON
- || food_is_rotten(you.inv[idx]))
+ || item.sub_type == CORPSE_SKELETON
+ || food_is_rotten(item))
{
break;
}
// intentional fall-through for Vampires
case OBJ_FOOD:
- if (check_warning_inscriptions(you.inv[idx], OPER_EAT))
+ if (check_warning_inscriptions(item, OPER_EAT))
eat_food(false, idx);
return;
case OBJ_BOOKS:
- if (you.inv[idx].sub_type == BOOK_MANUAL
- || you.inv[idx].sub_type == BOOK_DESTRUCTION)
+ if (item.sub_type == BOOK_MANUAL
+ || item.sub_type == BOOK_DESTRUCTION)
{
- if (check_warning_inscriptions(you.inv[idx], OPER_READ))
+ if (check_warning_inscriptions(item, OPER_READ))
handle_read_book(idx);
} // else it's a spellbook
- else if (check_warning_inscriptions(you.inv[idx], OPER_MEMORISE))
+ else if (check_warning_inscriptions(item, OPER_MEMORISE))
learn_spell(idx);
return;
-
+
case OBJ_SCROLLS:
- if (check_warning_inscriptions(you.inv[idx], OPER_READ))
+ if (check_warning_inscriptions(item, OPER_READ))
read_scroll(idx);
return;
case OBJ_JEWELLERY:
if (equipped && !equipped_weapon)
{
- if (check_warning_inscriptions(you.inv[idx], OPER_REMOVE))
+ if (check_warning_inscriptions(item, OPER_REMOVE))
remove_ring(idx);
}
- else if (check_warning_inscriptions(you.inv[idx], OPER_PUTON))
+ else if (check_warning_inscriptions(item, OPER_PUTON))
puton_ring(idx, false);
return;
case OBJ_POTIONS:
- if (check_warning_inscriptions(you.inv[idx], OPER_QUAFF))
+ if (check_warning_inscriptions(item, OPER_QUAFF))
drink(idx);
return;
diff --git a/crawl-ref/source/libgui.cc b/crawl-ref/source/libgui.cc
index 9547d64ccf..c65f754ed3 100644
--- a/crawl-ref/source/libgui.cc
+++ b/crawl-ref/source/libgui.cc
@@ -21,9 +21,11 @@
#include "describe.h"
#include "direct.h"
#include "files.h"
+#include "food.h"
#include "itemname.h"
#include "itemprop.h"
#include "items.h"
+#include "it_use2.h"
#include "externs.h"
#include "guic.h"
#include "message.h"
@@ -368,15 +370,18 @@ void GmapUpdate(int x, int y, int what, bool upd_tile)
if (c == Options.tile_monster_col && mgrd[x][y] != NON_MONSTER
&& upd_tile)
{
- if (mons_friendly(&menv[mgrd[x][y]]))
+ const int grid = mgrd[x][y];
+ if (mons_friendly(&menv[grid]))
c = Options.tile_friendly_col; // colour friendly monsters
- else if (mons_neutral(&menv[mgrd[x][y]])
+ else if (mons_neutral(&menv[grid])
&& Options.tile_neutral_col != Options.tile_monster_col)
{
c = Options.tile_neutral_col; // colour neutral monsters
}
+ else if (mons_class_flag( menv[grid].type, M_NO_EXP_GAIN ))
+ c = Options.tile_plant_col;
}
-
+
if (c == Options.tile_floor_col || c == Options.tile_item_col)
{
if (is_exclude_root( coord_def(x,y) ))
@@ -1325,25 +1330,27 @@ static int _handle_mouse_motion(int mouse_x, int mouse_y, bool init)
if (itemlist_iflag[cx] & TILEI_FLAG_FLOOR)
{
+ const item_def item = mitm[ix];
+
if (itemlist_key[cx])
{
desc = itemlist_key[cx];
desc += " - ";
}
- desc += mitm[ix].name(DESC_NOCAP_A);
+ desc += item.name(DESC_NOCAP_A);
if (display_actions)
desc += EOL "[L-Click] Pick up (g)";
- if (mitm[ix].base_type == OBJ_CORPSES
- && mitm[ix].sub_type != CORPSE_SKELETON
- && !food_is_rotten(mitm[ix]))
+ if (item.base_type == OBJ_CORPSES
+ && item.sub_type != CORPSE_SKELETON
+ && !food_is_rotten(item))
{
desc += EOL "[Shift-L-Click] Dissect (D)";
-
+
if (you.species == SP_VAMPIRE)
desc += EOL "[Shift-R-Click] Drink blood (e)";
}
- else if (mitm[ix].base_type == OBJ_FOOD
+ else if (item.base_type == OBJ_FOOD
&& you.species != SP_VAMPIRE
&& you.species != SP_MUMMY)
{
@@ -1352,26 +1359,26 @@ static int _handle_mouse_motion(int mouse_x, int mouse_y, bool init)
}
else // in inventory
{
- desc = you.inv[ix].name(DESC_INVENTORY_EQUIP);
+ const item_def item = you.inv[ix];
+
+ desc = item.name(DESC_INVENTORY_EQUIP);
- // FIX ME: Might have to allow wielding as a secondary action
- // for arrows (Sticks to Snakes), skeletons (Boneshards),
- // chunks/potions of blood (Sublimation of Blood)
if (display_actions)
{
- int type = you.inv[ix].base_type;
+ int type = item.base_type;
const bool equipped = itemlist_iflag[cx] & TILEI_FLAG_EQUIP;
+ bool wielded = (you.equip[EQ_WEAPON] == ix);
desc += EOL;
-
+
if (_can_use_item(you.inv[ix], equipped))
{
desc += "[L-Click] ";
if (equipped)
{
- if (you.equip[EQ_WEAPON] == ix
+ if (wielded
&& type != OBJ_MISCELLANY
- && !item_is_rod(you.inv[ix]))
+ && !item_is_rod(item))
{
if (type == OBJ_JEWELLERY || type == OBJ_ARMOUR
|| type == OBJ_WEAPONS || type == OBJ_STAVES)
@@ -1390,17 +1397,17 @@ static int _handle_mouse_motion(int mouse_x, int mouse_y, bool init)
case OBJ_STAVES:
case OBJ_MISCELLANY:
desc += "Wield (w)";
- if (is_throwable(you.inv[ix], player_size(PSIZE_BODY)))
+ if (is_throwable(item, player_size(PSIZE_BODY)))
desc += EOL "[Ctrl-L-Click] Fire (f)";
break;
case OBJ_WEAPONS + 18:
desc += "Unwield";
- if (is_throwable(you.inv[ix], player_size(PSIZE_BODY)))
+ if (is_throwable(item, player_size(PSIZE_BODY)))
desc += EOL "[Ctrl-L-Click] Fire (f)";
break;
case OBJ_MISCELLANY + 18:
- if (you.inv[ix].sub_type >= MISC_DECK_OF_ESCAPE
- && you.inv[ix].sub_type <= MISC_DECK_OF_DEFENCE)
+ if (item.sub_type >= MISC_DECK_OF_ESCAPE
+ && item.sub_type <= MISC_DECK_OF_DEFENCE)
{
desc += "Draw a card (E)";
desc += EOL "[Ctrl-L-Click] Unwield";
@@ -1425,37 +1432,94 @@ static int _handle_mouse_motion(int mouse_x, int mouse_y, bool init)
break;
case OBJ_MISSILES:
desc += "Fire (f)";
+
+ if (wielded)
+ desc += EOL "[Ctrl-L-Click] Unwield";
+ else if ( item.sub_type == MI_STONE
+ && player_knows_spell(SPELL_SANDBLAST)
+ || item.sub_type == MI_ARROW
+ && player_knows_spell(
+ SPELL_STICKS_TO_SNAKES) )
+ {
+ // For Sandblast and Sticks to Snakes, respectively.
+ desc += EOL "[Ctrl-L-Click] Wield (w)";
+ }
break;
case OBJ_WANDS:
desc += "Zap (z)";
+ if (wielded)
+ desc += EOL "[Ctrl-L-Click] Unwield";
break;
case OBJ_BOOKS:
- if (item_type_known(you.inv[ix])
- && you.inv[ix].sub_type != BOOK_MANUAL
- && you.inv[ix].sub_type != BOOK_DESTRUCTION)
+ if (item_type_known(item)
+ && item.sub_type != BOOK_MANUAL
+ && item.sub_type != BOOK_DESTRUCTION)
{
desc += "Memorise (M)";
+ if (wielded)
+ desc += EOL "[Ctrl-L-Click] Unwield";
break;
}
// else fall-through
case OBJ_SCROLLS:
desc += "Read (r)";
+ if (wielded)
+ desc += EOL "[Ctrl-L-Click] Unwield";
break;
case OBJ_POTIONS:
desc += "Quaff (q)";
+ // For Sublimation of Blood.
+ if (wielded)
+ desc += EOL "[Ctrl-L-Click] Unwield";
+ else if ( item_type_known(item)
+ && (item.sub_type == POT_BLOOD
+ || item.sub_type
+ == POT_BLOOD_COAGULATED)
+ && player_knows_spell(
+ SPELL_SUBLIMATION_OF_BLOOD) )
+ {
+ desc += EOL "[Ctrl-L-Click] Wield (w)";
+ }
break;
case OBJ_FOOD:
desc += "Eat (e)";
+ // For Sublimation of Blood.
+ if (wielded)
+ desc += EOL "[Ctrl-L-Click] Unwield";
+ else if (item.sub_type == FOOD_CHUNK
+ && player_knows_spell(
+ SPELL_SUBLIMATION_OF_BLOOD))
+ {
+ desc += EOL "[Ctrl-L-Click] Wield (w)";
+ }
break;
case OBJ_CORPSES:
if (you.species == SP_VAMPIRE)
desc += "Drink blood (e)";
+
+ if (wielded)
+ {
+ if (you.species == SP_VAMPIRE)
+ desc += EOL;
+ desc += "[Ctrl-L-Click] Unwield";
+ }
break;
default:
desc += "Use";
}
}
+ // For Boneshards.
+ // special handling since skeletons have no primary action
+ if (item.base_type == OBJ_CORPSES
+ && item.sub_type == CORPSE_SKELETON)
+ {
+ if (wielded)
+ desc += EOL "[Ctrl-L-Click] Unwield";
+ else if (player_knows_spell(SPELL_BONE_SHARDS))
+ desc += EOL "[Ctrl-L-Click] Wield (w)";
+ }
+
desc += EOL "[R-Click] Info";
// has to be non-equipped or non-cursed to drop
if (!equipped || !_is_true_equipped_item(you.inv[ix])
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index c4e9cf1ce7..54f4379754 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -1132,6 +1132,15 @@ int player_spell_levels(void)
return (sl);
}
+bool player_knows_spell(int spell)
+{
+ for (int i = 0; i < 25; i++)
+ if (you.spells[i] == spell)
+ return true;
+
+ return false;
+}
+
int player_res_magic(void)
{
int rm = 0;
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index 457db18132..2a31244d4e 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -228,6 +228,10 @@ int player_speed(void);
* *********************************************************************** */
int player_spell_levels(void);
+/* ***********************************************************************
+ * called from: libgui - item_use
+ * *********************************************************************** */
+bool player_knows_spell(int spell);
// last updated 18may2000 {dlb}
/* ***********************************************************************