#include "AppHdr.h"
#include <algorithm>
#include "enum.h"
#include "externs.h"
#include "makeitem.h"
#include "artefact.h"
#include "colour.h"
#include "coord.h"
#include "decks.h"
#include "describe.h"
#include "dungeon.h"
#include "food.h"
#include "itemprop.h"
#include "items.h"
#include "misc.h"
#include "mon-util.h"
#include "player.h"
#include "random.h"
#include "spl-book.h"
#include "travel.h"
#include "view.h"
void item_set_appearance(item_def &item);
static bool _got_curare_roll(const int item_level)
{
return one_chance_in(item_level > 27 ? 6 :
item_level < 2 ? 15 :
(364 - 7 * item_level) / 25);
}
static bool _got_distortion_roll(const int item_level)
{
return (one_chance_in(25));
}
static int _exciting_colour()
{
switch (random2(4))
{
case 0: return YELLOW;
case 1: return LIGHTGREEN;
case 2: return LIGHTRED;
case 3: return LIGHTMAGENTA;
default: return MAGENTA;
}
}
static int _newwave_weapon_colour(const item_def &item)
{
int item_colour = BLACK;
std::string itname = item.name(DESC_PLAIN);
lowercase(itname);
const bool item_runed = itname.find(" runed ") != std::string::npos;
const bool heav_runed = itname.find(" heavily ") != std::string::npos;
if ( is_random_artefact(item) && (!item_runed || heav_runed) )
return _exciting_colour();
if (is_range_weapon(item))
{
switch (range_skill(item))
{
case SK_BOWS:
item_colour = BLUE;
break;
case SK_CROSSBOWS:
item_colour = LIGHTBLUE;
break;
case SK_DARTS:
item_colour = WHITE;
break;
case SK_SLINGS:
item_colour = BROWN;
break;
default:
item_colour = MAGENTA;
break;
}
}
else
{
switch (weapon_skill(item))
{
case SK_SHORT_BLADES:
item_colour = CYAN;
break;
case SK_LONG_BLADES:
item_colour = LIGHTCYAN;
break;
case SK_AXES:
item_colour = DARKGREY;
break;
case SK_MACES_FLAILS:
item_colour = LIGHTGREY;
break;
case SK_POLEARMS:
item_colour = RED;
break;
case SK_STAVES:
item_colour = GREEN;
break;
default:
item_colour = random_colour();
break;
}
}
return (item_colour);
}
static int _classic_weapon_colour(const item_def &item)
{
int item_colour = BLACK;
if (is_range_weapon(item))
item_colour = BROWN;
else
{
switch (item.sub_type)
{
case WPN_CLUB:
case WPN_GIANT_CLUB:
case WPN_GIANT_SPIKED_CLUB:
case WPN_ANKUS:
case WPN_WHIP:
case WPN_QUARTERSTAFF:
item_colour = BROWN;
break;
case WPN_QUICK_BLADE:
item_colour = LIGHTBLUE;
break;
case WPN_EXECUTIONERS_AXE:
item_colour = RED;
break;
default:
item_colour = LIGHTCYAN;
if (get_equip_race(item) == ISFLAG_DWARVEN)
item_colour = CYAN;
break;
}
}
return (item_colour);
}
static int _weapon_colour(const item_def &item)
{
return (Options.classic_item_colours ? _classic_weapon_colour(item)
: _newwave_weapon_colour(item));
}
static int _newwave_missile_colour(const item_def &item)
{
int item_colour = BLACK;
switch (item.sub_type)
{
case MI_STONE:
case MI_SLING_BULLET:
case MI_LARGE_ROCK:
item_colour = BROWN;
break;
case MI_ARROW:
item_colour = BLUE;
break;
case MI_NEEDLE:
item_colour = WHITE;
break;
case MI_BOLT:
item_colour = LIGHTBLUE;
break;
case MI_DART:
item_colour = CYAN;
break;
case MI_JAVELIN:
item_colour = RED;
break;
case MI_THROWING_NET:
item_colour = DARKGREY;
break;
default:
item_colour = LIGHTCYAN;
if (get_equip_race(item) == ISFLAG_DWARVEN)
item_colour = CYAN;
break;
}
return (item_colour);
}
static int _classic_missile_colour(const item_def &item)
{
int item_colour = BLACK;
switch (item.sub_type)
{
case MI_STONE:
case MI_LARGE_ROCK:
case MI_ARROW:
item_colour = BROWN;
break;
case MI_SLING_BULLET:
item_colour = BLUE;
break;
case MI_NEEDLE:
item_colour = WHITE;
break;
case MI_THROWING_NET:
item_colour = DARKGREY;
break;
default:
item_colour = LIGHTCYAN;
if (get_equip_race(item) == ISFLAG_DWARVEN)
item_colour = CYAN;
break;
}
return (item_colour);
}
static int _missile_colour(const item_def &item)
{
return (Options.classic_item_colours ? _classic_missile_colour(item)
: _newwave_missile_colour(item));
}
static int _newwave_armour_colour(const item_def &item)
{
int item_colour = BLACK;
std::string itname = item.name(DESC_PLAIN);
lowercase(itname);
const bool item_runed = itname.find(" runed ") != std::string::npos;
const bool heav_runed = itname.find(" heavily ") != std::string::npos;
if (is_random_artefact(item) && (!item_runed || heav_runed))
return (_exciting_colour());
switch (item.sub_type)
{
case ARM_CLOAK:
item_colour = WHITE;
break;
case ARM_NAGA_BARDING:
case ARM_CENTAUR_BARDING:
item_colour = GREEN;
break;
case ARM_ROBE:
item_colour = RED;
break;
case ARM_CAP:
case ARM_WIZARD_HAT:
item_colour = MAGENTA;
break;
case ARM_HELMET:
item_colour = DARKGREY;
break;
case ARM_BOOTS:
item_colour = BLUE;
break;
case ARM_GLOVES:
item_colour = LIGHTBLUE;
break;
case ARM_LEATHER_ARMOUR:
item_colour = BROWN;
break;
case ARM_ANIMAL_SKIN:
item_colour = LIGHTGREY;
break;
case ARM_CRYSTAL_PLATE_MAIL:
item_colour = WHITE;
break;
case ARM_SHIELD:
case ARM_LARGE_SHIELD:
case ARM_BUCKLER:
item_colour = CYAN;
break;
default:
item_colour = LIGHTCYAN;
break;
}
return (item_colour);
}
static int _classic_armour_colour(const item_def &item)
{
int item_colour = BLACK;
switch (item.sub_type)
{
case ARM_CLOAK:
case ARM_ROBE:
case ARM_NAGA_BARDING:
case ARM_CENTAUR_BARDING:
case ARM_CAP:
case ARM_WIZARD_HAT:
item_colour = random_colour();
break;
case ARM_HELMET:
item_colour = LIGHTCYAN;
break;
case ARM_BOOTS: case ARM_GLOVES:
case ARM_LEATHER_ARMOUR:
item_colour = BROWN;
break;
case ARM_CRYSTAL_PLATE_MAIL:
item_colour = LIGHTGREY;
break;
case ARM_ANIMAL_SKIN:
item_colour = BROWN;
break;
default:
item_colour = LIGHTCYAN;
if (get_equip_race(item) == ISFLAG_DWARVEN)
item_colour = CYAN;
break;
}
return (item_colour);
}
static int _armour_colour(const item_def &item)
{
return (Options.classic_item_colours ? _classic_armour_colour(item)
: _newwave_armour_colour(item));
}
void item_colour(item_def &item)
{
int switchnum = 0;
int temp_value;
switch (item.base_type)
{
case OBJ_WEAPONS:
if (is_unrandom_artefact(item))
break;
if (is_demonic(item))
item.colour = random_uncommon_colour();
else
item.colour = _weapon_colour(item);
if (is_random_artefact(item) && one_chance_in(5)
&& Options.classic_item_colours)
{
item.colour = random_colour();
}
break;
case OBJ_MISSILES:
item.colour = _missile_colour(item);
break;
case OBJ_ARMOUR:
if (is_unrandom_artefact(item))
break;
switch (item.sub_type)
{
case ARM_DRAGON_HIDE:
case ARM_DRAGON_ARMOUR:
item.colour = mons_class_colour(MONS_DRAGON);
break;
case ARM_TROLL_HIDE:
case ARM_TROLL_LEATHER_ARMOUR:
item.colour = mons_class_colour(MONS_TROLL);
break;
case ARM_ICE_DRAGON_HIDE:
case ARM_ICE_DRAGON_ARMOUR:
item.colour = mons_class_colour(MONS_ICE_DRAGON);
break;
case ARM_STEAM_DRAGON_HIDE:
case ARM_STEAM_DRAGON_ARMOUR:
item.colour = mons_class_colour(MONS_STEAM_DRAGON);
break;
case ARM_MOTTLED_DRAGON_HIDE:
case ARM_MOTTLED_DRAGON_ARMOUR:
item.colour = mons_class_colour(MONS_MOTTLED_DRAGON);
break;
case ARM_STORM_DRAGON_HIDE:
case ARM_STORM_DRAGON_ARMOUR:
item.colour = mons_class_colour(MONS_STORM_DRAGON);
break;
case ARM_GOLD_DRAGON_HIDE:
case ARM_GOLD_DRAGON_ARMOUR:
item.colour = mons_class_colour(MONS_GOLDEN_DRAGON);
break;
case ARM_SWAMP_DRAGON_HIDE:
case ARM_SWAMP_DRAGON_ARMOUR:
item.colour = mons_class_colour(MONS_SWAMP_DRAGON);
break;
default:
item.colour = _armour_colour(item);
break;
}
if (is_random_artefact(item) && one_chance_in(5))
item.colour = random_colour();
break;
case OBJ_WANDS:
item.special = you.item_description[IDESC_WANDS][item.sub_type];
switch (item.special % 12)
{
case 0: item.colour = CYAN;
break;
case 1: case 5: item.colour = YELLOW;
break;
case 2: case 8: case 9: case 10: default:
item.colour = LIGHTGREY;
break;
case 3: case 4: case 7: item.colour = BROWN;
break;
case 6: item.colour = WHITE;
break;
case 11: item.colour = random_colour();
break;
}
if (item.special / 12 == 9) item.colour = DARKGREY;
break;
case OBJ_POTIONS:
item.plus = you.item_description[IDESC_POTIONS][item.sub_type];
switch (item.plus % 14)
{
case 0: default:
item.colour = LIGHTGREY;
break;
case 1: case 7: item.colour = BLUE;
break;
case 2: item.colour = DARKGREY;
break;
case 3: case 13: item.colour = WHITE;
break;
case 4: item.colour = CYAN;
break;
case 5: item.colour = MAGENTA;
break;
case 6: item.colour = LIGHTRED;
break;
case 8: item.colour = RED;
break;
case 9: item.colour = YELLOW;
break;
case 10: item.colour = GREEN;
break;
case 11: item.colour = BROWN;
break;
case 12: item.colour = LIGHTMAGENTA;
break;
}
break;
case OBJ_FOOD:
switch (item.sub_type)
{
case FOOD_BEEF_JERKY:
case FOOD_BREAD_RATION:
case FOOD_LYCHEE:
case FOOD_MEAT_RATION:
case FOOD_RAMBUTAN:
case FOOD_SAUSAGE:
case FOOD_SULTANA:
item.colour = BROWN;
break;
case FOOD_BANANA:
case FOOD_CHEESE:
case FOOD_HONEYCOMB:
case FOOD_LEMON:
case FOOD_PIZZA:
case FOOD_ROYAL_JELLY:
item.colour = YELLOW;
break;
case FOOD_PEAR:
item.colour = LIGHTGREEN;
break;
case FOOD_CHOKO:
case FOOD_SNOZZCUMBER:
item.colour = GREEN;
break;
case FOOD_APRICOT:
case FOOD_ORANGE:
item.colour = LIGHTRED;
break;
case FOOD_STRAWBERRY:
item.colour = RED;
break;
case FOOD_APPLE:
item.colour = (coinflip() ? RED : GREEN);
break;
case FOOD_GRAPE:
item.colour = (coinflip() ? MAGENTA : GREEN);
break;
case FOOD_CHUNK:
temp_value = mons_class_colour(item.plus);
item.colour = (temp_value == BLACK) ? LIGHTRED : temp_value;
break;
default:
item.colour = BROWN;
}
break;
case OBJ_JEWELLERY:
if (is_unrandom_artefact(item))
break;
else if (is_random_artefact(item))
{
item.colour = random_colour();
break;
}
item.colour = YELLOW;
item.special = you.item_description[IDESC_RINGS][item.sub_type];
switchnum = item.special % 13;
switch (switchnum)
{
case 0:
case 5:
item.colour = BROWN;
break;
case 1:
case 8:
case 11:
item.colour = LIGHTGREY;
break;
case 2:
case 6:
item.colour = YELLOW;
break;
case 3:
case 4:
item.colour = CYAN;
break;
case 7:
item.colour = BROWN;
break;
case 9:
case 10:
item.colour = WHITE;
break;
case 12:
item.colour = GREEN;
break;
case 13:
item.colour = LIGHTCYAN;
break;
}
if (item.sub_type >= AMU_RAGE)
{
switch (switchnum)
{
case 0: case 9: case 11: item.colour = WHITE;
break;
case 1: item.colour = LIGHTBLUE;
break;
case 2: case 6: item.colour = YELLOW;
break;
case 3: item.colour = GREEN;
break;
case 4: case 8: item.colour = RED;
break;
case 5: case 7: item.colour = BROWN;
break;
case 10: item.colour = LIGHTGREY;
break;
case 12: item.colour = GREEN;
break;
case 13: item.colour = random_colour();
}
}
if (item.special / 13 == 5)
item.colour = DARKGREY;
break;
case OBJ_SCROLLS:
item.colour = LIGHTGREY;
item.special = you.item_description[IDESC_SCROLLS][item.sub_type];
item.plus = you.item_description[IDESC_SCROLLS_II][item.sub_type];
break;
case OBJ_BOOKS:
switch (item.special % 10)
{
case 0:
case 1:
default:
item.colour = random_colour();
break;
case 2:
item.colour = (one_chance_in(3) ? BROWN : DARKGREY);
break;
case 3:
item.colour = CYAN;
break;
case 4:
item.colour = LIGHTGREY;
break;
}
break;
case OBJ_STAVES:
item.colour = BROWN;
item.special = you.item_description[IDESC_STAVES][item.sub_type];
break;
case OBJ_ORBS:
item.colour = ETC_MUTAGENIC;
break;
case OBJ_MISCELLANY:
if (is_deck(item))
break;
switch (item.sub_type)
{
case MISC_BOTTLED_EFREET:
case MISC_STONE_OF_EARTH_ELEMENTALS:
item.colour = BROWN;
break;
case MISC_AIR_ELEMENTAL_FAN:
case MISC_CRYSTAL_BALL_OF_ENERGY:
case MISC_CRYSTAL_BALL_OF_FIXATION:
case MISC_CRYSTAL_BALL_OF_SEEING:
case MISC_DISC_OF_STORMS:
case MISC_HORN_OF_GERYON:
case MISC_LANTERN_OF_SHADOWS:
item.colour = LIGHTGREY;
break;
case MISC_LAMP_OF_FIRE:
item.colour = YELLOW;
break;
case MISC_BOX_OF_BEASTS:
item.colour = DARKGREY;
break;
case MISC_RUNE_OF_ZOT:
switch (item.plus)
{
case RUNE_DIS: item.colour = ETC_IRON;
break;
case RUNE_COCYTUS: item.colour = ETC_ICE;
break;
case RUNE_TARTARUS: item.colour = ETC_BONE;
break;
case RUNE_SLIME_PITS: item.colour = ETC_SLIME;
break;
case RUNE_SNAKE_PIT: item.colour = ETC_POISON;
break;
case RUNE_ELVEN_HALLS: item.colour = ETC_ELVEN;
break;
case RUNE_VAULTS: item.colour = ETC_SILVER;
break;
case RUNE_TOMB: item.colour = ETC_GOLD;
break;
case RUNE_SWAMP: item.colour = ETC_DECAY;
break;
case RUNE_SHOALS: item.colour = ETC_WATER;
break;
case RUNE_DEMONIC: {
element_type types[] =
{ETC_EARTH, ETC_ELECTRICITY, ETC_ENCHANT, ETC_HEAL,
ETC_BLOOD, ETC_DEATH, ETC_UNHOLY, ETC_VEHUMET, ETC_BEOGH,
ETC_CRYSTAL, ETC_SMOKE, ETC_DWARVEN, ETC_ORCISH, ETC_GILA};
item.colour = RANDOM_ELEMENT(types);
break;
}
case RUNE_ABYSSAL: item.colour = ETC_RANDOM;
break;
case RUNE_MNOLEG: item.colour = ETC_MUTAGENIC;
break;
case RUNE_LOM_LOBON: item.colour = ETC_MAGIC;
break;
case RUNE_CEREBOV: item.colour = ETC_FIRE;
break;
case RUNE_GEHENNA: case RUNE_GLOORX_VLOQ: default:
item.colour = ETC_DARK;
break;
}
break;
case MISC_EMPTY_EBONY_CASKET:
item.colour = DARKGREY;
break;
default:
item.colour = random_colour();
break;
}
break;
case OBJ_CORPSES:
temp_value = mons_class_colour(item.plus);
item.colour = (temp_value == BLACK) ? LIGHTRED : temp_value;
break;
case OBJ_GOLD:
item.colour = YELLOW;
break;
default:
break;
}
}
static bool _is_boring_item(int type, int sub_type)
{
switch (type)
{
case OBJ_POTIONS:
return (sub_type == POT_CURE_MUTATION);
case OBJ_SCROLLS:
switch (sub_type)
{
case SCR_DETECT_CURSE:
case SCR_REMOVE_CURSE:
case SCR_IDENTIFY:
case SCR_MAGIC_MAPPING:
return (true);
default:
break;
}
break;
case OBJ_JEWELLERY:
return (sub_type == RING_TELEPORT_CONTROL
|| sub_type == AMU_RESIST_MUTATION);
default:
break;
}
return (false);
}
static weapon_type _determine_weapon_subtype(int item_level)
{
weapon_type rc = WPN_UNKNOWN;
const weapon_type common_subtypes[] = {
WPN_KNIFE, WPN_QUARTERSTAFF, WPN_SLING,
WPN_SPEAR, WPN_HAND_AXE, WPN_MACE,
WPN_DAGGER, WPN_DAGGER, WPN_CLUB,
WPN_HAMMER, WPN_WHIP, WPN_SABRE
};
const weapon_type rare_subtypes[] = {
WPN_LAJATANG, WPN_DEMON_WHIP, WPN_DEMON_BLADE,
WPN_DEMON_TRIDENT, WPN_DOUBLE_SWORD, WPN_EVENINGSTAR,
WPN_EXECUTIONERS_AXE, WPN_KATANA, WPN_QUICK_BLADE,
WPN_TRIPLE_SWORD
};
if (item_level > 6 && one_chance_in(30)
&& x_chance_in_y(10 + item_level, 100))
{
rc = RANDOM_ELEMENT(rare_subtypes);
}
else if (x_chance_in_y(20 - item_level, 20))
rc = RANDOM_ELEMENT(common_subtypes);
else
{
while (true)
{
const int wpntype = random2(NUM_WEAPONS);
if (x_chance_in_y(weapon_rarity(wpntype), 10))
{
rc = static_cast<weapon_type>(wpntype);
break;
}
}
}
return rc;
}
static bool _try_make_item_special_unrand(item_def& item, int force_type,
int item_level)
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Making special unrand artefact.");
#endif
bool abyss = item_level == level_id(LEVEL_ABYSS).absdepth();
int idx = find_okay_unrandart(item.base_type, force_type,
UNRANDSPEC_SPECIAL, abyss);
if (idx != -1 && make_item_unrandart(item, idx))
return (true);
return (false);
}
static bool _try_make_weapon_artefact(item_def& item, int force_type,
int item_level)
{
if (item.sub_type != WPN_CLUB && item_level > 2
&& x_chance_in_y(101 + item_level * 3, 4000))
{
if (you.level_type != LEVEL_ABYSS
&& you.level_type != LEVEL_PANDEMONIUM
&& one_chance_in(50))
{
const int idx = find_okay_unrandart(OBJ_WEAPONS, force_type,
UNRANDSPEC_NORMAL);
if (idx != -1)
{
make_item_unrandart(item, idx);
return (true);
}
}
make_item_randart(item);
item.plus = random2(7);
item.plus2 = random2(7);
if (one_chance_in(3))
item.plus += random2(7);
if (one_chance_in(3))
item.plus2 += random2(7);
if (one_chance_in(9))
item.plus -= random2(7);
if (one_chance_in(9))
item.plus2 -= random2(7);
if (one_chance_in(4))
{
do_curse_item(item);
item.plus = -random2(6);
item.plus2 = -random2(6);
}
else if ((item.plus < 0 || item.plus2 < 0)
&& !one_chance_in(3))
{
do_curse_item(item);
}
return (true);
}
if (item_level > 6
&& one_chance_in(12)
&& x_chance_in_y(31 + item_level * 3, 3000))
{
return (_try_make_item_special_unrand(item, force_type, item_level));
}
return (false);
}
static item_status_flag_type _determine_weapon_race(const item_def& item,
int item_race)
{
item_status_flag_type rc = ISFLAG_NO_RACE;
switch (item_race)
{
case MAKE_ITEM_ELVEN:
rc = ISFLAG_ELVEN;
break;
case MAKE_ITEM_DWARVEN:
rc = ISFLAG_DWARVEN;
break;
case MAKE_ITEM_ORCISH:
rc = ISFLAG_ORCISH;
break;
case MAKE_ITEM_RANDOM_RACE:
if (coinflip())
break;
switch (item.sub_type)
{
case WPN_CLUB:
if (coinflip())
rc = ISFLAG_ORCISH;
break;
case WPN_WHIP:
if (one_chance_in(4))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_ELVEN;
break;
case WPN_MACE:
case WPN_FLAIL:
case WPN_SPIKED_FLAIL:
case WPN_GREAT_MACE:
case WPN_DIRE_FLAIL:
if (one_chance_in(4))
rc = ISFLAG_DWARVEN;
if (one_chance_in(3))
rc = ISFLAG_ORCISH;
break;
case WPN_MORNINGSTAR:
case WPN_HAMMER:
if (one_chance_in(3))
rc = ISFLAG_ORCISH;
if (one_chance_in(3))
rc = ISFLAG_DWARVEN;
break;
case WPN_EVENINGSTAR:
if (one_chance_in(5))
rc = ISFLAG_ORCISH;
if (one_chance_in(5))
rc = ISFLAG_DWARVEN;
break;
case WPN_DAGGER:
if (one_chance_in(3))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_DWARVEN;
if (one_chance_in(4))
rc = ISFLAG_ELVEN;
break;
case WPN_SHORT_SWORD:
case WPN_SABRE:
if (one_chance_in(3))
rc = ISFLAG_ORCISH;
if (one_chance_in(3))
rc = ISFLAG_DWARVEN;
if (one_chance_in(3))
rc = ISFLAG_ELVEN;
break;
case WPN_FALCHION:
if (one_chance_in(5))
rc = ISFLAG_DWARVEN;
if (one_chance_in(3))
rc = ISFLAG_ORCISH;
if (one_chance_in(3))
rc = ISFLAG_ELVEN;
break;
case WPN_LONG_SWORD:
if (one_chance_in(6))
rc = ISFLAG_DWARVEN;
if (one_chance_in(4))
rc = ISFLAG_ORCISH;
if (coinflip())
rc = ISFLAG_ELVEN;
break;
case WPN_GREAT_SWORD:
if (one_chance_in(3))
rc = ISFLAG_ORCISH;
break;
case WPN_SCIMITAR:
if (one_chance_in(5))
rc = ISFLAG_ELVEN;
if (coinflip())
rc = ISFLAG_ORCISH;
break;
case WPN_WAR_AXE:
case WPN_HAND_AXE:
case WPN_BROAD_AXE:
case WPN_BATTLEAXE:
if (one_chance_in(3))
rc = ISFLAG_ORCISH;
if (coinflip())
rc = ISFLAG_DWARVEN;
break;
case WPN_SPEAR:
case WPN_TRIDENT:
if (one_chance_in(4))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_ELVEN;
break;
case WPN_HALBERD:
case WPN_GLAIVE:
case WPN_BARDICHE:
if (one_chance_in(5))
rc = ISFLAG_ORCISH;
break;
case WPN_EXECUTIONERS_AXE:
if (one_chance_in(5))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_DWARVEN;
break;
case WPN_QUICK_BLADE:
if (one_chance_in(4))
rc = ISFLAG_ELVEN;
break;
case WPN_BOW:
if (one_chance_in(6))
rc = ISFLAG_ORCISH;
if (coinflip())
rc = ISFLAG_ELVEN;
break;
case WPN_LONGBOW:
if (one_chance_in(3))
rc = ISFLAG_ELVEN;
break;
case WPN_CROSSBOW:
if (one_chance_in(4))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_DWARVEN;
break;
case WPN_HAND_CROSSBOW:
if (one_chance_in(3))
rc = ISFLAG_ELVEN;
break;
case WPN_BLOWGUN:
if (one_chance_in(6))
rc = ISFLAG_ELVEN;
if (one_chance_in(4))
rc = ISFLAG_ORCISH;
break;
}
break;
}
return rc;
}
static void _weapon_add_racial_modifiers(item_def& item)
{
switch (get_equip_race(item))
{
case ISFLAG_ORCISH:
if (coinflip())
item.plus--;
if (coinflip())
item.plus2++;
break;
case ISFLAG_ELVEN:
item.plus += random2(3);
break;
case ISFLAG_DWARVEN:
if (coinflip())
item.plus++;
if (coinflip())
item.plus2++;
break;
}
}
static brand_type _determine_weapon_brand(const item_def& item, int item_level)
{
if (item.special != 0)
return static_cast<brand_type>(item.special);
const bool force_good = (item_level == MAKE_GOOD_ITEM);
const int tries = force_good ? 5 : 1;
brand_type rc = SPWPN_NORMAL;
for (int count = 0; count < tries && rc == SPWPN_NORMAL; ++count)
{
if (!force_good && !is_demonic(item)
&& !x_chance_in_y(101 + item_level, 300))
{
continue;
}
switch (item.sub_type)
{
case WPN_EVENINGSTAR:
if (coinflip())
rc = SPWPN_DRAINING;
case WPN_MORNINGSTAR:
if (one_chance_in(4))
rc = SPWPN_VENOM;
if (one_chance_in(4))
rc = coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING;
if (one_chance_in(20))
rc = SPWPN_VAMPIRICISM;
case WPN_MACE:
case WPN_GREAT_MACE:
case WPN_FLAIL:
case WPN_SPIKED_FLAIL:
case WPN_DIRE_FLAIL:
case WPN_HAMMER:
if (one_chance_in(25))
rc = SPWPN_PAIN;
if (_got_distortion_roll(item_level))
rc = SPWPN_DISTORTION;
if (one_chance_in(3) && (rc == SPWPN_NORMAL || one_chance_in(5)))
rc = SPWPN_VORPAL;
if (one_chance_in(4))
rc = SPWPN_HOLY_WRATH;
if (one_chance_in(3))
rc = SPWPN_PROTECTION;
if (one_chance_in(10))
rc = SPWPN_DRAINING;
break;
case WPN_DAGGER:
if (one_chance_in(4))
rc = SPWPN_RETURNING;
if (one_chance_in(10))
rc = SPWPN_PAIN;
if (one_chance_in(3))
rc = SPWPN_VENOM;
case WPN_SHORT_SWORD:
case WPN_SABRE:
if (_got_distortion_roll(item_level))
rc = SPWPN_DISTORTION;
if (one_chance_in(10))
rc = SPWPN_VAMPIRICISM;
if (one_chance_in(8))
rc = SPWPN_ELECTROCUTION;
if (one_chance_in(8))
rc = SPWPN_PROTECTION;
if (one_chance_in(8))
rc = coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING;
if (one_chance_in(12))
rc = SPWPN_HOLY_WRATH;
if (one_chance_in(8))
rc = SPWPN_DRAINING;
if (one_chance_in(8))
rc = SPWPN_SPEED;
if (one_chance_in(6))
rc = SPWPN_VENOM;
break;
case WPN_FALCHION:
case WPN_LONG_SWORD:
if (one_chance_in(12))
rc = SPWPN_VENOM;
case WPN_SCIMITAR:
if (one_chance_in(25))
rc = SPWPN_PAIN;
if (one_chance_in(7))
rc = SPWPN_SPEED;
case WPN_GREAT_SWORD:
case WPN_DOUBLE_SWORD:
case WPN_TRIPLE_SWORD:
if (one_chance_in(10))
rc = SPWPN_VAMPIRICISM;
if (_got_distortion_roll(item_level))
rc = SPWPN_DISTORTION;
if (one_chance_in(5))
rc = coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING;
if (one_chance_in(7))
rc = SPWPN_PROTECTION;
if (one_chance_in(12))
rc = SPWPN_DRAINING;
if (one_chance_in(7))
rc = SPWPN_ELECTROCUTION;
if (one_chance_in(4))
rc = SPWPN_HOLY_WRATH;
if (one_chance_in(4) && (rc == SPWPN_NORMAL || one_chance_in(3)))
rc = SPWPN_VORPAL;
break;
case WPN_WAR_AXE:
case WPN_BROAD_AXE:
case WPN_BATTLEAXE:
case WPN_EXECUTIONERS_AXE:
if (one_chance_in(25))
rc = SPWPN_HOLY_WRATH;
if (one_chance_in(14))
rc = SPWPN_DRAINING;
case WPN_HAND_AXE:
if (one_chance_in(30))
rc = SPWPN_PAIN;
if (one_chance_in(10))
rc = SPWPN_VAMPIRICISM;
if (item.sub_type == WPN_HAND_AXE && one_chance_in(10))
rc = SPWPN_RETURNING;
if (_got_distortion_roll(item_level))
rc = SPWPN_DISTORTION;
if (one_chance_in(3) && (rc == SPWPN_NORMAL || one_chance_in(5)))
rc = SPWPN_VORPAL;
if (one_chance_in(4))
rc = coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING;
if (one_chance_in(8))
rc = SPWPN_ELECTROCUTION;
if (one_chance_in(12))
rc = SPWPN_VENOM;
break;
case WPN_WHIP:
if (one_chance_in(10))
rc = SPWPN_PAIN;
if (_got_distortion_roll(item_level))
rc = SPWPN_DISTORTION;
if (one_chance_in(6))
rc = coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING;
if (one_chance_in(6))
rc = SPWPN_VENOM;
if (one_chance_in(3))
rc = SPWPN_REACHING;
if (one_chance_in(5))
rc = SPWPN_SPEED;
if (one_chance_in(5))
rc = SPWPN_ELECTROCUTION;
break;
case WPN_HALBERD:
case WPN_GLAIVE:
case WPN_SCYTHE:
case WPN_TRIDENT:
case WPN_BARDICHE:
if (one_chance_in(30))
rc = SPWPN_HOLY_WRATH;
if (one_chance_in(4))
rc = SPWPN_PROTECTION;
if (one_chance_in(5))
rc = SPWPN_SPEED;
case WPN_SPEAR:
if (one_chance_in(25))
rc = SPWPN_PAIN;
if (one_chance_in(10))
rc = SPWPN_VAMPIRICISM;
if (item.sub_type == WPN_SPEAR && one_chance_in(6))
rc = SPWPN_RETURNING;
if (_got_distortion_roll(item_level))
rc = SPWPN_DISTORTION;
if (one_chance_in(5) && (rc == SPWPN_NORMAL || one_chance_in(6)))
rc = SPWPN_VORPAL;
if (one_chance_in(6))
rc = coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING;
if (one_chance_in(6))
rc = SPWPN_VENOM;
if (one_chance_in(5))
rc = SPWPN_DRAGON_SLAYING;
if (one_chance_in(3))
rc = SPWPN_REACHING;
break;
case WPN_SLING:
case WPN_HAND_CROSSBOW:
if (coinflip())
break;
case WPN_BOW:
case WPN_LONGBOW:
case WPN_CROSSBOW:
{
const int tmp = random2(1000);
if (tmp < 250)
rc = SPWPN_FLAME;
else if (tmp < 500)
rc = SPWPN_FROST;
else if (tmp < 650)
rc = SPWPN_PENETRATION;
else if (tmp < 800)
rc = SPWPN_REAPING;
else if (tmp < 920)
rc = SPWPN_PROTECTION;
else if (tmp < 980)
rc = SPWPN_VORPAL;
else
rc = SPWPN_SPEED;
break;
}
case WPN_QUARTERSTAFF:
if (one_chance_in(30))
rc = SPWPN_PAIN;
if (_got_distortion_roll(item_level))
rc = SPWPN_DISTORTION;
if (one_chance_in(5))
rc = SPWPN_SPEED;
if (one_chance_in(10))
rc = SPWPN_VORPAL;
if (one_chance_in(5))
rc = SPWPN_PROTECTION;
break;
case WPN_LAJATANG:
if (one_chance_in(8))
rc = SPWPN_SPEED;
else if (one_chance_in(12))
rc = SPWPN_PAIN;
else if (_got_distortion_roll(item_level))
rc = SPWPN_DISTORTION;
else if (one_chance_in(9))
rc = SPWPN_PROTECTION;
else if (one_chance_in(6))
rc = SPWPN_ELECTROCUTION;
else if (one_chance_in(5))
rc = SPWPN_VAMPIRICISM;
else if (one_chance_in(6))
rc = SPWPN_VENOM;
break;
case WPN_DEMON_WHIP:
case WPN_DEMON_BLADE:
case WPN_DEMON_TRIDENT:
if (one_chance_in(10))
rc = SPWPN_PAIN;
if (one_chance_in(3)
&& (item.sub_type == WPN_DEMON_WHIP
|| item.sub_type == WPN_DEMON_TRIDENT))
{
rc = SPWPN_REACHING;
}
if (one_chance_in(5))
rc = SPWPN_DRAINING;
if (one_chance_in(5))
rc = coinflip() ? SPWPN_FLAMING : SPWPN_FREEZING;
if (one_chance_in(5))
rc = SPWPN_ELECTROCUTION;
if (one_chance_in(5))
rc = SPWPN_VAMPIRICISM;
if (one_chance_in(5))
rc = SPWPN_VENOM;
break;
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:
rc = SPWPN_HOLY_WRATH;
break;
default:
break;
}
}
return (rc);
}
static void _generate_weapon_item(item_def& item, bool allow_uniques,
int force_type, int item_level,
int item_race)
{
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
item.sub_type = _determine_weapon_subtype(item_level);
if (allow_uniques
&& _try_make_weapon_artefact(item, force_type, item_level))
{
return;
}
ASSERT(!is_artefact(item));
const bool force_good = (item_level == MAKE_GOOD_ITEM);
const bool forced_ego = item.special > 0;
const bool no_brand = item.special == SPWPN_FORBID_BRAND;
if (no_brand)
set_item_ego_type(item, OBJ_WEAPONS, SPWPN_NORMAL);
if (force_good
&& force_type == OBJ_RANDOM
&& (item.sub_type == WPN_CLUB || item.sub_type == WPN_SLING))
{
item.sub_type = WPN_LONG_SWORD;
}
item.plus = 0;
item.plus2 = 0;
set_equip_race(item, _determine_weapon_race(item, item_race));
if (force_good && !forced_ego && get_equip_race(item) == ISFLAG_ORCISH)
set_equip_race(item, ISFLAG_NO_RACE);
_weapon_add_racial_modifiers(item);
if (item_level < 0)
{
if (!no_brand && (forced_ego || one_chance_in(4)))
{
set_item_ego_type(item, OBJ_WEAPONS,
_determine_weapon_brand(item, 2+2*you.your_level));
}
item.plus -= 1 + random2(3);
item.plus2 -= 1 + random2(3);
if (item_level == -5)
do_curse_item(item);
}
else if ((force_good || is_demonic(item) || forced_ego
|| x_chance_in_y(51 + item_level, 200))
&& !item_is_mundane(item))
{
if (!no_brand)
{
set_item_ego_type(item, OBJ_WEAPONS,
_determine_weapon_brand(item, item_level));
}
if (force_good && item.special == SPWPN_NORMAL)
{
item.plus += 2 + random2(3);
item.plus2 += 2 + random2(3);
}
const int chance = (force_good ? 200 : item_level);
for (int i = 0; i < 4; ++i)
{
item.plus += random2(3);
if (random2(350) > 20 + chance)
break;
}
for (int i = 0; i < 4; ++i)
{
item.plus2 += random2(3);
if (random2(500) > 50 + chance)
break;
}
}
else
{
if (one_chance_in(12))
{
do_curse_item(item);
item.plus -= random2(4);
item.plus2 -= random2(4);
set_item_ego_type(item, OBJ_WEAPONS, SPWPN_NORMAL);
}
}
if (get_equip_race(item) == ISFLAG_ORCISH
&& !(item_race == MAKE_ITEM_ORCISH && forced_ego))
{
const int brand = get_weapon_brand(item);
if (brand == SPWPN_ORC_SLAYING
|| (brand != SPWPN_NORMAL && !forced_ego && coinflip()))
{
set_item_ego_type(item, OBJ_WEAPONS, SPWPN_NORMAL);
}
}
}
static item_status_flag_type _determine_missile_race(const item_def& item,
int item_race)
{
item_status_flag_type rc = ISFLAG_NO_RACE;
switch (item_race)
{
case MAKE_ITEM_ELVEN:
rc = ISFLAG_ELVEN;
break;
case MAKE_ITEM_DWARVEN:
rc = ISFLAG_DWARVEN;
break;
case MAKE_ITEM_ORCISH:
rc = ISFLAG_ORCISH;
break;
case MAKE_ITEM_RANDOM_RACE:
if ((item.sub_type == MI_ARROW
|| item.sub_type == MI_DART
|| item.sub_type == MI_JAVELIN)
&& one_chance_in(4))
{
rc = ISFLAG_ELVEN;
}
if ((item.sub_type == MI_ARROW
|| item.sub_type == MI_BOLT
|| item.sub_type == MI_DART
|| item.sub_type == MI_JAVELIN)
&& one_chance_in(4))
{
rc = ISFLAG_ORCISH;
}
if ((item.sub_type == MI_DART || item.sub_type == MI_BOLT)
&& one_chance_in(6))
{
rc = ISFLAG_DWARVEN;
}
if (item.sub_type == MI_NEEDLE)
{
if (one_chance_in(10))
rc = ISFLAG_ELVEN;
if (one_chance_in(6))
rc = ISFLAG_ORCISH;
}
break;
}
return rc;
}
static special_missile_type _determine_missile_brand(const item_def& item,
int item_level)
{
if (item.special != 0)
return static_cast<special_missile_type>(item.special);
const bool force_good = (item_level == MAKE_GOOD_ITEM);
special_missile_type rc = SPMSL_NORMAL;
if (item.sub_type == MI_NEEDLE)
rc = _got_curare_roll(item_level) ? SPMSL_CURARE : SPMSL_POISONED;
else
{
const int temp_rand =
(force_good ? random2(150) : random2(2000 - 55 * item_level));
if (temp_rand < 30)
rc = SPMSL_FLAME;
else if (temp_rand < 60)
rc = SPMSL_FROST;
else if (temp_rand < 80)
rc = SPMSL_POISONED;
else if (temp_rand < 90)
rc = SPMSL_PENETRATION;
else if (temp_rand < 100)
rc = SPMSL_REAPING;
else if (temp_rand < 110)
rc = SPMSL_SILVER;
else if (temp_rand < 120)
rc = SPMSL_STEEL;
else if (temp_rand < 130)
rc = SPMSL_DISPERSAL;
else if (temp_rand < 150)
rc = SPMSL_EXPLODING;
else
rc = SPMSL_NORMAL;
}
if (item.sub_type == MI_JAVELIN && one_chance_in(25))
rc = SPMSL_RETURNING;
if (get_equip_race(item) == ISFLAG_ORCISH && one_chance_in(3))
rc = SPMSL_POISONED;
if (item.sub_type == MI_SLING_BULLET && rc == SPMSL_POISONED
|| item.sub_type == MI_THROWING_NET)
{
rc = SPMSL_NORMAL;
}
return rc;
}
static void _generate_missile_item(item_def& item, int force_type,
int item_level, int item_race)
{
const bool no_brand = (item.special == SPMSL_FORBID_BRAND);
if (no_brand)
item.special = SPMSL_NORMAL;
item.plus = 0;
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
{
item.sub_type =
random_choose_weighted(30, MI_STONE,
20, MI_DART,
20, MI_ARROW,
12, MI_BOLT,
10, MI_NEEDLE,
5, MI_SLING_BULLET,
2, MI_JAVELIN,
1, MI_THROWING_NET,
0);
}
if (item.sub_type == MI_LARGE_ROCK)
{
item.quantity = 2 + random2avg(5,2);
return;
}
else if (item.sub_type == MI_STONE)
{
item.quantity = 1 + random2(9) + random2(12) + random2(15) + random2(12);
return;
}
else if (item.sub_type == MI_THROWING_NET) {
item.quantity = 1 + one_chance_in(4); return;
}
set_equip_race(item, _determine_missile_race(item, item_race));
if (!no_brand)
{
set_item_ego_type( item, OBJ_MISSILES,
_determine_missile_brand(item, item_level) );
}
if (item.sub_type == MI_JAVELIN
|| get_ammo_brand( item ) == SPMSL_CURARE
|| get_ammo_brand( item ) == SPMSL_RETURNING)
{
item.quantity = random_range(2, 8);
}
else if (get_ammo_brand( item ) != SPMSL_NORMAL)
item.quantity = 1 + random2(9) + random2(12) + random2(12);
else
item.quantity = 1 + random2(9) + random2(12) + random2(12) + random2(15);
if (x_chance_in_y(11 + item_level, 100))
item.plus += random2(5);
if (get_equip_race(item) == ISFLAG_ELVEN && item.sub_type == MI_ARROW
|| get_equip_race(item) == ISFLAG_DWARVEN && item.sub_type == MI_BOLT)
{
item.plus += random2(3);
}
}
static bool _try_make_armour_artefact(item_def& item, int force_type,
int item_level)
{
if (item_level > 2 && x_chance_in_y(101 + item_level * 3, 4000))
{
if (you.level_type != LEVEL_ABYSS
&& you.level_type != LEVEL_PANDEMONIUM
&& one_chance_in(50))
{
const int idx = find_okay_unrandart(OBJ_ARMOUR, force_type,
UNRANDSPEC_NORMAL);
if (idx != -1)
{
make_item_unrandart(item, idx);
return (true);
}
}
if (item.sub_type == ARM_BOOTS && one_chance_in(10))
{
item.sub_type = coinflip() ? ARM_NAGA_BARDING
: ARM_CENTAUR_BARDING;
}
else
hide2armour(item);
make_item_randart(item);
if (one_chance_in(5))
{
do_curse_item(item);
item.plus = -random2(6);
}
else
{
item.plus = random2(4);
if (one_chance_in(5))
item.plus += random2(4);
if (one_chance_in(6))
item.plus -= random2(8);
if (item.plus < 0 && !one_chance_in(3))
do_curse_item(item);
}
return (true);
}
if (item_level > 6
&& one_chance_in(12)
&& x_chance_in_y(31 + item_level * 3, 3000))
{
return (_try_make_item_special_unrand(item, force_type, item_level));
}
return (false);
}
static item_status_flag_type _determine_armour_race(const item_def& item,
int item_race)
{
item_status_flag_type rc = ISFLAG_NO_RACE;
switch (item_race)
{
case MAKE_ITEM_ELVEN:
rc = ISFLAG_ELVEN;
break;
case MAKE_ITEM_DWARVEN:
rc = ISFLAG_DWARVEN;
break;
case MAKE_ITEM_ORCISH:
rc = ISFLAG_ORCISH;
break;
case MAKE_ITEM_RANDOM_RACE:
if (coinflip())
break;
switch (item.sub_type)
{
case ARM_SHIELD:
case ARM_BUCKLER:
case ARM_LARGE_SHIELD:
if (one_chance_in(4))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_ELVEN;
if (one_chance_in(3))
rc = ISFLAG_DWARVEN;
break;
case ARM_CLOAK:
if (one_chance_in(4))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_DWARVEN;
if (one_chance_in(4))
rc = ISFLAG_ELVEN;
break;
case ARM_GLOVES:
case ARM_BOOTS:
if (one_chance_in(4))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_ELVEN;
if (one_chance_in(6))
rc = ISFLAG_DWARVEN;
break;
case ARM_CAP:
case ARM_WIZARD_HAT:
if (one_chance_in(6))
rc = ISFLAG_ELVEN;
break;
case ARM_HELMET:
if (one_chance_in(6))
rc = ISFLAG_ORCISH;
if (one_chance_in(5))
rc = ISFLAG_DWARVEN;
break;
case ARM_ROBE:
if (one_chance_in(6))
rc = ISFLAG_ORCISH;
if (one_chance_in(4))
rc = ISFLAG_ELVEN;
break;
case ARM_LEATHER_ARMOUR:
case ARM_RING_MAIL:
case ARM_SCALE_MAIL:
case ARM_CHAIN_MAIL:
case ARM_SPLINT_MAIL:
case ARM_BANDED_MAIL:
case ARM_PLATE_MAIL:
if (item.sub_type <= ARM_CHAIN_MAIL && one_chance_in(6))
rc = ISFLAG_ELVEN;
if (item.sub_type >= ARM_RING_MAIL && one_chance_in(5))
rc = ISFLAG_DWARVEN;
if (one_chance_in(5))
rc = ISFLAG_ORCISH;
default:
break;
}
}
return (rc);
}
static special_armour_type _determine_armour_ego(const item_def& item,
int force_type, int item_level)
{
if (item.special != 0)
return static_cast<special_armour_type>(item.special);
special_armour_type rc = SPARM_NORMAL;
switch (item.sub_type)
{
case ARM_SHIELD:
case ARM_LARGE_SHIELD:
case ARM_BUCKLER:
rc = static_cast<special_armour_type>(
random_choose_weighted(40, SPARM_RESISTANCE,
120, SPARM_FIRE_RESISTANCE,
120, SPARM_COLD_RESISTANCE,
120, SPARM_POISON_RESISTANCE,
120, SPARM_POSITIVE_ENERGY,
480, SPARM_PROTECTION,
1000, SPARM_REFLECTION, 0));
break;
case ARM_CLOAK:
{
const special_armour_type cloak_egos[] = {
SPARM_POISON_RESISTANCE, SPARM_DARKNESS,
SPARM_MAGIC_RESISTANCE, SPARM_PRESERVATION
};
rc = RANDOM_ELEMENT(cloak_egos);
break;
}
case ARM_WIZARD_HAT:
if (coinflip())
{
rc = (one_chance_in(3) ? SPARM_MAGIC_RESISTANCE
: SPARM_INTELLIGENCE);
}
break;
case ARM_CAP:
if (one_chance_in(10))
{
rc = SPARM_SPIRIT_SHIELD;
break;
}
case ARM_HELMET:
rc = coinflip() ? SPARM_SEE_INVISIBLE : SPARM_INTELLIGENCE;
break;
case ARM_GLOVES:
rc = coinflip() ? SPARM_DEXTERITY : SPARM_STRENGTH;
break;
case ARM_BOOTS:
case ARM_NAGA_BARDING:
case ARM_CENTAUR_BARDING:
{
const int tmp = random2(600) + 200 * (item.sub_type != ARM_BOOTS);
rc = (tmp < 200) ? SPARM_RUNNING :
(tmp < 400) ? SPARM_LEVITATION :
(tmp < 600) ? SPARM_STEALTH :
(tmp < 700) ? SPARM_COLD_RESISTANCE
: SPARM_FIRE_RESISTANCE;
break;
}
case ARM_ROBE:
switch (random2(4))
{
case 0:
rc = coinflip() ? SPARM_COLD_RESISTANCE : SPARM_FIRE_RESISTANCE;
break;
case 1:
rc = SPARM_MAGIC_RESISTANCE;
break;
case 2:
rc = coinflip() ? SPARM_POSITIVE_ENERGY : SPARM_RESISTANCE;
break;
case 3:
if (force_type == OBJ_RANDOM && x_chance_in_y(11 + item_level, 50))
rc = SPARM_ARCHMAGI;
break;
}
break;
default:
rc = coinflip() ? SPARM_COLD_RESISTANCE : SPARM_FIRE_RESISTANCE;
if (one_chance_in(9))
rc = SPARM_POSITIVE_ENERGY;
if (one_chance_in(5))
rc = SPARM_MAGIC_RESISTANCE;
if (one_chance_in(5))
rc = SPARM_POISON_RESISTANCE;
if (item.sub_type == ARM_PLATE_MAIL && one_chance_in(15))
rc = SPARM_PONDEROUSNESS;
break;
}
return (rc);
}
static void _generate_armour_item(item_def& item, bool allow_uniques,
int force_type, int item_level,
int item_race)
{
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
item.sub_type = get_random_armour_type(item_level);
if (allow_uniques
&& _try_make_armour_artefact(item, force_type, item_level))
{
return;
}
if (is_helmet(item) && one_chance_in(3))
set_helmet_random_desc(item);
if (item_race == MAKE_ITEM_RANDOM_RACE && item.sub_type == ARM_BOOTS)
{
if (one_chance_in(8))
item.sub_type = ARM_NAGA_BARDING;
else if (one_chance_in(7))
item.sub_type = ARM_CENTAUR_BARDING;
}
set_equip_race(item, _determine_armour_race(item, item_race));
if (get_equip_race(item) == ISFLAG_DWARVEN && coinflip())
item.plus++;
const bool force_good = (item_level == MAKE_GOOD_ITEM);
const bool forced_ego = (item.special > 0);
const bool no_ego = (item.special == SPARM_FORBID_EGO);
if (no_ego)
item.special = SPARM_NORMAL;
if (item_level < 0)
{
if (!no_ego && (forced_ego || one_chance_in(4)))
{
set_item_ego_type(item, OBJ_ARMOUR,
_determine_armour_ego(item, item.sub_type, 2+2*you.your_level));
}
item.plus -= 1 + random2(3);
if (item_level == -5)
do_curse_item(item);
}
else if ((force_good || forced_ego || item.sub_type == ARM_WIZARD_HAT
|| x_chance_in_y(51 + item_level, 250))
&& !item_is_mundane(item))
{
item.plus += random2(3);
if (item.sub_type <= ARM_PLATE_MAIL
&& x_chance_in_y(21 + item_level, 300))
{
item.plus += random2(3);
}
if (!no_ego
&& x_chance_in_y(31 + item_level, 350)
&& (force_good
|| forced_ego
|| get_equip_race(item) != ISFLAG_ORCISH
|| item.sub_type <= ARM_PLATE_MAIL && coinflip()))
{
set_item_ego_type(item, OBJ_ARMOUR,
_determine_armour_ego(item, force_type,
item_level));
if (get_armour_ego_type(item) == SPARM_PONDEROUSNESS)
item.plus += 3 + random2(4);
}
}
else if (one_chance_in(12))
{
do_curse_item(item);
if (one_chance_in(5))
item.plus -= random2(3);
set_item_ego_type(item, OBJ_ARMOUR, SPARM_NORMAL);
}
if (force_good)
hide2armour(item);
if (armour_is_hide(item, true)
|| item.sub_type == ARM_ANIMAL_SKIN
|| item.sub_type == ARM_CRYSTAL_PLATE_MAIL)
{
if (!forced_ego)
set_item_ego_type(item, OBJ_ARMOUR, SPARM_NORMAL);
}
if (item.plus > armour_max_enchant(item))
item.plus = armour_max_enchant(item);
if (armour_is_hide(item))
item.plus = 0;
}
static monster_type _choose_random_monster_corpse()
{
for (int count = 0; count < 1000; ++count)
{
monster_type spc = mons_species(random2(NUM_MONSTERS));
if (mons_weight(spc) > 0) return spc;
}
return (MONS_RAT); }
static int _random_wand_subtype()
{
int rc = random2( NUM_WANDS );
if (rc == WAND_INVISIBILITY || rc == WAND_HASTING || rc == WAND_HEALING
|| (rc == WAND_FIREBALL || rc == WAND_TELEPORTATION) && coinflip())
{
rc = random2( NUM_WANDS );
}
return rc;
}
static int _wand_max_charges(int subtype)
{
switch (subtype)
{
case WAND_HEALING: case WAND_HASTING: case WAND_INVISIBILITY:
return 8;
case WAND_FLAME: case WAND_FROST: case WAND_MAGIC_DARTS:
case WAND_RANDOM_EFFECTS:
return 28;
default:
return 16;
}
}
static void _generate_wand_item(item_def& item, int force_type)
{
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
item.sub_type = _random_wand_subtype();
item.plus = random2avg(_wand_max_charges(item.sub_type), 3);
if (item.plus == 0)
item.plus++;
item.plus2 = 0;
}
static void _generate_food_item(item_def& item, int force_quant, int force_type)
{
if (force_type == OBJ_RANDOM)
{
item.sub_type = random_choose_weighted( 250, FOOD_MEAT_RATION,
300, FOOD_BREAD_RATION,
100, FOOD_PEAR,
100, FOOD_APPLE,
100, FOOD_CHOKO,
10, FOOD_CHEESE,
10, FOOD_PIZZA,
10, FOOD_SNOZZCUMBER,
10, FOOD_APRICOT,
10, FOOD_ORANGE,
10, FOOD_BANANA,
10, FOOD_STRAWBERRY,
10, FOOD_RAMBUTAN,
10, FOOD_LEMON,
10, FOOD_GRAPE,
10, FOOD_SULTANA,
10, FOOD_LYCHEE,
10, FOOD_BEEF_JERKY,
10, FOOD_SAUSAGE,
5, FOOD_HONEYCOMB,
5, FOOD_ROYAL_JELLY,
0);
}
else
item.sub_type = force_type;
if (item.sub_type == FOOD_CHUNK)
{
item.plus = _choose_random_monster_corpse();
item.special = (10 + random2(11)) * 10;
}
if (force_quant > 1)
item.quantity = force_quant;
else
{
item.quantity = 1;
if (item.sub_type != FOOD_MEAT_RATION
&& item.sub_type != FOOD_BREAD_RATION)
{
if (one_chance_in(80))
item.quantity += random2(3);
if (item.sub_type == FOOD_STRAWBERRY
|| item.sub_type == FOOD_GRAPE
|| item.sub_type == FOOD_SULTANA)
{
item.quantity += 3 + random2avg(15,2);
}
}
}
}
static void _generate_potion_item(item_def& item, int force_type,
int item_level, int agent)
{
item.quantity = 1;
if (one_chance_in(18))
item.quantity++;
if (one_chance_in(25))
item.quantity++;
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
{
int stype;
do
{
stype = random_choose_weighted( 2815, POT_HEALING,
1407, POT_HEAL_WOUNDS,
900, POT_RESTORE_ABILITIES,
648, POT_POISON,
612, POT_SPEED,
612, POT_MIGHT,
612, POT_AGILITY,
612, POT_BRILLIANCE,
340, POT_INVISIBILITY,
340, POT_LEVITATION,
340, POT_RESISTANCE,
324, POT_MUTATION,
324, POT_SLOWING,
324, POT_PARALYSIS,
324, POT_CONFUSION,
278, POT_DEGENERATION,
222, POT_CURE_MUTATION,
162, POT_STRONG_POISON,
140, POT_MAGIC,
136, POT_BERSERK_RAGE,
111, POT_BLOOD,
70, POT_PORRIDGE,
38, POT_GAIN_STRENGTH,
38, POT_GAIN_DEXTERITY,
38, POT_GAIN_INTELLIGENCE,
13, POT_EXPERIENCE,
10, POT_DECAY,
0);
}
while (stype == POT_POISON && item_level < 1
|| stype == POT_STRONG_POISON && item_level < 11
|| agent == GOD_XOM && _is_boring_item(OBJ_POTIONS, stype));
if (stype == POT_GAIN_STRENGTH || stype == POT_GAIN_DEXTERITY
|| stype == POT_GAIN_INTELLIGENCE || stype == POT_EXPERIENCE
|| stype == POT_MAGIC || stype == POT_RESTORE_ABILITIES)
{
item.quantity = 1;
}
item.sub_type = stype;
}
if (is_blood_potion(item))
init_stack_blood_potions(item);
}
static void _generate_scroll_item(item_def& item, int force_type,
int item_level, int agent)
{
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
{
const int depth_mod = random2(1 + item_level);
do
{
item.sub_type = random_choose_weighted(
1797, SCR_IDENTIFY,
1305, SCR_REMOVE_CURSE,
802, SCR_TELEPORTATION,
642, SCR_DETECT_CURSE,
321, SCR_FEAR,
321, SCR_NOISE,
321, SCR_MAGIC_MAPPING,
321, SCR_FOG,
321, SCR_RANDOM_USELESSNESS,
321, SCR_CURSE_WEAPON,
321, SCR_CURSE_ARMOUR,
321, SCR_RECHARGING,
321, SCR_BLINKING,
321, SCR_ENCHANT_ARMOUR,
321, SCR_ENCHANT_WEAPON_I,
321, SCR_ENCHANT_WEAPON_II,
321, (item_level < 4 ? SCR_TELEPORTATION : SCR_IMMOLATION),
161, SCR_PAPER,
140, (depth_mod < 4 ? SCR_TELEPORTATION : SCR_ACQUIREMENT),
140, (depth_mod < 4 ? SCR_TELEPORTATION : SCR_ENCHANT_WEAPON_III),
140, (depth_mod < 4 ? SCR_DETECT_CURSE : SCR_SUMMONING),
140, (depth_mod < 4 ? SCR_PAPER : SCR_VULNERABILITY),
140, (depth_mod < 4 ? SCR_PAPER : SCR_SILENCE),
140, (depth_mod < 7 ? SCR_TELEPORTATION : SCR_VORPALISE_WEAPON),
140, (depth_mod < 7 ? SCR_DETECT_CURSE : SCR_TORMENT),
140, (depth_mod < 7 ? SCR_DETECT_CURSE : SCR_HOLY_WORD),
0);
}
while (agent == GOD_XOM && _is_boring_item(OBJ_SCROLLS, item.sub_type));
}
if (item.sub_type == SCR_VORPALISE_WEAPON
|| item.sub_type == SCR_ENCHANT_WEAPON_III
|| item.sub_type == SCR_ACQUIREMENT
|| item.sub_type == SCR_TORMENT
|| item.sub_type == SCR_HOLY_WORD
|| item.sub_type == SCR_SILENCE)
{
item.quantity = 1;
}
else
{
if (one_chance_in(24))
item.quantity = (coinflip() ? 2 : 3);
else
item.quantity = 1;
}
item.plus = 0;
}
static void _generate_book_item(item_def& item, int allow_uniques,
int force_type, int item_level)
{
item.special = random2(5);
if (one_chance_in(10))
item.special += random2(8) * 10;
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
{
do
{
item.sub_type = random2(NUM_FIXED_BOOKS);
if (book_rarity(item.sub_type) != 100
&& one_chance_in(10))
{
item.sub_type = coinflip() ? BOOK_WIZARDRY : BOOK_POWER;
}
if (!one_chance_in(100)
&& x_chance_in_y(book_rarity(item.sub_type)-1, item_level+1))
{
continue;
}
}
while (book_rarity(item.sub_type) == 100);
if (item_level > 10 && x_chance_in_y(21 + item_level, 7000))
item.sub_type = BOOK_DESTRUCTION;
if (item_level > 6 && x_chance_in_y(21 + item_level, 4000))
item.sub_type = BOOK_MANUAL;
}
if (item.sub_type == BOOK_MANUAL)
{
if (one_chance_in(4))
item.plus = SK_SPELLCASTING + random2(NUM_SKILLS - SK_SPELLCASTING);
else
{
item.plus = random2(SK_UNARMED_COMBAT);
if (item.plus == SK_UNUSED_1)
item.plus = SK_UNARMED_COMBAT;
}
item.plus2 = 3 + random2(15);
}
if (item.sub_type == BOOK_MANUAL || item.sub_type == BOOK_DESTRUCTION)
return;
if (allow_uniques && item_level > 2 && force_type == OBJ_RANDOM
&& x_chance_in_y(101 + item_level * 3, 4000))
{
int choice = random_choose_weighted(
58, BOOK_RANDART_THEME,
2, BOOK_RANDART_LEVEL, 0);
item.sub_type = choice;
}
if (item.sub_type == BOOK_RANDART_THEME)
make_book_theme_randart(item, 0, 0, 5 + coinflip(), 20);
else if (item.sub_type == BOOK_RANDART_LEVEL)
{
int max_level = std::min( 9, std::max(1, item_level / 3) );
int spl_level = random_range(1, max_level);
int max_spells = 5 + spl_level/3;
make_book_level_randart(item, spl_level, max_spells);
}
}
static void _generate_staff_item(item_def& item, int force_type)
{
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
{
item.sub_type = random2(STAFF_FIRST_ROD);
if (one_chance_in(10))
item.sub_type = random_rod_subtype();
if ((item.sub_type == STAFF_ENERGY
|| item.sub_type == STAFF_CHANNELING)
&& one_chance_in(4))
{
item.sub_type = coinflip() ? STAFF_WIZARDRY : STAFF_POWER;
}
}
if (item_is_rod(item))
init_rod_mp(item);
}
static bool _try_make_jewellery_unrandart(item_def& item, int force_type,
int item_level)
{
bool rc = false;
if (item_level > 2
&& you.level_type != LEVEL_ABYSS
&& you.level_type != LEVEL_PANDEMONIUM
&& one_chance_in(20)
&& x_chance_in_y(101 + item_level * 3, 2000))
{
const int idx = find_okay_unrandart(OBJ_JEWELLERY, force_type,
UNRANDSPEC_NORMAL);
if (idx != -1)
{
make_item_unrandart(item, idx);
rc = true;
}
}
return (rc);
}
static int _determine_ring_plus(int subtype)
{
int rc = 0;
switch (subtype)
{
case RING_PROTECTION:
case RING_STRENGTH:
case RING_SLAYING:
case RING_EVASION:
case RING_DEXTERITY:
case RING_INTELLIGENCE:
if (one_chance_in(5)) {
rc = (coinflip() ? -2 : -3);
if (one_chance_in(3))
rc -= random2(4);
}
else
rc = 1 + (one_chance_in(3) ? random2(3) : random2avg(6, 2));
break;
default:
break;
}
return rc;
}
static void _generate_jewellery_item(item_def& item, bool allow_uniques,
int force_type, int item_level,
int agent)
{
if (allow_uniques
&& _try_make_jewellery_unrandart(item, force_type, item_level))
{
return;
}
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
{
do
{
item.sub_type = (one_chance_in(4) ? get_random_amulet_type()
: get_random_ring_type());
}
while (agent == GOD_XOM
&& _is_boring_item(OBJ_JEWELLERY, item.sub_type));
}
item.plus = 0;
item.plus2 = 0;
item.plus = _determine_ring_plus(item.sub_type);
if (item.plus < 0)
do_curse_item(item);
if (item.sub_type == RING_SLAYING ) {
if (item_cursed(item) && !one_chance_in(20))
item.plus2 = -1 - random2avg(6, 2);
else
{
item.plus2 = 1 + (one_chance_in(3) ? random2(3) : random2avg(6, 2));
if (x_chance_in_y(9, 25)) {
do_uncurse_item(item);
item.plus = 0;
item.plus2 += 2;
}
}
}
if (allow_uniques && item_level > 2
&& x_chance_in_y(101 + item_level * 3, 4000))
{
make_item_randart(item);
}
else if (item_level > 6
&& one_chance_in(12)
&& x_chance_in_y(31 + item_level * 3, 3000))
{
_try_make_item_special_unrand(item, force_type, item_level);
}
else if (item.sub_type == RING_HUNGER || item.sub_type == RING_TELEPORTATION
|| one_chance_in(50))
{
do_curse_item(item);
}
}
static void _generate_misc_item(item_def& item, int force_type, int item_race)
{
if (force_type != OBJ_RANDOM)
item.sub_type = force_type;
else
{
do
item.sub_type = random2(NUM_MISCELLANY);
while
(item.sub_type == MISC_RUNE_OF_ZOT
|| item.sub_type == MISC_HORN_OF_GERYON
|| item.sub_type == MISC_DECK_OF_PUNISHMENT
|| (item.sub_type == MISC_DECK_OF_ESCAPE
|| item.sub_type == MISC_DECK_OF_DESTRUCTION
|| item.sub_type == MISC_DECK_OF_DUNGEONS
|| item.sub_type == MISC_DECK_OF_SUMMONING
|| item.sub_type == MISC_DECK_OF_WONDERS)
&& !one_chance_in(5));
if (item.sub_type == MISC_EMPTY_EBONY_CASKET && !one_chance_in(20))
item.sub_type = MISC_BOX_OF_BEASTS;
}
if ( is_deck(item) )
{
item.plus = 4 + random2(10);
item.special = random_choose_weighted( 8, DECK_RARITY_LEGENDARY,
20, DECK_RARITY_RARE,
72, DECK_RARITY_COMMON,
0);
init_deck(item);
}
if (item.sub_type == MISC_RUNE_OF_ZOT)
item.plus = item_race;
}
int items(int allow_uniques, object_class_type force_class, int force_type, bool dont_place, int item_level, int item_race, unsigned mapmask,
int force_ego, int agent) {
ASSERT(force_ego <= 0
|| force_type != OBJ_RANDOM
&& (force_class == OBJ_WEAPONS || force_class == OBJ_ARMOUR
|| force_class == OBJ_MISSILES));
int p = get_item_slot(10);
if (p == NON_ITEM)
return (NON_ITEM);
item_def& item(mitm[p]);
if (agent != -1)
origin_acquired(item, agent);
const bool force_good = (item_level == MAKE_GOOD_ITEM);
if (force_ego != 0)
allow_uniques = false;
item.special = force_ego;
if (item_level > 50 && !force_good)
item_level = 50;
if (force_class != OBJ_RANDOM)
item.base_type = force_class;
else
{
item.base_type = static_cast<object_class_type>(
random_choose_weighted( 5, OBJ_STAVES,
15, OBJ_BOOKS,
25, OBJ_JEWELLERY,
35, OBJ_WANDS,
70, OBJ_FOOD,
100, OBJ_ARMOUR,
100, OBJ_WEAPONS,
100, OBJ_POTIONS,
150, OBJ_MISSILES,
200, OBJ_SCROLLS,
200, OBJ_GOLD,
0));
if (item_level > 7 && x_chance_in_y(21 + item_level, 3500))
item.base_type = OBJ_MISCELLANY;
if (item_level < 7
&& (item.base_type == OBJ_BOOKS
|| item.base_type == OBJ_STAVES
|| item.base_type == OBJ_WANDS)
&& random2(7) >= item_level)
{
item.base_type = coinflip() ? OBJ_POTIONS : OBJ_SCROLLS;
}
}
item.quantity = 1;
if (force_ego < SP_FORBID_EGO)
{
force_ego = -force_ego;
if (get_unique_item_status(force_ego) == UNIQ_NOT_EXISTS)
{
make_item_unrandart(mitm[p], force_ego);
return (p);
}
item.special = SPWPN_NORMAL;
force_ego = 0;
}
switch (item.base_type)
{
case OBJ_WEAPONS:
_generate_weapon_item(item, allow_uniques, force_type,
item_level, item_race);
break;
case OBJ_MISSILES:
_generate_missile_item(item, force_type, item_level, item_race);
break;
case OBJ_ARMOUR:
_generate_armour_item(item, allow_uniques, force_type,
item_level, item_race);
break;
case OBJ_WANDS:
_generate_wand_item(item, force_type);
break;
case OBJ_FOOD:
_generate_food_item(item, allow_uniques, force_type);
break;
case OBJ_POTIONS:
_generate_potion_item(item, force_type, item_level, agent);
break;
case OBJ_SCROLLS:
_generate_scroll_item(item, force_type, item_level, agent);
break;
case OBJ_JEWELLERY:
_generate_jewellery_item(item, allow_uniques, force_type, item_level,
agent);
break;
case OBJ_BOOKS:
_generate_book_item(item, allow_uniques, force_type, item_level);
break;
case OBJ_STAVES:
_generate_staff_item(item, force_type);
break;
case OBJ_ORBS: item.sub_type = force_type;
break;
case OBJ_MISCELLANY:
_generate_misc_item(item, force_type, item_race);
break;
default:
item.base_type = OBJ_GOLD;
if (force_good)
{
item.quantity = 150 + random2(150)
+ random2(random2(random2(2000)));
}
else
item.quantity = 1 + random2avg(19, 2) + random2(item_level);
break;
}
item_colour(item);
item_set_appearance(item);
if (dont_place)
{
item.pos.reset();
item.link = NON_ITEM;
}
else
{
coord_def itempos;
bool found = false;
for (int i = 0; i < 500 && !found; ++i)
{
itempos = random_in_bounds();
found = (grd(itempos) == DNGN_FLOOR
&& unforbidden(itempos, mapmask));
}
if (!found)
{
destroy_item(p);
return (NON_ITEM);
}
move_item_to_grid(&p, itempos);
}
ASSERT(is_valid_item(mitm[p]));
return (p);
}
void init_rod_mp(item_def &item, int ncharges)
{
if (!item_is_rod(item))
return;
if (ncharges != -1)
item.plus2 = ncharges * ROD_CHARGE_MULT;
else
{
if (item.sub_type == STAFF_STRIKING)
item.plus2 = random_range(6, 9) * ROD_CHARGE_MULT;
else
item.plus2 = random_range(9, 14) * ROD_CHARGE_MULT;
}
item.plus = item.plus2;
}
static bool _weapon_is_visibly_special(const item_def &item)
{
const int brand = get_weapon_brand(item);
const bool visibly_branded = (brand != SPWPN_NORMAL);
if (get_equip_desc(item) != ISFLAG_NO_DESC)
return (false);
if (visibly_branded || is_artefact(item))
return (true);
if (item_is_mundane(item))
return (false);
if ((item.plus || item.plus2)
&& (one_chance_in(3) || get_equip_race(item) && one_chance_in(7)))
{
return (true);
}
return (false);
}
static bool _armour_is_visibly_special(const item_def &item)
{
const int brand = get_armour_ego_type(item);
const bool visibly_branded = (brand != SPARM_NORMAL);
if (get_equip_desc(item) != ISFLAG_NO_DESC)
return (false);
if (visibly_branded || is_artefact(item))
return (true);
if (item_is_mundane(item))
return (false);
if (item.plus && !one_chance_in(3))
return (true);
return (false);
}
static void _give_monster_item(monsters *mon, int thing,
bool force_item = false,
bool (monsters::*pickupfn)(item_def&, int) = NULL)
{
if (thing == NON_ITEM || thing == -1)
return;
item_def &mthing = mitm[thing];
ASSERT(is_valid_item(mthing));
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
"Giving %s to %s...", mthing.name(DESC_PLAIN).c_str(),
mon->name(DESC_PLAIN, true).c_str());
#endif
mthing.pos.reset();
mthing.link = NON_ITEM;
unset_ident_flags(mthing, ISFLAG_IDENT_MASK);
if (mon->is_unholy()
&& (is_blessed_blade(mthing)
|| get_weapon_brand(mthing) == SPWPN_HOLY_WRATH))
{
if (is_blessed_blade(mthing))
convert2bad(mthing);
if (get_weapon_brand(mthing) == SPWPN_HOLY_WRATH)
set_item_ego_type(mthing, OBJ_WEAPONS, SPWPN_NORMAL);
}
unwind_var<int> save_speedinc(mon->speed_increment);
if (!(pickupfn ? (mon->*pickupfn)(mthing, false)
: mon->pickup_item(mthing, false, true)))
{
#ifdef DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Destroying %s because %s doesn't want it!",
mthing.name(DESC_PLAIN, false, true).c_str(),
mon->name(DESC_PLAIN, true).c_str());
#endif
destroy_item(thing, true);
return;
}
ASSERT(is_valid_item(mthing));
ASSERT(mthing.holding_monster() == mon);
if (!force_item || mthing.colour == BLACK)
item_colour(mthing);
}
static void _give_scroll(monsters *mon, int level)
{
int thing_created = NON_ITEM;
if (mon->type == MONS_ROXANNE)
{
int which_book = (one_chance_in(3) ? BOOK_TRANSFIGURATIONS
: BOOK_EARTH);
thing_created = items(0, OBJ_BOOKS, which_book, true, level, 0);
if (thing_created != NON_ITEM && coinflip())
{
item_def &item(mitm[thing_created]);
make_book_Roxanne_special(&item);
_give_monster_item(mon, thing_created, true);
return;
}
}
else if (mons_is_unique(mon->type) && one_chance_in(3))
thing_created = items(0, OBJ_SCROLLS, OBJ_RANDOM, true, level, 0);
if (thing_created == NON_ITEM)
return;
mitm[thing_created].flags = 0;
_give_monster_item(mon, thing_created, true);
}
static void _give_wand(monsters *mon, int level)
{
if (mons_is_unique(mon->type) && mon->type != MONS_GASTRONOK
&& (one_chance_in(5) || mon->type == MONS_MAURICE && one_chance_in(3)))
{
const int idx = items(0, OBJ_WANDS, OBJ_RANDOM, true, level, 0);
if (idx == NON_ITEM)
return;
item_def& wand = mitm[idx];
if (mon->hit_dice < 5)
{
if (wand.sub_type == WAND_FIRE)
wand.sub_type = WAND_FLAME;
if (wand.sub_type == WAND_COLD)
wand.sub_type = WAND_FROST;
if (wand.sub_type == WAND_LIGHTNING)
wand.sub_type = (coinflip() ? WAND_FLAME : WAND_FROST);
}
wand.flags = 0;
_give_monster_item(mon, idx);
}
}
static void _give_potion(monsters *mon, int level)
{
if (mons_species(mon->type) == MONS_VAMPIRE && one_chance_in(5))
{
const int thing_created =
items(0, OBJ_POTIONS, POT_BLOOD, true, level, 0);
if (thing_created == NON_ITEM)
return;
mitm[thing_created].flags = 0;
_give_monster_item(mon, thing_created);
}
else if (mons_is_unique(mon->type) && one_chance_in(3))
{
const int thing_created =
items(0, OBJ_POTIONS, OBJ_RANDOM, true, level, 0);
if (thing_created == NON_ITEM)
return;
mitm[thing_created].flags = 0;
_give_monster_item(mon, thing_created, false,
&monsters::pickup_potion);
}
}
static item_make_species_type _give_weapon(monsters *mon, int level,
bool melee_only = false,
bool give_aux_melee = true)
{
bool force_item = false;
item_def item;
item_make_species_type item_race = MAKE_ITEM_RANDOM_RACE;
item.base_type = OBJ_UNASSIGNED;
if (mon->type == MONS_DANCING_WEAPON
&& player_in_branch( BRANCH_HALL_OF_BLADES ))
{
level = MAKE_GOOD_ITEM;
}
item.quantity = 1;
switch (mon->type)
{
case MONS_KOBOLD:
if (one_chance_in(10) && level > 1)
{
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_BLOWGUN;
break;
}
case MONS_BIG_KOBOLD:
if (x_chance_in_y(3, 5)) {
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose(WPN_DAGGER, WPN_DAGGER,
WPN_SHORT_SWORD, WPN_SHORT_SWORD,
WPN_CLUB, WPN_WHIP, -1);
}
else
return (item_race);
break;
case MONS_HOBGOBLIN:
if (one_chance_in(3))
item_race = MAKE_ITEM_ORCISH;
if (x_chance_in_y(3, 5)) {
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_CLUB;
}
else
return (item_race);
break;
case MONS_GOBLIN:
if (one_chance_in(3))
item_race = MAKE_ITEM_ORCISH;
if (!melee_only && one_chance_in(12) && level)
{
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_SLING;
break;
}
case MONS_JESSICA:
case MONS_IJYB:
if (x_chance_in_y(3, 5)) {
item.base_type = OBJ_WEAPONS;
item.sub_type = (coinflip() ? WPN_DAGGER : WPN_CLUB);
}
else
return (item_race);
break;
case MONS_WIGHT:
case MONS_NORRIS:
item.base_type = OBJ_WEAPONS;
if (one_chance_in(6))
{
item.sub_type = random_choose(WPN_SPIKED_FLAIL, WPN_GREAT_MACE,
WPN_WAR_AXE, WPN_TRIDENT, -1);
}
else
{
item.sub_type = random_choose(
WPN_MACE, WPN_FLAIL, WPN_MORNINGSTAR,
WPN_DAGGER, WPN_SHORT_SWORD, WPN_LONG_SWORD,
WPN_SCIMITAR, WPN_GREAT_SWORD, WPN_HAND_AXE,
WPN_BATTLEAXE, WPN_SPEAR, WPN_HALBERD,
-1);
}
if (coinflip())
{
force_item = true;
item.plus += 1 + random2(3);
item.plus2 += 1 + random2(3);
if (one_chance_in(5))
set_item_ego_type(item, OBJ_WEAPONS, SPWPN_FREEZING);
}
if (one_chance_in(3))
do_curse_item( item );
break;
case MONS_GNOLL:
case MONS_OGRE_MAGE:
case MONS_NAGA_WARRIOR:
case MONS_GREATER_NAGA:
case MONS_EDMUND:
case MONS_DUANE:
item_race = MAKE_ITEM_NO_RACE;
if (!one_chance_in(5))
{
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose(WPN_SPEAR, WPN_SPEAR, WPN_HALBERD,
WPN_CLUB, WPN_WHIP, WPN_FLAIL, -1);
}
break;
case MONS_GRUM:
force_item = true; item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose(WPN_WHIP, WPN_WHIP, WPN_SPEAR,
WPN_HALBERD, WPN_GLAIVE, -1);
set_item_ego_type(item, OBJ_WEAPONS, SPWPN_REACHING);
item.plus += -2 + random2(4);
item.plus2 += -1 + random2(2);
break;
case MONS_ORC:
case MONS_ORC_PRIEST:
item_race = MAKE_ITEM_ORCISH;
case MONS_DRACONIAN:
case MONS_DRACONIAN_ZEALOT:
if (!one_chance_in(5))
{
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose_weighted(
30, WPN_DAGGER, 30, WPN_CLUB,
27, WPN_FLAIL, 24, WPN_HAND_AXE,
20, WPN_HAMMER, 20, WPN_SHORT_SWORD,
20, WPN_MACE, 10, WPN_WHIP,
10, WPN_TRIDENT, 10, WPN_FALCHION,
10, WPN_MORNINGSTAR, 6, WPN_WAR_AXE,
3, WPN_SPIKED_FLAIL,
0);
}
else
return (item_race);
break;
case MONS_TERENCE:
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose_weighted( 30, WPN_FLAIL,
20, WPN_HAND_AXE,
20, WPN_SHORT_SWORD,
20, WPN_MACE,
10, WPN_TRIDENT,
10, WPN_FALCHION,
10, WPN_MORNINGSTAR,
3, WPN_SPIKED_FLAIL,
0);
break;
case MONS_DUVESSA:
item_race = MAKE_ITEM_ELVEN;
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose_weighted(30, WPN_SHORT_SWORD,
10, WPN_SABRE,
0);
break;
case MONS_DEEP_ELF_FIGHTER:
case MONS_DEEP_ELF_HIGH_PRIEST:
case MONS_DEEP_ELF_KNIGHT:
case MONS_DEEP_ELF_PRIEST:
case MONS_DEEP_ELF_SOLDIER:
item_race = MAKE_ITEM_ELVEN;
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose_weighted(
20, WPN_LONG_SWORD, 20, WPN_SHORT_SWORD, 14, WPN_SCIMITAR,
14, WPN_MACE, 13, WPN_BOW, 13, WPN_HAND_CROSSBOW,
5, WPN_LONGBOW,
0);
break;
case MONS_DEEP_ELF_BLADEMASTER:
{
item_race = MAKE_ITEM_ELVEN;
item.base_type = OBJ_WEAPONS;
const item_def *weap = mon->mslot_item(MSLOT_WEAPON);
if (weap && weap->base_type == OBJ_WEAPONS)
item.sub_type = weap->sub_type;
else
{
item.sub_type = random_choose_weighted(40, WPN_SABRE,
10, WPN_SHORT_SWORD,
2, WPN_QUICK_BLADE,
0);
}
break;
}
case MONS_DEEP_ELF_MASTER_ARCHER:
item_race = MAKE_ITEM_ELVEN;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_LONGBOW;
break;
case MONS_DEEP_ELF_ANNIHILATOR:
case MONS_DEEP_ELF_CONJURER:
case MONS_DEEP_ELF_DEATH_MAGE:
case MONS_DEEP_ELF_DEMONOLOGIST:
case MONS_DEEP_ELF_MAGE:
case MONS_DEEP_ELF_SORCERER:
case MONS_DEEP_ELF_SUMMONER:
item_race = MAKE_ITEM_ELVEN;
case MONS_DRACONIAN_SHIFTER:
case MONS_DRACONIAN_SCORCHER:
case MONS_DRACONIAN_ANNIHILATOR:
case MONS_DRACONIAN_CALLER:
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose(WPN_LONG_SWORD, WPN_LONG_SWORD,
WPN_SHORT_SWORD, WPN_SABRE,
WPN_DAGGER, WPN_WHIP,
-1);
break;
case MONS_ORC_WARRIOR:
case MONS_ORC_HIGH_PRIEST:
case MONS_BLORK_THE_ORC:
item_race = MAKE_ITEM_ORCISH;
case MONS_DANCING_WEAPON: case MONS_FRANCES:
case MONS_FRANCIS:
case MONS_HAROLD:
case MONS_JOSEPH:
case MONS_LOUISE:
case MONS_MICHAEL:
case MONS_NAGA:
case MONS_NAGA_MAGE:
case MONS_RUPERT:
case MONS_SKELETAL_WARRIOR:
case MONS_WAYNE:
case MONS_PALE_DRACONIAN:
case MONS_RED_DRACONIAN:
case MONS_WHITE_DRACONIAN:
case MONS_GREEN_DRACONIAN:
case MONS_MOTTLED_DRACONIAN:
case MONS_BLACK_DRACONIAN:
case MONS_YELLOW_DRACONIAN:
case MONS_PURPLE_DRACONIAN:
case MONS_TIAMAT:
if (mons_genus(mon->type) == MONS_NAGA)
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose_weighted(
10, WPN_LONG_SWORD, 10, WPN_SHORT_SWORD,
10, WPN_SCIMITAR, 10, WPN_BATTLEAXE,
10, WPN_HAND_AXE, 10, WPN_HALBERD,
10, WPN_GLAIVE, 10, WPN_MORNINGSTAR,
10, WPN_GREAT_MACE, 10, WPN_TRIDENT,
9, WPN_WAR_AXE, 9, WPN_FLAIL,
1, WPN_BROAD_AXE, 1, WPN_SPIKED_FLAIL,
0);
break;
case MONS_ORC_WARLORD:
case MONS_SAINT_ROKA:
if (one_chance_in(3))
level = MAKE_GOOD_ITEM;
case MONS_ORC_KNIGHT:
item_race = MAKE_ITEM_ORCISH;
if (!melee_only && one_chance_in(9))
{
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_CROSSBOW;
break;
}
case MONS_URUG:
item_race = MAKE_ITEM_ORCISH;
case MONS_NORBERT:
case MONS_JOZEF:
case MONS_VAULT_GUARD:
case MONS_VAMPIRE_KNIGHT:
case MONS_DRACONIAN_KNIGHT:
{
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose_weighted(
4, WPN_GREAT_SWORD, 4, WPN_LONG_SWORD,
4, WPN_BATTLEAXE, 4, WPN_WAR_AXE,
3, WPN_GREAT_MACE, 2, WPN_DIRE_FLAIL,
1, WPN_BARDICHE, 1, WPN_GLAIVE,
1, WPN_BROAD_AXE, 1, WPN_HALBERD,
0);
if (one_chance_in(4))
item.plus += 1 + random2(3);
break;
}
case MONS_POLYPHEMUS:
case MONS_CYCLOPS:
case MONS_STONE_GIANT:
item.base_type = OBJ_MISSILES;
item.sub_type = MI_LARGE_ROCK;
break;
case MONS_TWO_HEADED_OGRE:
case MONS_ETTIN:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = (one_chance_in(3) ? WPN_GIANT_SPIKED_CLUB
: WPN_GIANT_CLUB);
if (one_chance_in(10) || mon->type == MONS_ETTIN)
{
item.sub_type = (one_chance_in(10) ? WPN_DIRE_FLAIL
: WPN_GREAT_MACE);
}
break;
case MONS_REAPER:
level = MAKE_GOOD_ITEM;
case MONS_SIGMUND:
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_SCYTHE;
break;
case MONS_BALRUG:
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_DEMON_WHIP;
break;
case MONS_RED_DEVIL:
if (!one_chance_in(3))
{
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = (one_chance_in(3) ? WPN_DEMON_TRIDENT
: WPN_TRIDENT);
}
break;
case MONS_OGRE:
case MONS_HILL_GIANT:
case MONS_EROLCHA:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = (one_chance_in(3) ? WPN_GIANT_SPIKED_CLUB
: WPN_GIANT_CLUB);
if (one_chance_in(10))
{
item.sub_type = (one_chance_in(10) ? WPN_DIRE_FLAIL
: WPN_GREAT_MACE);
}
break;
case MONS_MERFOLK:
if (one_chance_in(3))
{
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_TRIDENT;
break;
}
case MONS_MERMAID:
if (one_chance_in(3))
{
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_SPEAR;
}
break;
case MONS_CENTAUR:
case MONS_CENTAUR_WARRIOR:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_BOW;
if (mon->type == MONS_CENTAUR_WARRIOR && one_chance_in(3))
item.sub_type = WPN_LONGBOW;
break;
case MONS_NESSOS:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_LONGBOW;
item.special = SPWPN_FLAME;
item.plus += 1 + random2(3);
item.plus2 += 1 + random2(3);
item.colour = DARKGREY;
force_item = true;
break;
case MONS_YAKTAUR:
case MONS_YAKTAUR_CAPTAIN:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_CROSSBOW;
break;
case MONS_EFREET:
case MONS_ERICA:
case MONS_AZRAEL:
force_item = true;
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_SCIMITAR;
item.plus = random2(5);
item.plus2 = random2(5);
item.colour = RED; set_item_ego_type( item, OBJ_WEAPONS, SPWPN_FLAMING );
break;
case MONS_ANGEL:
force_item = true;
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.colour = YELLOW;
item.sub_type = (one_chance_in(4) ? WPN_GREAT_MACE
: WPN_MACE);
set_equip_desc(item, ISFLAG_GLOWING);
set_item_ego_type(item, OBJ_WEAPONS, SPWPN_HOLY_WRATH);
item.plus = 1 + random2(3);
item.plus2 = 1 + random2(3);
break;
case MONS_DAEVA:
force_item = true;
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.colour = YELLOW;
item.sub_type = (one_chance_in(4) ? WPN_BLESSED_EUDEMON_BLADE
: WPN_LONG_SWORD);
set_equip_desc(item, ISFLAG_GLOWING);
set_item_ego_type(item, OBJ_WEAPONS, SPWPN_HOLY_WRATH);
item.plus = 1 + random2(3);
item.plus2 = 1 + random2(3);
break;
case MONS_HELL_KNIGHT:
case MONS_MAUD:
case MONS_FREDERICK:
case MONS_MARGERY:
force_item = true;
item.base_type = OBJ_WEAPONS;
item.sub_type = (one_chance_in(3) ? WPN_LONG_SWORD :
coinflip() ? WPN_SCIMITAR
: WPN_GREAT_SWORD);
if (one_chance_in(7))
item.sub_type = WPN_HALBERD;
if (one_chance_in(7))
item.sub_type = WPN_GLAIVE;
if (one_chance_in(7))
item.sub_type = WPN_GREAT_MACE;
if (one_chance_in(7))
item.sub_type = WPN_BATTLEAXE;
if (one_chance_in(7))
item.sub_type = WPN_WAR_AXE;
if (one_chance_in(7))
item.sub_type = WPN_BROAD_AXE;
if (one_chance_in(7))
item.sub_type = WPN_DEMON_WHIP;
if (one_chance_in(7))
item.sub_type = WPN_DEMON_BLADE;
if (one_chance_in(7))
item.sub_type = WPN_DEMON_TRIDENT;
if (one_chance_in(3))
set_item_ego_type( item, OBJ_WEAPONS, SPWPN_FLAMING );
else if (one_chance_in(3))
{
set_item_ego_type(item, OBJ_WEAPONS,
random_choose(SPWPN_DRAINING, SPWPN_VORPAL,
SPWPN_PAIN, SPWPN_DISTORTION,
SPWPN_SPEED, -1));
}
item.plus += random2(6);
item.plus2 += random2(6);
item.colour = RED;
if (one_chance_in(3))
item.colour = DARKGREY;
if (one_chance_in(5))
item.colour = CYAN;
break;
case MONS_FIRE_GIANT:
force_item = true;
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_GREAT_SWORD;
item.plus = 0;
item.plus2 = 0;
set_item_ego_type( item, OBJ_WEAPONS, SPWPN_FLAMING );
item.colour = RED; if (one_chance_in(3))
item.colour = DARKGREY;
if (one_chance_in(5))
item.colour = CYAN;
break;
case MONS_FROST_GIANT:
force_item = true;
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_BATTLEAXE;
item.plus = 0;
item.plus2 = 0;
set_item_ego_type( item, OBJ_WEAPONS, SPWPN_FREEZING );
item.colour = (one_chance_in(3) ? WHITE : CYAN);
break;
case MONS_ORC_WIZARD:
case MONS_ORC_SORCERER:
case MONS_NERGALLE:
item_race = MAKE_ITEM_ORCISH;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_DAGGER;
break;
case MONS_DOWAN:
item_race = MAKE_ITEM_ELVEN;
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_DAGGER;
break;
case MONS_KOBOLD_DEMONOLOGIST:
case MONS_NECROMANCER:
case MONS_WIZARD:
case MONS_PSYCHE:
case MONS_DONALD:
case MONS_JOSEPHINE:
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_DAGGER;
if (mon->type == MONS_PSYCHE)
{
set_item_ego_type(item, OBJ_WEAPONS,
random_choose_weighted(3, SPWPN_CHAOS,
1, SPWPN_DISTORTION,
0));
}
break;
case MONS_AGNES:
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_LAJATANG;
if (!one_chance_in(3))
level = MAKE_GOOD_ITEM;
break;
case MONS_SONJA:
if (!melee_only)
{
item.base_type = OBJ_WEAPONS;
item.sub_type = WPN_BLOWGUN;
item_race = MAKE_ITEM_NO_RACE;
break;
}
force_item = true;
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = coinflip() ? WPN_DAGGER : WPN_SHORT_SWORD;
set_item_ego_type(item, OBJ_WEAPONS,
random_choose_weighted(3, SPWPN_DISTORTION,
2, SPWPN_VENOM,
1, SPWPN_DRAINING,
0));
break;
case MONS_MAURICE:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = coinflip() ? WPN_DAGGER : WPN_SHORT_SWORD;
break;
case MONS_EUSTACHIO:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = (one_chance_in(3) ? WPN_FALCHION : WPN_SABRE);
break;
case MONS_CEREBOV:
force_item = true;
make_item_unrandart( item, UNRAND_CEREBOV ); break;
case MONS_DISPATER:
force_item = true;
make_item_unrandart( item, UNRAND_DISPATER );
break;
case MONS_ASMODEUS:
force_item = true;
make_item_unrandart( item, UNRAND_ASMODEUS );
break;
case MONS_GERYON:
item.base_type = OBJ_MISCELLANY;
item.sub_type = MISC_HORN_OF_GERYON;
break;
case MONS_SALAMANDER: force_item = true;
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_WEAPONS;
item.sub_type = random_choose(WPN_GREAT_SWORD, WPN_TRIDENT,
WPN_SPEAR, WPN_GLAIVE,
WPN_BOW, WPN_HALBERD,
-1);
set_item_ego_type(item, OBJ_WEAPONS, is_range_weapon(item) ?
SPWPN_FLAME : SPWPN_FLAMING);
item.plus = random2(5);
item.plus2 = random2(5);
item.colour = RED; break;
default:
break;
}
if (item.base_type == OBJ_UNASSIGNED)
return (item_race);
if (!force_item && mons_is_unique( mon->type ))
{
if (x_chance_in_y(10 + mon->hit_dice, 100))
level = MAKE_GOOD_ITEM;
else if (level != MAKE_GOOD_ITEM)
level += 5;
}
const object_class_type xitc = item.base_type;
const int xitt = item.sub_type;
const int thing_created =
((force_item) ? get_item_slot() : items(0, xitc, xitt, true,
level, item_race));
if (thing_created == NON_ITEM)
return (item_race);
if (force_item)
mitm[thing_created] = item;
item_def &i = mitm[thing_created];
if (melee_only && (i.base_type != OBJ_WEAPONS || is_range_weapon(i)))
{
destroy_item(thing_created);
return (item_race);
}
if (force_item)
item_set_appearance(i);
_give_monster_item(mon, thing_created, force_item);
if (give_aux_melee && (i.base_type != OBJ_WEAPONS || is_range_weapon(i)))
_give_weapon(mon, level, true, false);
return (item_race);
}
static void _give_ammo(monsters *mon, int level,
item_make_species_type item_race,
bool mons_summoned)
{
if (const item_def *launcher = mon->launcher())
{
const object_class_type xitc = OBJ_MISSILES;
int xitt = fires_ammo_type(*launcher);
if (xitt == MI_STONE && one_chance_in(15))
xitt = MI_SLING_BULLET;
const int thing_created = items(0, xitc, xitt, true, level, item_race);
if (thing_created == NON_ITEM)
return;
if (xitt == MI_NEEDLE)
{
if (mon->type == MONS_SONJA)
{
set_item_ego_type(mitm[thing_created], OBJ_MISSILES,
SPMSL_CURARE);
mitm[thing_created].quantity = random_range(4, 10);
}
else
{
set_item_ego_type(mitm[thing_created], OBJ_MISSILES,
_got_curare_roll(level) ? SPMSL_CURARE
: SPMSL_POISONED);
if (get_ammo_brand( mitm[thing_created] ) == SPMSL_CURARE)
mitm[thing_created].quantity = random_range(2, 8);
}
}
else
{
const int bow_brand = get_weapon_brand(*launcher);
const int ammo_brand = get_ammo_brand(mitm[thing_created]);
if (ammo_brand != SPMSL_NORMAL
&& (bow_brand == SPWPN_FLAME || bow_brand == SPWPN_FROST))
{
mitm[thing_created].special = SPMSL_NORMAL;
}
}
if (mon->type == MONS_DEEP_ELF_MASTER_ARCHER)
mitm[thing_created].quantity *= 2;
else if (mon->type == MONS_NESSOS)
mitm[thing_created].special = SPMSL_POISONED;
_give_monster_item(mon, thing_created);
}
else
{
int weap_type = -1;
object_class_type weap_class = OBJ_WEAPONS;
int qty = 0;
switch (mon->type)
{
case MONS_KOBOLD:
case MONS_BIG_KOBOLD:
if (x_chance_in_y(2, 5))
{
item_race = MAKE_ITEM_NO_RACE;
weap_class = OBJ_MISSILES;
weap_type = MI_DART;
qty = 1 + random2(5);
}
break;
case MONS_ORC_WARRIOR:
if (one_chance_in(
you.where_are_you == BRANCH_ORCISH_MINES? 9 : 20))
{
weap_type = random_choose(WPN_HAND_AXE, WPN_SPEAR, -1);
qty = random_range(4, 8);
item_race = MAKE_ITEM_ORCISH;
}
break;
case MONS_ORC:
if (one_chance_in(20))
{
weap_type = random_choose(WPN_HAND_AXE, WPN_SPEAR, -1);
qty = random_range(2, 5);
item_race = MAKE_ITEM_ORCISH;
}
break;
case MONS_URUG:
weap_type = MI_JAVELIN;
weap_class = OBJ_MISSILES;
item_race = MAKE_ITEM_ORCISH;
qty = random_range(4, 7);
break;
case MONS_MERFOLK:
if (!one_chance_in(3))
{
item_race = MAKE_ITEM_NO_RACE;
if (coinflip())
{
weap_type = WPN_SPEAR;
qty = 1 + random2(3);
}
else
{
weap_class = OBJ_MISSILES;
weap_type = MI_JAVELIN;
qty = 3 + random2(6);
}
}
if (one_chance_in(6) && !mons_summoned)
{
weap_class = OBJ_MISSILES;
weap_type = MI_THROWING_NET;
qty = 1;
if (one_chance_in(4))
qty += random2(3); }
break;
case MONS_DRACONIAN_KNIGHT:
case MONS_GNOLL:
case MONS_HILL_GIANT:
if (!one_chance_in(20))
break;
case MONS_HAROLD: case MONS_JOZEF: if (mons_summoned)
break;
weap_class = OBJ_MISSILES;
weap_type = MI_THROWING_NET;
qty = 1;
if (one_chance_in(3))
qty++;
if (mon->type == MONS_HAROLD || mon->type == MONS_JOZEF)
qty += random2(4);
break;
default:
break;
}
if (weap_type == -1)
return;
const int thing_created =
items(0, weap_class, weap_type, true, level, item_race);
if (thing_created != NON_ITEM)
{
item_def& w(mitm[thing_created]);
if (weap_type == OBJ_WEAPONS
&& get_weapon_brand(w) == SPWPN_RETURNING)
{
qty = 1;
}
w.quantity = qty;
_give_monster_item(mon, thing_created, false,
&monsters::pickup_throwable_weapon);
}
}
}
static bool make_item_for_monster(
monsters *mons,
object_class_type base,
int subtype,
int level,
item_make_species_type race = MAKE_ITEM_NO_RACE,
int allow_uniques = 0)
{
const int bp = get_item_slot();
if (bp == NON_ITEM)
return (false);
const int thing_created =
items(allow_uniques, base, subtype, true, level, race);
if (thing_created == NON_ITEM)
return (false);
_give_monster_item(mons, thing_created);
return (true);
}
void give_shield(monsters *mon, int level)
{
const item_def *main_weap = mon->mslot_item(MSLOT_WEAPON);
const item_def *alt_weap = mon->mslot_item(MSLOT_ALT_WEAPON);
if (main_weap && hands_reqd(*main_weap, mon->body_size()) == HANDS_TWO
|| alt_weap && hands_reqd(*alt_weap, mon->body_size()) == HANDS_TWO)
{
return;
}
switch (mon->type)
{
case MONS_DAEVA:
make_item_for_monster(mon, OBJ_ARMOUR, ARM_LARGE_SHIELD,
level * 2 + 1, MAKE_ITEM_NO_RACE, 1);
break;
case MONS_DEEP_ELF_SOLDIER:
case MONS_DEEP_ELF_FIGHTER:
if (one_chance_in(6))
{
make_item_for_monster(mon, OBJ_ARMOUR, ARM_BUCKLER,
level, MAKE_ITEM_ELVEN);
}
break;
case MONS_NAGA_WARRIOR:
case MONS_VAULT_GUARD:
if (one_chance_in(3))
{
make_item_for_monster(mon, OBJ_ARMOUR,
one_chance_in(3) ? ARM_LARGE_SHIELD
: ARM_SHIELD,
level, MAKE_ITEM_NO_RACE);
}
break;
case MONS_DRACONIAN_KNIGHT:
if (coinflip())
{
make_item_for_monster(mon, OBJ_ARMOUR,
coinflip()? ARM_LARGE_SHIELD : ARM_SHIELD,
level, MAKE_ITEM_NO_RACE);
}
break;
case MONS_DEEP_ELF_KNIGHT:
if (one_chance_in(3))
{
make_item_for_monster(mon, OBJ_ARMOUR, ARM_BUCKLER,
level, MAKE_ITEM_ELVEN);
}
break;
case MONS_NORRIS:
make_item_for_monster(mon, OBJ_ARMOUR, ARM_BUCKLER,
level * 2 + 1, MAKE_ITEM_RANDOM_RACE, 1);
break;
case MONS_NORBERT:
case MONS_LOUISE:
make_item_for_monster(mon, OBJ_ARMOUR, ARM_LARGE_SHIELD,
level * 2 + 1, MAKE_ITEM_RANDOM_RACE, 1);
break;
case MONS_DONALD:
make_item_for_monster(mon, OBJ_ARMOUR, ARM_SHIELD,
level * 2 + 1, MAKE_ITEM_RANDOM_RACE, 1);
break;
default:
break;
}
}
void give_armour(monsters *mon, int level)
{
item_make_species_type item_race = MAKE_ITEM_RANDOM_RACE;
int force_colour = 0;
item_def item;
switch (mon->type)
{
case MONS_DEEP_ELF_BLADEMASTER:
case MONS_DEEP_ELF_MASTER_ARCHER:
item_race = MAKE_ITEM_ELVEN;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_LEATHER_ARMOUR;
break;
case MONS_DUVESSA:
case MONS_DEEP_ELF_ANNIHILATOR:
case MONS_DEEP_ELF_CONJURER:
case MONS_DEEP_ELF_DEATH_MAGE:
case MONS_DEEP_ELF_DEMONOLOGIST:
case MONS_DEEP_ELF_FIGHTER:
case MONS_DEEP_ELF_HIGH_PRIEST:
case MONS_DEEP_ELF_KNIGHT:
case MONS_DEEP_ELF_MAGE:
case MONS_DEEP_ELF_PRIEST:
case MONS_DEEP_ELF_SOLDIER:
case MONS_DEEP_ELF_SORCERER:
case MONS_DEEP_ELF_SUMMONER:
if (item_race == MAKE_ITEM_RANDOM_RACE)
item_race = MAKE_ITEM_ELVEN;
case MONS_IJYB:
case MONS_ORC:
case MONS_ORC_HIGH_PRIEST:
case MONS_ORC_PRIEST:
case MONS_ORC_SORCERER:
if (item_race == MAKE_ITEM_RANDOM_RACE)
item_race = MAKE_ITEM_ORCISH;
case MONS_ERICA:
case MONS_HAROLD:
case MONS_JOSEPH:
case MONS_JOSEPHINE:
case MONS_JOZEF:
case MONS_NORBERT:
case MONS_PSYCHE:
if (x_chance_in_y(2, 5))
{
item.base_type = OBJ_ARMOUR;
const int temp_rand = random2(8);
item.sub_type = ((temp_rand < 4) ? ARM_LEATHER_ARMOUR :
(temp_rand < 6) ? ARM_RING_MAIL :
(temp_rand == 6) ? ARM_SCALE_MAIL
: ARM_CHAIN_MAIL);
}
else
return;
break;
case MONS_TERENCE:
item.base_type = OBJ_ARMOUR;
item.sub_type = random_choose_weighted(1, ARM_RING_MAIL,
3, ARM_SCALE_MAIL,
2, ARM_CHAIN_MAIL,
0);
break;
case MONS_GRUM:
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_ANIMAL_SKIN;
break;
case MONS_URUG:
item_race = MAKE_ITEM_ORCISH;
case MONS_DUANE:
case MONS_EDMUND:
case MONS_RUPERT:
case MONS_WAYNE:
{
item.base_type = OBJ_ARMOUR;
const int temp_rand = random2(4);
item.sub_type = ((temp_rand == 0) ? ARM_LEATHER_ARMOUR :
(temp_rand == 1) ? ARM_RING_MAIL :
(temp_rand == 2) ? ARM_SCALE_MAIL
: ARM_CHAIN_MAIL);
break;
}
case MONS_ORC_WARLORD:
case MONS_SAINT_ROKA:
if (one_chance_in(3))
level = MAKE_GOOD_ITEM;
case MONS_ORC_KNIGHT:
case MONS_ORC_WARRIOR:
item_race = MAKE_ITEM_ORCISH;
case MONS_FREDERICK:
case MONS_HELL_KNIGHT:
case MONS_LOUISE:
case MONS_MARGERY:
case MONS_MAUD:
case MONS_VAMPIRE_KNIGHT:
case MONS_VAULT_GUARD:
{
item.base_type = OBJ_ARMOUR;
const int temp_rand = random2(4);
item.sub_type = ((temp_rand == 0) ? ARM_CHAIN_MAIL :
(temp_rand == 1) ? ARM_SPLINT_MAIL :
(temp_rand == 2) ? ARM_BANDED_MAIL
: ARM_PLATE_MAIL);
break;
}
case MONS_ANGEL:
case MONS_SIGMUND:
case MONS_WIGHT:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_ROBE;
force_colour = WHITE;
break;
case MONS_CENTAUR:
case MONS_CENTAUR_WARRIOR:
case MONS_YAKTAUR:
case MONS_YAKTAUR_CAPTAIN:
if ( one_chance_in( mon->type == MONS_CENTAUR ? 1000 :
mon->type == MONS_CENTAUR_WARRIOR ? 500 :
mon->type == MONS_YAKTAUR ? 300
: 200))
{
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_CENTAUR_BARDING;
}
else
return;
break;
case MONS_NAGA:
case MONS_NAGA_MAGE:
case MONS_NAGA_WARRIOR:
case MONS_GREATER_NAGA:
if ( one_chance_in( mon->type == MONS_NAGA ? 800 :
mon->type == MONS_NAGA_WARRIOR ? 300 :
mon->type == MONS_NAGA_MAGE ? 200
: 100 ))
{
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_NAGA_BARDING;
}
else if (mon->type == MONS_GREATER_NAGA || one_chance_in(3))
{
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_ROBE;
}
else
return;
break;
case MONS_GASTRONOK:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_WIZARD_HAT;
break;
case MONS_MAURICE:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_CLOAK;
force_colour = DARKGREY;
break;
case MONS_DOWAN:
item_race = MAKE_ITEM_ELVEN;
case MONS_DONALD:
case MONS_JESSICA:
case MONS_KOBOLD_DEMONOLOGIST:
case MONS_OGRE_MAGE:
case MONS_EROLCHA:
case MONS_DRACONIAN:
case MONS_RED_DRACONIAN:
case MONS_WHITE_DRACONIAN:
case MONS_GREEN_DRACONIAN:
case MONS_PALE_DRACONIAN:
case MONS_MOTTLED_DRACONIAN:
case MONS_BLACK_DRACONIAN:
case MONS_YELLOW_DRACONIAN:
case MONS_PURPLE_DRACONIAN:
case MONS_DRACONIAN_SHIFTER:
case MONS_DRACONIAN_SCORCHER:
case MONS_DRACONIAN_ANNIHILATOR:
case MONS_DRACONIAN_CALLER:
case MONS_DRACONIAN_MONK:
case MONS_DRACONIAN_ZEALOT:
case MONS_DRACONIAN_KNIGHT:
case MONS_WIZARD:
case MONS_ILSUIW:
if (item_race == MAKE_ITEM_RANDOM_RACE)
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_ROBE;
break;
case MONS_TIAMAT:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_GOLD_DRAGON_ARMOUR;
break;
case MONS_ORC_WIZARD:
case MONS_BLORK_THE_ORC:
case MONS_NERGALLE:
item_race = MAKE_ITEM_ORCISH;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_ROBE;
break;
case MONS_BORIS:
level = MAKE_GOOD_ITEM;
case MONS_AGNES:
case MONS_FRANCES:
case MONS_FRANCIS:
case MONS_NECROMANCER:
case MONS_VAMPIRE_MAGE:
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_ROBE;
force_colour = DARKGREY;
break;
case MONS_EUSTACHIO:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_LEATHER_ARMOUR;
break;
case MONS_NESSOS:
item_race = MAKE_ITEM_NO_RACE;
item.base_type = OBJ_ARMOUR;
item.sub_type = ARM_CENTAUR_BARDING;
force_colour = DARKGREY;
break;
default:
return;
}
const object_class_type xitc = item.base_type;
const int xitt = item.sub_type;
if (mons_is_unique( mon->type ) && level != MAKE_GOOD_ITEM)
{
if (x_chance_in_y(9 + mon->hit_dice, 100))
level = MAKE_GOOD_ITEM;
else
level = level * 2 + 5;
}
const int thing_created = items(0, xitc, xitt, true, level, item_race);
if (thing_created == NON_ITEM)
return;
_give_monster_item(mon, thing_created);
if (force_colour)
mitm[thing_created].colour = force_colour;
}
static void _give_gold(monsters *mon, int level)
{
const int idx = items(0, OBJ_GOLD, 0, true, level, 0);
_give_monster_item(mon, idx);
}
void give_item(int mid, int level_number, bool mons_summoned)
{
monsters *mons = &menv[mid];
if (mons->type == MONS_MAURICE)
_give_gold(mons, level_number);
_give_scroll(mons, level_number);
_give_wand(mons, level_number);
_give_potion(mons, level_number);
const item_make_species_type item_race = _give_weapon(mons, level_number);
_give_ammo(mons, level_number, item_race, mons_summoned);
give_armour(mons, 1 + level_number / 2);
give_shield(mons, 1 + level_number / 2);
}
jewellery_type get_random_amulet_type()
{
return (jewellery_type)
(AMU_FIRST_AMULET + random2(NUM_JEWELLERY - AMU_FIRST_AMULET));
}
static jewellery_type _get_raw_random_ring_type()
{
return (jewellery_type) (RING_REGENERATION + random2(NUM_RINGS));
}
jewellery_type get_random_ring_type()
{
const jewellery_type j = _get_raw_random_ring_type();
if ((j == RING_INVISIBILITY
|| j == RING_REGENERATION
|| j == RING_TELEPORT_CONTROL
|| j == RING_SLAYING)
&& !one_chance_in(3))
{
return (_get_raw_random_ring_type());
}
return (j);
}
armour_type get_random_body_armour_type(int item_level)
{
for (int tries = 100; tries > 0; --tries)
{
const armour_type tr = get_random_armour_type(item_level);
if (get_armour_slot(tr) == EQ_BODY_ARMOUR)
return (tr);
}
return (ARM_ROBE);
}
armour_type get_random_armour_type(int item_level)
{
const armour_type defarmours[] = { ARM_ROBE, ARM_LEATHER_ARMOUR,
ARM_RING_MAIL };
int armtype = RANDOM_ELEMENT(defarmours);
if (x_chance_in_y(11 + item_level, 35))
{
const armour_type lowarmours[] = { ARM_ROBE, ARM_LEATHER_ARMOUR,
ARM_RING_MAIL, ARM_SCALE_MAIL,
ARM_CHAIN_MAIL };
armtype = RANDOM_ELEMENT(lowarmours);
if (one_chance_in(4))
armtype = ARM_ANIMAL_SKIN;
}
if (x_chance_in_y(11 + item_level, 60))
{
const armour_type medarmours[] = { ARM_ROBE, ARM_LEATHER_ARMOUR,
ARM_RING_MAIL, ARM_SCALE_MAIL,
ARM_CHAIN_MAIL, ARM_SPLINT_MAIL,
ARM_BANDED_MAIL, ARM_PLATE_MAIL };
armtype = RANDOM_ELEMENT(medarmours);
}
if (one_chance_in(20) && x_chance_in_y(11 + item_level, 400))
{
const armour_type hiarmours[] = { ARM_CRYSTAL_PLATE_MAIL,
ARM_TROLL_HIDE,
ARM_TROLL_LEATHER_ARMOUR,
ARM_DRAGON_HIDE, ARM_DRAGON_ARMOUR,
ARM_ICE_DRAGON_HIDE,
ARM_ICE_DRAGON_ARMOUR };
armtype = RANDOM_ELEMENT(hiarmours);
}
if (one_chance_in(20) && x_chance_in_y(11 + item_level, 500))
{
const armour_type morehiarmours[] = { ARM_ANIMAL_SKIN,
ARM_STEAM_DRAGON_HIDE,
ARM_STEAM_DRAGON_ARMOUR,
ARM_MOTTLED_DRAGON_HIDE,
ARM_MOTTLED_DRAGON_ARMOUR,
ARM_STORM_DRAGON_HIDE,
ARM_STORM_DRAGON_ARMOUR,
ARM_GOLD_DRAGON_HIDE,
ARM_GOLD_DRAGON_ARMOUR,
ARM_SWAMP_DRAGON_HIDE,
ARM_SWAMP_DRAGON_ARMOUR };
armtype = RANDOM_ELEMENT(morehiarmours);
if (armtype == ARM_ANIMAL_SKIN && one_chance_in(20))
armtype = ARM_CRYSTAL_PLATE_MAIL;
}
if (one_chance_in(5))
{
const armour_type secarmours[] = { ARM_SHIELD, ARM_CLOAK, ARM_HELMET,
ARM_GLOVES, ARM_BOOTS };
armtype = RANDOM_ELEMENT(secarmours);
if (armtype == ARM_HELMET && one_chance_in(3))
{
const armour_type hats[] = { ARM_CAP, ARM_WIZARD_HAT, ARM_HELMET };
armtype = RANDOM_ELEMENT(hats);
}
else if (armtype == ARM_SHIELD)
{
armtype = random_choose_weighted(333, ARM_SHIELD,
500, ARM_BUCKLER,
167, ARM_LARGE_SHIELD,
0);
}
}
return static_cast<armour_type>(armtype);
}
void item_set_appearance(item_def &item)
{
if (get_equip_desc(item) != ISFLAG_NO_DESC)
return;
switch (item.base_type)
{
case OBJ_WEAPONS:
if (_weapon_is_visibly_special(item))
{
set_equip_desc(item,
(coinflip() ? ISFLAG_GLOWING : ISFLAG_RUNED));
}
break;
case OBJ_ARMOUR:
if (_armour_is_visibly_special(item))
{
const item_status_flag_type descs[] = { ISFLAG_GLOWING,
ISFLAG_RUNED,
ISFLAG_EMBROIDERED_SHINY };
set_equip_desc(item, RANDOM_ELEMENT(descs));
}
break;
default:
break;
}
}