E76RRHMXEPJCNDNKMI3AP7OI7IOMXXRHVYWRIYA75BQMMIST2XRAC
6G5C44RL5V7GDKZTMUQZZSTA6ZALVUKYA4A6QYZ6OMNT6NLJUK6QC
W6VQWJ54YYI3GZAOVONSD3ZWCKCRHO6HKQSLII6CQYRD2V2X25SQC
ZXMXDBYYGS2YYAFUZFWBZ5VT2HQ2NRZIC4HJJLWZYXRJ2ZSGN36QC
AVCWYX6CU7PR3H5ZSEV2G3B7BSXPCD4ZYLSO2WPCHRMRPPXUKFAAC
C35MTVNINKCQBR7V52L7SLPO7455LDCQ5MBBXJFPQKJBF43JHRPQC
VY2RJLJQMUOVIJOYPTA7AEXPURIV3H6VF7O5QQ7LF44ZS36RTFYAC
4LSDVTTNEK7LTLUCGP5SUVXJBUFF457AKWA7CEUQURWXGGLHRGCQC
WV7UHA3KCZ5FOIFXFVCTSPVPR6YR5FAG2RSGCQCF6INYG5OYYHYAC
NUNJUNR747QJMJW7COJXCLYKHQ27N426GYGDJHTVDV6QAOE36PBQC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
U6HLBU2OIMKVNWWZ55SERG56WKAW3GSFFEGUJBP4SQVYSESGXC2QC
4NBPZKMZBKB3QYX4FFUAKDXQS43NJCBDLMHKDJFVXHQLX4MQDINAC
BK6MGPSEAEMU4URBAPKY3VTKK6JC6IZVN5CNOSN2UPTIOWQYEWLQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
ZI3XDQ75HFW54FG6ZK6ERZYV6FEXUGFY35Z6VZMKMQK3IMDG6XBQC
T3R2D5M4YSC6NFZ6YO3AEG4VWORECX72CHUM5UBADV4UPAAZG7WQC
NDKS43E4XVAU3FDY276OF5JW7E5SF6F5EJD2XLV5JLKZ5W6N554QC
5WVUTEZLEZEML54CKPR6GACQBYY3EMVNXMLJOREN6SSEUZGC47AQC
LM764EO6YIFOKMRXWZ5S4GYZB4BHZQDTEFP7MEVYO4NN4EDOFGNQC
PBKRKGKARGZSLVFVDTK5NWDXQD26NHNN67LDSSB75CLEWBR6TLEQC
MG6LLF3XYCOEBQRX7TJ4MUTKM3IROYWUMZGCMYVW4TGDG36CJMJQC
JYEEOUYQ7ZPKOGWUV7VCORBVSOLF2UCBFBH3TR75RGOSS6PNKYUAC
KVMJCPD4RM6YUWIMO4LDHEIB5W62MTOCGBWAEFBHNOUDYLGKXQ3QC
43B5XMJUEZWNLIQQPZFAMKMXAZT5MSCN5DU25AKC5IOZNELULONQC
XJZXBPVEV3HQIWKQ5UYSEMQQ26C4N7QYW23ZIIXMUR2I2S73LUYAC
HIJKLSREZFBQTAZ52CEWVYWHNFQA2CYWO5I3WJX3AN7OVZZW6EMAC
FWNNTOEERPUKXPE4OC52UABFZLKIU3O5GRNNLDK4QI4HR2IOU36QC
QO5ZJWQ3JK3PEGBPTQSAYIPEJEHG2M2KTD74227G5VG7DVXUL3BQC
HC2E2YYLYOAABU4ZTRAK3MZKGVKGXP3LM3CJVIPZFHYEE53NGADAC
WZNB427K3EUNV3FMVXLQTM4UIHER4FIKQXWLUUXRNQC3OQ33VQYAC
3DQXSE4YGFBBDUWK4YEOFWW4UPWILWELFSLP37SL6BERGAZJC5YAC
P2OYYNPHIBGOLT4CRLNTTIXDN34EU2QCMFQJNLAMUAHQXZTEDPXQC
4QYXUNAH54YJPAHB42Z3PPG7MGWGZ3G6Q5V2GTVOAB4MWECG52IAC
GUK3LTWA6FGBAHQ3VMRDVVFHOI3IT5NF33MOC6I43IZ5R4JZS4WAC
GWRYKZ22ZWQE4NRX2YLCWBHZSF7KHXUVTLBHOOKE5ICLS3T3NHNQC
NVD2HSEW2ONWNYDDCTOMZZOUP6NG4DCXI4LNYYIY4BQEBDMJQK5AC
JW2KRJHES33W7UTWZ6NDO4TLMK4EFU4HKZXBWR2UJOMPCCOTR4CQC
3NFVCXRVGHN2CHLLWFZES5RBS4R2BCDS4EEQNSDCFYIFQWQK7MUQC
LZUTEJNAVTXSZJX35HC4VIHNIHPCJ7WNQUNWB2SUE6IY7A5HAC7AC
2SU35FKBXMKAYJY76OXAC55R6JWTSHQSHBNBR3ICWUQREJME2ZSAC
PEXHYCLRKDG2PVOJ3DDCMUZUK2HTSPU5WKH4MODFL4FTBQRQTY5QC
5SKXI22WN2Y4SWUG634WDB7QXLBNV54RPN5OHAXRI55OFM5YBF5QC
NRIZKLUO26UHNKB4IERXI6ECMD2IJYZACQNIUU3SH6BPLGHAJYVAC
V633AMMPMHJB5ZLP5IHFXCT6FCENVTPX25TY7T5MF2QZLDDN24HAC
R5UWCN73VGZBWSRVBEMDX5D6WH3NGKUGBTNUGVAH32QFQSKSSZDAC
RQR4PTMGQLTRWLYRU3KXIIDGND7FBORESJWMWFVD3WYU5SISZXAAC
OWGIMHN3XYFWT7G24XCDK5VWM7I3TOOJO4HVN6UQEZ55C6T2BG7QC
RCFS63VUDBLUMOF2T4OS6OFHBA2LEGCKX7KHMUWTFJNMVASDGWAAC
VXAWOFQSBFAZZ4YTSHMLNI5JSR6HWLAPO7XIWCLRHGY2MTWRUGRQC
EZ3ZUOFAHXI73BSCXNYS36TTK4OGCQBSFEIRVNXUAE64ZVKDW5PAC
X3MRSKOVU6UONTCL2DPNJ3IXV2GAHDDHVZX6SRV4JPNSRCV5GMLAC
DCZMEKDHQWSQCQYQD6ZXB3XOMWLVLPSPVSBVVMPXMSZF7GO3BVCAC
FAVME2A2U4OUKN2BTISAG5PCI5Y4BN6YVFKCSQQHHZLEVVVF4LKAC
VCQYSNAWZZHOZMARWQ4AJBDNFSS7T7CZBQISSPZ2YIIK5PVAWPRQC
V4F3SDV2H4HBH6G6W5M3REN3BDSSE4IDF2RNM7PJMKRW3IDJ7PNAC
F44V6MFL4ILR3O76DNIF4B3ULX7Z6IIQQNHGEH3TWGU7SGU5VZ7AC
3ZT5EQNS5KXWEXAKV7C3TTFZ6QHOCR57LTFTETPKIVZGTXHZKRQAC
4GYZYBY7FFORRNPIEFTV4ZM2C7Z6D2KTQOM537ZCC2YBXT2TNSHAC
RHRLRHNN6F7OOLUXUK7ZAA75QRQLYIEBZUOWJKUCOMDUAQWDGKXAC
JBZ7NU4BB5PGQWCOSZHD5OQUHQIVOD4XGJLSJQ7BUGQEGPRTVGZQC
KK5IGMPS7OBB2LA7SMGWVR534Q4LYKUD2MESO5IAMOKLNBBDWOMQC
KAGCUOULIUHCPZSOSC6EJGOTH4PMEWCTMA4KGT7F5GQOQY5QX32QC
IIBG4SGYYEGKVLTHIDTMDHPVEWHEDADC4U2O7FZYGU34XMPMJGCAC
L75LNED7KDX22QA53XAQHYWNFVZUUIBWF23YG5WPSBRTCAIBW4DQC
JUKQIMBJHAYSBUZIEHLQ6UBQXLMESF4PPIA5CEHBYMYP73RJINNAC
LRNJ7O6FCNZ6TWEEQLXB6ZTKSDJNZ6HXV6T6RFVW5VU6E73MX4AQC
H62KGV237ZWD6HV7U7DRE5JYAJVKQ2LOQ4I7OVH6NJ6DB3U7N5CQC
HT3H2NAJLIUIZS2XKGODGDZPRGPCORKOCWSCTMZBRMIXJP4FEYIQC
LFJAIJGMBJHZQIYSLDJ57N56WFUY67LVM3GRWOPIDIVNELEQU5EAC
CCRQESB4ADT4WA7FGLNZZXAJ6G5QMCTYCZIWORBN45P6ZPILC34AC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC
MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC
OFH2B2UZBK43QLFQBZ54FOCFLFNE54BZVDNCEUGDTBCUGNVZULIQC
NGW2XPEX2XRK3CYC37DNUZSSB5IQLECMKRB6NX257I2X3G35LMPAC
U6OTXM3JN7SGPVIGQ5F6NR2I7J5V7KOWFQ7AVNNRQQDNLBEDMYFQC
ABLV37FMURRJPEZV2VRKOUYAKEMLI7E6RA4PDAII2EJ5L7WBHKZQC
UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC
bool is_holy_item(const item_def& item);
bool is_evil_item(const item_def& item);
bool is_chaotic_item(const item_def& item);
bool is_holy_discipline(int discipline);
bool is_evil_discipline(int discipline);
bool is_holy_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_evil_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_chaotic_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_hasty_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_any_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_spellbook_type(const item_def& item, bool book_or_rod,
bool (*suitable)(spell_type spell, god_type god) =
is_any_spell,
god_type god = you.religion);
bool is_holy_spellbook(const item_def& item);
bool is_evil_spellbook(const item_def& item);
bool is_chaotic_spellbook(const item_def& item);
bool god_hates_spellbook(const item_def& item);
bool is_holy_rod(const item_def& item);
bool is_evil_rod(const item_def& item);
bool is_chaotic_rod(const item_def& item);
bool god_hates_rod(const item_def& item);
conduct_type good_god_hates_item_handling(const item_def &item);
conduct_type god_hates_item_handling(const item_def &item);
bool god_hates_spell_type(spell_type spell, god_type god = you.religion);
// NOTE: As of now, these two functions only say if a god won't give a
// spell/school when giving a gift.
bool god_dislikes_spell_type(spell_type spell, god_type god = you.religion);
bool god_dislikes_spell_discipline(int discipline, god_type god = you.religion);
}
bool is_holy_item(const item_def& item)
{
bool retval = false;
if (is_unrandom_artefact(item))
{
unrandart_entry* entry = get_unrand_entry(item.special);
if (entry->flags & UNRAND_FLAG_HOLY)
return (true);
}
switch (item.base_type)
{
case OBJ_WEAPONS:
retval = (is_blessed_blade(item)
|| get_weapon_brand(item) == SPWPN_HOLY_WRATH);
break;
case OBJ_SCROLLS:
retval = (item.sub_type == SCR_HOLY_WORD);
break;
case OBJ_BOOKS:
retval = is_holy_spellbook(item);
break;
case OBJ_STAVES:
retval = is_holy_rod(item);
break;
default:
break;
}
return (retval);
}
bool is_evil_item(const item_def& item)
{
bool retval = false;
if (is_unrandom_artefact(item))
{
unrandart_entry* entry = get_unrand_entry(item.special);
if (entry->flags & UNRAND_FLAG_EVIL)
return (true);
}
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
retval = (is_demonic(item)
|| item_brand == SPWPN_DRAINING
|| item_brand == SPWPN_PAIN
|| item_brand == SPWPN_VAMPIRICISM
|| item_brand == SPWPN_SHADOW);
}
break;
case OBJ_MISSILES:
{
const int item_brand = get_ammo_brand(item);
retval = is_demonic(item) || item_brand == SPMSL_SHADOW;
break;
}
case OBJ_WANDS:
retval = (item.sub_type == WAND_DRAINING);
break;
case OBJ_SCROLLS:
retval = (item.sub_type == SCR_SUMMONING
|| item.sub_type == SCR_TORMENT);
break;
case OBJ_POTIONS:
retval = is_blood_potion(item);
break;
case OBJ_BOOKS:
retval = is_evil_spellbook(item);
break;
case OBJ_STAVES:
retval = (item.sub_type == STAFF_DEATH || is_evil_rod(item));
break;
case OBJ_MISCELLANY:
retval = (item.sub_type == MISC_BOTTLED_EFREET
|| item.sub_type == MISC_LANTERN_OF_SHADOWS);
break;
default:
break;
}
return (retval);
}
bool is_chaotic_item(const item_def& item)
{
bool retval = false;
if (is_unrandom_artefact(item))
{
unrandart_entry* entry = get_unrand_entry(item.special);
if (entry->flags & UNRAND_FLAG_CHAOTIC)
return (true);
}
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
retval = (item_brand == SPWPN_CHAOS);
}
break;
case OBJ_MISSILES:
{
const int item_brand = get_ammo_brand(item);
retval = (item_brand == SPMSL_CHAOS);
}
break;
case OBJ_WANDS:
retval = (item.sub_type == WAND_POLYMORPH_OTHER);
break;
case OBJ_POTIONS:
retval = (item.sub_type == POT_MUTATION);
break;
case OBJ_BOOKS:
retval = is_chaotic_spellbook(item);
break;
case OBJ_STAVES:
retval = is_chaotic_rod(item);
break;
default:
break;
}
if (is_artefact(item) && artefact_wpn_property(item, ARTP_MUTAGENIC))
retval = true;
return (retval);
}
bool is_hasty_item(const item_def& item)
{
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
if (item_brand == SPWPN_SPEED)
return (true);
}
break;
case OBJ_ARMOUR:
{
const int item_brand = get_armour_ego_type(item);
if (item_brand == SPARM_RUNNING)
return (true);
}
break;
case OBJ_WANDS:
if (item.sub_type == WAND_HASTING)
return (true);
break;
case OBJ_POTIONS:
if (item.sub_type == POT_SPEED || item.sub_type == POT_BERSERK_RAGE)
return (true);
break;
case OBJ_JEWELLERY:
// should this include AMU_RESIST_SLOWING?
if (item.sub_type == AMU_RAGE)
return (true);
break;
default:
break;
}
return (false);
}
bool is_holy_discipline(int discipline)
{
return (discipline & SPTYP_HOLY);
}
bool is_evil_discipline(int discipline)
{
return (discipline & SPTYP_NECROMANCY);
}
bool is_holy_spell(spell_type spell, god_type god)
{
UNUSED(god);
unsigned int disciplines = get_spell_disciplines(spell);
return (is_holy_discipline(disciplines));
}
bool is_evil_spell(spell_type spell, god_type god)
{
UNUSED(god);
unsigned int flags = get_spell_flags(spell);
unsigned int disciplines = get_spell_disciplines(spell);
return ((flags & SPFLAG_UNHOLY) || (is_evil_discipline(disciplines)));
}
bool is_chaotic_spell(spell_type spell, god_type god)
{
UNUSED(god);
return (spell == SPELL_POLYMORPH_OTHER
|| spell == SPELL_ALTER_SELF
|| spell == SPELL_SUMMON_UGLY_THING);
}
bool is_hasty_spell(spell_type spell, god_type god)
{
UNUSED(god);
return (spell == SPELL_HASTE
|| spell == SPELL_SWIFTNESS
|| spell == SPELL_BERSERKER_RAGE);
}
// The default suitable() function for is_spellbook_type().
bool is_any_spell(spell_type spell, god_type god)
{
UNUSED(god);
return (true);
}
// If book_or_rod is false, only look at actual spellbooks. Otherwise,
// only look at rods.
bool is_spellbook_type(const item_def& item, bool book_or_rod,
bool (*suitable)(spell_type spell, god_type god),
god_type god)
{
const bool is_spellbook = (item.base_type == OBJ_BOOKS
&& item.sub_type != BOOK_MANUAL
&& item.sub_type != BOOK_DESTRUCTION);
const bool is_rod = item_is_rod(item);
if (!is_spellbook && !is_rod)
return (false);
if (!book_or_rod && is_rod)
return (false);
int total = 0;
int total_liked = 0;
for (int i = 0; i < SPELLBOOK_SIZE; ++i)
{
spell_type spell = which_spell_in_book(item, i);
if (spell == SPELL_NO_SPELL)
continue;
total++;
if (suitable(spell, god))
total_liked++;
}
// If at least half of the available spells are suitable, the whole
// spellbook or rod is, too.
return (total_liked >= (total / 2) + 1);
}
bool is_holy_spellbook(const item_def& item)
{
return (is_spellbook_type(item, false, is_holy_spell));
}
bool is_evil_spellbook(const item_def& item)
{
return (is_spellbook_type(item, false, is_evil_spell));
bool is_chaotic_spellbook(const item_def& item)
{
return (is_spellbook_type(item, false, is_chaotic_spell));
}
bool god_hates_spellbook(const item_def& item)
{
return (is_spellbook_type(item, false, god_hates_spell_type));
}
bool is_holy_rod(const item_def& item)
{
return (is_spellbook_type(item, true, is_holy_spell));
}
bool is_evil_rod(const item_def& item)
{
return (is_spellbook_type(item, true, is_evil_spell));
}
bool is_chaotic_rod(const item_def& item)
{
return (is_spellbook_type(item, true, is_chaotic_spell));
}
bool god_hates_rod(const item_def& item)
{
return (is_spellbook_type(item, true, god_hates_spell_type));
}
conduct_type good_god_hates_item_handling(const item_def &item)
{
if (!is_good_god(you.religion) || !is_evil_item(item))
return (DID_NOTHING);
if (is_demonic(item))
return (DID_UNHOLY);
if (item_type_known(item)
|| item.base_type == OBJ_WEAPONS
&& get_weapon_brand(item) == SPWPN_CHAOS)
{
return (DID_NECROMANCY);
}
return (DID_NOTHING);
}
conduct_type god_hates_item_handling(const item_def &item)
{
switch (you.religion)
{
case GOD_ZIN:
if (item_type_known(item) && is_chaotic_item(item))
return (DID_CHAOS);
break;
case GOD_FEAWN:
if (!item_type_known(item))
return (DID_NOTHING);
if (is_evil_item(item)
|| item.base_type == OBJ_WEAPONS
&& get_weapon_brand(item) == SPWPN_CHAOS)
{
return (DID_NECROMANCY);
}
break;
case GOD_SHINING_ONE:
{
if (!item_type_known(item))
return (DID_NOTHING);
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
if (item_brand == SPWPN_VENOM)
return (DID_POISON);
break;
}
case OBJ_MISSILES:
{
const int item_brand = get_ammo_brand(item);
if (item_brand == SPMSL_POISONED || item_brand == SPMSL_CURARE)
return (DID_POISON);
break;
}
case OBJ_STAVES:
if (item.sub_type == STAFF_POISON)
return (DID_POISON);
break;
default:
break;
}
break;
}
case GOD_YREDELEMNUL:
if (item_type_known(item) && is_holy_item(item))
return (DID_HOLY);
break;
case GOD_TROG:
if (item.base_type == OBJ_BOOKS
&& item.sub_type != BOOK_MANUAL
&& item.sub_type != BOOK_DESTRUCTION)
{
return (DID_SPELL_MEMORISE);
}
break;
case GOD_CHRONOS:
if (item_type_known(item) && is_hasty_item(item))
return (DID_HASTY);
break;
default:
break;
}
if (item_type_known(item)
&& (god_hates_spellbook(item) || god_hates_rod(item)))
{
return (NUM_CONDUCTS); // FIXME: get the specific reason, if it
} // will ever be needed for spellbooks.
return (DID_NOTHING);
}
bool god_hates_spell_type(spell_type spell, god_type god)
{
if (is_good_god(god) && is_evil_spell(spell))
return (true);
unsigned int disciplines = get_spell_disciplines(spell);
switch (god)
{
case GOD_ZIN:
if (is_chaotic_spell(spell))
return (true);
break;
case GOD_SHINING_ONE:
// TSO hates using poison, but is fine with curing it, resisting
// it, or destroying it.
if ((disciplines & SPTYP_POISON) && spell != SPELL_CURE_POISON
&& spell != SPELL_RESIST_POISON && spell != SPELL_IGNITE_POISON)
{
return (true);
}
case GOD_YREDELEMNUL:
if (is_holy_spell(spell))
return (true);
break;
case GOD_CHRONOS:
if (is_hasty_spell(spell))
return (true);
break;
default:
break;
}
return (false);
}
bool god_dislikes_spell_type(spell_type spell, god_type god)
{
if (god_hates_spell_type(spell, god))
return (true);
unsigned int flags = get_spell_flags(spell);
unsigned int disciplines = get_spell_disciplines(spell);
switch (god)
{
case GOD_SHINING_ONE:
// TSO probably wouldn't like spells which would put enemies
// into a state where attacking them would be unchivalrous.
if (spell == SPELL_CAUSE_FEAR || spell == SPELL_PARALYSE
|| spell == SPELL_CONFUSE || spell == SPELL_MASS_CONFUSION
|| spell == SPELL_SLEEP || spell == SPELL_MASS_SLEEP)
{
return (true);
}
break;
case GOD_XOM:
// Ideally, Xom would only like spells which have a random effect,
// are risky to use, or would otherwise amuse him, but that would
// be a really small number of spells.
// Xom would probably find these extra boring.
if (flags & (SPFLAG_HELPFUL | SPFLAG_NEUTRAL | SPFLAG_ESCAPE
| SPFLAG_RECOVERY | SPFLAG_MAPPING))
{
return (true);
}
// Things are more fun for Xom the less the player knows in
// advance.
if (disciplines & SPTYP_DIVINATION)
return (true);
// Holy spells are probably too useful for Xom to find them
// interesting.
if (disciplines & SPTYP_HOLY)
return (true);
break;
case GOD_ELYVILON:
// A peaceful god of healing wouldn't like combat spells.
if (disciplines & SPTYP_CONJURATION)
return (true);
// Also doesn't like battle spells of the non-conjuration type.
if (flags & SPFLAG_BATTLE)
return (true);
break;
default:
break;
}
return (false);
}
bool god_dislikes_spell_discipline(int discipline, god_type god)
{
ASSERT(discipline < (1 << (SPTYP_LAST_EXPONENT + 1)));
if (is_good_god(god) && is_evil_discipline(discipline))
return (true);
switch (god)
{
case GOD_SHINING_ONE:
return (discipline & SPTYP_POISON);
case GOD_YREDELEMNUL:
return (discipline & SPTYP_HOLY);
case GOD_XOM:
return (discipline & (SPTYP_DIVINATION | SPTYP_HOLY));
case GOD_ELYVILON:
return (discipline & (SPTYP_CONJURATION | SPTYP_SUMMONING));
default:
break;
}
return (false);
}
#ifndef GODITEM_H
#define GODITEM_H
#include "enum.h"
#include "externs.h"
#include "artefact.h"
#include "itemname.h"
#include "spl-book.h"
#include "spl-cast.h"
#include "spl-util.h"
bool is_holy_item(const item_def& item);
bool is_evil_item(const item_def& item);
bool is_chaotic_item(const item_def& item);
bool is_holy_discipline(int discipline);
bool is_evil_discipline(int discipline);
bool is_holy_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_evil_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_chaotic_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_hasty_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_any_spell(spell_type spell, god_type god = GOD_NO_GOD);
bool is_spellbook_type(const item_def& item, bool book_or_rod,
bool (*suitable)(spell_type spell, god_type god) =
is_any_spell,
god_type god = you.religion);
bool is_holy_spellbook(const item_def& item);
bool is_evil_spellbook(const item_def& item);
bool is_chaotic_spellbook(const item_def& item);
bool god_hates_spellbook(const item_def& item);
bool is_holy_rod(const item_def& item);
bool is_evil_rod(const item_def& item);
bool is_chaotic_rod(const item_def& item);
bool god_hates_rod(const item_def& item);
conduct_type good_god_hates_item_handling(const item_def &item);
conduct_type god_hates_item_handling(const item_def &item);
bool god_hates_spell_type(spell_type spell, god_type god = you.religion);
// NOTE: As of now, these two functions only say if a god won't give a
// spell/school when giving a gift.
bool god_dislikes_spell_type(spell_type spell, god_type god = you.religion);
bool god_dislikes_spell_discipline(int discipline, god_type god = you.religion);
#endif
/*
* File: goditem.cc
* Summary: Gods' attitude towards items.
*/
#include "AppHdr.h"
#include "religion.h"
#include "goditem.h"
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <cmath>
#include "externs.h"
bool is_holy_item(const item_def& item)
{
bool retval = false;
if (is_unrandom_artefact(item))
{
unrandart_entry* entry = get_unrand_entry(item.special);
if (entry->flags & UNRAND_FLAG_HOLY)
return (true);
}
switch (item.base_type)
{
case OBJ_WEAPONS:
retval = (is_blessed_blade(item)
|| get_weapon_brand(item) == SPWPN_HOLY_WRATH);
break;
case OBJ_SCROLLS:
retval = (item.sub_type == SCR_HOLY_WORD);
break;
case OBJ_BOOKS:
retval = is_holy_spellbook(item);
break;
case OBJ_STAVES:
retval = is_holy_rod(item);
break;
default:
break;
}
return (retval);
}
bool is_evil_item(const item_def& item)
{
bool retval = false;
if (is_unrandom_artefact(item))
{
unrandart_entry* entry = get_unrand_entry(item.special);
if (entry->flags & UNRAND_FLAG_EVIL)
return (true);
}
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
retval = (is_demonic(item)
|| item_brand == SPWPN_DRAINING
|| item_brand == SPWPN_PAIN
|| item_brand == SPWPN_VAMPIRICISM
|| item_brand == SPWPN_SHADOW);
}
break;
case OBJ_MISSILES:
{
const int item_brand = get_ammo_brand(item);
retval = is_demonic(item) || item_brand == SPMSL_SHADOW;
break;
}
case OBJ_WANDS:
retval = (item.sub_type == WAND_DRAINING);
break;
case OBJ_SCROLLS:
retval = (item.sub_type == SCR_SUMMONING
|| item.sub_type == SCR_TORMENT);
break;
case OBJ_POTIONS:
retval = is_blood_potion(item);
break;
case OBJ_BOOKS:
retval = is_evil_spellbook(item);
break;
case OBJ_STAVES:
retval = (item.sub_type == STAFF_DEATH || is_evil_rod(item));
break;
case OBJ_MISCELLANY:
retval = (item.sub_type == MISC_BOTTLED_EFREET
|| item.sub_type == MISC_LANTERN_OF_SHADOWS);
break;
default:
break;
}
return (retval);
}
bool is_chaotic_item(const item_def& item)
{
bool retval = false;
if (is_unrandom_artefact(item))
{
unrandart_entry* entry = get_unrand_entry(item.special);
if (entry->flags & UNRAND_FLAG_CHAOTIC)
return (true);
}
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
retval = (item_brand == SPWPN_CHAOS);
}
break;
case OBJ_MISSILES:
{
const int item_brand = get_ammo_brand(item);
retval = (item_brand == SPMSL_CHAOS);
}
break;
case OBJ_WANDS:
retval = (item.sub_type == WAND_POLYMORPH_OTHER);
break;
case OBJ_POTIONS:
retval = (item.sub_type == POT_MUTATION);
break;
case OBJ_BOOKS:
retval = is_chaotic_spellbook(item);
break;
case OBJ_STAVES:
retval = is_chaotic_rod(item);
break;
default:
break;
}
if (is_artefact(item) && artefact_wpn_property(item, ARTP_MUTAGENIC))
retval = true;
return (retval);
}
bool is_hasty_item(const item_def& item)
{
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
if (item_brand == SPWPN_SPEED)
return (true);
}
break;
case OBJ_ARMOUR:
{
const int item_brand = get_armour_ego_type(item);
if (item_brand == SPARM_RUNNING)
return (true);
}
break;
case OBJ_WANDS:
if (item.sub_type == WAND_HASTING)
return (true);
break;
case OBJ_POTIONS:
if (item.sub_type == POT_SPEED || item.sub_type == POT_BERSERK_RAGE)
return (true);
break;
case OBJ_JEWELLERY:
// should this include AMU_RESIST_SLOWING?
if (item.sub_type == AMU_RAGE)
return (true);
break;
default:
break;
}
return (false);
}
bool is_holy_discipline(int discipline)
{
return (discipline & SPTYP_HOLY);
}
bool is_evil_discipline(int discipline)
{
return (discipline & SPTYP_NECROMANCY);
}
bool is_holy_spell(spell_type spell, god_type god)
{
UNUSED(god);
unsigned int disciplines = get_spell_disciplines(spell);
return (is_holy_discipline(disciplines));
}
bool is_evil_spell(spell_type spell, god_type god)
{
UNUSED(god);
unsigned int flags = get_spell_flags(spell);
unsigned int disciplines = get_spell_disciplines(spell);
return ((flags & SPFLAG_UNHOLY) || (is_evil_discipline(disciplines)));
}
bool is_chaotic_spell(spell_type spell, god_type god)
{
UNUSED(god);
return (spell == SPELL_POLYMORPH_OTHER
|| spell == SPELL_ALTER_SELF
|| spell == SPELL_SUMMON_UGLY_THING);
}
bool is_hasty_spell(spell_type spell, god_type god)
{
UNUSED(god);
return (spell == SPELL_HASTE
|| spell == SPELL_SWIFTNESS
|| spell == SPELL_BERSERKER_RAGE);
}
// The default suitable() function for is_spellbook_type().
bool is_any_spell(spell_type spell, god_type god)
{
UNUSED(god);
return (true);
}
// If book_or_rod is false, only look at actual spellbooks. Otherwise,
// only look at rods.
bool is_spellbook_type(const item_def& item, bool book_or_rod,
bool (*suitable)(spell_type spell, god_type god),
god_type god)
{
const bool is_spellbook = (item.base_type == OBJ_BOOKS
&& item.sub_type != BOOK_MANUAL
&& item.sub_type != BOOK_DESTRUCTION);
const bool is_rod = item_is_rod(item);
if (!is_spellbook && !is_rod)
return (false);
if (!book_or_rod && is_rod)
return (false);
int total = 0;
int total_liked = 0;
for (int i = 0; i < SPELLBOOK_SIZE; ++i)
{
spell_type spell = which_spell_in_book(item, i);
if (spell == SPELL_NO_SPELL)
continue;
total++;
if (suitable(spell, god))
total_liked++;
}
// If at least half of the available spells are suitable, the whole
// spellbook or rod is, too.
return (total_liked >= (total / 2) + 1);
}
bool is_holy_spellbook(const item_def& item)
{
return (is_spellbook_type(item, false, is_holy_spell));
}
bool is_evil_spellbook(const item_def& item)
{
return (is_spellbook_type(item, false, is_evil_spell));
}
bool is_chaotic_spellbook(const item_def& item)
{
return (is_spellbook_type(item, false, is_chaotic_spell));
}
bool god_hates_spellbook(const item_def& item)
{
return (is_spellbook_type(item, false, god_hates_spell_type));
}
bool is_holy_rod(const item_def& item)
{
return (is_spellbook_type(item, true, is_holy_spell));
}
bool is_evil_rod(const item_def& item)
{
return (is_spellbook_type(item, true, is_evil_spell));
}
bool is_chaotic_rod(const item_def& item)
{
return (is_spellbook_type(item, true, is_chaotic_spell));
}
bool god_hates_rod(const item_def& item)
{
return (is_spellbook_type(item, true, god_hates_spell_type));
}
conduct_type good_god_hates_item_handling(const item_def &item)
{
if (!is_good_god(you.religion) || !is_evil_item(item))
return (DID_NOTHING);
if (is_demonic(item))
return (DID_UNHOLY);
if (item_type_known(item)
|| item.base_type == OBJ_WEAPONS
&& get_weapon_brand(item) == SPWPN_CHAOS)
{
return (DID_NECROMANCY);
}
return (DID_NOTHING);
}
conduct_type god_hates_item_handling(const item_def &item)
{
switch (you.religion)
{
case GOD_ZIN:
if (item_type_known(item) && is_chaotic_item(item))
return (DID_CHAOS);
break;
case GOD_FEAWN:
if (!item_type_known(item))
return (DID_NOTHING);
if (is_evil_item(item)
|| item.base_type == OBJ_WEAPONS
&& get_weapon_brand(item) == SPWPN_CHAOS)
{
return (DID_NECROMANCY);
}
break;
case GOD_SHINING_ONE:
{
if (!item_type_known(item))
return (DID_NOTHING);
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
if (item_brand == SPWPN_VENOM)
return (DID_POISON);
break;
}
case OBJ_MISSILES:
{
const int item_brand = get_ammo_brand(item);
if (item_brand == SPMSL_POISONED || item_brand == SPMSL_CURARE)
return (DID_POISON);
break;
}
case OBJ_STAVES:
if (item.sub_type == STAFF_POISON)
return (DID_POISON);
break;
default:
break;
}
break;
}
case GOD_YREDELEMNUL:
if (item_type_known(item) && is_holy_item(item))
return (DID_HOLY);
break;
case GOD_TROG:
if (item.base_type == OBJ_BOOKS
&& item.sub_type != BOOK_MANUAL
&& item.sub_type != BOOK_DESTRUCTION)
{
return (DID_SPELL_MEMORISE);
}
break;
case GOD_CHRONOS:
if (item_type_known(item) && is_hasty_item(item))
return (DID_HASTY);
break;
default:
break;
}
if (item_type_known(item)
&& (god_hates_spellbook(item) || god_hates_rod(item)))
{
return (NUM_CONDUCTS); // FIXME: get the specific reason, if it
} // will ever be needed for spellbooks.
return (DID_NOTHING);
}
bool god_hates_spell_type(spell_type spell, god_type god)
{
if (is_good_god(god) && is_evil_spell(spell))
return (true);
unsigned int disciplines = get_spell_disciplines(spell);
switch (god)
{
case GOD_ZIN:
if (is_chaotic_spell(spell))
return (true);
break;
case GOD_SHINING_ONE:
// TSO hates using poison, but is fine with curing it, resisting
// it, or destroying it.
if ((disciplines & SPTYP_POISON) && spell != SPELL_CURE_POISON
&& spell != SPELL_RESIST_POISON && spell != SPELL_IGNITE_POISON)
{
return (true);
}
case GOD_YREDELEMNUL:
if (is_holy_spell(spell))
return (true);
break;
case GOD_CHRONOS:
if (is_hasty_spell(spell))
return (true);
break;
default:
break;
}
return (false);
}
bool god_dislikes_spell_type(spell_type spell, god_type god)
{
if (god_hates_spell_type(spell, god))
return (true);
unsigned int flags = get_spell_flags(spell);
unsigned int disciplines = get_spell_disciplines(spell);
switch (god)
{
case GOD_SHINING_ONE:
// TSO probably wouldn't like spells which would put enemies
// into a state where attacking them would be unchivalrous.
if (spell == SPELL_CAUSE_FEAR || spell == SPELL_PARALYSE
|| spell == SPELL_CONFUSE || spell == SPELL_MASS_CONFUSION
|| spell == SPELL_SLEEP || spell == SPELL_MASS_SLEEP)
{
return (true);
}
break;
case GOD_XOM:
// Ideally, Xom would only like spells which have a random effect,
// are risky to use, or would otherwise amuse him, but that would
// be a really small number of spells.
// Xom would probably find these extra boring.
if (flags & (SPFLAG_HELPFUL | SPFLAG_NEUTRAL | SPFLAG_ESCAPE
| SPFLAG_RECOVERY | SPFLAG_MAPPING))
{
return (true);
}
// Things are more fun for Xom the less the player knows in
// advance.
if (disciplines & SPTYP_DIVINATION)
return (true);
// Holy spells are probably too useful for Xom to find them
// interesting.
if (disciplines & SPTYP_HOLY)
return (true);
break;
case GOD_ELYVILON:
// A peaceful god of healing wouldn't like combat spells.
if (disciplines & SPTYP_CONJURATION)
return (true);
// Also doesn't like battle spells of the non-conjuration type.
if (flags & SPFLAG_BATTLE)
return (true);
break;
default:
break;
}
return (false);
}
bool god_dislikes_spell_discipline(int discipline, god_type god)
{
ASSERT(discipline < (1 << (SPTYP_LAST_EXPONENT + 1)));
if (is_good_god(god) && is_evil_discipline(discipline))
return (true);
switch (god)
{
case GOD_SHINING_ONE:
return (discipline & SPTYP_POISON);
case GOD_YREDELEMNUL:
return (discipline & SPTYP_HOLY);
case GOD_XOM:
return (discipline & (SPTYP_DIVINATION | SPTYP_HOLY));
case GOD_ELYVILON:
return (discipline & (SPTYP_CONJURATION | SPTYP_SUMMONING));
default:
break;
}
return (false);
}