git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1489 c06c8d41-db1a-0410-9941-cceddc491573
KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC
ONKB2ZZ2MWY7UGPBHW6EE4N3EEPJONPRRALEFZZR2YTZHNEIGV5AC
GRH4XPIYHDOXXF3R3QPMZTFHGLO2OJAZS4FLNBBXG3DHTQQM7RDQC
SW3RLYFNRT3IJBK6LYKHKP2J2YDU7SXQWAJZX7U6S7ICYW43OMNQC
JVSCP4FTW2G57C6YD5HZOZXTODGZH7TR75JQGFJBEPX3LCZH236QC
X2FMEN4E345XD26Z2X7JMJ7VGHOGCGIELMHQRE2ITLVNQACP3NOQC
QKGDOYIYKE6B36ION5O2DRW65DWWPZMYNWJVH7LJJ7FPGGM2MYAQC
APMT6XTVAD4ZCXCMUPTW5KCNR7TXW6W37SNYUP5A6NLFLXT3BCYQC
UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
JW2KRJHES33W7UTWZ6NDO4TLMK4EFU4HKZXBWR2UJOMPCCOTR4CQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
CJ6OSJQPAZOGWC56OYBALICSITGVUEQERE7LWIYJL2AXWRZE523AC
Y7ZDLE2BHSLBQUXBWLAFBJXXIH5WYGPBRJDIH33WX7VPLO7PFODQC
2Q3P7FHAAZRJ337GTR2ZLD72ECBUDJ42MROKVCNKNDV6CGMQOSYAC
3NFVCXRVGHN2CHLLWFZES5RBS4R2BCDS4EEQNSDCFYIFQWQK7MUQC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC
74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
L4PKJZERR7WADKWHY3MR6J6OZFREVPL3CB43I6MLJ2BVKWCUTE7AC
6L4EP4ZRWWYLT55PD5KTTJON5J2JB5VV5MWNHF5VPZQZ5BKEYZ4QC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
3GSAVTNKEG45AT2U734R5STSRP22WJZL3H6KUFRUWCIA6A4CZE5QC
QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC
HH3HFWVXABJ4IRMN22PPJCREMULZSN6DA7VYKOGECGMNUQTZ5QNQC
43ZTEB57FU7KE5EVMYWZONNVJBZCGF3JEAJZIY25LC4LGE65PG5QC
EIULXYQC3OPXDGTBRDOI7ITILQ22RGEGG6UFCGY2O5HD7SN5NUUQC
MOT3YZFRY3JG2MH3GN2VD6IY3IJSAXJUXMXS222TXWKRFCENOCDQC
VIFRP3HZEONFR6PQRYZYM3YUEJOQ7T4F5CZY4MN4YJMB23FMU7XAC
7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC
ACKNLTFL2RI3PMRWLNRVLRWGQAMLRFKNGNS5LED6NFE5GVGFIHFAC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
BIZDHHK5LIO57S5AKHEPJFLWV5DAFKZIKYBGOUNGICSWTX7DCXKAC
UDYVF65OZSNPANLHDI3ODBEGUAKAVZ4KH4OZFAKR2CQJPO4AXU6QC
R325RPUV26YH65VIJKYEFZ2XCVXQHO5N3ELPX6RNQ5TSI3JJNQGQC
5UVDIVD4NSXA52U4QMQIVST3GSZJ2A2YZK3RUEXKPM43YVQ7LI5AC
ZP2KE7A2LE7Z2S7AC45WE4CXDSEVDTWIMV2EM4IBUKXYJIDU6R7QC
JDM27QE4HR52AYFSQE763BFF57ANOTF5MXKMO377PP5EXMN7SAOAC
DTO3EUKWHZ5RJNGNCFYXSOVTIPVXPP637F2W7WFGYKJ7JK7VNKNQC
MQ62OAMLGJVRW2QIL4PAZRAU6PC52ZVGY2FCOBIY6IWGQIHMU5CAC
GCIZIUXO5TYROKDUYB3HAY7H7MRDTJNM7HR7DGSH7KXDIZC2LCDAC
TOKBONNNPTP2CIEHMMR4QAJZTXYETS55OGGDA6FY6NIMNDYMWJDAC
QVVC7AYGVA6U64PTNA7L27422NLMO327P22BQKXEVIMPZHIHO7MQC
B62ICMDTN5V7R7RBL4JALFVKEMVOOVLRSJASRNYS6CGFWBEEF5JQC
TAVHZJPVNJBZR7CUURAOYNDZPNVQ3AGHTXDEP5K4JGYETBLQJDRQC
RISMOCQM6BKK4XSIRKYLOBB2UPDYJNDAL6OGIIR5GGNZQAK5YSZAC
W5VEC2PBIM5DMU5233HOWAZUEPTGWJRZZIA3H35YYQQW6BTP6XUAC
ITDUEUO7XAZANPC4GRB3SEDFBOV7GLFPNPTYE5LYNC3CS6BSVZTQC
T7PHMSG47WP4MTKIGVBP4EAQRGXHMZPYSI3GT3DAEWKHUDFCH3QQC
/*
* File: xom.cc
* Summary: All things Xomly
* Written by: Zooko
*
* Modified for Crawl Reference by $Author: haranp $ on $Date: 2007-05-15T17:02:30.826843Z $
*/
#include "AppHdr.h"
#include "beam.h"
#include "effects.h"
#include "it_use2.h"
#include "items.h"
#include "makeitem.h"
#include "misc.h"
#include "mon-util.h"
#include "monplace.h"
#include "monstuff.h"
#include "mutation.h"
#include "ouch.h"
#include "player.h"
#include "religion.h"
#include "spells3.h"
#include "spl-cast.h"
#include "stuff.h"
#include "view.h"
// Which spell? First I copied all spells from you_spells(), then I
// filtered some out (especially conjurations). Then I sorted them in
// roughly ascending order of power. ([ds] Removed SUMMON_GUARDIAN and
// SUMMON_DAEVA which are inappropriate for a god of chaos; need to
// investigate substitutes).
//
static const spell_type xom_spells[] =
{
SPELL_BLINK, SPELL_CONFUSING_TOUCH, SPELL_MAGIC_MAPPING,
SPELL_DETECT_ITEMS, SPELL_DETECT_CREATURES, SPELL_MASS_CONFUSION,
SPELL_MASS_SLEEP, SPELL_CONTROLLED_BLINK, SPELL_STONESKIN,
SPELL_RING_OF_FLAMES, SPELL_OLGREBS_TOXIC_RADIANCE,
SPELL_TUKIMAS_VORPAL_BLADE, SPELL_FIRE_BRAND, SPELL_FREEZING_AURA,
SPELL_POISON_WEAPON, SPELL_STONEMAIL, SPELL_WARP_BRAND, SPELL_ALTER_SELF,
SPELL_TUKIMAS_DANCE, SPELL_SUMMON_BUTTERFLIES, SPELL_SUMMON_SMALL_MAMMAL,
SPELL_CALL_IMP, SPELL_SUMMON_SCORPIONS, SPELL_FLY, SPELL_SPIDER_FORM,
SPELL_STATUE_FORM, SPELL_ICE_FORM, SPELL_DRAGON_FORM, SPELL_SWARM,
SPELL_SUMMON_WRAITHS, SPELL_SHADOW_CREATURES, SPELL_SUMMON_ELEMENTAL,
SPELL_SUMMON_HORRIBLE_THINGS, SPELL_SUMMON_LARGE_MAMMAL,
SPELL_CONJURE_BALL_LIGHTNING, SPELL_SUMMON_DRAGON, SPELL_DEATH_CHANNEL,
SPELL_NECROMUTATION
};
static const char *xom_try_this[] =
{
"\"Perhaps you should try this instead.\"",
"\"Maybe this would work better.\"",
"\"Catch!\""
};
static const char *xom_try_this_ring[] =
{
"\"Try this.\"",
"\"Catch!\"",
"\"Take this!\""
};
static const char *xom_try_this_other_thing[] =
{
"\"Perhaps you should try this instead.\"",
"\"Have you considered using one of these?\"",
"\"How about this?\""
};
static const char *xom_try_these_duds[] =
{
"\"Perhaps you should try this instead.\"",
"\"Have you considered wearing one of these?\"",
"\"Here you go.\""
};
static const char *xom_generic_beneficence[] =
{
"Xom grants you a gift!",
"\"Here.\"",
"Xom's generous nature manifests itself.",
"Xom grants you an implement of some kind.",
"\"Take this instrument of something!\"",
"\"Take this token of my esteem.\"",
"Xom smiles on you."
};
const char *describe_xom_favour()
{
return (you.piety > 160) ? "A beloved toy of Xom." :
(you.piety > 145) ? "A favorite toy of Xom." :
(you.piety > 130) ? "A very special toy of Xom." :
(you.piety > 115) ? "A special toy of Xom." :
(you.piety > 100) ? "A toy of Xom." :
(you.piety > 85) ? "A plaything of Xom." :
(you.piety > 70) ? "A special plaything of Xom." :
(you.piety > 55) ? "A very special plaything of Xom." :
(you.piety > 40) ? "A favorite plaything of Xom." :
"A beloved plaything of Xom.";
}
bool xom_is_nice()
{
return (you.gift_timeout > 0 && you.piety > 100);
}
void xom_is_stimulated(int maxinterestingness)
{
if (you.religion != GOD_XOM)
return;
int interestingness = random2(maxinterestingness);
if (interestingness < 12)
return;
if (interestingness > 255)
interestingness = 255;
if (interestingness > you.gift_timeout)
{
you.gift_timeout = interestingness;
god_speaks(GOD_XOM,
((interestingness > 200) ? "Xom roars with laughter!" :
(interestingness > 100) ? "Xom thinks this is hilarious!" :
(interestingness > 75) ? "Xom is highly amused!" :
(interestingness > 50) ? "Xom is amused." :
(interestingness > 25) ? "Xom is mildly amused." :
"Xom is interested."));
}
if (you.piety < 100 && coinflip())
you.piety = 200 - you.piety;
}
void xom_makes_you_cast_random_spell(int sever)
{
int spellenum = sever;
const int nxomspells = ARRAYSIZE(xom_spells);
if (spellenum >= nxomspells)
spellenum = nxomspells - 1;
const spell_type spell = xom_spells[random2(spellenum)];
god_speaks(GOD_XOM, "Xom's power flows through you!");
#if DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS,
"Xom_acts();spell: %d, spellenum: %d", spell, spellenum);
#endif
your_spells(spell, sever, false);
}
static void xom_make_item(object_class_type base,
int subtype,
int power,
const char *failmsg = "\"No, never mind.\"")
{
int thing_created =
items(true, base, subtype, true, power, MAKE_ITEM_RANDOM_RACE);
if (thing_created == NON_ITEM)
{
god_speaks(GOD_XOM, failmsg);
return;
}
move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
canned_msg(MSG_SOMETHING_APPEARS);
origin_acquired(mitm[thing_created], GOD_XOM);
}
static void xom_suggest(const char **messages, int nmsgs)
{
if (nmsgs && messages)
{
const char *sel = messages[random2(nmsgs)];
if (sel)
god_speaks(GOD_XOM, sel);
}
}
#define XOM_SAY(x) xom_suggest(x, ARRAYSIZE(x))
static object_class_type get_unrelated_wield_class(object_class_type ref)
{
object_class_type objtype = OBJ_WEAPONS;
if (ref == OBJ_WEAPONS)
{
if (random2(10))
objtype = OBJ_STAVES;
else
objtype = OBJ_MISCELLANY;
}
else if (ref == OBJ_STAVES)
{
if (random2(10))
objtype = OBJ_WEAPONS;
else
objtype = OBJ_MISCELLANY;
}
else
{
const int temp_rand = random2(3);
objtype =
(temp_rand == 0) ? OBJ_WEAPONS :
(temp_rand == 1) ? OBJ_STAVES :
OBJ_MISCELLANY;
}
return (objtype);
}
static bool xom_annoyance_gift(int power)
{
if (coinflip() && player_in_a_dangerous_place())
{
const item_def *weapon = you.weapon();
// Xom has a sense of humour.
if (coinflip() && weapon && weapon->cursed())
{
// If you are wielding a cursed item on then Xom will give
// you an item of that same type. Ha ha!
XOM_SAY(xom_try_this);
if (coinflip())
// For added humour, give the same sub-type.
xom_make_item(weapon->base_type, weapon->sub_type, power * 3);
else
acquirement(weapon->base_type, GOD_XOM);
return (true);
}
const item_def *gloves = you.slot_item(EQ_GLOVES);
if (coinflip() && gloves && gloves->cursed())
{
// If you are wearing cursed gloves then Xom will give you
// a ring. Ha ha!
//
// A random ring. (Not necessarily a good one.)
XOM_SAY(xom_try_this);
xom_make_item(OBJ_JEWELLERY, get_random_ring_type(), power * 3);
return (true);
};
const item_def *amulet = you.slot_item(EQ_AMULET);
if (coinflip() && amulet && amulet->cursed())
{
// If you are wearing a cursed amulet then Xom will give
// you an amulet. Ha ha!
XOM_SAY(xom_try_this);
xom_make_item(OBJ_JEWELLERY, get_random_amulet_type(), power * 3);
return (true);
};
const item_def *left_ring = you.slot_item(EQ_LEFT_RING);
const item_def *right_ring = you.slot_item(EQ_RIGHT_RING);
if (coinflip() && ((left_ring && left_ring->cursed())
|| (right_ring && right_ring->cursed())))
{
// If you are wearing a cursed ring then Xom will give you
// a ring. Ha ha!
XOM_SAY(xom_try_this_ring);
xom_make_item(OBJ_JEWELLERY, get_random_ring_type(), power * 3);
return (true);
}
if (one_chance_in(5) && weapon)
{
// Xom will give you a wielded item of a type different
// than what you are currently wielding.
XOM_SAY(xom_try_this_other_thing);
const object_class_type objtype =
get_unrelated_wield_class(weapon->base_type);
if (power > random2(256))
acquirement(objtype, GOD_XOM);
else
xom_make_item(objtype, OBJ_RANDOM, power * 3);
return (true);
}
}
return (false);
}
bool xom_gives_item(int power)
{
if (xom_annoyance_gift(power))
return (true);
const item_def *cloak = you.slot_item(EQ_CLOAK);
if (coinflip() && cloak && cloak->cursed())
{
// If you are wearing a cursed cloak then Xom will give you a
// cloak or body armour . Ha ha!
XOM_SAY(xom_try_these_duds);
xom_make_item(OBJ_ARMOUR,
random2(10)?
get_random_body_armour_type(you.your_level * 2)
: ARM_CLOAK,
power * 3);
return (true);
}
XOM_SAY(xom_generic_beneficence);
// There are two kinds of Xom gifts: acquirement and random
// object. The result from acquirement is very good (usually as
// good or better than random object), and it is sometimes tuned
// to the player's skills and nature. Being tuned to the player's
// skills and nature is not very Xomlike...
if (power > random2(256))
{
// 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;
acquirement(objtype, GOD_XOM);
}
else
{
// random-type random object
xom_make_item(OBJ_RANDOM, OBJ_RANDOM, power * 3);
}
more();
return (true);
}
bool there_are_monsters_nearby()
{
int ystart = you.y_pos - 9, xstart = you.x_pos - 9;
int yend = you.y_pos + 9, xend = you.x_pos + 9;
if (xstart < 0) xstart = 0;
if (ystart < 0) ystart = 0;
if (xend >= GXM) xend = GXM;
if (ystart >= GYM) yend = GYM;
/* monster check */
for ( int y = ystart; y < yend; ++y )
{
for ( int x = xstart; x < xend; ++x )
{
/* if you can see a nonfriendly monster then you feel
unsafe */
if ( see_grid(x,y) )
{
const int targ_monst = mgrd[x][y];
if ( targ_monst != NON_MONSTER )
{
const monsters *mon = &menv[targ_monst];
if (!mons_is_submerged(mon))
return (true);
}
}
}
}
return (false);
}
monsters *get_random_nearby_monster()
{
monsters *monster = NULL;
/* not particular efficient, but oh well */
for (int it = 0, num = 0; it < MAX_MONSTERS; it++)
{
monsters *mons = &menv[it];
if (mons->alive() && mons_near(mons)
&& !mons_is_submerged(mons)
&& one_chance_in(++num))
{
monster = mons;
}
}
return (monster);
}
static bool xom_is_good(int sever)
{
// niceness = false - bad, true - nice
int temp_rand; // probability determination {dlb}
bool done = false;
bolt beam;
// Okay, now for the nicer stuff (note: these things are not
// necessarily nice):
if (random2(sever) <= 1)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Go forth and destroy!\"" :
(temp_rand == 1) ? "\"Go forth and cause havoc, mortal!\"" :
(temp_rand == 2) ? "Xom grants you a minor favour."
: "Xom smiles on you.");
switch (random2(7))
{
case 0:
potion_effect(POT_HEALING, 150);
break;
case 1:
potion_effect(POT_HEAL_WOUNDS, 150);
break;
case 2:
potion_effect(POT_SPEED, 150);
break;
case 3:
potion_effect(POT_MIGHT, 150);
break;
case 4:
potion_effect(POT_INVISIBILITY, 150);
break;
case 5:
if (one_chance_in(6))
potion_effect(POT_EXPERIENCE, 150);
else
{
you.berserk_penalty = NO_BERSERK_PENALTY;
potion_effect(POT_BERSERK_RAGE, 150);
}
break;
case 6:
you.berserk_penalty = NO_BERSERK_PENALTY;
potion_effect(POT_BERSERK_RAGE, 150);
break;
}
done = true;
}
else if (random2(sever) <= 2)
{
xom_makes_you_cast_random_spell(sever);
done = true;
}
else if (random2(sever) <= 3)
{
temp_rand = random2(3);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Serve the mortal, my children!\"" :
(temp_rand == 1) ? "Xom grants you some temporary aid."
: "Xom momentarily opens a gate.");
int i;
int r = random2(random2(random2(sever+1)+1)+1)+2;
int numdemons = MIN(r, 24);
for (i=0; i < numdemons; i++)
{
r = random2(random2(random2(sever)));
int demonnum = MONS_WHITE_IMP + MIN(r, 20);
if (!player_res_poison())
{
while (demonnum == MONS_GREEN_DEATH)
{
r = random2(random2(random2(sever)));
demonnum = MONS_WHITE_IMP + MIN(r, 20);
}
}
ASSERT (demonnum >= MONS_WHITE_IMP);
ASSERT (demonnum <= MONS_WHITE_IMP+20);
create_monster(demonnum, 3,
BEH_GOD_GIFT, you.x_pos, you.y_pos,
you.pet_target, 250 );
}
done = true;
}
else if (random2(sever) <= 4)
{
xom_gives_item(sever);
done = true;
}
else if (random2(sever) <= 5)
{
int r = random2(random2(random2(sever)));
int demonnum = MONS_WHITE_IMP + MIN(r, 20);
ASSERT (demonnum >= MONS_WHITE_IMP);
ASSERT (demonnum <= MONS_WHITE_IMP+20);
if (!player_res_poison())
{
while (demonnum == MONS_GREEN_DEATH)
{
r = random2(random2(random2(sever)));
demonnum = MONS_WHITE_IMP + MIN(r, 20);
}
}
if (create_monster( demonnum, 6,
BEH_GOD_GIFT, you.x_pos, you.y_pos,
you.pet_target, 250 ) != -1)
{
temp_rand = random2(3);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Serve the mortal, my child!\"" :
(temp_rand == 1) ? "Xom grants you a demonic assistant."
: "Xom opens a gate so that something can appear.");
done = true;
}
}
else if ((random2(sever) <= 6) && there_are_monsters_nearby())
{
if (monsters* mon = get_random_nearby_monster())
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"This might be better!\"" :
(temp_rand == 1) ? "\"Hum-dee-hum-dee-hum...\"" :
(temp_rand == 2) ?
"Xom's power touches on a nearby monster."
: "You hear Xom's avuncular chuckle.");
bool isFriendly = mons_friendly(mon);
if (isFriendly)
monster_polymorph(mon, RANDOM_MONSTER, PPT_MORE);
else
monster_polymorph(mon, RANDOM_MONSTER, PPT_LESS);
done = true;
}
}
else if (random2(sever) <= 7)
{
xom_gives_item(sever);
done = true;
}
else if (!you.is_undead && random2(sever) <= 8)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"You need some minor adjustments, mortal!\"" :
(temp_rand == 1) ? "\"Let me alter your pitiful body.\"" :
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal chuckling.");
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;
int i = 0;
int j = random2(4);
while (i < j)
{
if (mutate(100, failMsg, true))
done = true;
else
failMsg = false;
i++;
}
}
else if (random2(sever) <= 9)
{
int r = random2(random2(random2(sever)));
int demonnum = MONS_WHITE_IMP + MIN(r, 20);
if (!player_res_poison())
{
while (demonnum == MONS_GREEN_DEATH)
{
r = random2(random2(random2(sever)));
demonnum = MONS_WHITE_IMP + MIN(r, 20);
}
}
if (create_monster( demonnum, 0, BEH_GOD_GIFT,
you.x_pos, you.y_pos, you.pet_target, 250 ) != -1)
{
temp_rand = random2(3);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Serve the toy, my child!\"" :
(temp_rand == 1) ? "Xom grants you a demonic servitor."
: "Xom opens a gate.");
done = true;
}
}
else if ((random2(sever) <= 10) && player_in_a_dangerous_place())
{
bool lightningprot = false;
if (you.hp <= random2(201)
&& !you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION])
{
you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION] = 1;
lightningprot = true;
} else
lightningprot = false;
mpr("The area is suffused with divine lightning!");
beam.beam_source = NON_MONSTER;
beam.type = SYM_BURST;
beam.damage = dice_def( 3, 30 );
beam.flavour = BEAM_ELECTRICITY;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
beam.name = "blast of lightning";
beam.colour = LIGHTCYAN;
beam.thrower = KILL_MISC;
beam.aux_source = "Xom's lightning strike";
beam.ex_size = 2;
beam.is_tracer = false;
beam.is_explosion = true;
explosion(beam);
if (lightningprot)
{
mpr("Your divine protection wanes.");
you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION] = 0;
}
done = true;
}
return (done);
}
static bool xom_is_bad(int sever)
{
// niceness = false - bad, true - nice
int temp_rand; // probability determination {dlb}
bool done = false;
bolt beam;
// begin "Bad Things"
while (!done)
{
if (random2(sever) <= 2)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "Xom almost notices you." :
(temp_rand == 1) ? "Xom's attention almost turns to you for a moment.":
(temp_rand == 2) ? "Xom's power almost touches on you for a moment."
: "You almost hear Xom's maniacal laughter.");
miscast_effect( SPTYP_RANDOM, 0, 0, 0,
"the mischievity of Xom" );
done = true;
}
else if (random2(sever) <= 3)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "Xom notices you." :
(temp_rand == 1) ? "Xom's attention turns to you for a moment.":
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
miscast_effect( SPTYP_RANDOM, 0, 0, random2(2),
"the capriciousness of Xom" );
done = true;
}
else if (random2(sever) <= 4)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Suffer!\"" :
(temp_rand == 1) ? "Xom's malign attention turns to you for a moment." :
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
lose_stat(STAT_RANDOM, 1 + random2(3), true);
done = true;
}
else if (random2(sever) <= 5)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "Xom notices you." :
(temp_rand == 1) ? "Xom's attention turns to you for a moment.":
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
miscast_effect( SPTYP_RANDOM, 0, 0, random2(3),
"the capriciousness of Xom" );
done = true;
}
else if (!you.is_undead && random2(sever) <= 6)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"You need some minor improvements, mortal!\"" :
(temp_rand == 1) ? "\"Let me alter your body.\"" :
(temp_rand == 2) ? "Xom's power brushes against you for a moment."
: "You hear Xom's avuncular chuckle.");
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 = 0; i < random2(4)+1; i++)
{
if (mutate(101, failMsg, true))
done = true;
else
failMsg = false;
}
}
else if ((random2(sever) <= 7) && there_are_monsters_nearby())
{
struct monsters* mon = get_random_nearby_monster();
ASSERT (mon != NULL);
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"This might be better!\"" :
(temp_rand == 1) ? "\"Hum-dee-hum-dee-hum...\"" :
(temp_rand == 2) ? "Xom's power touches on a nearby monster."
: "You hear Xom's avuncular chuckle.");
bool isFriendly = mons_friendly(mon);
if (isFriendly)
monster_polymorph(mon, RANDOM_MONSTER, PPT_LESS);
else
monster_polymorph(mon, RANDOM_MONSTER, PPT_MORE);
done = true;
}
else if (!you.is_undead && random2(sever) <= 8)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"You have displeased me, mortal.\"" :
(temp_rand == 1) ? "\"You have grown too confident for your meagre worth.\"" :
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
if (one_chance_in(4))
{
drain_exp();
if (random2(sever) > 3)
drain_exp();
if (random2(sever) > 3)
drain_exp();
}
else
{
mpr("A wave of agony tears through your body!");
set_hp(1 + (you.hp / 2), false);
}
done = true;
}
else if (random2(sever) <= 9)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Time to have some fun!\"" :
(temp_rand == 1) ? "\"Fight to survive, mortal.\"" :
(temp_rand == 2) ? "\"Let's see if it's strong enough to survive yet.\""
: "You hear Xom's maniacal laughter.");
if (one_chance_in(4))
dancing_weapon(100, true); // nasty, but fun
else
{
int r = random2(random2(random2(sever+1)+1)+1)+1;
int numdemons = MIN(r, 24);
for (int i = 0; i < numdemons; i++)
{
create_monster(MONS_WHITE_IMP +
random2(random2(random2(MIN(sever, 22)))),
4,
BEH_HOSTILE, you.x_pos, you.y_pos,
MHITNOT, 250);
}
}
done = true;
}
else if (random2(sever) <= 10)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Try this!\"" :
(temp_rand == 1) ? "Xom's attention turns to you.":
(temp_rand == 2) ? "Xom's power touches on you."
: "Xom giggles.");
miscast_effect( SPTYP_RANDOM, 0, 0, random2(4),
"the severe capriciousness of Xom" );
done = true;
}
else if ((random2(sever) == 0) && (you.level_type != LEVEL_ABYSS))
{
temp_rand = random2(3);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"You have grown too comfortable in your little world, mortal!\"" :
(temp_rand == 1) ? "Xom casts you into the Abyss!"
: "The world seems to spin as Xom's maniacal laughter rings in your ears.");
banished(DNGN_ENTER_ABYSS);
done = true;
}
}
return (done);
}
void xom_acts(bool niceness, int sever)
{
#if DEBUG_DIAGNOSTICS
mprf(MSGCH_DIAGNOSTICS, "Xom_acts(%u, %d); piety: %u, interest: %u\n",
niceness, sever, you.piety, you.gift_timeout);
#endif
if (sever < 1)
sever = 1;
if (niceness)
{
// Good stuff.
while (!xom_is_good(sever))
;
}
else
{
// Bad mojo.
while (!xom_is_bad(sever))
;
}
if (coinflip())
you.piety = 200 - you.piety;
}
} // end you_teleport()
return !is_controlled;
}
void you_teleport_now( bool allow_control, bool new_abyss_area )
{
const bool randtele = teleport_player(allow_control, new_abyss_area);
// Xom is amused by uncontrolled teleports that land you in a
// dangerous place.
if (randtele && player_in_a_dangerous_place())
xom_is_stimulated(255);
}
void gain_piety(char pgn);
void god_speaks( int god, const char *mesg );
void lose_piety(char pgn);
void gain_piety(int pgn);
void god_speaks(god_type god, const char *mesg );
void lose_piety(int pgn);
if (one_chance_in(100))
{
// Every now and then, Xom listens
// This is for flavour, not effect, so praying should not be
// encouraged.
// Xom is nicer to experienced players
bool nice = (27 <= random2( 27 + you.experience_level ));
mpr("Xom ignores you.");
void Xom_acts(bool niceness, int sever, bool force_sever)
{
// niceness = false - bad, true - nice
int temp_rand; // probability determination {dlb}
bool done_bad = false; // flag to clarify logic {dlb}
bool done_good = false; // flag to clarify logic {dlb}
struct bolt beam;
if (sever < 1)
sever = 1;
if (!force_sever)
sever = random2(sever);
if (sever == 0)
return;
okay_try_again:
if (!niceness || one_chance_in(3))
{
// begin "Bad Things"
done_bad = false;
// this should always be first - it will often be called
// deliberately, with a low sever value
if (random2(sever) <= 2)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "Xom notices you." :
(temp_rand == 1) ? "Xom's attention turns to you for a moment.":
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
miscast_effect( SPTYP_RANDOM, 5 + random2(10), random2(100), 0,
"the capriciousness of Xom" );
done_bad = true;
}
else if (random2(sever) <= 2)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Suffer!\"" :
(temp_rand == 1) ? "Xom's malign attention turns to you for a moment." :
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
lose_stat(STAT_RANDOM, 1 + random2(3), true);
done_bad = true;
}
else if (random2(sever) <= 2)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "Xom notices you." :
(temp_rand == 1) ? "Xom's attention turns to you for a moment.":
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
miscast_effect( SPTYP_RANDOM, 5 + random2(15), random2(250), 0,
"the capriciousness of Xom" );
done_bad = true;
}
else if (!you.is_undead && random2(sever) <= 3)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"You need some minor adjustments, mortal!\"" :
(temp_rand == 1) ? "\"Let me alter your pitiful body.\"" :
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
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 = 0; i < 4; i++)
{
if (!mutate(100, failMsg))
failMsg = false;
}
done_bad = true;
}
else if (!you.is_undead && random2(sever) <= 3)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"You have displeased me, mortal.\"" :
(temp_rand == 1) ? "\"You have grown too confident for your meagre worth.\"" :
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal laughter.");
if (one_chance_in(4))
{
drain_exp();
if (random2(sever) > 3)
drain_exp();
if (random2(sever) > 3)
drain_exp();
}
else
{
mpr("A wave of agony tears through your body!");
set_hp(1 + (you.hp / 2), false);
}
done_bad = true;
}
else if (random2(sever) <= 3)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Time to have some fun!\"" :
(temp_rand == 1) ? "\"Fight to survive, mortal.\"" :
(temp_rand == 2) ? "\"Let's see if it's strong enough to survive yet.\""
: "You hear Xom's maniacal laughter.");
if (one_chance_in(4) && (you.equip[EQ_WEAPON] != -1) )
dancing_weapon(100, true); // nasty, but fun
else
{
create_monster(MONS_NEQOXEC + random2(5), 3,
BEH_HOSTILE, you.x_pos, you.y_pos, MHITNOT, 250);
if (one_chance_in(3))
create_monster(MONS_NEQOXEC + random2(5), 3,
BEH_HOSTILE, you.x_pos, you.y_pos, MHITNOT, 250);
if (one_chance_in(4))
create_monster(MONS_NEQOXEC + random2(5), 3,
BEH_HOSTILE, you.x_pos, you.y_pos, MHITNOT, 250);
if (one_chance_in(3))
create_monster(MONS_HELLION + random2(10), 3,
BEH_HOSTILE, you.x_pos, you.y_pos, MHITNOT, 250);
if (one_chance_in(4))
create_monster(MONS_HELLION + random2(10), 3,
BEH_HOSTILE, you.x_pos, you.y_pos, MHITNOT, 250);
}
done_bad = true;
}
else if (you.your_level == 0)
{
// this should remain the last possible outcome {dlb}
temp_rand = random2(3);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"You have grown too comfortable in your little world, mortal!\"" :
(temp_rand == 1) ? "Xom casts you into the Abyss!"
: "The world seems to spin as Xom's maniacal laughter rings in your ears.");
banished(DNGN_ENTER_ABYSS, "Xom");
done_bad = true;
}
} // end "Bad Things"
else
{
// begin "Good Things"
done_good = false;
// Okay, now for the nicer stuff (note: these things are not necessarily nice):
if (random2(sever) <= 2)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Go forth and destroy!\"" :
(temp_rand == 1) ? "\"Go forth and destroy, mortal!\"" :
(temp_rand == 2) ? "Xom grants you a minor favour."
: "Xom smiles on you.");
switch (random2(7))
{
case 0:
potion_effect(POT_HEALING, 150);
break;
case 1:
potion_effect(POT_HEAL_WOUNDS, 150);
break;
case 2:
potion_effect(POT_SPEED, 150);
break;
case 3:
potion_effect(POT_MIGHT, 150);
break;
case 4:
potion_effect(POT_INVISIBILITY, 150);
break;
case 5:
if (one_chance_in(6))
potion_effect(POT_EXPERIENCE, 150);
else
{
you.berserk_penalty = NO_BERSERK_PENALTY;
potion_effect(POT_BERSERK_RAGE, 150);
}
break;
case 6:
you.berserk_penalty = NO_BERSERK_PENALTY;
potion_effect(POT_BERSERK_RAGE, 150);
break;
}
done_good = true;
}
else if (random2(sever) <= 4)
{
temp_rand = random2(3);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Serve the mortal, my children!\"" :
(temp_rand == 1) ? "Xom grants you some temporary aid."
: "Xom opens a gate.");
create_monster( MONS_NEQOXEC + random2(5), 3,
BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, 250 );
create_monster( MONS_NEQOXEC + random2(5), 3,
BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, 250 );
if (random2( you.experience_level ) >= 8)
{
create_monster( MONS_NEQOXEC + random2(5), 3,
BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, 250 );
}
if (random2( you.experience_level ) >= 8)
{
create_monster( MONS_HELLION + random2(10), 3,
BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, 250 );
}
if (random2( you.experience_level ) >= 8)
{
create_monster( MONS_HELLION + random2(10), 3,
BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, 250 );
}
done_good = true;
}
else if (random2(sever) <= 3)
{
temp_rand = random2(3);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Take this token of my esteem.\"" :
(temp_rand == 1) ? "Xom grants you a gift!"
: "Xom's generous nature manifests itself.");
if (grid_destroys_items(grd[you.x_pos][you.y_pos])) {
// How unfortunate. I'll bet Xom feels sorry for you.
mprf(MSGCH_SOUND,
grid_item_destruction_message(grd[you.x_pos][you.y_pos]));
}
else
{
int thing_created = items(1, OBJ_RANDOM, OBJ_RANDOM, true,
you.experience_level * 3, 250);
move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
if (thing_created != NON_ITEM)
{
origin_acquired(mitm[thing_created], GOD_XOM);
canned_msg(MSG_SOMETHING_APPEARS);
more();
}
}
done_good = true;
}
else if (random2(sever) <= 4)
{
const int demon = (random2(you.experience_level) < 6)
? MONS_WHITE_IMP + random2(5)
: MONS_NEQOXEC + random2(5);
if (create_monster( demon, 0, BEH_FRIENDLY, you.x_pos, you.y_pos,
you.pet_target, 250 ) != -1)
{
temp_rand = random2(3);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Serve the mortal, my child!\"" :
(temp_rand == 1) ? "Xom grants you a demonic servitor."
: "Xom opens a gate.");
}
else
{
god_speaks(GOD_XOM, "You hear Xom cackling.");
}
done_good = true; // well, for Xom, trying == doing {dlb}
}
else if (random2(sever) <= 4)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"Take this instrument of destruction!\"" :
(temp_rand == 1) ? "\"You have earned yourself a gift.\"" :
(temp_rand == 2) ? "Xom grants you an implement of death."
: "Xom smiles on you.");
if (acquirement(OBJ_WEAPONS, GOD_XOM))
more();
done_good = true;
}
else if (!you.is_undead && random2(sever) <= 5)
{
temp_rand = random2(4);
god_speaks(GOD_XOM,
(temp_rand == 0) ? "\"You need some minor adjustments, mortal!\"" :
(temp_rand == 1) ? "\"Let me alter your pitiful body.\"" :
(temp_rand == 2) ? "Xom's power touches on you for a moment."
: "You hear Xom's maniacal chuckling.");
mpr("Your body is suffused with distortional energy.");
set_hp(1 + random2(you.hp), false);
deflate_hp(you.hp_max / 2, true);
if (coinflip() || !give_cosmetic_mutation())
give_good_mutation();
done_good = true;
}
else if (random2(sever) <= 2)
{
// this should remain the last possible outcome {dlb}
if (!one_chance_in(8))
you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION] = 1;
god_speaks(GOD_XOM, "The area is suffused with divine lightning!");
beam.beam_source = NON_MONSTER;
beam.type = SYM_BURST;
beam.damage = dice_def( 3, 30 );
beam.flavour = BEAM_ELECTRICITY;
beam.target_x = you.x_pos;
beam.target_y = you.y_pos;
beam.name = "blast of lightning";
beam.colour = LIGHTCYAN;
beam.thrower = KILL_MISC;
beam.aux_source = "Xom's lightning strike";
beam.ex_size = 2;
beam.is_tracer = false;
beam.is_explosion = true;
explosion(beam);
if (you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION] == 1)
{
mpr("Your divine protection wanes.");
you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION] = 0;
}
done_good = true;
}
} // end "Good Things"
if (done_bad || done_good )
return;
if ( one_chance_in(4) ) {
god_speaks(GOD_XOM, "Xom's attention is distracted from you.");
return;
}
goto okay_try_again;
} // end Xom_acts()
{
// One in ten chance that Xom might do something good...
// but that isn't forced, bad things are though
bool nice = one_chance_in(10);
bool force = !nice;
Xom_acts(nice, you.experience_level, force);
}
// One in ten chance that Xom might do something good...
xom_acts(one_chance_in(10), abs(you.piety - 100));
you.piety = 15; // to prevent near instant excommunication
you.gift_timeout = 0;
if (you.religion == GOD_XOM)
{
// Xom uses piety and gift_timeout differently.
you.piety = 100;
you.gift_timeout = random2(40) + random2(40);
}
else
{
you.piety = 15; // to prevent near instant excommunication
you.gift_timeout = 0;
}
if (one_chance_in(75))
Xom_acts(true, you.experience_level + random2(15), true);
{
// Xom semi-randomly drifts your piety.
int delta;
const char *origfavour = describe_xom_favour();
const bool good = you.piety >= 100;
int size = abs(you.piety - 100);
delta = (random2(1000) < 511) ? 1 : -1;
size += delta;
you.piety = 100 + (good ? size : -size);
const char *newfavour = describe_xom_favour();
if (strcmp(origfavour, newfavour))
{
// Dampen oscillation across announcement boundaries:
size += delta * 2;
you.piety = 100 + (good ? size : -size);
}
// ... but he gets bored... (I re-use gift_timeout for
// this instead of making a separate field because I don't
// want to learn how to save and restore a new field). In
// this usage, the "gift" is the gift you give to Xom of
// something interesting happening.
if (you.gift_timeout == 1)
{
mpr("Xom is getting BORED.");
you.gift_timeout = 0;
}
else if (you.gift_timeout > 1)
{
you.gift_timeout -= random2(2);
}
if (one_chance_in(20))
{
// If you.gift_timeout was == 0, then Xom was BORED.
// He HATES that.
xom_acts(you.gift_timeout > 0 && you.piety > 100,
abs(you.piety - 100));
}
static void xom_checks_damage(kill_method_type death_type,
int dam, int death_source)
{
//if (you.hp <= dam)
// xom_is_stimulated(32);
if ((death_type != KILLED_BY_MONSTER && death_type != KILLED_BY_BEAM)
|| death_source < 0 || death_source >= MAX_MONSTERS)
{
return ;
}
int amusementvalue = 1;
const monsters *monster = &menv[death_source];
if (!monster->alive())
return;
int leveldif = monster->hit_dice - you.experience_level;
if (leveldif == 0)
leveldif = 1;
/* Note that Xom is amused when you are significantly hurt
* by a creature of higher level than yourself as well as
* by a creatured of lower level than yourself. */
amusementvalue += leveldif * leveldif * dam;
if (!player_monster_visible(monster))
amusementvalue += 10;
if (monster->speed < (int) player_movement_speed())
amusementvalue += 8;
if (death_type != KILLED_BY_BEAM)
{
if (you.skills[SK_RANGED_COMBAT] <= (you.experience_level / 4))
amusementvalue += 2;
}
else
{
if (you.skills[SK_FIGHTING] <= (you.experience_level / 4))
amusementvalue += 2;
}
if (player_in_a_dangerous_place())
amusementvalue += 2;
amusementvalue /= (you.hp > 0) ? you.hp : 1;
xom_is_stimulated(amusementvalue);
}
mpr( "* * * LOW HITPOINT WARNING * * *", MSGCH_DANGER );
if (Options.hp_warning
&& you.hp <= (you.hp_max * Options.hp_warning) / 100)
{
mpr( "* * * LOW HITPOINT WARNING * * *", MSGCH_DANGER );
}
xom_checks_damage(death_type, dam, death_source);
return;
else // you.religion == GOD_MAKHLEB
// the new (piety-aware) Xom uses piety in his own special way...
// (namely, 100 is neutral)
you.piety = 100;
// the new (piety-aware) Xom uses gift_timeout in his own special
// way... (namely, a countdown to becoming bored)
you.gift_timeout = random2(40) + random2(40);
}
else // Makhleb
{
you.piety = 25;
int mutat = which_mutation;
bool force_mutation = false; // is mutation forced?
bool demonspawn = false; // demonspawn mutation?
int i;
int amusement = 16 * (11 - mutation_rarity[which_mutation]);
demonspawn = true;
force_mutation = true;
mutat -= 2000;
which_mutation -= 2000;
case MUT_TOUGH_SKIN:
case MUT_STRONG:
case MUT_CLEVER:
case MUT_AGILE:
case MUT_POISON_RESISTANCE:
case MUT_TELEPORT_CONTROL:
case MUT_MAGIC_RESISTANCE:
case MUT_TELEPORT_AT_WILL:
case MUT_MAPPING:
case MUT_CLARITY:
case MUT_MUTATION_RESISTANCE:
amusement /= 2; // not funny
break;
case MUT_CARNIVOROUS:
case MUT_HERBIVOROUS:
case MUT_FAST_METABOLISM:
case MUT_WEAK:
case MUT_DOPEY:
case MUT_CLUMSY:
case MUT_TELEPORT:
case MUT_FAST:
case MUT_DEFORMED:
case MUT_SPIT_POISON:
case MUT_BREATHE_FLAMES:
case MUT_BLINK:
case MUT_HORNS:
case MUT_LOST:
case MUT_BERSERK:
case MUT_DETERIORATION:
case MUT_BLURRY_VISION:
case MUT_FRAIL:
case MUT_CLAWS:
case MUT_HOOVES:
case MUT_BREATHE_POISON:
case MUT_STINGER:
case MUT_BIG_WINGS:
case MUT_BLUE_MARKS:
case MUT_GREEN_MARKS:
amusement *= 2; // funny!
break;
default:
break;
if (you.mutation[mutat] >= 3
&& (mutat != MUT_STRONG && mutat != MUT_CLEVER && mutat != MUT_AGILE)
&& (mutat != MUT_WEAK && mutat != MUT_DOPEY && mutat != MUT_CLUMSY))
if (one_chance_in(1000))
return false;
if (one_chance_in(5))
{
switch (random2(8))
{
case 0: mutat = MUT_WEAK; break;
case 1: mutat = MUT_DOPEY; break;
case 2: mutat = MUT_CLUMSY; break;
case 3: mutat = MUT_DEFORMED; break;
case 4: mutat = MUT_LOST; break;
case 5: mutat = MUT_DETERIORATION; break;
case 6: mutat = MUT_BLURRY_VISION; break;
case 7: mutat = MUT_FRAIL; break;
}
}
}
while ((you.mutation[mutat] >= 3
&& (mutat != MUT_STRONG && mutat != MUT_CLEVER
&& mutat != MUT_AGILE) && (mutat != MUT_WEAK
&& mutat != MUT_DOPEY
&& mutat != MUT_CLUMSY))
|| you.mutation[mutat] > 13
|| random2(10) >= mutation_rarity[mutat] + you.demon_pow[mutat]);
}
else if (you.mutation[mutat] >= 3
&& (mutat != MUT_STRONG && mutat != MUT_CLEVER
&& mutat != MUT_AGILE)
&& (mutat != MUT_WEAK && mutat != MUT_DOPEY
&& mutat != MUT_CLUMSY))
&& (mutat != MUT_STRONG && mutat != MUT_CLEVER && mutat != MUT_AGILE)
&& (mutat != MUT_WEAK && mutat != MUT_DOPEY && mutat != MUT_CLUMSY))
&& (mutat != MUT_STRONG && mutat != MUT_CLEVER
&& mutat != MUT_AGILE)
&& (mutat != MUT_WEAK && mutat != MUT_DOPEY
&& mutat != MUT_CLUMSY))
bool give_good_mutation(bool failMsg)
{
int temp_rand = 0; // probability determination {dlb}
int which_good_one = 0;
temp_rand = random2(25);
which_good_one = ((temp_rand >= 24) ? MUT_TOUGH_SKIN :
(temp_rand == 23) ? MUT_STRONG :
(temp_rand == 22) ? MUT_CLEVER :
(temp_rand == 21) ? MUT_AGILE :
(temp_rand == 20) ? MUT_HEAT_RESISTANCE :
(temp_rand == 19) ? MUT_COLD_RESISTANCE :
(temp_rand == 18) ? MUT_SHOCK_RESISTANCE :
(temp_rand == 17) ? MUT_REGENERATION :
(temp_rand == 16) ? MUT_TELEPORT_CONTROL :
(temp_rand == 15) ? MUT_MAGIC_RESISTANCE :
(temp_rand == 14) ? MUT_FAST :
(temp_rand == 13) ? MUT_ACUTE_VISION :
(temp_rand == 12) ? MUT_GREEN_SCALES :
(temp_rand == 11) ? MUT_BLACK_SCALES :
(temp_rand == 10) ? MUT_GREY_SCALES :
(temp_rand == 9) ? MUT_BONEY_PLATES :
(temp_rand == 8) ? MUT_REPULSION_FIELD :
(temp_rand == 7) ? MUT_POISON_RESISTANCE :
(temp_rand == 6) ? MUT_TELEPORT_AT_WILL :
(temp_rand == 5) ? MUT_SPIT_POISON :
(temp_rand == 4) ? MUT_MAPPING :
(temp_rand == 3) ? MUT_BREATHE_FLAMES :
(temp_rand == 2) ? MUT_BLINK :
(temp_rand == 1) ? MUT_CLARITY
: MUT_ROBUST);
// last updated: 08jun2000 {dlb}
/* ***********************************************************************
* called from: beam - effects - monstuff
* *********************************************************************** */
bool monster_polymorph(struct monsters *monster, int targetc, int power);
enum poly_power_type {
PPT_LESS,
PPT_MORE,
PPT_SAME
};
bool monster_polymorph(monsters *monster, monster_type targetc,
poly_power_type p = PPT_SAME);
// Xom doesn't care who you killed:
if (you.religion == GOD_XOM
&& random2(70) <= 10 + monster->hit_dice)
{
// postpone Xom action until after the monster dies
xom_will_act = 1 + random2(monster->hit_dice);
}
// Trying to prevent summoning abuse here, so we're trying to
// note that power is (as of yet) unused within this function -
// may be worthy of consideration of later implementation, though,
// so I'll still let the parameter exist for the time being {dlb}
bool monster_polymorph( monsters *monster, int targetc, int power )
static bool is_poly_power_unsuitable(
poly_power_type power,
int src_pow,
int tgt_pow,
int relax)
{
switch (power)
{
case PPT_LESS:
return (tgt_pow > src_pow - 3 + (relax * 3) / 2)
|| (power == PPT_LESS && (tgt_pow < src_pow - (relax / 2)));
case PPT_MORE:
return (tgt_pow < src_pow + 2 - relax)
|| (power == PPT_MORE && (tgt_pow > src_pow + relax));
default:
case PPT_SAME:
return (tgt_pow < src_pow - relax)
|| (tgt_pow > src_pow + (relax * 3) / 2);
}
}
/*
* if targetc == RANDOM_MONSTER then relpower indicates the desired
* power of the new monster relative to the current monster.
* Relaxation still takes effect when needed no matter what relpower
* says.
*/
bool monster_polymorph( monsters *monster, monster_type targetc,
poly_power_type power )
mprf(MSGCH_SOUND, "You hear a splashing noise.");
const bool can_see =
mons_near(this) && player_monster_visible(this);
if (can_see)
mprf("%s splashes around in the water.");
else if (!silenced(you.x_pos, you.y_pos) && !silenced(x, y))
mprf(MSGCH_SOUND, "You hear a splashing noise.");
}
static const char *shop_types[] = {
"weapon",
"armour",
"antique weapon",
"antique armour",
"antiques",
"jewellery",
"wand",
"book",
"food",
"distillery",
"scroll",
"general"
};
int str_to_shoptype(const std::string &s)
{
if (s == "random" || s == "any")
return (SHOP_RANDOM);
for (unsigned i = 0; i < sizeof(shop_types) / sizeof (*shop_types); ++i)
{
if (s == shop_types[i])
return (i);
}
return (-1);
}
/* Decides whether autoprayer Right Now is a good idea. */
static bool should_autopray()
{
if ( Options.autoprayer_on == false ||
you.religion == GOD_NO_GOD ||
you.duration[DUR_PRAYER] ||
grid_altar_god( grd[you.x_pos][you.y_pos] ) != GOD_NO_GOD ||
!i_feel_safe() )
return false;
// We already know that we're not praying now. So if you
// just autoprayed, there's a problem.
if ( you.just_autoprayed )
{
mpr("Autoprayer failed, deactivating.", MSGCH_WARN);
Options.autoprayer_on = false;
return false;
}
return true;
}
/* Actually performs autoprayer. */
bool do_autopray()
{
if ( you.turn_is_over ) // can happen with autopickup, I think
return false;
if ( should_autopray() )
{
pray();
you.just_autoprayed = true;
return true;
}
else
{
you.just_autoprayed = false;
return false;
}
}
// general threat = sum_of_logexpervalues_of_nearby_unfriendly_monsters
// highest threat = highest_logexpervalue_of_nearby_unfriendly_monsters
void monster_threat_values(double *general, double *highest)
{
double sum = 0;
int highest_xp = -1;
monsters *monster = NULL;
for (int it = 0; it < MAX_MONSTERS; it++)
{
monster = &menv[it];
if (monster->alive() && mons_near(monster) && !mons_friendly(monster))
{
const int xp = exper_value(monster);
const double log_xp = log(xp);
sum += log_xp;
if (xp > highest_xp)
{
highest_xp = xp;
*highest = log_xp;
}
}
}
*general = sum;
}
bool player_in_a_dangerous_place()
{
const double logexp = log(you.experience);
double gen_threat = 0.0, hi_threat = 0.0;
monster_threat_values(&gen_threat, &hi_threat);
return (gen_threat > logexp * 1.3 || hi_threat > logexp / 2);
}
}
static const char *shop_types[] = {
"weapon",
"armour",
"antique weapon",
"antique armour",
"antiques",
"jewellery",
"wand",
"book",
"food",
"distillery",
"scroll",
"general"
};
int str_to_shoptype(const std::string &s)
{
if (s == "random" || s == "any")
return (SHOP_RANDOM);
for (unsigned i = 0; i < sizeof(shop_types) / sizeof (*shop_types); ++i)
{
if (s == shop_types[i])
return (i);
}
return (-1);
}
/* Decides whether autoprayer Right Now is a good idea. */
static bool should_autopray()
{
if ( Options.autoprayer_on == false ||
you.religion == GOD_NO_GOD ||
you.duration[DUR_PRAYER] ||
grid_altar_god( grd[you.x_pos][you.y_pos] ) != GOD_NO_GOD ||
!i_feel_safe() )
return false;
// We already know that we're not praying now. So if you
// just autoprayed, there's a problem.
if ( you.just_autoprayed )
{
mpr("Autoprayer failed, deactivating.", MSGCH_WARN);
Options.autoprayer_on = false;
return false;
mitm[p].sub_type = random2(3);
if (random2(35) <= item_level + 10)
{
mitm[p].sub_type = random2(5);
if (one_chance_in(4))
mitm[p].sub_type = ARM_ANIMAL_SKIN;
}
if (random2(60) <= item_level + 10)
mitm[p].sub_type = random2(8);
if (10 + item_level >= random2(400) && one_chance_in(20))
mitm[p].sub_type = ARM_DRAGON_HIDE + random2(7);
if (10 + item_level >= random2(500) && one_chance_in(20))
{
mitm[p].sub_type = ARM_STEAM_DRAGON_HIDE + random2(11);
if (mitm[p].sub_type == ARM_ANIMAL_SKIN && one_chance_in(20))
mitm[p].sub_type = ARM_CRYSTAL_PLATE_MAIL;
}
// secondary armours:
if (one_chance_in(5))
{
mitm[p].sub_type = ARM_SHIELD + random2(5);
if (mitm[p].sub_type == ARM_SHIELD) // 33.3%
{
if (coinflip())
mitm[p].sub_type = ARM_BUCKLER; // 50.0%
else if (one_chance_in(3))
mitm[p].sub_type = ARM_LARGE_SHIELD; // 16.7%
}
}
mitm[p].sub_type = get_random_armour_type(item_level);
// Note that acquirement level gold gives much less than the
// price of a scroll of acquirement (520 gold). -- bwr
if (item_level == MAKE_GOOD_ITEM)
quant = 50 + random2avg(100, 2) + random2avg(100, 2);
// Acquirement now gives more gold: The base price of a scroll
// of acquirement is 520 gold. The expected value of the gold
// it produces is about 480. So you cannot consistently make a
// profit by buying scrolls of acquirement. However, there is
// a very low chance you'll get lucky and receive up to 2296!
// This is quite rare: 50% of the time you'll get less than
// 360 gold and 90% of the time you'll get less than 900 and
// 99% of the time you'll get less than 1500. --Zooko
if (make_good_item)
quant = 150 + random2(150) + random2(random2(random2(2000)));
jewellery_type get_random_amulet_type()
{
return (jewellery_type)
(AMU_FIRST_AMULET + random2(NUM_JEWELLERY - AMU_FIRST_AMULET));
}
static jewellery_type get_raw_random_ring_type()
{
return (jewellery_type) (RING_REGENERATION + random2(NUM_RINGS));
}
jewellery_type get_random_ring_type()
{
const jewellery_type j = get_raw_random_ring_type();
// Adjusted distribution here -- bwr
if ((j == RING_INVISIBILITY
|| j == RING_REGENERATION
|| j == RING_TELEPORT_CONTROL
|| j == RING_SLAYING)
&& !one_chance_in(3))
{
return get_raw_random_ring_type();
}
return (j);
}
armour_type get_random_body_armour_type(int item_level)
{
for (int tries = 100; tries > 0; --tries)
{
const armour_type tr = get_random_armour_type(item_level);
if (get_armour_slot(tr) == EQ_BODY_ARMOUR)
return (tr);
}
return (ARM_ROBE);
}
// FIXME: Need to clean up this mess.
armour_type get_random_armour_type(int item_level)
{
int armtype = random2(3);
if (random2(35) <= item_level + 10)
{
armtype = random2(5);
if (one_chance_in(4))
armtype = ARM_ANIMAL_SKIN;
}
if (random2(60) <= item_level + 10)
armtype = random2(8);
if (10 + item_level >= random2(400) && one_chance_in(20))
armtype = ARM_DRAGON_HIDE + random2(7);
if (10 + item_level >= random2(500) && one_chance_in(20))
{
armtype = ARM_STEAM_DRAGON_HIDE + random2(11);
if (armtype == ARM_ANIMAL_SKIN && one_chance_in(20))
armtype = ARM_CRYSTAL_PLATE_MAIL;
}
// secondary armours:
if (one_chance_in(5))
{
armtype = ARM_SHIELD + random2(5);
if (armtype == ARM_SHIELD) // 33.3%
{
if (coinflip())
armtype = ARM_BUCKLER; // 50.0%
else if (one_chance_in(3))
armtype = ARM_LARGE_SHIELD; // 16.7%
}
}
return static_cast<armour_type>(armtype);
}
#endif /* #if defined(WIN32CONSOLE) */
#endif /* #if defined(DOS) */
bool item_def::cursed() const
{
return (item_cursed(*this));
}
static std::string describe_favour_generic(god_type which_god)
{
std::string godname = god_name(which_god);
return (you.piety > 130) ? "A prized avatar of " + godname + ".":
(you.piety > 100) ? "A shining star in the eyes of " + godname + "." :
(you.piety > 70) ? "A rising star in the eyes of " + godname + "." :
(you.piety > 40) ? godname + " is most pleased with you." :
(you.piety > 20) ? godname + " has noted your presence." :
(you.piety > 5) ? godname + " is noncommittal."
: "You are beneath notice.";
}
if (player_under_penance()) //mv: penance check
{
cprintf( (you.penance[which_god] >= 50) ? "Godly wrath is upon you!" :
(you.penance[which_god] >= 20) ? "You've transgressed heavily! Be penitent!" :
(you.penance[which_god] >= 5 ) ? "You are under penance."
: "You should show more discipline." );
}
else
{
if (which_god == GOD_XOM)
cprintf("You are ignored.");
else
{
cprintf( (you.piety > 130) ? "A prized avatar of %s.":
(you.piety > 100) ? "A shining star in the eyes of %s." :
(you.piety > 70) ? "A rising star in the eyes of %s." :
(you.piety > 40) ? "%s is most pleased with you." :
(you.piety > 20) ? "%s has noted your presence." :
(you.piety > 5) ? "%s is noncommittal."
: "You are beneath %s's notice.",
god_name(which_god));
}
}
//end of favour
cprintf(describe_favour(which_god).c_str());
if (you.religion != GOD_XOM) // Xom doesn't care
{
text += god_prayer_reaction();
text += "\n";
}
text += god_prayer_reaction();
text += "\n";
// you can swap places with a friendly monster if you
// can see it and you're not confused
if (mons_friendly( mon ) && player_monster_visible( mon ) && !you.conf)
// you can swap places with a friendly monster if you're not confused
if (mons_friendly( mon ) && !you.conf)