When giving or deleting a random mutation you can now request that the mutation picked doesn't instantly kill the player. Xom code now uses this option, except for when the player is under penance from Xom or Xom is bored.
Improvements to the code that prevents Xom from accidently killing the player.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7835 c06c8d41-db1a-0410-9941-cceddc491573
BQ5QKUWLCYSBO4A7EWZN4FXPNSIAR6JPBAZE4PSV6XCUNTV53ERQC
NTLY3XBVMGR2PTGCDOBYLZTZKYGDMAY6VNC6TVK2EBY2VMS5SUMAC
ERS7DYNAVCC7QUVG5FXJJRONYESLZU22CQGKCA5HLLLG6DMXYRLQC
5CPP63H7WJ3GLSHJM4Z2YSU2NISLVESEJ3OYMO4MFZEXVOCV4NIAC
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
KBIIMBVTWPMMUZLPLK2KJOXKSVMGUREIYJ57VCYVXDX5F23QXDEQC
5MGUZD2UACJCSG74TEZHI3Z4YL5KL6ZVUCQ3XVZKDOLKM7EMGWJAC
5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
CQMX53TEZCRYKPNWUSNMMRRYBTRDF4Z4LXZWD7CSCZH6GDVDEK7QC
2UVHNPJRS352B7HNGZMEQRAIN5NE4R44B7JRQWCHUMZJIALWOEGAC
TH2RUX3XQ5I43J4ASC4C3KHFCBUOYQ4EUBMXPQV4JCJGPTZZAYAAC
MVKBMSNCIAJACMDTLUWUZC2VZPWLYWMS6CI55JJL3X3J7IGQJQ2AC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
5HS3R3WWH7YQKXDAEJNMOCRPVYXRC4P4AIE25RO7QAD7YY5Y4OYAC
CMNLYUECIMEZSOYG4KOSINOPER5OM7PPCGIHCM7LQVWEO77XFUYQC
QWGKTN3UC5YEKX7KVABFAPMAQZFH3JGKO32RJM2NE2UXUHHVDYKQC
R7S5SFHDENT3VTY7LAE3RXYDXDMJNB2QDNVZBD3TVBWV2RDHCWSAC
EWFP6RFDHTEGD6SX36LYRLQB3APIKGAHNBKWPD56RGYBUE4FWJUQC
3ZWALZFSTSIVYXY4BAY6ANGINTDACZC6RSSJTEMQSTSUIE66YOBQC
UEEDQIFBOUZOXHCWGSEBED4Z3SYGN3DVHOVRJYQVWQQ6BIDLWAQAC
LS5XCCGKQHSJQGWLWLGTP2F5OYWK4ND5AQQAGRN6H2HVBSXNCCZAC
QCBXSBZWASF2IGRWPE45IGR3MJQRK3RBQZYI336M76DO653TKE7QC
S34LKQDIQJLIWVIPASOJBBZ6ZCXDHP5KPS7TRBZJSCDRVNCLK6UAC
UISCFODQTHZG4576DDR4QCFOGGOIT4BQI7DTVBSMLKHANTE7D3IAC
AQ36MO7VNGSGQ5KK7JCQA2WEHUELAFLSU2QBUWROVJFOTPMGFGMQC
NMZFCCM6O3KO2GJWKOSULN27B3QIZKWPBOB62PAILXMRQD4JMIMAC
FixedVector<unsigned char, NUM_MUTATIONS> orig_mutation = you.mutation;
char* stat_ptrs[3] = {&you.strength, &you.intel, &you.dex};
const char orig_stats[3] = {*(stat_ptrs[0]), *(stat_ptrs[1]),
*(stat_ptrs[2])};
const FixedVector<unsigned char, NUM_MUTATIONS> orig_mutation
= you.mutation;
int changes = 0;
for (int i = 0; i < NUM_MUTATIONS; i++)
already_oopsed = true;
if (you.hp <= 0)
you.hp = orig_hp;
mutation_type dex_muts[5] = {MUT_GREY2_SCALES, MUT_METALLIC_SCALES,
MUT_YELLOW_SCALES, MUT_RED2_SCALES,
MUT_STRONG_STIFF};
for (int i = 0; i < 5; i++)
if (orig_mutation[i] != you.mutation[i])
changes++;
mutation_type bad = dex_muts[i];
while (you.dex <= 0 && you.mutation[bad] > orig_mutation[bad])
delete_mutation(bad, true, true);
}
while(you.dex <= 0
&& you.mutation[MUT_FLEXIBLE_WEAK] <
orig_mutation[MUT_FLEXIBLE_WEAK])
{
mutate(MUT_FLEXIBLE_WEAK, true, true, true);
std::string str = "Xom undoes your latest mutation";
if (changes > 1)
str += "s";
str += ".";
god_speaks(GOD_XOM, str.c_str());
delete_mutation(MUT_FLEXIBLE_WEAK, true, true);
}
while (you.strength <= 0
&& you.mutation[MUT_STRONG_STIFF] <
orig_mutation[MUT_STRONG_STIFF])
{
mutate(MUT_STRONG_STIFF, true, true, true);
you.hp = orig_hp;
you.strength = orig_str;
you.dex = orig_dex;
you.intel = orig_int;
for (int i = 0; i < 3; i++)
{
while (*(stat_ptrs[i]) <= 0)
{
mutation_type good = good_muts[i];
mutation_type bad = bad_muts[i];
if (you.mutation[bad] > orig_mutation[bad]
|| you.mutation[good] < orig_mutation[good])
{
mutate(good, true, true, true);
}
else
{
*(stat_ptrs[i]) = orig_stats[i];
break;
}
}
}
}
// Or maybe Xom accidentally tossed you in deep water or lava.
dungeon_feature_type feat = grd(you.pos());
if (feat != orig_feat && !you.airborne()
&& (feat == DNGN_DEEP_WATER && !you.swimming()
|| feat == DNGN_LAVA && player_res_fire() <= 0))
{
if (!already_oopsed)
{
mpr("You die...");
god_speaks(GOD_XOM,
_get_xom_speech("accidental homicide").c_str());
god_speaks(GOD_XOM, _get_xom_speech("resurrection").c_str());
}
you.teleport(true);
// Also don't kill wizards testing Xom acts.
if (crawl_state.prev_cmd == CMD_WIZARD)
return;
// Ensure some minimal informfullness about Xom's involvment.
if (aux == NULL)
{
if (death_type != KILLED_BY_XOM)
aux = "Xom";
}
else if(strstr(aux, "Xom") == NULL)
death_type = KILLED_BY_XOM;
static bool _is_deadly(mutation_type mutat, bool delete_mut)
{
if (delete_mut)
{
// First handle non-stat related problems.
if ( mutat == MUT_HEAT_RESISTANCE && grd(you.pos()) == DNGN_LAVA
&& player_res_fire() == 1 && !you.airborne() )
{
// Don't let player instantly fry to a crisp in lava.
return (true);
}
// Swap things around to the same effect, but as if we were gaining
// a mutation, or return early if deleting the mutation is never
// a problem.
switch(mutat)
{
case MUT_GREY2_SCALES:
case MUT_METALLIC_SCALES:
case MUT_YELLOW_SCALES:
case MUT_RED2_SCALES:
case MUT_WEAK:
case MUT_DOPEY:
case MUT_CLUMSY:
return (false);
case MUT_STRONG_STIFF:
mutat = MUT_FLEXIBLE_WEAK;
break;
case MUT_FLEXIBLE_WEAK:
mutat = MUT_STRONG_STIFF;
break;
case MUT_STRONG:
mutat = MUT_WEAK;
break;
static bool accept_mutation(mutation_type mutat, bool ignore_rarity = false)
case MUT_CLEVER:
mutat = MUT_DOPEY;
break;
case MUT_AGILE:
mutat = MUT_CLUMSY;
break;
default:
break;
}
}
unsigned char cur_level = you.mutation[mutat];
char *stat_ptr = &you.dex; // Default for the scales.
char amnt = 1;
char mod = 0;
switch(mutat)
{
case MUT_GREY2_SCALES:
if (cur_level == 0 || cur_level == 2)
amnt = 1;
else
amnt = 0;
break;
case MUT_METALLIC_SCALES:
if (cur_level == 0)
amnt = 2;
else
amnt = 1;
break;
case MUT_YELLOW_SCALES:
case MUT_RED2_SCALES:
if (cur_level == 0)
amnt = 0;
else
amnt = 1;
break;
case MUT_FLEXIBLE_WEAK:
case MUT_WEAK:
stat_ptr = &you.strength;
// Take might into account so we don't lower base strength below
// one.
if (you.duration[DUR_MIGHT])
mod = -5;
break;
case MUT_DOPEY:
stat_ptr = &you.intel;
case MUT_STRONG_STIFF:
case MUT_CLUMSY:
stat_ptr = &you.dex;
break;
default:
return (false);
}
return (amnt >= (*stat_ptr + mod));
}
static bool accept_mutation(mutation_type mutat, bool ignore_rarity = false,
bool non_fatal = false, bool delete_mut = false)