git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8549 c06c8d41-db1a-0410-9941-cceddc491573
43XCHFXZ34FDVT2QG23RZ65V6NRBY6PE3ENQEEDXFYKRR7IRFHCAC M4FZOH6OHMO5ILBBMOBQOXBVSURRPUANJEKWGSFRXVTDJZWDJ66AC YYGGJB2XHBNYLHPV3V5Q7IO4TR2MZ5CPMHZELOKVRXT46COA4PNQC YRPFSFBFCP23X6DCROXKIVLLPCMWELAFSQN5XNBPK4SJXEM55U5QC 2EAWKRFSOQQ3ZGPMIRFNY6UWDH4Y5S4H4YKLH4T6RU4CTC7IQE6QC PUY2VWZJ3G7HNCLIHZP5VGT2DAGHI436ETDJQTPEBFPRSEHOM2NQC KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC LUD5XPFLSYPJOYZG6DDV4C5WIQUGZPE7YV6AR75ENCAIISD3LZWQC IQGGFC563RBS7GDOACKCLXK752EE5RC3T6G5L6H446SXTMSA7T2AC B3HWU2BEQQ4E6WKVTW3JQQJFMWTVW3XWKY6BHFNBRHSZPRCF2OTQC 64HB7VYSYHQEN5UP7OYJ5GSVA2XMDSLLH647UPWE5NSFF3AVZSSQC JYEEOUYQ7ZPKOGWUV7VCORBVSOLF2UCBFBH3TR75RGOSS6PNKYUAC RDOOG5LBE5TCTFYCKJIB7TGGTRFX4HBLMJZYXS5TCFWNCU3QII5QC TO3JMTZO6ETZWBXPA75JLCFD7ML546WXBRLWHPKL44ZIQ2H5HW6QC HCVH2CWL32UD66O6Z7ZYDUASWN3RF5TW6FSWURGMD7MELKB772FAC IBV5MNXWCCOWCI7DPVTPFEEMLX7QWP75EP6YQ3RA2WJOKWSGMPSQC FYSQ7HXDIKXZXDGYVKZMODW7HYQQLRZO52Q2HVM3PYBD37UT5B4AC ERS7DYNAVCC7QUVG5FXJJRONYESLZU22CQGKCA5HLLLG6DMXYRLQC TRBDS4IKHBASW2CTAQ2YHMBMBMRB6QEBQ4ZE7GRSR3U2VJXA7TJQC 2NVJIPJ5NMHUI2J4WOR6KE4XZOCJIVWHQK4M2M6KG7PL24PGBDGAC 5MGUZD2UACJCSG74TEZHI3Z4YL5KL6ZVUCQ3XVZKDOLKM7EMGWJAC TPO6FNMPNUSWH4NCKO3VLYNAADEPSAXLUITCCACLZZSY53PKA62QC NMZFCCM6O3KO2GJWKOSULN27B3QIZKWPBOB62PAILXMRQD4JMIMAC 22YVHM74WBJNJE4PA5CBEUTDWM6FAGGGILI26A4LXAURX55TNRKAC 5WHLQTLOJRJ67M4KAJZURHMNQLYHBW4XHQFBXV2LUQ4W6YKTOXVAC CLIEHAE2PP7ZIGLLIMYCWM4FC54KBOAN5AILOLAZJ5S26GTJM4RQC BAQJ26USF7KRR6ALYPXUPUFOYLNGBQVQOS53JXJJWZKDVREHFL2QC 5CPP63H7WJ3GLSHJM4Z2YSU2NISLVESEJ3OYMO4MFZEXVOCV4NIAC XDB2YEWS2WYH4FQZG3CIQ7P5JNS47MDYII2MV2IQ6BCAEPBYO5EQC 2RW7ANB4PPWJC2MP2XCBAWBDGMHJUNNWKMXR74JONERE4X522CNQC BQ5QKUWLCYSBO4A7EWZN4FXPNSIAR6JPBAZE4PSV6XCUNTV53ERQC ZR4ALQ5F2ETOD3GXMBYXSN6P75DPDGI3C275A7W5XHYI5TGPHNUQC LQH6T3DTCDOS5LAJ4PIPHMQY6UYRFWMVVUX32YJAELGIVR5RZTGQC LPPYA57KUWV53DIXGFMMNJUWBQOH5EDBZFFLYCWXBH347V6OLLCQC V7KMVXS2DILGLKP5XIKXEK7RFEABZGHHCG24QNSMMUAXRJ66THJQC QL3UTDJCNTASBU67LD5QODTIH7LCSAOW672CLJCDT4HED6PP5OPAC 53BVN4ZHKGUAJE53HM6FC6GKUGXOU5QBUT7CLXV2ONS6S5NPW55AC WEAAN2EBCCSUDTVAREPHLT7L7I7JR64F6MEWODY6QUMV3OAIK4WAC HZF272SANK2AOSUXM4WVKQKK767KCZUDXOQTHKBAHQPOTDEWEAZQC GTG5BFLJ5GBLJEEWK6AVZSCL5SQ4VSUW6IWEMZM7PAAT7KTSJQ5QC IOMAHHDYJ6P65ZZK4Q44YX2PEBZWBPB7ZOA3OKXPUBI5BRLRQ5JAC W3XVTY4C5S3OYK3TY3KDMJP2M7X7RJV33NLGYSEPUPHV2FSVTZCAC C5YQSTQ76D3OSNKOXBZD5MLX6GISUKXGPXLYZB5VKWZWXRAYPPQAC 25ADVXLZ7BCN6EHSVAZPAX6K75XPJYPG7IVRDY3S5YS5JMQGPMBQC YCKKYPEEODERLRF5DVJ6IKIXEHLKJQ37COYKGXCEXHMBT5Y2B32QC NGW2XPEX2XRK3CYC37DNUZSSB5IQLECMKRB6NX257I2X3G35LMPAC O4ZFDG3AEV3K4NPGCCLB7DXUH5CBETKP5FBKLCIET7JNTNDX5DUAC RMPMIONAOIYDZ5GWRUT65OVWAIQX7NWQ5QAPU6FSIODAGBAI5BIAC WHURZ7S6MM5OAEVGAM7ZNYXK3V62HUYYQM4NDB4NRJHG23YK35RAC MKJ2ORKSFPOPYEB5C36WZTR2QFHQYQ23PCLSC6SA44LJZ2AFBZFQC DVK4UATWXWXC5WZODCYAEMZM2TQUNC3URSUGMZSFYE6N76NQRK7AC 76XONKEXTJDLNAJCQTPN5MTBBPJZ55WFYX3B5CN5AKII6CW3SDCAC UHL7ECQOTO3SHFAPV4T6ODJ2HLSMUKVHQJQF3CXM3IUNICR7LACAC CQE2PS6RJI7QIP5YWGJKM6227HSIP7ZB2CBCJH5S2FN3PUDMLXUQC PVX27BLN5U3FAKDIGAANLLNJ75HYFB3M2WKQZN5BCNCBZ2OCQ3KQC KJO5N6UIPKQ6TZNNOWZEHUAWZNUW7CAHLIW2ARX47K4SIE3N5LYAC 3WNSWDDTTPWQ24SUOFU7EL6GODIMVTK4TL3P3AFLNB6AXUIIHFSAC HSDVFA7GIQ3JG6XK3OLW5UI63VZSBZUZ4VMTKL3XFBJXILYF67RQC OJXLFQMDM4XF2WSDVMAC3FXG5HJQB3QAQXLZM35RA34YYLTAP2HQC QME3SNESM4AEPUDL3QUVQUXGGFY7PJ7GQKFWBCHX257NSQU6O5GAC 4SWAT5KCKQV527NKELAXFQ5XA4Q5HONQXD4VBXMUZNPVPQKPCPNAC 45CWQUPQHKUFUJ4MVL5K3KCVCCKLY2Z7RZWZ53UT723RV5STPSRAC UKBVBVJK23OUOOKQJRGLZWEZYED5KZ4NLODW6U67UEBYCFWGGQOAC 377IO63NX2CXDYLKI2DUH5X6CKU7BJSPWIJYSCJXEAQTKFV53K5QC GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC KPSCSVGHKEQ4ENM3QQU2U3GYMV52NDFO5L6ML7YDPUKV3365OA3QC AYU5OVG2HZO46KDAPKUWAVHS5HTYFKUWIMIRMTHAXVVFEDJE7YPAC NYURIMPCM2RADLMIQSN76OPKXQSK4XBLFNXD2OO53KGZI3MA6AQAC SGJYXCP2TMR2VQNNO2W4HDHOA72LZOULFORRQVOIURH3KGGZPTDAC OJKUO2UJ2O2MUITGVQNF3BQITGVYE3XK6QTG7XW6OYPJ4YFWCFQQC 56D656WZS2LWVTXGWPR5FFJ7MDHP25XGPTBMYM4NHT4TKSJILX3QC 3XL4DKV7PSWAU3ZBJSKZFJ2VUYABC47I7KKWGIRCJYXULQD453MQC IE3INS4WUXZOBVXB5VWRBYPVPXADD2U2W5H3TBTOYNWJ3EGRSGQQC LK4XZLY5I73MFPFDUHPROWVHGEBXPVI6QDU2XMEBOJCNJPRLQLCQC R4URIVUHLBA4OJFNBWFCDDFOJFHN77DP4YDPL5AAB5TB7CWX2ICQC BSYEZ767GXLUDAHWF3UBPEZNM7VJNPDCJHID57SF5SP53KYAUQTQC PSJ7QDBYFBE35ANUDUTNE5VMKOTNVD66AXCCYC45WWJZRTGBJYLQC FAT7OTV4CYNUPXMS7KE3OSPMOFFIJX62KHPYCVE5TIOQYB4RPH2QC // Random-type acquirement.const int r = random2(7);const object_class_type objtype = (r == 0) ? OBJ_WEAPONS :(r == 1) ? OBJ_ARMOUR :(r == 2) ? OBJ_JEWELLERY :(r == 3) ? OBJ_BOOKS :(r == 4) ? OBJ_STAVES :(r == 5) ? OBJ_FOOD :(r == 6) ? OBJ_MISCELLANY: OBJ_GOLD;
const object_class_type types[] = {OBJ_WEAPONS, OBJ_ARMOUR, OBJ_JEWELLERY, OBJ_BOOKS,OBJ_STAVES, OBJ_FOOD, OBJ_MISCELLANY, OBJ_GOLD};
// Don't kill the player unless Xom is being nasty.if (!_xom_feels_nasty()){// Make sure not to lower strength so much that the player// will die once might wears off.char vals[3] ={you.strength - (you.duration[DUR_MIGHT] ? 5 : 0),you.dex, you.intel};stat_type types[3] = {STAT_STRENGTH, STAT_DEXTERITY,STAT_INTELLIGENCE};int tries = 0;do {int idx = random2(3);stat = types[idx];max = std::min(3, vals[idx] - 1);} while (max < 2 && (++tries < 30));if (tries >= 30)return (false);}god_speaks(GOD_XOM, _get_xom_speech("lose stats").c_str());lose_stat(stat, 1 + random2(max), true, "the vengeance of Xom" );return (true);}static bool _xom_chaos_upgrade_nearby_monster(){bool rc = false;monsters *mon = choose_random_nearby_monster(0, _choose_chaos_upgrade);if (!mon)return (false);god_speaks(GOD_XOM, _get_xom_speech("chaos upgrade").c_str());mon_inv_type slots[] = {MSLOT_WEAPON, MSLOT_ALT_WEAPON, MSLOT_MISSILE};for (int i = 0; i < 3 && !rc; ++i){item_def* const item = mon->mslot_item(slots[i]);if (item && _is_chaos_upgradeable(*item, mon)){_do_chaos_upgrade(*item, mon);rc = true;}}ASSERT(rc);// Wake the monster up.behaviour_event(mon, ME_ALERT, MHITYOU);return (rc);}static bool _xom_player_confusion_effect(int sever){bool rc = false;// Looks like this will *always* succeed?if (confuse_player(random2(sever)+1, false)){// FIXME: Message order is a bit off here.god_speaks(GOD_XOM, _get_xom_speech("confusion").c_str());rc = true;// Sometimes Xom gets carried away and starts confusing// other creatures too.if (coinflip()){for (unsigned i = 0; i < MAX_MONSTERS; ++i){monsters* const monster = &menv[i];if (!monster->alive()|| !mons_near(monster)|| !mons_class_is_confusable(monster->type)|| one_chance_in(20)){continue;}if (monster->add_ench(mon_enchant(ENCH_CONFUSION, 0,KC_FRIENDLY, random2(sever)))){simple_monster_message(monster," looks rather confused.");}}}}return (rc);}static bool _xom_draining_torment_effect(int sever){const std::string speech = _get_xom_speech("draining or torment");const bool nasty = _xom_feels_nasty();bool rc = false;if (one_chance_in(4)){// XP drain effect (25%).if (player_prot_life() < 3 && (nasty || you.experience > 0)){god_speaks(GOD_XOM, speech.c_str());drain_exp();if (random2(sever) > 3 && (nasty || you.experience > 0))drain_exp();if (random2(sever) > 3 && (nasty || you.experience > 0))drain_exp();rc = true;}}else{// Torment effect (75%).if (!player_res_torment()){god_speaks(GOD_XOM, speech.c_str());torment_player(0, TORMENT_XOM);rc = true;}}return (rc);}static bool _xom_summon_hostiles(int sever){bool rc = false;const std::string speech = _get_xom_speech("hostile monster");// Nasty, but fun.if (one_chance_in(4)){god_speaks(GOD_XOM, speech.c_str());cast_tukimas_dance(100, GOD_XOM, true);// FIXME: We should probably only do this if the spell// succeeded.rc = true;}else{// XXX: Can we clean up this ugliness, please?const int numdemons =std::min(random2(random2(random2(sever+1)+1)+1)+1, 14);for (int i = 0; i < numdemons; ++i){if (create_monster(mgen_data::hostile_at(_xom_random_demon(sever),you.pos(), 4, 0, true, GOD_XOM,MON_SUMM_WRATH)) != -1){rc = true;}}if (rc)god_speaks(GOD_XOM, speech.c_str());}return (rc);}
// Xom will only directly kill you with a bad effect if you're under// penance from him, or if he's bored.const bool nasty = you.penance[GOD_XOM]|| (you.religion == GOD_XOM && you.gift_timeout == 0);
stat_type stat = STAT_RANDOM;int max = 3;// Don't kill the player unless Xom is being nasty.if (!nasty){// Make sure not to lower strength so much that the player// will die once might wears off.char vals[3] ={you.strength - (you.duration[DUR_MIGHT] ? 5 : 0),you.dex, you.intel};stat_type types[3] = {STAT_STRENGTH, STAT_DEXTERITY,STAT_INTELLIGENCE};int count = 0;for (int i = 0; i < 3; ++i){int val = vals[i];if (val > 1 && one_chance_in(++count)){stat = types[i];max = val - 1;}}if (count == 0)continue;}god_speaks(GOD_XOM, _get_xom_speech("lose stats").c_str());lose_stat(stat, 1 + random2(max), true, "the vengeance of Xom" );done = true;
done = _xom_lose_stats();
monsters *mon =choose_random_nearby_monster(0, _choose_chaos_upgrade);if (!mon)continue;god_speaks(GOD_XOM, _get_xom_speech("chaos upgrade").c_str());mon_inv_type slots[] = {MSLOT_WEAPON, MSLOT_ALT_WEAPON,MSLOT_MISSILE};for (int i = 0; i < 3; ++i){int idx = mon->inv[slots[i]];if (idx == NON_ITEM)continue;item_def &item(mitm[idx]);if (!_is_chaos_upgradeable(item, mon))continue;_do_chaos_upgrade(item, mon);done = true;break;}ASSERT(done);// Wake the monster up.behaviour_event(mon, ME_ALERT, MHITYOU);
done = _xom_chaos_upgrade_nearby_monster();
if (you.can_safely_mutate()&& player_mutation_level(MUT_MUTATION_RESISTANCE) < 3){god_speaks(GOD_XOM, _get_xom_speech("random mutations").c_str());mpr("Your body is suffused with distortional energy.");set_hp(1 + random2(you.hp), false);deflate_hp(you.hp_max / 2, true);bool failMsg = true;for (int i = random2(4); i >= 0; --i){if (mutate(RANDOM_XOM_MUTATION, failMsg, false, true,false, false, !nasty)){done = true;}elsefailMsg = false;}}
done = _xom_give_mutation(false);
if (there_are_monsters_nearby(false, false)){monsters *mon =choose_random_nearby_monster(0, _choose_mutatable_monster);if (mon){god_speaks(GOD_XOM, _get_xom_speech("bad monster polymorph").c_str());bool made_shifter = false;if (one_chance_in(8) && !mons_is_shapeshifter(mon)){mon->add_ench(one_chance_in(3) ?ENCH_GLOWING_SHAPESHIFTER : ENCH_SHAPESHIFTER);made_shifter = true;}monster_polymorph(mon, RANDOM_MONSTER,mons_wont_attack(mon) ? PPT_LESS : PPT_MORE, made_shifter);done = true;}}
done = _xom_polymorph_nearby_monster(false);
std::string speech = _get_xom_speech("confusion");if (confuse_player(random2(sever)+1, false)){done = true;// Sometimes Xom gets carried away and starts confusing// other creatures too.if (coinflip()){monsters* monster;for (unsigned i = 0; i < MAX_MONSTERS; ++i){monster = &menv[i];if (monster->type == -1 || !mons_near(monster)|| !mons_class_is_confusable(monster->type)|| one_chance_in(20)){continue;}if (monster->add_ench(mon_enchant(ENCH_CONFUSION, 0,KC_FRIENDLY, random2(sever)))){simple_monster_message(monster," looks rather confused.");}}}}
done = _xom_player_confusion_effect(sever);
std::string speech = _get_xom_speech("draining or torment");if (one_chance_in(4)){if (player_prot_life() < 3 && (nasty || you.experience > 0)){god_speaks(GOD_XOM, speech.c_str());drain_exp();if (random2(sever) > 3 && (nasty || you.experience > 0))drain_exp();if (random2(sever) > 3 && (nasty || you.experience > 0))drain_exp();done = true;}}else{if (!player_res_torment()){god_speaks(GOD_XOM, speech.c_str());torment_player(0, TORMENT_XOM);done = true;}}
done = _xom_draining_torment_effect(sever);
std::string speech = _get_xom_speech("hostile monster");// Nasty, but fun.if (one_chance_in(4)){god_speaks(GOD_XOM, speech.c_str());cast_tukimas_dance(100, GOD_XOM, true);done = true;}else{// XXX: Can we clean up this ugliness, please?const int numdemons =std::min(random2(random2(random2(sever+1)+1)+1)+1, 14);bool success = false;for (int i = 0; i < numdemons; ++i){if (create_monster(mgen_data::hostile_at(_xom_random_demon(sever),you.pos(), 4, 0, true, GOD_XOM,MON_SUMM_WRATH)) != -1){success = true;}}if (success){god_speaks(GOD_XOM, speech.c_str());done = true;}}
done = _xom_summon_hostiles(sever);