git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9561 c06c8d41-db1a-0410-9941-cceddc491573
TPJYUAKSEZMCCCJANJ5EQ7F67QVTPFEOWBD7WYK33NLRN657Y5VQC
TKSZKOFLIYT35SO2RSDNKZ3FZ5C7EDLEME53AUSP7GRVIODRLVRQC
PHTCOVKTGDX2ZN4QTG2X2Y2M6HAW2EZJQ5WXWQ3NDFAFF2DR6WDQC
H7GMWXGBKDNFSKIDR5IWTS6UYPRHPBBSAFMVXHZQOZTCZ7OMNVKQC
I5UHW5AFW2NXN65Y74SH6O5D7AIIYWEBU4H673TJEZYXQOZ22OBQC
VF3Y6IKB5WKEMZRPG6KMWXGST6GU5HDKZ26BFYGKAQBDUZ5JE2TQC
G3K77T4XACH5B2SSAMYVC72X5FM3VWGYI5P6JZQUQZWAXCT36YZQC
MERLKNHUR5GLLDZUCFEDEO32AG3EHSPGZUFPMW7WYC55KY5Z5QRAC
EFWEYIB2R3DPD3JWIPU6LS6SFLPMYN7J7X4GBZR7DJWKHJ3UELSAC
GP7RUHLNB4KISSZAENEYVNY3MB5YRCFRWRWYAROBZIQ5MR4DXB7QC
5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC
NMZFCCM6O3KO2GJWKOSULN27B3QIZKWPBOB62PAILXMRQD4JMIMAC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
IBV5MNXWCCOWCI7DPVTPFEEMLX7QWP75EP6YQ3RA2WJOKWSGMPSQC
TYAUNNAVB4GEKXYSR447JXRDKRJJZHAVV7XLWGU7RXEP5JMJCQKAC
LEZWYG752CKY6URMLSQTOADDRAJ5NTT7KH7BC5ENGQ55GXKHQMWQC
5MGUZD2UACJCSG74TEZHI3Z4YL5KL6ZVUCQ3XVZKDOLKM7EMGWJAC
PUY2VWZJ3G7HNCLIHZP5VGT2DAGHI436ETDJQTPEBFPRSEHOM2NQC
7DHFQM7MCCELAZL3YR53E263WMSQHQECCI5D7MCPQEF7B56IB2EAC
H2OHWQKMHL66CPVJGJL35RY7EIZB74SZTGOLDJDSCG5WVEVPIIUAC
7RDIBNLUIBTAYOJXJ5Q3DOW3MKKYXBAA3Q4G4QE74KJL23NW6C7AC
43XCHFXZ34FDVT2QG23RZ65V6NRBY6PE3ENQEEDXFYKRR7IRFHCAC
HCVH2CWL32UD66O6Z7ZYDUASWN3RF5TW6FSWURGMD7MELKB772FAC
KO7PZNWIRLSAPOXUHK7U446ZXT562QCPIT3AYFYKPG7OWRLNBU4QC
IQGGFC563RBS7GDOACKCLXK752EE5RC3T6G5L6H446SXTMSA7T2AC
PHBACPMH3F34GODHVDKNCMXWU373RJQGVTDLBFCCDLLWDXVYOLTAC
2NVJIPJ5NMHUI2J4WOR6KE4XZOCJIVWHQK4M2M6KG7PL24PGBDGAC
5WHLQTLOJRJ67M4KAJZURHMNQLYHBW4XHQFBXV2LUQ4W6YKTOXVAC
5UERXKWLQVLPKE6LN74XZ6V6NGZ3RL3RE22O4MH3ID7IQQ27YWPAC
TRBDS4IKHBASW2CTAQ2YHMBMBMRB6QEBQ4ZE7GRSR3U2VJXA7TJQC
FYSQ7HXDIKXZXDGYVKZMODW7HYQQLRZO52Q2HVM3PYBD37UT5B4AC
YRPFSFBFCP23X6DCROXKIVLLPCMWELAFSQN5XNBPK4SJXEM55U5QC
VALKRIRLS27G6SHGZ5HFVOHYCQWJPV22SIEGI5NQOJN25PANS2GQC
SX3VGUXM2GHYN7AQX3UPKDGICIQLRCJ5O45FTPMX7XN4VNPBKKVQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
SZBMBNW34N2SM7Y6QBKBSA7OMLEMLFGCE4NSMHCBH6ORU2MYY2MQC
3U54KX4JPCEBGC3USUQJVX35HBEWV6DX6ZZ4RV7GT3HBX7LMLKPAC
MCQZ4HEOF65FEVWUEAMO2765JYMJPKXQ454HCCWWK3JUYEUSUXTAC
3ANUQ333WACKBBC4XHJWADIWDFWWX4RQM2MEFZPJ6GBRWSZ6WMCQC
S5IPZ6TIY6ICVYGJ25DHWDVAHWTNTTFJUDYE3MV5FVEDXY7J4APQC
JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC
JJHOTW7LDUJ6DLUG2DTFWASCAFPGD2WBW7MHBSECJZU7PTJYWQDQC
NM6UK4SZ3JWD3WWDY355C5NW2MBIFR4N73QHF43AE4CKR5LOLRCQC
4M56FGNV3IDCB7I4H7TMK3EWSQKWEJ5Z2AKIMHED272TOB34DO4QC
YCOIKIHIKDUTYCNQZASNG6FG2VY2YYZHCA435K7XECLXDZDCSXHQC
ZI7643NG3LOKVSDXHFNV2YU3ZIQUVEY25AOXZCPBXJB5SQAUCE6QC
IGN3Q5YCLHXKWFZQRSRABCHW2JFW5TFVU7TM5EXE2EW7PDBBSQWAC
JDZCDMUCQ7VENYVLB62KQWUIRGABID37OKATOKCBUPCDL7W75NPAC
NO2HRD7RZS42S55UG4FQ5EFQDY6WYWKGIXHUKYLWF36HHE3VZ7WAC
V53DXVC5T3N6J47H2CNG4MMPRR4PHW4AIS66QNVTKJNNYTTTQL4AC
WFG3MHLJUHQEHV65SPAIOI74NIZTGM447T4WKWKF7CMUIUNRUQOAC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
MDAJYB6STTZPNHRQ2X66MMMSONMKXTESLHJSFPGN7H3D3TOVBAVAC
2H32CFFM2FNS63JJPNM2S6HMO543EX72GMPOU5GI6HTMQYPL6I3AC
CPNHNCRBZMUV7CYPWFKICGRW57LDRGJPCMFSJV6NB72YBGR67BNQC
JBZ7NU4BB5PGQWCOSZHD5OQUHQIVOD4XGJLSJQ7BUGQEGPRTVGZQC
JZTWTPXIUEVACX5B6FYQRVRJD3KQN653C4G4GXT2VSMX4EP7WS3AC
A5YOVQMFZRMT6NK7YUQI632TWC3CFATXDNCSB7M33EEYB62SA3XAC
C4IC7ARZE6R3NY2URQGPES7U2IS35Z6ZGH7DY32L6ULD7JV5IXFQC
BYURAML2EPTULHH22Q5RPXYGDEYAJYESR6C72UMNPPYHTCJZUPFAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
VO5CYD7Z4FYFDT6DGVBX6RT3PHLRSUJA6TWV3GPYVE7QCSJ3JEAAC
5XNQ3SSNBFXFNWA6DPM74W6FH65NX665P3DMH6YCWVFOPZTJSYCQC
22YVHM74WBJNJE4PA5CBEUTDWM6FAGGGILI26A4LXAURX55TNRKAC
ZNMT5CZHP2FC4HTLNA7KYEDGFBXSCUE5QHJOALVPE6RDPHSEDXRQC
NGDLKK45NREMXETWADSYSC6NNAGN4X5BZDJXHLL432WTAJKCG36AC
BBQWA33DPXWEDYOOPO45VAYD4JQDZQVMZSEJ4RUI5LLC733IMIIQC
RQR4PTMGQLTRWLYRU3KXIIDGND7FBORESJWMWFVD3WYU5SISZXAAC
G4TVXOLIF5X2MWV7I4UPT3MSQHRMGME6QRIIFAQ64C45JGYK7SIAC
4EZVKDQA5GM3QDTNTCKEKGH4F6LGAYNLBT756PXODKZ2B7C4ZVHAC
23PFLB2E4QHL5SF3Q2YV5FXRH6MFHENEU2ACVC572ZCYDXCBZVQAC
M6MBPHNAERUXYJ7KHK5FE2B44CLBY4M5MR5KY74HVDFNHVLOEQIAC
OI7JKBFFIMIGWID2EJSMRP2EPEJH5YY42WTEY4QSSL6PFKRU3KJQC
PLJI4CMQZJ773B3QFPKBM3NBDHOMKTR63TRI7IRC67LHFNOQNUHQC
UEI5JAVCMN7Y2SACTEZPZSNFJWOJTC55G24Q6LKQCT4XNDH5ZQIAC
S34LKQDIQJLIWVIPASOJBBZ6ZCXDHP5KPS7TRBZJSCDRVNCLK6UAC
HVEU33HIUHCYFINJMVSSOIRUPZGGVC7NMWUN2EADG2W373JP3WOAC
JP7SVXCIKEPVDD4Q5CDYDATPK7X5XOYW3T6QK2Y6EWHFH52LBK3QC
WQLOHSNCA3VOMDJF6IINJYKSYVYZEBPJJWBB33QSNE4RP5HEXPMAC
COUZNM7NGJEXPZ77X6BUD7CUN3BF3GHDPZZETAWIORNT66DUO4ZQC
6OYJQSUM2HW3KQ6YQFW7RGMJC3VA2P5BSC3OKHLPZJMZGAEIEN4QC
HAMUM5IA4BJMLRIME7KVVVYLRHVS55RIYMGLLQZL3F7QEP7FJ5KAC
SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC
3LAYABJRTAOJQZ3R5MYCAWHSDKI2VLU54NNGNHCIN3ZHYS6QUNZAC
TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC
OEHJJ5X5CBOHTXISZLJHVLCAPH77RYSVKKBGW3US2GGXZMZJ5CEQC
3KAINFIXO7WNWGUGZB43EUNFRS2ZPBLQZDTY456QACMRHYIJ7WDAC
UADYVV3UD5ERJTZZJGY4EUQ4NJ2JSBG7YYUJ75ZRBIXRQXQKOJPAC
if (_xom_is_bored())
xom_acts(abs(you.piety - MAX_PIETY/2));
else
{
const int tension = get_tension(GOD_XOM);
const int chance = (tension == 0 ? 1 :
tension <= 5 ? 2 :
tension <= 10 ? 3 :
tension <= 20 ? 4
: 5);
const int tension = get_tension(GOD_XOM);
const int chance = (tension == 0 ? 1 :
tension <= 5 ? 2 :
tension <= 10 ? 3 :
tension <= 20 ? 4
: 5);
if (x_chance_in_y(chance, 5))
xom_acts(abs(you.piety - MAX_PIETY/2), tension);
// During tension, Xom may briefly forget about being bored.
if (_xom_is_bored() && x_chance_in_y(chance-1, 4))
{
you.gift_timeout += random2(chance*20);
#if defined(DEBUG_RELIGION) || defined(DEBUG_XOM)
mprf(MSGCH_DIAGNOSTICS,
"tension %d (chance: %d) -> increase interest to %d",
tension, chance, you.gift_timeout);
#endif
// Blink every monster on this level and the player.
static void _confuse_monster(monsters mons, int sever)
{
// monsters& mons(*mon);
if (!mons_class_is_confusable(mons.type))
return;
const bool was_confused = mons.confused();
if (mons.add_ench(mon_enchant(ENCH_CONFUSION, 0, KC_FRIENDLY,
random2(sever))))
{
if (was_confused)
simple_monster_message(&mons, " looks rather more confused.");
else
simple_monster_message(&mons, " looks rather confused.");
}
}
static bool _swap_monsters(monsters *m1, monsters *m2)
{
monsters& mon1(*m1);
monsters& mon2(*m2);
const bool mon1_caught = mons_is_caught(&mon1);
const bool mon2_caught = mons_is_caught(&mon2);
const coord_def mon1_pos = mon1.pos();
const coord_def mon2_pos = mon2.pos();
if (!mon2.is_habitable(mon1_pos) || !mon1.is_habitable(mon2_pos))
return (false);
// Make submerged monsters unsubmerge.
mon1.del_ench(ENCH_SUBMERGED);
mon2.del_ench(ENCH_SUBMERGED);
mgrd(mon1_pos) = mon2.mindex();
mon1.moveto(mon2_pos);
mgrd(mon2_pos) = mon1.mindex();
mon2.moveto(mon1_pos);
if (mon1_caught && !mon2_caught)
{
check_net_will_hold_monster(&mon2);
mon1.del_ench(ENCH_HELD, true);
}
else if (mon2_caught && !mon1_caught)
{
check_net_will_hold_monster(&mon1);
mon2.del_ench(ENCH_HELD, true);
}
return (true);
}
// Swap places with a random monster and, depending on severity, also
// between monsters. This can be pretty bad if there are a lot of hostile
// monsters around.
if (monster_blink(monster))
god_speaks(GOD_XOM, _get_xom_speech("rearrange the pieces").c_str());
const int num_mons = mons.size();
// Swap places with a random monster.
monsters *mon = mons[random2(num_mons)];
swap_with_monster(mon);
// Occasionally confuse said monster.
if (one_chance_in(5))
_confuse_monster(*mon, sever);
if (num_mons > 1 && x_chance_in_y(sever,70))
{
bool did_message = false;
const int max_repeats = std::min(num_mons/2, 8);
const int repeats = std::min(random2(sever/10)+1, max_repeats);
for (int i = 0; i < repeats; ++i)
// If Xom blinked at least one monster, blink the player, too, and
// then consider this act done.
if (rc)
random_blink(false);
return (rc);
return (true);
if (you.level_type != LEVEL_ABYSS)
{
god_speaks(GOD_XOM, _get_xom_speech("banishment").c_str());
banished(DNGN_ENTER_ABYSS, "Xom");
done = true;
}
god_speaks(GOD_XOM, _get_xom_speech("banishment").c_str());
banished(DNGN_ENTER_ABYSS, "Xom");
badness = 5;
done = true;
// If we got here because Xom was bored, reset gift timeout according
// to the badness of the effect.
if (done && _xom_is_bored())
{
const int interest = random2avg(badness*60, 2);
you.gift_timeout = std::min(interest, 255);
#if defined(DEBUG_RELIGION) || defined(DEBUG_XOM)
mprf(MSGCH_DIAGNOSTICS, "badness: %d, new interest: %d",
badness, you.gift_timeout);
#endif
}
#if DEBUG_DIAGNOSTICS || DEBUG_RELIGION || DEBUG_XOM
mprf(MSGCH_DIAGNOSTICS, "xom_acts(%u, %d); piety: %u, interest: %u\n",
niceness, sever, you.piety, you.gift_timeout);
#if defined(DEBUG_DIAGNOSTICS) || defined(DEBUG_RELIGION) || defined(DEBUG_XOM)
mprf(MSGCH_DIAGNOSTICS, "xom_acts(%u, %d, %d); piety: %u, interest: %u\n",
niceness, sever, tension, you.piety, you.gift_timeout);
void xom_death_message()
static bool _death_is_funny(const kill_method_type killed_by)
{
switch (killed_by)
{
// The less original deaths are boring.
case KILLED_BY_MONSTER:
case KILLED_BY_BEAM:
case KILLED_BY_CLOUD:
case KILLED_BY_FREEZING:
case KILLED_BY_BURNING:
case KILLED_BY_SELF_AIMED:
case KILLED_BY_SOMETHING:
return (false);
default:
// All others are fun (says Xom).
return (true);
}
}
void xom_death_message(const kill_method_type killed_by)
void swap_with_monster(monsters *mon_to_swap);
}
// Make the player swap positions with a given monster.
void swap_with_monster(monsters *mon_to_swap)
{
monsters& mon(*mon_to_swap);
ASSERT(mon.alive());
const coord_def newpos = mon.pos();
// Be nice: no swapping into uninhabitable environments.
if (!you.is_habitable(newpos) || !mon.is_habitable(you.pos()))
{
mpr("You spin around.");
return;
}
const bool mon_caught = mons_is_caught(&mon);
const bool you_caught = you.attribute[ATTR_HELD];
// If it was submerged, it surfaces first.
mon.del_ench(ENCH_SUBMERGED);
mprf("You swap places with %s.", mon.name(DESC_NOCAP_THE).c_str());
// Pick the monster up.
mgrd(newpos) = NON_MONSTER;
mon.moveto(you.pos());
// Plunk it down.
mgrd(mon.pos()) = mon_to_swap->mindex();
if (you_caught)
{
check_net_will_hold_monster(&mon);
if (!mon_caught)
you.attribute[ATTR_HELD] = 0;
}
// Move you to its previous location.
move_player_to_grid(newpos, false, true, true, false);
if (mon_caught)
{
if (you.body_size(PSIZE_BODY) >= SIZE_GIANT)
{
mpr("The net rips apart!");
you.attribute[ATTR_HELD] = 0;
int net = get_trapping_net(you.pos());
if (net != NON_ITEM)
destroy_item(net);
}
else
{
you.attribute[ATTR_HELD] = 10;
mpr("You become entangled in the net!");
// Xom thinks this is hilarious if you trap yourself this way.
if (you_caught)
xom_is_stimulated(16);
else
xom_is_stimulated(255);
}
if (!you_caught)
mon.del_ench(ENCH_HELD, true);
}
xom_is_stimulated(32);
{
// Xom loves when you ID a distortion weapon this way,
// and even more so if he gifted the weapon himself.
god_type god;
if (origin_is_god_gift(item, &god) && god == GOD_XOM)
xom_is_stimulated(255);
else
xom_is_stimulated(128);
}
if (known_cursed || was_known && special == SPWPN_SCYTHE_OF_CURSES)
xom_is_stimulated(32);
else
xom_is_stimulated(64);
int amusement = 16;
if (!known_cursed
&& !(was_known && special == SPWPN_SCYTHE_OF_CURSES))
{
amusement *= 2;
god_type god;
if (origin_is_god_gift(item, &god) && god == GOD_XOM)
amusement *= 2;
}
const int wpn_skill = weapon_skill(item.base_type, item.sub_type);
if (wpn_skill != SK_FIGHTING && you.skills[wpn_skill] == 0)
amusement *= 2;
xom_is_stimulated(amusement);
if (known_cursed || known_bad)
xom_is_stimulated(64);
else
xom_is_stimulated(128);
int amusement = 32;
if (!known_cursed && !known_bad)
{
amusement *= 2;
god_type god;
if (origin_is_god_gift(item, &god) && god == GOD_XOM)
amusement *= 2;
}
xom_is_stimulated(amusement);
// dangerous monster nearby...
xom_is_stimulated(255);
// dangerous monster nearby... (though not as much as potions
// since there are no *really* bad scrolls, merely useless ones).
xom_is_stimulated(bad_effect ? 128 : 64);
bool you_are_delayed( void );
delay_type current_delay_action( void );
int check_recital_audience( void );
void handle_delay( void );
bool you_are_delayed();
delay_type current_delay_action();
int check_recital_audience();
void handle_delay();
{
monsters& mon(*mon_to_swap);
const coord_def newpos = mon.pos();
// Be nice: no swapping into uninhabitable environments.
if (!you.is_habitable(newpos) || !mon.is_habitable(you.pos()))
{
mpr("You spin around.");
return;
}
const bool mon_caught = mons_is_caught(&mon);
const bool you_caught = you.attribute[ATTR_HELD];
// If it was submerged, it surfaces first.
mon.del_ench(ENCH_SUBMERGED);
// Pick the monster up.
mgrd(newpos) = NON_MONSTER;
mon.moveto(you.pos());
// Plunk it down.
mgrd(mon.pos()) = mon_to_swap->mindex();
if (you_caught)
{
check_net_will_hold_monster(&mon);
if (!mon_caught)
you.attribute[ATTR_HELD] = 0;
}
// Move you to its previous location.
move_player_to_grid(newpos, false, true, true, false);
if (mon_caught)
{
if (you.body_size(PSIZE_BODY) >= SIZE_GIANT)
{
mpr("The net rips apart!");
you.attribute[ATTR_HELD] = 0;
int net = get_trapping_net(you.pos());
if (net != NON_ITEM)
destroy_item(net);
}
else
{
you.attribute[ATTR_HELD] = 10;
mpr("You become entangled in the net!");
// Xom thinks this is hilarious if you trap yourself this way.
if (you_caught)
xom_is_stimulated(16);
else
xom_is_stimulated(255);
}
if (!you_caught)
mon.del_ench(ENCH_HELD, true);
}
}
swap_with_monster(mon_to_swap);