git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7746 c06c8d41-db1a-0410-9941-cceddc491573
QO5ZJWQ3JK3PEGBPTQSAYIPEJEHG2M2KTD74227G5VG7DVXUL3BQC KK3VOK55GODD7XJKCQGQEXR7KUFXRDI5RRMTMLHRZTPXHYKVNUIQC FWNNTOEERPUKXPE4OC52UABFZLKIU3O5GRNNLDK4QI4HR2IOU36QC HH7B5SORPUW74EC3V2ZVZTMDH7UXG2FLAELXUQII4TNGGHDLPETAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC DDU4A3JGN5IUIPP5IASOODKPR2WBHSDSV4FITZ6HNXNSXXQACWAQC 7BREK7U6OWZ6YU3JDSJSH4CMNNULDYABCKCAUHGZIUJZBIRJS5WQC NQMXQ6OQVUSC7Y7F7IL252QW4A5JED224EECNHWAM4ZZYVNY745AC 4HHCHQD26LSGYC5TSQV25D2KIWLRJDB4BJQHJPSIB3MWNSSE4TGAC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC CHO4U5JC3RNTLXVIDXXJYZMOBZJ4VXW2GVJWDOTBRKK3AJ36LDLQC 46MRRHVYJ3BS74R2BEVUWEWJCI4FCRBSLZ3NWMQCE6FUCNE5P73QC KOSAQXB3KF6VAYTG2TOTHGJBB3F7AL6O32EMCXPVZJ5WHQX6XR5AC 25VJTGR3AWZJ7OHKYWS53VJ6TVMMU6UT7BA6V3QVVWDGI6FYKD7QC E6JXIMRH2TX5WHZ6BT2QZ3EANM3PWCHCVYC4XWRJGRBDSP42X2RAC 2KTJHQUX2LTU2BCLS5YXVRRKMOYKKIZAPF2LBKORFGSHEN5IO3IAC XDJGQNFELURGXMUAOOVALQMSLAJVHMG63KPKVA33HTJFVZROGZ4AC DF5LOTJFSXOT7UBDHLBDLGA22OY4L7ZF6CVFP6H3KL4N5CHB5C5QC 4QMMF3ZQ37PVVPLFUCNA6VJAL6S7QCFJ4QBU6V7ZFJR4FRDH3R6QC LY7DLLD7IKL6ZQPVROLDJ46XRM5CMAAEBRFDKJ4M53CPC5GFCGSQC XI7X6SNTHG67D4NQWM75HWB6TVRXVFDPGNSQLTXN6JAZBZIVZXIQC SN3VSV7G6NF6NLX5E47QJQQFDIPC2LQUUYGZMH6AWBF3FOUHXCBQC VCG3BRIYRTNNWYC3LOXD6KFGXOX37HAFW2HNV7WXVG2V7EUHLDZQC VBG2GGMVC66LQM4OSI67VKXGAQK4GVOEHX3OL6V3IFOO52MQL72QC LDBTCT5WIPLJPZWXS2RUQ26QKISCUUTLO77M464WOE6VSYSNPKYAC static unsigned char _lowest_rarity[NUM_SPELLS];void init_spell_rarities(){for (int i = 0; i < NUM_SPELLS; i++)_lowest_rarity[i] = 255;for (int i = 0; i < NUM_BOOKS; i++){const int rarity = book_rarity(i);// Manuals, books of destruction, books only created as gifts// from specific gods, and the unused Book of Healing.if (rarity >= 20)continue;for (int j = 0; j < SPELLBOOK_SIZE; j++){spell_type spell = which_spell_in_book(i, j);if (spell == SPELL_NO_SPELL)continue;#ifdef DEBUGint unsigned flags = get_spell_flags(spell);if (flags & (SPFLAG_MONSTER | SPFLAG_TESTING)){item_def item;item.base_type = OBJ_BOOKS;item.sub_type = i;end(1, false, "Spellbook '%s' contains invalid spell ""'%s'",item.name(DESC_PLAIN, false, true).c_str(),spell_title(spell));}#endif
static void _get_spell_list(std::vector<spell_type> &spell_list, int level,unsigned int disc1, unsigned int disc2,god_type god, bool avoid_uncastable,int &god_discard, int &uncastable_discard){for (int i = 0; i < NUM_SPELLS; i++){const spell_type spell = (spell_type) i;if (!is_valid_spell(spell))continue;// Only use spells available in books you might find laying about// the dungeon.if (spell_rarity(spell) == -1)continue;const unsigned int disciplines = get_spell_disciplines(spell);if (level != -1){if (spell_difficulty(spell) != level)continue;}else if (!((disciplines & disc1) || (disciplines & disc2))|| disciplines_conflict(disc1, disciplines)|| disciplines_conflict(disc2, disciplines)){continue;}// Only wizards gets spells still under development.const unsigned int flags = get_spell_flags(spell);if (flags & SPFLAG_DEVEL){#ifdef WIZARDif (!you.wizard)continue;#elsecontinue;#endif}if (avoid_uncastable && undead_cannot_memorise(spell, you.is_undead)){uncastable_discard++;continue;}if (god_dislikes_spell_type(spell, god)){god_discard++;continue;}// Passed all tests.spell_list.push_back(spell);}}static void _get_spell_list(std::vector<spell_type> &spell_list,unsigned int disc1, unsigned int disc2,god_type god, bool avoid_uncastable,int &god_discard, int &uncastable_discard){_get_spell_list(spell_list, -1, disc1, disc2,god, avoid_uncastable, god_discard, uncastable_discard);}static void _get_spell_list(std::vector<spell_type> &spell_list, int level,god_type god, bool avoid_uncastable,int &god_discard, int &uncastable_discard){_get_spell_list(spell_list, level, SPTYP_NONE, SPTYP_NONE,god, avoid_uncastable, god_discard, uncastable_discard);}
for (int i = 0; i < NUM_SPELLS; i++){const spell_type spell = (spell_type) i;if (!is_valid_spell(spell))continue;if (spell_difficulty(spell) != level)continue;const unsigned int flags = get_spell_flags(spell);const unsigned int schools = get_spell_disciplines(spell);// Don't include schoolless spells, like Smiting.if (schools == 0)continue;// Holy spells don't show up in books.if (schools & SPTYP_HOLY)continue;if (flags & (SPFLAG_MONSTER | SPFLAG_CARD | SPFLAG_TESTING))continue;// Only wizards gets spells still under development.if (flags & SPFLAG_DEVEL){#ifdef WIZARDif (!you.wizard)continue;#elsecontinue;#endif}if (avoid_uncastable && undead_cannot_memorise(spell, you.is_undead)){uncastable_discard++;continue;}if (god_dislikes_spell_type(spell, god)){god_discard++;continue;}// Passed all tests.spell_list.push_back(spell);}
_get_spell_list(spell_list, level, god, avoid_uncastable,god_discard, uncastable_discard);
bool make_book_theme_randart(item_def &book, int disc1, int disc2,int num_spells, int max_levels){ASSERT(book.base_type == OBJ_BOOKS);ASSERT(book.book_number() != BOOK_MANUAL&& book.book_number() != BOOK_DESTRUCTION);ASSERT(is_random_artefact(book));ASSERT(!book.props.exists(SPELL_LIST_KEY));god_type god;(void) origin_is_god_gift(book, &god);const bool avoid_uncastable = (god != GOD_NO_GOD && god != GOD_XOM)|| origin_is_acquirement(book);if (num_spells == -1)num_spells = SPELLBOOK_SIZE;ASSERT(num_spells > 0 && num_spells <= SPELLBOOK_SIZE);if (max_levels == -1)max_levels = INT_MAX;ASSERT(max_levels > 0);if (disc1 == 0 && disc2 == 0){// Eliminate disciplines that the god disapproves of or from which// all spells are discarded.std::vector<int> ok_discs;for (int i = 0; i < SPTYP_LAST_EXPONENT; i++){int disc = 1 << i;if (god_dislikes_spell_discipline(disc, god))continue;int junk1 = 0, junk2 = 0;std::vector<spell_type> spell_list;_get_spell_list(spell_list, disc, disc, god, avoid_uncastable,junk1, junk2);if(spell_list.empty())continue;ok_discs.push_back(i);}ASSERT( !ok_discs.empty() );if (ok_discs.empty()){mpr("No valid disciplines with which to make a themed ranadart ""spellbook.", MSGCH_ERROR);return (false);}do{disc1 = 1 << ok_discs[random2(ok_discs.size())];disc2 = 1 << ok_discs[random2(ok_discs.size())];} while(disciplines_conflict(disc1, disc2));}else if (disc2 == 0)disc2 = disc1;ASSERT(disc1 < (1 << (SPTYP_LAST_EXPONENT + 1)));ASSERT(disc2 < (1 << (SPTYP_LAST_EXPONENT + 1)));ASSERT(count_bits(disc1) == 1 && count_bits(disc2) == 1);int god_discard = 0;int uncastable_discard = 0;std::vector<spell_type> spell_list;_get_spell_list(spell_list, disc1, disc2, god, avoid_uncastable,god_discard, uncastable_discard);if (num_spells > (int) spell_list.size())num_spells = spell_list.size();std::vector<bool> spell_used(spell_list.size(), false);spell_type chosen_spells[SPELLBOOK_SIZE];for (int i = 0; i < SPELLBOOK_SIZE; i++){chosen_spells[i] = SPELL_NO_SPELL;}int book_pos = 0;while (book_pos < num_spells && max_levels > 0){int spell_pos = random2(spell_list.size());if (spell_used[spell_pos])continue;spell_type spell = spell_list[spell_pos];ASSERT(spell != SPELL_NO_SPELL);int spell_level = spell_difficulty(spell);if (spell_level > max_levels)continue;spell_used[spell_pos] = true;chosen_spells[book_pos++] = spell;max_levels -= spell_level;}std::sort(chosen_spells, chosen_spells + SPELLBOOK_SIZE,_compare_spells);ASSERT(chosen_spells[0] != SPELL_NO_SPELL);CrawlHashTable &props = book.props;props[SPELL_LIST_KEY].new_vector(SV_LONG).resize(SPELLBOOK_SIZE);CrawlVector &spell_vec = props[SPELL_LIST_KEY];spell_vec.set_max_size(SPELLBOOK_SIZE);for (int i = 0; i < SPELLBOOK_SIZE; i++)spell_vec[i] = (long) chosen_spells[i];std::string name;if (god != GOD_NO_GOD){name = '"';name += god_name(god, false) + "'s book";}name += " of ";name += spelltype_long_name(disc1);if (disc1 != disc2){name += " and ";name += spelltype_long_name(disc2);}if (god != GOD_NO_GOD)name += '"';set_randart_name(book, name);return (true);}bool book_has_title(const item_def &book){ASSERT(book.base_type == OBJ_BOOKS);if (!is_artefact(book))return (false);return (get_artefact_name(book)[0] == '"');}
{int rarity = 0;if (is_random_artefact(item)){// Consider spellbook as rare as its rarest spell.// NOTE: This probably undervalues a book if it contains// lots of rare spells.for (int i = 0; i < SPELLBOOK_SIZE; i++){spell_type spell = which_spell_in_book(item, i);if (spell == SPELL_NO_SPELL)continue;if (rarity > spell_rarity(spell))rarity = spell_rarity(spell);}}elserarity = book_rarity(item.sub_type);
/* ************************************************************************ called from: spl-book* *********************************************************************** */void set_randart_name( item_def &item, const std::string &name );void set_randart_appearance( item_def &item, const std::string &appear );
}void set_randart_name( item_def &item, const std::string &name ){ASSERT( is_random_artefact( item ));ASSERT( !name.empty() );item.props[RANDART_NAME_KEY].get_string() = name;}void set_randart_appearance( item_def &item, const std::string &appear ){ASSERT( is_random_artefact( item ));ASSERT( !appear.empty() );item.props[RANDART_APPEAR_KEY].get_string() = appear;
ASSERT(!item.props.exists( RANDART_NAME_KEY ));item.props[RANDART_NAME_KEY].get_string() = artefact_name(item, false);
if (item.props.exists( RANDART_NAME_KEY ))ASSERT(item.props[RANDART_NAME_KEY].get_type() == SV_STR);elseitem.props[RANDART_NAME_KEY].get_string() = artefact_name(item, false);
ASSERT(!item.props.exists( RANDART_APPEAR_KEY ));item.props[RANDART_APPEAR_KEY].get_string() = artefact_name(item, true);
if (item.props.exists( RANDART_APPEAR_KEY ))ASSERT(item.props[RANDART_APPEAR_KEY].get_type() == SV_STR);elseitem.props[RANDART_APPEAR_KEY].get_string() =artefact_name(item, true);
mpr("Fake item as gift from which god (ENTER to leave alone): ",MSGCH_PROMPT);char name[80];if (!cancelable_get_line( name, sizeof( name ) ) && name[0]){god_type god = string_to_god(name, false);if (god == GOD_NO_GOD)mpr("No such god, leaving item origin alone.");else{mprf("God gift of %s.", god_name(god, false).c_str());item.orig_monnum = -god;}}