#include "AppHdr.h"
#include "itemname.h"
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef TARGET_OS_DOS
#include <conio.h>
#endif
#include "externs.h"
#include "artefact.h"
#include "decks.h"
#include "food.h"
#include "invent.h"
#include "items.h"
#include "itemprop.h"
#include "macro.h"
#include "mon-util.h"
#include "monstuff.h"
#include "notes.h"
#include "player.h"
#include "quiver.h"
#include "random.h"
#include "shopping.h"
#include "stuff.h"
#include "transfor.h"
#include "xom.h"
struct armour_def
{
armour_type id;
const char *name;
int ac;
int ev;
int mass;
bool light;
equipment_type slot;
size_type fit_min;
size_type fit_max;
};
static int Armour_index[NUM_ARMOURS];
static armour_def Armour_prop[NUM_ARMOURS] =
{
{ ARM_ANIMAL_SKIN, "animal skin", 2, 0, 100,
true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_ROBE, "robe", 2, 0, 60,
true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_BIG },
{ ARM_LEATHER_ARMOUR, "leather armour", 3, -1, 150,
true, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_RING_MAIL, "ring mail", 4, -2, 250,
false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_SCALE_MAIL, "scale mail", 5, -3, 350,
false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_CHAIN_MAIL, "chain mail", 6, -4, 400,
false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_BANDED_MAIL, "banded mail", 7, -5, 500,
false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_SPLINT_MAIL, "splint mail", 8, -5, 550,
false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_PLATE_MAIL, "plate mail", 10, -6, 650,
false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_CRYSTAL_PLATE_MAIL, "crystal plate mail", 14, -8, 1200,
false, EQ_BODY_ARMOUR, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_TROLL_HIDE, "troll hide", 2, -1, 220,
true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_TROLL_LEATHER_ARMOUR, "troll leather armour", 4, -1, 220,
true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_STEAM_DRAGON_HIDE, "steam dragon hide", 2, 0, 120,
true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_STEAM_DRAGON_ARMOUR, "steam dragon armour", 4, 0, 120,
true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_MOTTLED_DRAGON_HIDE, "mottled dragon hide", 3, -1, 150,
true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_MOTTLED_DRAGON_ARMOUR,"mottled dragon armour", 5, -1, 150,
true, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_SWAMP_DRAGON_HIDE, "swamp dragon hide", 3, -2, 200,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_SWAMP_DRAGON_ARMOUR, "swamp dragon armour", 7, -2, 200,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_DRAGON_HIDE, "dragon hide", 3, -3, 350,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_DRAGON_ARMOUR, "dragon armour", 8, -3, 350,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_ICE_DRAGON_HIDE, "ice dragon hide", 4, -3, 350,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_ICE_DRAGON_ARMOUR, "ice dragon armour", 9, -3, 350,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_STORM_DRAGON_HIDE, "storm dragon hide", 4, -4, 600,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_STORM_DRAGON_ARMOUR, "storm dragon armour", 10, -5, 600,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_GOLD_DRAGON_HIDE, "gold dragon hide", 4, -5, 1100,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_GOLD_DRAGON_ARMOUR, "gold dragon armour", 11, -9, 1100,
false, EQ_BODY_ARMOUR, SIZE_LITTLE, SIZE_GIANT },
{ ARM_CLOAK, "cloak", 1, 0, 40,
true, EQ_CLOAK, SIZE_LITTLE, SIZE_BIG },
{ ARM_GLOVES, "gloves", 1, 0, 20,
true, EQ_GLOVES, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_HELMET, "helmet", 1, 0, 80,
false, EQ_HELMET, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_CAP, "cap", 0, 0, 40,
true, EQ_HELMET, SIZE_LITTLE, SIZE_LARGE },
{ ARM_WIZARD_HAT, "wizard hat", 0, 0, 40,
true, EQ_HELMET, SIZE_LITTLE, SIZE_LARGE },
{ ARM_BOOTS, "boots", 1, 0, 30,
true, EQ_BOOTS, SIZE_SMALL, SIZE_MEDIUM },
{ ARM_CENTAUR_BARDING, "centaur barding", 4, -2, 100,
true, EQ_BOOTS, SIZE_MEDIUM, SIZE_LARGE },
{ ARM_NAGA_BARDING, "naga barding", 4, -2, 100,
true, EQ_BOOTS, SIZE_MEDIUM, SIZE_LARGE },
{ ARM_BUCKLER, "buckler", 3, 0, 90,
true, EQ_SHIELD, SIZE_LITTLE, SIZE_MEDIUM },
{ ARM_SHIELD, "shield", 5, -1, 150,
false, EQ_SHIELD, SIZE_SMALL, SIZE_BIG },
{ ARM_LARGE_SHIELD, "large shield", 7, -2, 230,
false, EQ_SHIELD, SIZE_MEDIUM, SIZE_GIANT },
};
struct weapon_def
{
int id;
const char *name;
int dam;
int hit;
int speed;
int mass;
int str_weight;
skill_type skill;
hands_reqd_type hands;
size_type fit_size; missile_type ammo; bool throwable;
int dam_type;
int acquire_weight;
};
static int Weapon_index[NUM_WEAPONS];
static weapon_def Weapon_prop[NUM_WEAPONS] =
{
{ WPN_CLUB, "club", 5, 3, 13, 50, 7,
SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, true,
DAMV_CRUSHING, 0 },
{ WPN_WHIP, "whip", 6, 2, 11, 30, 2,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLASHING, 0 },
{ WPN_HAMMER, "hammer", 7, 3, 13, 90, 7,
SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
DAMV_CRUSHING, 0 },
{ WPN_MACE, "mace", 8, 3, 14, 120, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
DAMV_CRUSHING, 10 },
{ WPN_FLAIL, "flail", 9, 2, 15, 130, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
DAMV_CRUSHING, 10 },
{ WPN_ANKUS, "ankus", 9, 2, 14, 120, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_PIERCING | DAM_BLUDGEON, 10 },
{ WPN_MORNINGSTAR, "morningstar", 10, -1, 15, 140, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_PIERCING | DAM_BLUDGEON, 10 },
{ WPN_DEMON_WHIP, "demon whip", 10, 1, 11, 30, 2,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLASHING, 2 },
{ WPN_SPIKED_FLAIL, "spiked flail", 12, -2, 16, 190, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_PIERCING | DAM_BLUDGEON, 10 },
{ WPN_DIRE_FLAIL, "dire flail", 13, -3, 14, 240, 9,
SK_MACES_FLAILS, HANDS_DOUBLE, SIZE_LARGE, MI_NONE, false,
DAMV_PIERCING | DAM_BLUDGEON, 10 },
{ WPN_EVENINGSTAR, "eveningstar", 14, -1, 15, 180, 8,
SK_MACES_FLAILS, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_PIERCING | DAM_BLUDGEON, 2 },
{ WPN_GREAT_MACE, "great mace", 17, -4, 17, 270, 9,
SK_MACES_FLAILS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_CRUSHING, 10 },
{ WPN_GIANT_CLUB, "giant club", 20, -6, 17, 330, 10,
SK_MACES_FLAILS, HANDS_TWO, SIZE_BIG, MI_NONE, false,
DAMV_CRUSHING, 0 },
{ WPN_GIANT_SPIKED_CLUB, "giant spiked club", 22, -7, 18, 350, 10,
SK_MACES_FLAILS, HANDS_TWO, SIZE_BIG, MI_NONE, false,
DAMV_PIERCING | DAM_BLUDGEON, 0 },
{ WPN_KNIFE, "knife", 3, 5, 10, 10, 1,
SK_SHORT_BLADES, HANDS_ONE, SIZE_LITTLE, MI_NONE, false,
DAMV_STABBING | DAM_SLICE, 0 },
{ WPN_DAGGER, "dagger", 4, 6, 10, 20, 1,
SK_SHORT_BLADES, HANDS_ONE, SIZE_LITTLE, MI_NONE, true,
DAMV_STABBING | DAM_SLICE, 10 },
{ WPN_QUICK_BLADE, "quick blade", 5, 6, 7, 50, 0,
SK_SHORT_BLADES, HANDS_ONE, SIZE_LITTLE, MI_NONE, false,
DAMV_STABBING | DAM_SLICE, 2 },
{ WPN_SHORT_SWORD, "short sword", 6, 4, 11, 80, 2,
SK_SHORT_BLADES, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
DAMV_SLICING | DAM_PIERCE, 10 },
{ WPN_SABRE, "sabre", 7, 4, 12, 90, 2,
SK_SHORT_BLADES, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
DAMV_SLICING | DAM_PIERCE, 10 },
{ WPN_FALCHION, "falchion", 8, 2, 13, 170, 4,
SK_LONG_BLADES, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
DAMV_SLICING, 10 }, { WPN_BLESSED_FALCHION, "blessed falchion", 10, 2, 11, 170, 4,
SK_LONG_BLADES, HANDS_ONE, SIZE_SMALL, MI_NONE, false,
DAMV_SLICING, 10 }, { WPN_LONG_SWORD, "long sword", 10, 1, 14, 160, 3,
SK_LONG_BLADES, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 10 },
{ WPN_BLESSED_LONG_SWORD, "blessed long sword", 12, 0, 12, 160, 3,
SK_LONG_BLADES, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 10 },
{ WPN_SCIMITAR, "scimitar", 11, -1, 14, 170, 3,
SK_LONG_BLADES, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 10 },
{ WPN_BLESSED_SCIMITAR, "blessed scimitar", 13, -1, 13, 170, 3,
SK_LONG_BLADES, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 10 },
{ WPN_KATANA, "katana", 13, 2, 13, 160, 3,
SK_LONG_BLADES, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 2 },
{ WPN_BLESSED_KATANA, "blessed katana", 14, 1, 13, 160, 3,
SK_LONG_BLADES, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 2 },
{ WPN_DEMON_BLADE, "demon blade", 13, -1, 15, 200, 4,
SK_LONG_BLADES, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 2 },
{ WPN_BLESSED_EUDEMON_BLADE, "blessed eudemon blade", 14, -2, 14, 200, 4,
SK_LONG_BLADES, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 0 },
{ WPN_DOUBLE_SWORD, "double sword", 15, -2, 16, 220, 5,
SK_LONG_BLADES, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 2 },
{ WPN_BLESSED_DOUBLE_SWORD, "blessed double sword", 15, -2, 15, 220, 5,
SK_LONG_BLADES, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
DAMV_SLICING, 2 },
{ WPN_GREAT_SWORD, "great sword", 16, -3, 17, 250, 6,
SK_LONG_BLADES, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_SLICING, 10 },
{ WPN_BLESSED_GREAT_SWORD, "blessed great sword", 17, -3, 17, 250, 6,
SK_LONG_BLADES, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_SLICING, 10 },
{ WPN_TRIPLE_SWORD, "triple sword", 19, -4, 19, 260, 6,
SK_LONG_BLADES, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_SLICING, 2 },
{ WPN_BLESSED_TRIPLE_SWORD, "blessed triple sword", 19, -4, 18, 260, 6,
SK_LONG_BLADES, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_SLICING, 2 },
{ WPN_HAND_AXE, "hand axe", 7, 3, 13, 80, 6,
SK_AXES, HANDS_ONE, SIZE_SMALL, MI_NONE, true,
DAMV_CHOPPING, 10 },
{ WPN_WAR_AXE, "war axe", 11, 0, 16, 180, 7,
SK_AXES, HANDS_ONE, SIZE_MEDIUM, MI_NONE, false,
DAMV_CHOPPING, 10 },
{ WPN_BROAD_AXE, "broad axe", 14, -2, 17, 230, 8,
SK_AXES, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
DAMV_CHOPPING, 10 },
{ WPN_BATTLEAXE, "battleaxe", 17, -4, 18, 250, 8,
SK_AXES, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_CHOPPING, 10 },
{ WPN_EXECUTIONERS_AXE, "executioner\'s axe", 20, -6, 20, 280, 9,
SK_AXES, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_CHOPPING, 2 },
{ WPN_SPEAR, "spear", 6, 3, 12, 50, 3,
SK_POLEARMS, HANDS_HALF, SIZE_SMALL, MI_NONE, true,
DAMV_PIERCING, 10 },
{ WPN_TRIDENT, "trident", 9, 2, 14, 160, 4,
SK_POLEARMS, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
DAMV_PIERCING, 10 },
{ WPN_DEMON_TRIDENT, "demon trident", 13, 0, 14, 160, 4,
SK_POLEARMS, HANDS_HALF, SIZE_MEDIUM, MI_NONE, false,
DAMV_PIERCING, 2 },
{ WPN_HALBERD, "halberd", 13, -3, 16, 200, 5,
SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_CHOPPING | DAM_PIERCE, 10 },
{ WPN_SCYTHE, "scythe", 14, -4, 20, 220, 7,
SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_SLICING, 10 },
{ WPN_GLAIVE, "glaive", 15, -3, 18, 200, 6,
SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_CHOPPING, 10 },
{ WPN_BARDICHE, "bardiche", 18, -6, 20, 200, 8,
SK_POLEARMS, HANDS_TWO, SIZE_LARGE, MI_NONE, false,
DAMV_CHOPPING, 2 },
{ WPN_QUARTERSTAFF, "quarterstaff", 7, 6, 12, 180, 7,
SK_STAVES, HANDS_DOUBLE, SIZE_LARGE, MI_NONE, false,
DAMV_CRUSHING, 10 },
{ WPN_LAJATANG, "lajatang", 14, -3, 14, 200, 3,
SK_STAVES, HANDS_DOUBLE, SIZE_LARGE, MI_NONE, false,
DAMV_SLICING, 2 },
{ WPN_BLOWGUN, "blowgun", 0, 2, 10, 20, 0,
SK_DARTS, HANDS_HALF, SIZE_LITTLE, MI_NEEDLE, false,
DAMV_NON_MELEE, 0 },
{ WPN_SLING, "sling", 0, 2, 11, 20, 1,
SK_SLINGS, HANDS_HALF, SIZE_LITTLE, MI_STONE, false,
DAMV_NON_MELEE, 10 },
{ WPN_HAND_CROSSBOW, "hand crossbow", 3, 4, 15, 70, 5,
SK_CROSSBOWS, HANDS_HALF, SIZE_SMALL, MI_DART, false,
DAMV_NON_MELEE, 10 },
{ WPN_CROSSBOW, "crossbow", 5, 4, 15, 150, 8,
SK_CROSSBOWS, HANDS_TWO, SIZE_MEDIUM, MI_BOLT, false,
DAMV_NON_MELEE, 10 },
{ WPN_BOW, "bow", 3, 1, 11, 90, 2,
SK_BOWS, HANDS_TWO, SIZE_MEDIUM, MI_ARROW, false,
DAMV_NON_MELEE, 10 },
{ WPN_LONGBOW, "longbow", 6, 0, 12, 120, 3,
SK_BOWS, HANDS_TWO, SIZE_LARGE, MI_ARROW, false,
DAMV_NON_MELEE, 10 },
};
struct missile_def
{
int id;
const char *name;
int dam;
int mass;
bool throwable;
};
static int Missile_index[NUM_MISSILES];
static missile_def Missile_prop[NUM_MISSILES] =
{
{ MI_NEEDLE, "needle", 0, 1, false },
{ MI_STONE, "stone", 4, 2, true },
{ MI_DART, "dart", 5, 3, true },
{ MI_ARROW, "arrow", 7, 5, false },
{ MI_BOLT, "bolt", 9, 5, false },
{ MI_LARGE_ROCK, "large rock", 20, 400, true },
{ MI_SLING_BULLET, "sling bullet", 6, 4, false },
{ MI_JAVELIN, "javelin", 10, 80, true },
{ MI_THROWING_NET, "throwing net", 0, 30, true },
};
struct food_def
{
int id;
const char *name;
int value;
int carn_mod;
int herb_mod;
int mass;
int turns;
};
static int Food_index[NUM_FOODS];
static food_def Food_prop[NUM_FOODS] =
{
{ FOOD_MEAT_RATION, "meat ration", 5000, 500, -1500, 80, 4 },
{ FOOD_SAUSAGE, "sausage", 1500, 150, -400, 40, 1 },
{ FOOD_CHUNK, "chunk", 1000, 100, -500, 100, 3 },
{ FOOD_BEEF_JERKY, "beef jerky", 800, 100, -250, 20, 1 },
{ FOOD_BREAD_RATION, "bread ration", 4400, -1500, 750, 80, 4 },
{ FOOD_SNOZZCUMBER, "snozzcumber", 1500, -500, 500, 50, 1 },
{ FOOD_ORANGE, "orange", 1000, -350, 400, 20, 1 },
{ FOOD_BANANA, "banana", 1000, -350, 400, 20, 1 },
{ FOOD_LEMON, "lemon", 1000, -350, 400, 20, 1 },
{ FOOD_PEAR, "pear", 700, -250, 300, 20, 1 },
{ FOOD_APPLE, "apple", 700, -250, 300, 20, 1 },
{ FOOD_APRICOT, "apricot", 700, -250, 300, 15, 1 },
{ FOOD_CHOKO, "choko", 600, -200, 250, 30, 1 },
{ FOOD_RAMBUTAN, "rambutan", 600, -200, 250, 10, 1 },
{ FOOD_LYCHEE, "lychee", 600, -200, 250, 10, 1 },
{ FOOD_STRAWBERRY, "strawberry", 200, -80, 100, 5, 1 },
{ FOOD_GRAPE, "grape", 100, -40, 50, 2, 1 },
{ FOOD_SULTANA, "sultana", 70, -30, 30, 1, 1 },
{ FOOD_ROYAL_JELLY, "royal jelly", 4000, 0, 0, 55, 1 },
{ FOOD_HONEYCOMB, "honeycomb", 2000, 0, 0, 40, 1 },
{ FOOD_PIZZA, "pizza", 1500, 0, 0, 40, 1 },
{ FOOD_CHEESE, "cheese", 1200, 0, 0, 40, 1 },
};
void init_properties()
{
COMPILE_CHECK(NUM_ARMOURS == 37, c1);
COMPILE_CHECK(NUM_WEAPONS == 55, c2);
COMPILE_CHECK(NUM_MISSILES == 9, c3);
COMPILE_CHECK(NUM_FOODS == 22, c4);
int i;
for (i = 0; i < NUM_ARMOURS; i++)
Armour_index[ Armour_prop[i].id ] = i;
for (i = 0; i < NUM_WEAPONS; i++)
Weapon_index[ Weapon_prop[i].id ] = i;
for (i = 0; i < NUM_MISSILES; i++)
Missile_index[ Missile_prop[i].id ] = i;
for (i = 0; i < NUM_FOODS; i++)
Food_index[ Food_prop[i].id ] = i;
}
bool item_cursed( const item_def &item )
{
return (item.flags & ISFLAG_CURSED);
}
bool item_known_cursed( const item_def &item )
{
return ((item.flags & ISFLAG_KNOW_CURSE) && (item.flags & ISFLAG_CURSED));
}
bool item_known_uncursed( const item_def &item )
{
return ((item.flags & ISFLAG_KNOW_CURSE) && !(item.flags & ISFLAG_CURSED));
}
void do_curse_item( item_def &item, bool quiet )
{
if (item.flags & ISFLAG_CURSED)
return;
if (item.base_type == OBJ_WEAPONS
&& get_weapon_brand(item) == SPWPN_HOLY_WRATH)
{
if (!quiet)
{
mprf("Your %s glows black briefly, but repels the curse",
item.name(DESC_PLAIN).c_str());
}
return;
}
if (!quiet)
{
mprf("Your %s glows black for a moment.",
item.name(DESC_PLAIN).c_str());
item.flags |= ISFLAG_KNOW_CURSE;
}
item.flags |= ISFLAG_CURSED;
if (in_inventory(item))
{
int amusement = 64;
if (item_is_equipped(item))
{
amusement *= 2;
if (item.base_type == OBJ_ARMOUR
&& (get_armour_slot(item) == EQ_CLOAK
|| get_armour_slot(item) == EQ_GLOVES))
{
amusement *= 2;
}
else if (you.equip[EQ_WEAPON] == item.link)
{
you.wield_change = true;
}
}
xom_is_stimulated(amusement);
}
}
void do_uncurse_item( item_def &item )
{
if (in_inventory(item) && you.equip[EQ_WEAPON] == item.link)
{
you.wield_change = true;
}
item.flags &= (~ISFLAG_CURSED);
}
void set_item_stationary( item_def &item )
{
if (item.base_type == OBJ_MISSILES && item.sub_type == MI_THROWING_NET)
item.plus2 = 1;
}
void remove_item_stationary( item_def &item )
{
if (item.base_type == OBJ_MISSILES && item.sub_type == MI_THROWING_NET)
item.plus2 = 0;
}
bool item_is_stationary( const item_def &item )
{
return (item.base_type == OBJ_MISSILES
&& item.sub_type == MI_THROWING_NET
&& item.plus2);
}
bool item_ident( const item_def &item, unsigned long flags )
{
return ((item.flags & flags) == flags);
}
bool item_is_critical(const item_def &item)
{
if (!is_valid_item(item))
return (false);
if (item.base_type == OBJ_ORBS)
return (true);
return (item.base_type == OBJ_MISCELLANY
&& item.sub_type == MISC_RUNE_OF_ZOT
&& item.plus != RUNE_DEMONIC
&& item.plus != RUNE_ABYSSAL);
}
bool item_is_mundane(const item_def &item)
{
switch (item.base_type)
{
case OBJ_WEAPONS:
if (item.sub_type == WPN_CLUB
|| item.sub_type == WPN_GIANT_CLUB
|| item.sub_type == WPN_GIANT_SPIKED_CLUB
|| item.sub_type == WPN_KNIFE)
{
return (true);
}
break;
case OBJ_ARMOUR:
if (item.sub_type == ARM_ANIMAL_SKIN)
return (true);
break;
default:
break;
}
return (false);
}
void set_ident_flags( item_def &item, unsigned long flags )
{
preserve_quiver_slots p;
if ((item.flags & flags) != flags)
{
item.flags |= flags;
request_autoinscribe();
if (in_inventory(item))
shopping_list.cull_identical_items(item);
}
if (notes_are_active() && !(item.flags & ISFLAG_NOTED_ID)
&& get_ident_type(item) != ID_KNOWN_TYPE
&& fully_identified(item) && is_interesting_item(item))
{
take_note(Note(NOTE_ID_ITEM, 0, 0, item.name(DESC_NOCAP_A).c_str(),
origin_desc(item).c_str()));
item.flags |= (ISFLAG_NOTED_ID | ISFLAG_NOTED_GET);
}
}
void unset_ident_flags( item_def &item, unsigned long flags )
{
preserve_quiver_slots p;
item.flags &= (~flags);
}
unsigned long full_ident_mask( const item_def& item )
{
unsigned long flagset = ISFLAG_IDENT_MASK;
switch (item.base_type)
{
case OBJ_FOOD:
case OBJ_CORPSES:
flagset = 0;
break;
case OBJ_MISCELLANY:
if (item.sub_type == MISC_RUNE_OF_ZOT)
flagset = 0;
else
flagset = ISFLAG_KNOW_TYPE;
break;
case OBJ_BOOKS:
case OBJ_ORBS:
case OBJ_SCROLLS:
case OBJ_POTIONS:
case OBJ_STAVES:
flagset = ISFLAG_KNOW_TYPE;
break;
case OBJ_WANDS:
flagset = (ISFLAG_KNOW_TYPE | ISFLAG_KNOW_PLUSES);
break;
case OBJ_JEWELLERY:
flagset = (ISFLAG_KNOW_CURSE | ISFLAG_KNOW_TYPE);
if (ring_has_pluses(item))
flagset |= ISFLAG_KNOW_PLUSES;
break;
case OBJ_MISSILES:
flagset = ISFLAG_KNOW_PLUSES | ISFLAG_KNOW_TYPE;
if (get_ammo_brand(item) == SPMSL_NORMAL)
flagset &= ~ISFLAG_KNOW_TYPE;
break;
case OBJ_WEAPONS:
case OBJ_ARMOUR:
default:
break;
}
if (item_type_known(item))
flagset &= (~ISFLAG_KNOW_TYPE);
if (is_artefact(item))
flagset |= ISFLAG_KNOW_PROPERTIES;
return flagset;
}
bool fully_identified( const item_def& item )
{
return item_ident(item, full_ident_mask(item));
}
unsigned long get_equip_race( const item_def &item )
{
return (item.flags & ISFLAG_RACIAL_MASK);
}
unsigned long get_equip_desc( const item_def &item )
{
return (item.flags & ISFLAG_COSMETIC_MASK);
}
void set_equip_race( item_def &item, unsigned long flags )
{
ASSERT( (flags & ~ISFLAG_RACIAL_MASK) == 0 );
switch (item.base_type)
{
case OBJ_WEAPONS:
if (item.sub_type > WPN_MAX_RACIAL)
return;
break;
case OBJ_ARMOUR:
if (item.sub_type > ARM_MAX_RACIAL)
return;
break;
case OBJ_MISSILES:
if (item.sub_type > MI_MAX_RACIAL)
return;
break;
default:
return;
}
switch (flags)
{
case ISFLAG_ELVEN:
switch (item.base_type)
{
case OBJ_WEAPONS:
if ((weapon_skill(item) == SK_MACES_FLAILS
&& item.sub_type != WPN_WHIP)
|| (weapon_skill(item) == SK_LONG_BLADES
&& item.sub_type != WPN_FALCHION
&& item.sub_type != WPN_LONG_SWORD
&& item.sub_type != WPN_SCIMITAR)
|| weapon_skill(item) == SK_AXES
|| (weapon_skill(item) == SK_POLEARMS
&& item.sub_type != WPN_SPEAR
&& item.sub_type != WPN_TRIDENT)
|| item.sub_type == WPN_CROSSBOW)
{
return;
}
break;
case OBJ_ARMOUR:
if (item.sub_type == ARM_SPLINT_MAIL
|| item.sub_type == ARM_BANDED_MAIL
|| item.sub_type == ARM_PLATE_MAIL
|| is_hard_helmet(item))
{
return;
}
break;
case OBJ_MISSILES:
if (item.sub_type == MI_BOLT)
return;
break;
default:
break;
}
break;
case ISFLAG_DWARVEN:
switch (item.base_type)
{
case OBJ_WEAPONS:
if (item.sub_type == WPN_WHIP
|| item.sub_type == WPN_CLUB
|| item.sub_type == WPN_QUICK_BLADE
|| (weapon_skill(item) == SK_LONG_BLADES
&& item.sub_type != WPN_FALCHION
&& item.sub_type != WPN_LONG_SWORD)
|| weapon_skill(item) == SK_POLEARMS
|| item.sub_type == WPN_BLOWGUN
|| item.sub_type == WPN_HAND_CROSSBOW
|| item.sub_type == WPN_BOW
|| item.sub_type == WPN_LONGBOW)
{
return;
}
break;
case OBJ_ARMOUR:
if (item.sub_type == ARM_ROBE
|| item.sub_type == ARM_LEATHER_ARMOUR
|| get_armour_slot(item) == EQ_HELMET && !is_hard_helmet(item))
{
return;
}
break;
case OBJ_MISSILES:
if (item.sub_type == MI_NEEDLE
|| item.sub_type == MI_ARROW
|| item.sub_type == MI_JAVELIN)
{
return;
}
break;
default:
break;
}
break;
case ISFLAG_ORCISH:
switch (item.base_type)
{
case OBJ_WEAPONS:
if (item.sub_type == WPN_QUICK_BLADE
|| item.sub_type == WPN_HAND_CROSSBOW
|| item.sub_type == WPN_LONGBOW)
return;
break;
case OBJ_ARMOUR:
if (get_armour_slot(item) == EQ_HELMET && !is_hard_helmet(item))
return;
break;
default:
break;
}
default:
break;
}
item.flags &= ~ISFLAG_RACIAL_MASK; item.flags |= flags;
}
void set_equip_desc( item_def &item, unsigned long flags )
{
ASSERT( (flags & ~ISFLAG_COSMETIC_MASK) == 0 );
item.flags &= ~ISFLAG_COSMETIC_MASK; item.flags |= flags;
}
short get_helmet_desc( const item_def &item )
{
ASSERT( is_helmet(item) );
return item.plus2;
}
void set_helmet_desc( item_def &item, helmet_desc_type type )
{
ASSERT( is_helmet(item) );
if (!is_hard_helmet(item) && type > THELM_DESC_MAX_SOFT)
type = THELM_DESC_PLAIN;
item.plus2 = type;
}
bool is_helmet(const item_def& item)
{
return (item.base_type == OBJ_ARMOUR && get_armour_slot(item) == EQ_HELMET);
}
bool is_hard_helmet(const item_def &item)
{
return (item.base_type == OBJ_ARMOUR && item.sub_type == ARM_HELMET);
}
void set_helmet_random_desc( item_def &item )
{
ASSERT( is_helmet(item) );
if (is_hard_helmet(item))
item.plus2 = random2(THELM_NUM_DESCS);
else
item.plus2 = random2(THELM_DESC_MAX_SOFT + 1);
}
bool set_item_ego_type( item_def &item, int item_type, int ego_type )
{
if (item.base_type == item_type && !is_artefact(item))
{
item.special = ego_type;
return (true);
}
return (false);
}
int get_weapon_brand( const item_def &item )
{
if (item.base_type != OBJ_WEAPONS)
return (SPWPN_NORMAL);
if (is_artefact( item ))
return (artefact_wpn_property( item, ARTP_BRAND ));
return (item.special);
}
int get_ammo_brand( const item_def &item )
{
if (item.base_type != OBJ_MISSILES || is_artefact( item ))
return (SPMSL_NORMAL);
return (item.special);
}
special_armour_type get_armour_ego_type( const item_def &item )
{
if (item.base_type != OBJ_ARMOUR || is_artefact( item ))
return (SPARM_NORMAL);
return (static_cast<special_armour_type>(item.special));
}
bool hide2armour( item_def &item )
{
if (item.base_type != OBJ_ARMOUR)
return (false);
switch (item.sub_type)
{
default:
return (false);
case ARM_DRAGON_HIDE:
item.sub_type = ARM_DRAGON_ARMOUR;
break;
case ARM_TROLL_HIDE:
item.sub_type = ARM_TROLL_LEATHER_ARMOUR;
break;
case ARM_ICE_DRAGON_HIDE:
item.sub_type = ARM_ICE_DRAGON_ARMOUR;
break;
case ARM_MOTTLED_DRAGON_HIDE:
item.sub_type = ARM_MOTTLED_DRAGON_ARMOUR;
break;
case ARM_STORM_DRAGON_HIDE:
item.sub_type = ARM_STORM_DRAGON_ARMOUR;
break;
case ARM_GOLD_DRAGON_HIDE:
item.sub_type = ARM_GOLD_DRAGON_ARMOUR;
break;
case ARM_SWAMP_DRAGON_HIDE:
item.sub_type = ARM_SWAMP_DRAGON_ARMOUR;
break;
case ARM_STEAM_DRAGON_HIDE:
item.sub_type = ARM_STEAM_DRAGON_ARMOUR;
break;
}
return (true);
}
int armour_max_enchant( const item_def &item )
{
ASSERT( item.base_type == OBJ_ARMOUR );
const int eq_slot = get_armour_slot( item );
int max_plus = MAX_SEC_ENCHANT;
if (eq_slot == EQ_BODY_ARMOUR || item.sub_type == ARM_CENTAUR_BARDING
|| item.sub_type == ARM_NAGA_BARDING)
{
max_plus = MAX_ARM_ENCHANT;
}
return (max_plus);
}
bool armour_is_hide( const item_def &item, bool inc_made )
{
ASSERT( item.base_type == OBJ_ARMOUR );
switch (item.sub_type)
{
case ARM_TROLL_LEATHER_ARMOUR:
case ARM_DRAGON_ARMOUR:
case ARM_ICE_DRAGON_ARMOUR:
case ARM_STEAM_DRAGON_ARMOUR:
case ARM_MOTTLED_DRAGON_ARMOUR:
case ARM_STORM_DRAGON_ARMOUR:
case ARM_GOLD_DRAGON_ARMOUR:
case ARM_SWAMP_DRAGON_ARMOUR:
return (inc_made);
case ARM_TROLL_HIDE:
case ARM_DRAGON_HIDE:
case ARM_ICE_DRAGON_HIDE:
case ARM_STEAM_DRAGON_HIDE:
case ARM_MOTTLED_DRAGON_HIDE:
case ARM_STORM_DRAGON_HIDE:
case ARM_GOLD_DRAGON_HIDE:
case ARM_SWAMP_DRAGON_HIDE:
return (true);
default:
break;
}
return (false);
}
bool armour_not_shiny( const item_def &item )
{
ASSERT( item.base_type == OBJ_ARMOUR );
switch (item.sub_type)
{
case ARM_ROBE:
case ARM_CLOAK:
case ARM_GLOVES:
case ARM_BOOTS:
case ARM_NAGA_BARDING:
case ARM_CENTAUR_BARDING:
case ARM_LEATHER_ARMOUR:
case ARM_ANIMAL_SKIN:
case ARM_TROLL_HIDE:
case ARM_TROLL_LEATHER_ARMOUR:
case ARM_CAP:
case ARM_WIZARD_HAT:
return (true);
}
return (false);
}
int armour_str_required( const item_def &arm )
{
ASSERT( arm.base_type == OBJ_ARMOUR );
int ret = 0;
const equipment_type slot = get_armour_slot( arm );
const int mass = item_mass( arm );
switch (slot)
{
case EQ_BODY_ARMOUR:
ret = mass / 35;
break;
case EQ_SHIELD:
ret = mass / 15;
break;
default:
break;
}
return ((ret < STR_REQ_THRESHOLD) ? 0 : ret);
}
equipment_type get_armour_slot( const item_def &item )
{
ASSERT( item.base_type == OBJ_ARMOUR );
return (Armour_prop[ Armour_index[item.sub_type] ].slot);
}
equipment_type get_armour_slot( armour_type arm )
{
return (Armour_prop[ Armour_index[arm] ].slot);
}
bool jewellery_is_amulet( const item_def &item )
{
ASSERT( item.base_type == OBJ_JEWELLERY );
return (item.sub_type >= AMU_RAGE);
}
bool jewellery_is_amulet( int sub_type )
{
return (sub_type >= AMU_RAGE);
}
bool check_jewellery_size( const item_def &item, size_type size )
{
ASSERT( item.base_type == OBJ_JEWELLERY );
return (size <= SIZE_LARGE || jewellery_is_amulet( item ));
}
bool base_armour_is_light( const item_def &item )
{
ASSERT( item.base_type == OBJ_ARMOUR );
return (Armour_prop[ Armour_index[item.sub_type] ].light);
}
int fit_armour_size( const item_def &item, size_type size )
{
ASSERT( item.base_type == OBJ_ARMOUR );
const size_type min = Armour_prop[ Armour_index[item.sub_type] ].fit_min;
const size_type max = Armour_prop[ Armour_index[item.sub_type] ].fit_max;
if (size < min)
return (min - size); else if (size > max)
return (max - size);
return (0);
}
bool check_armour_size( const item_def &item, size_type size )
{
ASSERT( item.base_type == OBJ_ARMOUR );
return (fit_armour_size( item, size ) == 0);
}
bool check_armour_shape( const item_def &item, bool quiet )
{
ASSERT( item.base_type == OBJ_ARMOUR );
const int slot = get_armour_slot( item );
if (!player_is_shapechanged())
{
switch (slot)
{
case EQ_BOOTS:
if (player_mutation_level(MUT_HOOVES))
{
if (!quiet)
mpr("You can't wear boots with hooves!");
return (false);
}
if (player_mutation_level(MUT_TALONS))
{
if (!quiet)
mpr("Boots don't fit your talons!");
return (false);
}
switch (you.species)
{
case SP_NAGA:
if (item.sub_type != ARM_NAGA_BARDING)
{
if (!quiet)
mpr("You can't wear that!");
return (false);
}
break;
case SP_CENTAUR:
if (item.sub_type != ARM_CENTAUR_BARDING)
{
if (!quiet)
mpr("You can't wear that!");
return (false);
}
break;
case SP_MERFOLK:
if (player_in_water() && item.sub_type == ARM_BOOTS)
{
if (!quiet)
mpr("You don't currently have feet!");
return (false);
}
default:
if (item.sub_type == ARM_NAGA_BARDING
|| item.sub_type == ARM_CENTAUR_BARDING)
{
if (!quiet)
mpr("You can't wear barding!");
return (false);
}
break;
}
break;
case EQ_HELMET:
if (!is_hard_helmet(item))
break;
if (player_mutation_level(MUT_HORNS))
{
if (!quiet)
mpr("You can't wear that with your horns!");
return (false);
}
if (player_mutation_level(MUT_BEAK))
{
if (!quiet)
mpr("You can't wear that with your beak!");
return (false);
}
break;
case EQ_GLOVES:
if (you.has_claws(false) >= 3)
{
if (!quiet)
mpr("You can't wear gloves with your huge claws!");
return (false);
}
break;
case EQ_BODY_ARMOUR:
if (player_genus( GENPC_DRACONIAN )
&& !check_armour_size( item, SIZE_BIG ))
{
if (!quiet)
mpr("That armour doesn't fit your wings.");
return (false);
}
break;
default:
break;
}
}
else
{
if (item.sub_type == ARM_NAGA_BARDING
|| item.sub_type == ARM_CENTAUR_BARDING)
{
if (!quiet)
mpr("You can't wear barding in your current form!");
return (false);
}
}
return (true);
}
bool item_is_rechargeable(const item_def &it, bool hide_charged, bool weapons)
{
if (it.base_type == OBJ_WANDS)
{
if (!hide_charged)
return (true);
if (it.plus2 == ZAPCOUNT_MAX_CHARGED
|| item_ident(it, ISFLAG_KNOW_PLUSES)
&& it.plus >= 3 * wand_charge_value(it.sub_type))
{
return (false);
}
return (true);
}
else if (item_is_rod(it))
{
if (!hide_charged)
return (true);
if (item_ident(it, ISFLAG_KNOW_PLUSES))
{
return (it.plus2 < MAX_ROD_CHARGE * ROD_CHARGE_MULT
|| it.plus < it.plus2);
}
return (true);
}
else if (it.base_type == OBJ_WEAPONS)
{
if (weapons && !item_type_known(it))
return (true);
if (!is_artefact(it)
&& get_weapon_brand(it) == SPWPN_ELECTROCUTION
&& item_type_known(it)
&& (!item_ident(it, ISFLAG_KNOW_PLUSES)
|| it.plus2 < MAX_WPN_ENCHANT))
{
return (true);
}
}
return (false);
}
int wand_charge_value(int type)
{
switch (type)
{
case WAND_INVISIBILITY:
case WAND_FIREBALL:
case WAND_TELEPORTATION:
case WAND_HEALING:
case WAND_HASTING:
return 3;
case WAND_LIGHTNING:
case WAND_DRAINING:
return 4;
case WAND_FIRE:
case WAND_COLD:
return 5;
default:
return 8;
}
}
bool is_enchantable_weapon(const item_def &wpn, bool uncurse, bool first)
{
if (wpn.base_type != OBJ_WEAPONS && wpn.base_type != OBJ_MISSILES)
return (false);
if (wpn.base_type == OBJ_WEAPONS)
{
if (is_artefact(wpn)
|| first && wpn.plus >= MAX_WPN_ENCHANT
|| !first && wpn.plus2 >= MAX_WPN_ENCHANT)
{
return (uncurse && item_cursed(wpn));
}
}
else if (wpn.plus >= MAX_WPN_ENCHANT)
return (false);
return (true);
}
bool is_enchantable_armour(const item_def &arm, bool uncurse, bool unknown)
{
if (arm.base_type != OBJ_ARMOUR)
return (false);
if (!you_tran_can_wear(arm) && item_is_equipped(arm))
return (false);
if (unknown && !is_known_artefact(arm)
&& !item_ident(arm, ISFLAG_KNOW_PLUSES ))
{
return (true);
}
if (is_artefact(arm) || arm.plus >= armour_max_enchant(arm))
return (uncurse && item_cursed(arm));
return (true);
}
int weapon_rarity( int w_type )
{
switch (w_type)
{
case WPN_CLUB:
case WPN_DAGGER:
return (10);
case WPN_HAND_AXE:
case WPN_MACE:
case WPN_QUARTERSTAFF:
return (9);
case WPN_BOW:
case WPN_FLAIL:
case WPN_HAMMER:
case WPN_SABRE:
case WPN_SHORT_SWORD:
case WPN_SLING:
case WPN_SPEAR:
return (8);
case WPN_FALCHION:
case WPN_LONG_SWORD:
case WPN_MORNINGSTAR:
case WPN_WAR_AXE:
return (7);
case WPN_BATTLEAXE:
case WPN_CROSSBOW:
case WPN_GREAT_SWORD:
case WPN_SCIMITAR:
case WPN_TRIDENT:
return (6);
case WPN_GLAIVE:
case WPN_HALBERD:
case WPN_BLOWGUN:
return (5);
case WPN_BROAD_AXE:
case WPN_HAND_CROSSBOW:
case WPN_SPIKED_FLAIL:
case WPN_WHIP:
return (4);
case WPN_GREAT_MACE:
return (3);
case WPN_ANKUS:
case WPN_DIRE_FLAIL:
case WPN_SCYTHE:
case WPN_LONGBOW:
case WPN_LAJATANG:
return (2);
case WPN_GIANT_CLUB:
case WPN_GIANT_SPIKED_CLUB:
case WPN_BARDICHE:
return (1);
case WPN_DOUBLE_SWORD:
case WPN_EVENINGSTAR:
case WPN_EXECUTIONERS_AXE:
case WPN_KATANA:
case WPN_KNIFE:
case WPN_QUICK_BLADE:
case WPN_TRIPLE_SWORD:
case WPN_DEMON_WHIP:
case WPN_DEMON_BLADE:
case WPN_DEMON_TRIDENT:
case WPN_BLESSED_FALCHION:
case WPN_BLESSED_LONG_SWORD:
case WPN_BLESSED_SCIMITAR:
case WPN_BLESSED_KATANA:
case WPN_BLESSED_EUDEMON_BLADE:
case WPN_BLESSED_DOUBLE_SWORD:
case WPN_BLESSED_GREAT_SWORD:
case WPN_BLESSED_TRIPLE_SWORD:
return (0);
default:
break;
}
return (0);
}
int get_vorpal_type(const item_def &item)
{
int ret = DVORP_NONE;
if (item.base_type == OBJ_WEAPONS)
ret = (Weapon_prop[Weapon_index[item.sub_type]].dam_type & DAMV_MASK);
return (ret);
}
int get_damage_type(const item_def &item)
{
int ret = DAM_BASH;
if (item.base_type == OBJ_WEAPONS)
ret = (Weapon_prop[Weapon_index[item.sub_type]].dam_type & DAM_MASK);
return (ret);
}
bool does_damage_type(const item_def &item, int dam_type)
{
return (get_damage_type(item) & dam_type);
}
int single_damage_type(const item_def &item)
{
int ret = get_damage_type(item);
if (ret > 0)
{
int count = 0;
for (int i = 1; i <= DAM_MAX_TYPE; i <<= 1)
{
if (!does_damage_type(item, i))
continue;
if (one_chance_in(++count))
ret = i;
}
}
return (ret);
}
hands_reqd_type hands_reqd(object_class_type base_type, int sub_type,
size_type size)
{
item_def item;
item.base_type = base_type;
item.sub_type = sub_type;
return hands_reqd(item, size);
}
hands_reqd_type hands_reqd( const item_def &item, size_type size )
{
int ret = HANDS_ONE;
int fit;
bool doub = false;
switch (item.base_type)
{
case OBJ_STAVES:
case OBJ_WEAPONS:
if (item.base_type == OBJ_STAVES || weapon_skill(item) == SK_STAVES)
{
if (size < SIZE_SMALL)
ret = HANDS_TWO;
else if (size > SIZE_LARGE)
ret = HANDS_ONE;
else
ret = HANDS_HALF;
break;
}
ret = Weapon_prop[ Weapon_index[item.sub_type] ].hands;
if (ret == HANDS_DOUBLE)
{
doub = true;
ret = HANDS_TWO; }
if (!is_range_weapon(item)
&& item.sub_type != WPN_WHIP
&& item.sub_type != WPN_DEMON_WHIP)
{
fit = cmp_weapon_size(item, size);
if (size < SIZE_MEDIUM && fit > 0)
ret += fit;
else if (size > SIZE_MEDIUM && fit < 0)
ret += (fit + doub);
}
break;
case OBJ_CORPSES: ret = HANDS_TWO;
break;
case OBJ_ARMOUR: if (item.sub_type == ARM_NAGA_BARDING
|| item.sub_type == ARM_CENTAUR_BARDING
|| get_armour_slot( item ) == EQ_BODY_ARMOUR)
{
ret = HANDS_TWO;
}
break;
default:
break;
}
if (ret > HANDS_TWO)
ret = HANDS_TWO;
else if (ret < HANDS_ONE)
ret = HANDS_ONE;
return (static_cast< hands_reqd_type >( ret ));
}
bool is_double_ended( const item_def &item )
{
if (item.base_type == OBJ_STAVES)
return (true);
else if (item.base_type != OBJ_WEAPONS)
return (false);
return (Weapon_prop[ Weapon_index[item.sub_type] ].hands == HANDS_DOUBLE);
}
int double_wpn_awkward_speed( const item_def &item )
{
ASSERT( is_double_ended( item ) );
const int base = property( item, PWPN_SPEED );
return ((base * 30 + 10) / 20 + 2);
}
bool is_demonic(const item_def &item)
{
if (item.base_type == OBJ_WEAPONS)
{
switch (item.sub_type)
{
case WPN_DEMON_BLADE:
case WPN_DEMON_WHIP:
case WPN_DEMON_TRIDENT:
return (true);
default:
break;
}
}
return (false);
}
bool is_blessed_blade(const item_def &item)
{
if (item.base_type == OBJ_WEAPONS)
{
switch (item.sub_type)
{
case WPN_BLESSED_FALCHION:
case WPN_BLESSED_LONG_SWORD:
case WPN_BLESSED_SCIMITAR:
case WPN_BLESSED_KATANA:
case WPN_BLESSED_EUDEMON_BLADE:
case WPN_BLESSED_DOUBLE_SWORD:
case WPN_BLESSED_GREAT_SWORD:
case WPN_BLESSED_TRIPLE_SWORD:
return (true);
default:
break;
}
}
return (false);
}
bool is_blessed_blade_convertible(const item_def &item)
{
return (!is_artefact(item)
&& (item.base_type == OBJ_WEAPONS
&& (is_demonic(item)
|| weapon_skill(item) == SK_LONG_BLADES)));
}
bool convert2good(item_def &item, bool allow_blessed)
{
if (item.base_type != OBJ_WEAPONS)
return (false);
switch (item.sub_type)
{
default:
return (false);
case WPN_FALCHION:
if (!allow_blessed)
return (false);
item.sub_type = WPN_BLESSED_FALCHION;
break;
case WPN_LONG_SWORD:
if (!allow_blessed)
return (false);
item.sub_type = WPN_BLESSED_LONG_SWORD;
break;
case WPN_SCIMITAR:
if (!allow_blessed)
return (false);
item.sub_type = WPN_BLESSED_SCIMITAR;
break;
case WPN_DEMON_BLADE:
if (!allow_blessed)
item.sub_type = WPN_SCIMITAR;
else
item.sub_type = WPN_BLESSED_EUDEMON_BLADE;
break;
case WPN_KATANA:
if (!allow_blessed)
return (false);
item.sub_type = WPN_BLESSED_KATANA;
break;
case WPN_DOUBLE_SWORD:
if (!allow_blessed)
return (false);
item.sub_type = WPN_BLESSED_DOUBLE_SWORD;
break;
case WPN_GREAT_SWORD:
if (!allow_blessed)
return (false);
item.sub_type = WPN_BLESSED_GREAT_SWORD;
break;
case WPN_TRIPLE_SWORD:
if (!allow_blessed)
return (false);
item.sub_type = WPN_BLESSED_TRIPLE_SWORD;
break;
case WPN_DEMON_WHIP:
item.sub_type = WPN_WHIP;
break;
case WPN_DEMON_TRIDENT:
item.sub_type = WPN_TRIDENT;
break;
}
if (is_blessed_blade(item))
item.flags &= ~ISFLAG_RACIAL_MASK;
return (true);
}
bool convert2bad(item_def &item)
{
if (item.base_type != OBJ_WEAPONS)
return (false);
switch (item.sub_type)
{
default:
return (false);
case WPN_BLESSED_FALCHION:
item.sub_type = WPN_FALCHION;
break;
case WPN_BLESSED_LONG_SWORD:
item.sub_type = WPN_LONG_SWORD;
break;
case WPN_BLESSED_SCIMITAR:
item.sub_type = WPN_SCIMITAR;
break;
case WPN_BLESSED_EUDEMON_BLADE:
item.sub_type = WPN_DEMON_BLADE;
break;
case WPN_BLESSED_KATANA:
item.sub_type = WPN_KATANA;
break;
case WPN_BLESSED_DOUBLE_SWORD:
item.sub_type = WPN_DOUBLE_SWORD;
break;
case WPN_BLESSED_GREAT_SWORD:
item.sub_type = WPN_GREAT_SWORD;
break;
case WPN_BLESSED_TRIPLE_SWORD:
item.sub_type = WPN_TRIPLE_SWORD;
break;
}
return (true);
}
int weapon_str_weight( const item_def &wpn )
{
ASSERT (wpn.base_type == OBJ_WEAPONS || wpn.base_type == OBJ_STAVES);
if (wpn.base_type == OBJ_STAVES)
return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].str_weight);
return (Weapon_prop[ Weapon_index[wpn.sub_type] ].str_weight);
}
int weapon_dex_weight( const item_def &wpn )
{
return (10 - weapon_str_weight( wpn ));
}
int weapon_impact_mass( const item_def &wpn )
{
ASSERT (wpn.base_type == OBJ_WEAPONS || wpn.base_type == OBJ_STAVES);
return ((weapon_str_weight( wpn ) * item_mass( wpn ) + 5) / 10);
}
int weapon_str_required( const item_def &wpn, bool hand_half )
{
ASSERT (wpn.base_type == OBJ_WEAPONS || wpn.base_type == OBJ_STAVES);
const int req = weapon_impact_mass( wpn ) / ((hand_half) ? 11 : 10);
return ((req < STR_REQ_THRESHOLD) ? 0 : req);
}
skill_type weapon_skill( const item_def &item )
{
if (item.base_type == OBJ_WEAPONS && !is_range_weapon( item ))
return (Weapon_prop[ Weapon_index[item.sub_type] ].skill);
else if (item.base_type == OBJ_STAVES)
return (SK_STAVES);
return (SK_FIGHTING);
}
skill_type weapon_skill( object_class_type wclass, int wtype )
{
item_def wpn;
wpn.base_type = wclass;
wpn.sub_type = wtype;
return (weapon_skill( wpn ));
}
skill_type range_skill( const item_def &item )
{
if (item.base_type == OBJ_WEAPONS && is_range_weapon( item ))
return (Weapon_prop[ Weapon_index[item.sub_type] ].skill);
else if (item.base_type == OBJ_MISSILES)
{
switch (item.sub_type)
{
case MI_DART: return (SK_DARTS);
case MI_JAVELIN: return (SK_POLEARMS);
default: break;
}
}
return (SK_THROWING);
}
skill_type range_skill( object_class_type wclass, int wtype )
{
item_def wpn;
wpn.base_type = wclass;
wpn.sub_type = wtype;
return (range_skill( wpn ));
}
int weapon_ev_bonus( const item_def &wpn, int skill, size_type body, int dex,
bool hide_hidden )
{
ASSERT( wpn.base_type == OBJ_WEAPONS || wpn.base_type == OBJ_STAVES );
int ret = 0;
if (wpn.sub_type == WPN_WHIP || wpn.sub_type == WPN_DEMON_WHIP)
ret = 3 + (dex / 5);
else if (weapon_skill( wpn ) == SK_POLEARMS)
ret = 2 + (dex / 5);
if (!hide_hidden || item_type_known( wpn ))
{
if (get_weapon_brand( wpn ) == SPWPN_REACHING)
ret += 1;
}
if (ret > 0)
{
if (body > SIZE_LARGE)
ret -= (4 * (body - SIZE_LARGE) - 2);
else if (body < SIZE_MEDIUM)
ret += 1;
ret = (ret * (skill + 10)) / 20;
if (ret > 8)
ret = 8 + (ret - 8) / 2;
}
return ((ret > 0) ? ret : 0);
}
static size_type weapon_size( const item_def &item )
{
ASSERT (item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES);
if (item.base_type == OBJ_STAVES)
return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].fit_size);
return (Weapon_prop[ Weapon_index[item.sub_type] ].fit_size);
}
int cmp_weapon_size( const item_def &item, size_type size )
{
ASSERT( item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES );
return (weapon_size( item ) - size);
}
int fit_weapon_wieldable_size( const item_def &item, size_type size )
{
ASSERT( item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES );
const int fit = cmp_weapon_size( item, size );
return ((fit < -2) ? fit + 2 :
(fit > 1) ? fit - 1 : 0);
}
int fit_item_throwable_size( const item_def &item, size_type size )
{
int ret = item_size( item ) - size;
return ((ret >= 0) ? ret + 1 :
(ret > -6) ? 0
: ret + 5);
}
bool check_weapon_tool_size( const item_def &item, size_type size )
{
ASSERT( item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES );
if (item.base_type == OBJ_STAVES || weapon_skill(item) == SK_STAVES)
return (true);
const int fit = cmp_weapon_size( item, size );
return (fit >= -3 && fit <= 1);
}
bool check_weapon_wieldable_size( const item_def &item, size_type size )
{
ASSERT( item.base_type == OBJ_WEAPONS || item.base_type == OBJ_STAVES );
if (item.base_type == OBJ_STAVES || weapon_skill(item) == SK_STAVES)
return (true);
int fit = fit_weapon_wieldable_size( item, size );
if (size < SIZE_SMALL && fit > 0)
fit--;
else if (size > SIZE_LARGE && fit < 0)
fit++;
return (fit == 0);
}
bool check_weapon_shape( const item_def &item, bool quiet, bool check_id )
{
const int brand = get_weapon_brand( item );
if ((!check_id || item_type_known( item ))
&& ((item.base_type == OBJ_WEAPONS
&& is_blessed_blade(item))
|| brand == SPWPN_HOLY_WRATH)
&& you.is_unholy())
{
if (!quiet)
mpr("This weapon will not allow you to wield it.");
return (false);
}
return (true);
}
int get_inv_wielded( void )
{
return (player_weapon_wielded() ? you.equip[EQ_WEAPON] : -1);
}
int get_inv_hand_tool( void )
{
const int tool = you.equip[EQ_WEAPON];
return (tool);
}
int get_inv_in_hand( void )
{
return (you.equip[EQ_WEAPON]);
}
missile_type fires_ammo_type(const item_def &item)
{
if (item.base_type != OBJ_WEAPONS)
return (MI_NONE);
return (Weapon_prop[Weapon_index[item.sub_type]].ammo);
}
missile_type fires_ammo_type(weapon_type wtype)
{
item_def wpn;
wpn.base_type = OBJ_WEAPONS;
wpn.sub_type = wtype;
return (fires_ammo_type(wpn));
}
bool is_range_weapon(const item_def &item)
{
return (fires_ammo_type(item) != MI_NONE);
}
bool is_range_weapon_type(weapon_type wtype)
{
item_def wpn;
wpn.base_type = OBJ_WEAPONS;
wpn.sub_type = wtype;
return (is_range_weapon(wpn));
}
const char *ammo_name(missile_type ammo)
{
return (ammo < 0 || ammo >= NUM_MISSILES ? "eggplant"
: Missile_prop[ Missile_index[ammo] ].name);
}
const char *ammo_name(const item_def &bow)
{
ASSERT(is_range_weapon(bow));
return ammo_name(fires_ammo_type(bow));
}
bool has_launcher(const item_def &ammo)
{
ASSERT(ammo.base_type == OBJ_MISSILES);
return (ammo.sub_type != MI_LARGE_ROCK
&& ammo.sub_type != MI_JAVELIN
&& ammo.sub_type != MI_THROWING_NET);
}
bool is_throwable(const actor *actor, const item_def &wpn, bool force)
{
size_type bodysize = actor->body_size();
if (wpn.base_type == OBJ_WEAPONS)
return (Weapon_prop[Weapon_index[wpn.sub_type]].throwable);
else if (wpn.base_type == OBJ_MISSILES)
{
if (!force)
{
if ((bodysize < SIZE_LARGE
|| !actor->can_throw_large_rocks())
&& wpn.sub_type == MI_LARGE_ROCK)
{
return (false);
}
if (bodysize < SIZE_MEDIUM
&& (wpn.sub_type == MI_JAVELIN
|| wpn.sub_type == MI_THROWING_NET))
{
return (false);
}
}
return (Missile_prop[Missile_index[wpn.sub_type]].throwable);
}
return (false);
}
launch_retval is_launched(const actor *actor, const item_def *launcher,
const item_def &missile)
{
if (missile.base_type == OBJ_MISSILES
&& launcher
&& missile.launched_by(*launcher))
{
return (LRET_LAUNCHED);
}
return (is_throwable(actor, missile) ? LRET_THROWN : LRET_FUMBLED);
}
bool item_is_rod( const item_def &item )
{
return (item.base_type == OBJ_STAVES && item.sub_type >= STAFF_FIRST_ROD);
}
bool item_is_staff( const item_def &item )
{
return (item.base_type == OBJ_STAVES && !item_is_rod(item));
}
int ring_has_pluses( const item_def &item )
{
ASSERT (item.base_type == OBJ_JEWELLERY);
if (!item_type_known(item))
return (0);
switch (item.sub_type)
{
case RING_SLAYING:
return (2);
case RING_PROTECTION:
case RING_EVASION:
case RING_STRENGTH:
case RING_INTELLIGENCE:
case RING_DEXTERITY:
return (1);
default:
break;
}
return (0);
}
bool ring_has_stackable_effect( const item_def &item )
{
ASSERT (item.base_type == OBJ_JEWELLERY);
ASSERT (!jewellery_is_amulet(item));
if (!item_type_known(item))
return (false);
if (ring_has_pluses(item))
return (true);
switch (item.sub_type)
{
case RING_PROTECTION_FROM_FIRE:
case RING_PROTECTION_FROM_COLD:
case RING_LIFE_PROTECTION:
case RING_SUSTENANCE:
case RING_WIZARDRY:
case RING_FIRE:
case RING_ICE:
return (true);
default:
break;
}
return (false);
}
bool food_is_meat(const item_def &item)
{
ASSERT(is_valid_item(item) && item.base_type == OBJ_FOOD);
return (Food_prop[Food_index[item.sub_type]].carn_mod > 0);
}
bool food_is_veg( const item_def &item )
{
ASSERT(is_valid_item(item) && item.base_type == OBJ_FOOD);
return (Food_prop[Food_index[item.sub_type]].herb_mod > 0);
}
bool is_blood_potion(const item_def &item)
{
if (item.base_type != OBJ_POTIONS)
return (false);
return (item.sub_type == POT_BLOOD
|| item.sub_type == POT_BLOOD_COAGULATED);
}
int food_value(const item_def &item)
{
ASSERT(is_valid_item(item) && item.base_type == OBJ_FOOD);
const int herb = player_mutation_level(MUT_HERBIVOROUS);
const int carn = player_mutation_level(MUT_CARNIVOROUS);
const food_def &food = Food_prop[Food_index[item.sub_type]];
int ret = food.value;
ret += (carn * food.carn_mod);
ret += (herb * food.herb_mod);
return ((ret > 0) ? div_rand_round(ret, food.turns) : 0);
}
int food_turns(const item_def &item)
{
ASSERT(is_valid_item(item) && item.base_type == OBJ_FOOD);
return (Food_prop[Food_index[item.sub_type]].turns);
}
bool can_cut_meat(const item_def &item)
{
return (does_damage_type(item, DAM_SLICE));
}
bool is_fruit(const item_def & item)
{
if (item.base_type != OBJ_FOOD)
return (false);
switch (item.sub_type)
{
case FOOD_APPLE:
case FOOD_APRICOT:
case FOOD_BANANA:
case FOOD_CHOKO:
case FOOD_GRAPE:
case FOOD_LEMON:
case FOOD_LYCHEE:
case FOOD_ORANGE:
case FOOD_PEAR:
case FOOD_RAMBUTAN:
case FOOD_STRAWBERRY:
case FOOD_SULTANA:
return (true);
};
return (false);
}
bool food_is_rotten(const item_def &item)
{
return (item.special < 100) && (item.base_type == OBJ_CORPSES
&& item.sub_type == CORPSE_BODY
|| item.base_type == OBJ_FOOD
&& item.sub_type == FOOD_CHUNK);
}
int corpse_freshness(const item_def &item)
{
ASSERT(item.base_type == OBJ_CORPSES);
ASSERT(item.special <= FRESHEST_CORPSE);
return (item.special);
}
bool is_tool(const item_def &item)
{
return (item.base_type == OBJ_WEAPONS
|| item.base_type == OBJ_STAVES
|| (item.base_type == OBJ_MISCELLANY
&& item.sub_type != MISC_RUNE_OF_ZOT));
}
int property(const item_def &item, int prop_type)
{
switch (item.base_type)
{
case OBJ_ARMOUR:
if (prop_type == PARM_AC)
return (Armour_prop[ Armour_index[item.sub_type] ].ac);
else if (prop_type == PARM_EVASION)
return (Armour_prop[ Armour_index[item.sub_type] ].ev);
break;
case OBJ_WEAPONS:
if (prop_type == PWPN_DAMAGE)
return (Weapon_prop[ Weapon_index[item.sub_type] ].dam);
else if (prop_type == PWPN_HIT)
return (Weapon_prop[ Weapon_index[item.sub_type] ].hit);
else if (prop_type == PWPN_SPEED)
return (Weapon_prop[ Weapon_index[item.sub_type] ].speed);
else if (prop_type == PWPN_ACQ_WEIGHT)
return (Weapon_prop[ Weapon_index[item.sub_type] ].acquire_weight);
break;
case OBJ_MISSILES:
if (prop_type == PWPN_DAMAGE)
return (Missile_prop[ Missile_index[item.sub_type] ].dam);
break;
case OBJ_STAVES:
if (prop_type == PWPN_DAMAGE)
return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].dam);
else if (prop_type == PWPN_HIT)
return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].hit);
else if (prop_type == PWPN_SPEED)
return (Weapon_prop[ Weapon_index[WPN_QUARTERSTAFF] ].speed);
break;
default:
break;
}
return (0);
}
bool gives_ability(const item_def &item)
{
if (!item_type_known(item))
return (false);
switch (item.base_type)
{
case OBJ_WEAPONS:
break;
case OBJ_JEWELLERY:
if (!jewellery_is_amulet(item))
{
if (item.sub_type == RING_TELEPORTATION
|| item.sub_type == RING_LEVITATION
|| item.sub_type == RING_INVISIBILITY)
{
return (true);
}
}
else
{
if (item.sub_type == AMU_RAGE)
return (true);
}
break;
case OBJ_ARMOUR:
{
const equipment_type eq = get_armour_slot(item);
if (eq == EQ_NONE)
return (false);
const special_armour_type ego = get_armour_ego_type(item);
if (ego == SPARM_DARKNESS || ego == SPARM_LEVITATION)
return (true);
break;
}
default:
return (false);
}
if (!is_artefact(item))
return (false);
for (int rap = ARTP_INVISIBLE; rap <= ARTP_MAPPING; rap++)
if (artefact_wpn_property( item, static_cast<artefact_prop_type>(rap) ))
return (true);
return (false);
}
bool gives_resistance(const item_def &item)
{
if (!item_type_known(item))
return (false);
switch (item.base_type)
{
case OBJ_WEAPONS:
break;
case OBJ_JEWELLERY:
if (!jewellery_is_amulet(item))
{
if (item.sub_type >= RING_PROTECTION_FROM_FIRE
&& item.sub_type <= RING_PROTECTION_FROM_COLD
|| item.sub_type == RING_SEE_INVISIBLE
|| item.sub_type >= RING_LIFE_PROTECTION
&& item.sub_type <= RING_TELEPORT_CONTROL
|| item.sub_type == RING_SUSTAIN_ABILITIES)
{
return (true);
}
}
else
{
if (item.sub_type != AMU_RAGE && item.sub_type != AMU_INACCURACY)
return (true);
}
break;
case OBJ_ARMOUR:
{
const equipment_type eq = get_armour_slot(item);
if (eq == EQ_NONE)
return (false);
const int ego = get_armour_ego_type(item);
if (ego >= SPARM_FIRE_RESISTANCE && ego <= SPARM_SEE_INVISIBLE
|| ego == SPARM_RESISTANCE || ego == SPARM_POSITIVE_ENERGY)
{
return (true);
}
}
case OBJ_STAVES:
if (item.sub_type >= STAFF_FIRE && item.sub_type <= STAFF_POISON
|| item.sub_type == STAFF_AIR)
{
return (true);
}
return (false);
default:
return (false);
}
if (!is_artefact(item))
return (false);
for (int rap = ARTP_FIRE; rap <= ARTP_CAN_TELEPORT; rap++)
{
if (rap == ARTP_MAGIC || rap >= ARTP_INVISIBLE && rap != ARTP_CAN_TELEPORT)
continue;
if (artefact_wpn_property( item, static_cast<artefact_prop_type>(rap) ))
return (true);
}
return (false);
}
int item_mass(const item_def &item)
{
int unit_mass = 0;
switch (item.base_type)
{
case OBJ_WEAPONS:
unit_mass = Weapon_prop[ Weapon_index[item.sub_type] ].mass;
break;
case OBJ_ARMOUR:
unit_mass = Armour_prop[ Armour_index[item.sub_type] ].mass;
if (get_equip_race( item ) == ISFLAG_ELVEN)
{
const int reduc = (unit_mass >= 25) ? unit_mass / 5 : 5;
unit_mass -= ((reduc / 5) * 5);
unit_mass = std::max(unit_mass, 5);
}
break;
case OBJ_MISSILES:
{
unit_mass = Missile_prop[ Missile_index[item.sub_type] ].mass;
int brand = get_ammo_brand(item);
if (brand == SPMSL_SILVER)
unit_mass *= 2;
else if (brand == SPMSL_STEEL)
unit_mass *= 3;
break;
}
case OBJ_FOOD:
unit_mass = Food_prop[ Food_index[item.sub_type] ].mass;
break;
case OBJ_WANDS:
unit_mass = 100;
break;
case OBJ_UNKNOWN_I:
unit_mass = 200; break;
case OBJ_SCROLLS:
unit_mass = 20;
break;
case OBJ_JEWELLERY:
unit_mass = 10;
break;
case OBJ_POTIONS:
unit_mass = 40;
break;
case OBJ_UNKNOWN_II:
unit_mass = 5; break;
case OBJ_BOOKS:
unit_mass = 70;
break;
case OBJ_STAVES:
unit_mass = 130;
break;
case OBJ_ORBS:
unit_mass = 300;
break;
case OBJ_MISCELLANY:
if ( is_deck(item) )
{
unit_mass = 50;
break;
}
switch (item.sub_type)
{
case MISC_BOTTLED_EFREET:
case MISC_CRYSTAL_BALL_OF_SEEING:
case MISC_CRYSTAL_BALL_OF_ENERGY:
case MISC_CRYSTAL_BALL_OF_FIXATION:
unit_mass = 150;
break;
default:
unit_mass = 100;
break;
}
break;
case OBJ_CORPSES:
unit_mass = mons_weight( item.plus );
if (item.sub_type == CORPSE_SKELETON)
unit_mass /= 10;
break;
default:
case OBJ_GOLD:
unit_mass = 0;
break;
}
return ((unit_mass > 0) ? unit_mass : 0);
}
size_type item_size(const item_def &item)
{
int size = SIZE_TINY;
switch (item.base_type)
{
case OBJ_WEAPONS:
case OBJ_STAVES:
size = Weapon_prop[ Weapon_index[item.sub_type] ].fit_size - 1;
break;
case OBJ_ARMOUR:
size = SIZE_MEDIUM;
switch (item.sub_type)
{
case ARM_GLOVES:
case ARM_HELMET:
case ARM_CAP:
case ARM_WIZARD_HAT:
case ARM_BOOTS:
case ARM_BUCKLER:
size = SIZE_TINY;
break;
case ARM_SHIELD:
size = SIZE_LITTLE;
break;
case ARM_LARGE_SHIELD:
size = SIZE_SMALL;
break;
default: size = SIZE_MEDIUM;
break;
}
break;
case OBJ_MISSILES:
if (item.sub_type == MI_LARGE_ROCK)
size = SIZE_SMALL;
break;
case OBJ_MISCELLANY:
break;
case OBJ_CORPSES:
size = SIZE_SMALL;
break;
default: break;
}
if (size < SIZE_TINY)
size = SIZE_TINY;
else if (size > SIZE_HUGE)
size = SIZE_HUGE;
return (static_cast<size_type>(size));
}
equipment_type get_item_slot(const item_def& item)
{
return get_item_slot(item.base_type, item.sub_type);
}
equipment_type get_item_slot(object_class_type type, int sub_type)
{
switch(type)
{
case OBJ_WEAPONS:
case OBJ_STAVES:
case OBJ_MISCELLANY:
return (EQ_WEAPON);
case OBJ_ARMOUR:
return get_armour_slot(static_cast<armour_type>(sub_type));
case OBJ_JEWELLERY:
return (jewellery_is_amulet(sub_type) ? EQ_AMULET : EQ_RINGS);
default:
break;
}
return (EQ_NONE);
}
bool is_colourful_item(const item_def &item)
{
bool ret = false;
switch (item.base_type)
{
case OBJ_ARMOUR:
if (item.sub_type == ARM_ROBE
|| item.sub_type == ARM_CLOAK
|| item.sub_type == ARM_CAP
|| item.sub_type == ARM_NAGA_BARDING
|| item.sub_type == ARM_CENTAUR_BARDING)
{
ret = true;
}
break;
default:
break;
}
return (ret);
}
bool is_shield(const item_def &item)
{
return (item.base_type == OBJ_ARMOUR
&& get_armour_slot(item) == EQ_SHIELD);
}
bool is_shield_incompatible(const item_def &weapon, const item_def *shield)
{
if (!shield && !(shield = player_shield()))
return (false);
hands_reqd_type hand = hands_reqd(weapon, you.body_size());
return (hand == HANDS_TWO
&& !item_is_rod(weapon)
&& !is_range_weapon(weapon));
}
bool shield_reflects(const item_def &shield)
{
ASSERT(is_shield(shield));
return (get_armour_ego_type(shield) == SPARM_REFLECTION);
}
std::string item_base_name(const item_def &item)
{
switch (item.base_type)
{
case OBJ_WEAPONS:
return Weapon_prop[Weapon_index[item.sub_type]].name;
case OBJ_MISSILES:
return Missile_prop[Missile_index[item.sub_type]].name;
case OBJ_ARMOUR:
return Armour_prop[Armour_index[item.sub_type]].name;
case OBJ_JEWELLERY:
return (jewellery_is_amulet(item) ? "amulet" : "ring");
default:
return "";
}
}
const char* weapon_base_name(unsigned char subtype)
{
return Weapon_prop[Weapon_index[subtype]].name;
}