summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-05-28 08:47:30 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-05-28 08:47:30 +0000
commit20a6609453ee2b51c388c296516c1abc1beab1d2 (patch)
tree201d735a3a4d66471005cb763078a6c05056752c /crawl-ref/source
parent7aed4c41d7fa0f9d70df56a82abbe69061e56269 (diff)
downloadcrawl-ref-20a6609453ee2b51c388c296516c1abc1beab1d2.tar.gz
crawl-ref-20a6609453ee2b51c388c296516c1abc1beab1d2.zip
Preliminary integration of Zooko's Xom patch (untested).
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1489 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/abl-show.cc2
-rw-r--r--crawl-ref/source/acr.cc13
-rw-r--r--crawl-ref/source/beam.cc6
-rw-r--r--crawl-ref/source/chardump.cc7
-rw-r--r--crawl-ref/source/debug.cc8
-rw-r--r--crawl-ref/source/decks.cc5
-rw-r--r--crawl-ref/source/defines.h4
-rw-r--r--crawl-ref/source/delay.cc5
-rw-r--r--crawl-ref/source/describe.cc60
-rw-r--r--crawl-ref/source/describe.h2
-rw-r--r--crawl-ref/source/dungeon.cc18
-rw-r--r--crawl-ref/source/effects.cc16
-rw-r--r--crawl-ref/source/enum.h12
-rw-r--r--crawl-ref/source/externs.h8
-rw-r--r--crawl-ref/source/fight.cc6
-rw-r--r--crawl-ref/source/files.cc4
-rw-r--r--crawl-ref/source/files.h2
-rw-r--r--crawl-ref/source/food.cc11
-rw-r--r--crawl-ref/source/hiscores.cc10
-rw-r--r--crawl-ref/source/hiscores.h2
-rw-r--r--crawl-ref/source/it_use2.cc9
-rw-r--r--crawl-ref/source/it_use3.cc8
-rw-r--r--crawl-ref/source/item_use.cc61
-rw-r--r--crawl-ref/source/itemprop.cc5
-rw-r--r--crawl-ref/source/itemprop.h3
-rw-r--r--crawl-ref/source/items.cc7
-rw-r--r--crawl-ref/source/libdos.cc4
-rw-r--r--crawl-ref/source/libw32c.cc4
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/makeitem.cc164
-rw-r--r--crawl-ref/source/makeitem.h5
-rw-r--r--crawl-ref/source/message.cc4
-rw-r--r--crawl-ref/source/misc.cc200
-rw-r--r--crawl-ref/source/misc.h2
-rw-r--r--crawl-ref/source/mon-util.cc22
-rw-r--r--crawl-ref/source/monstuff.cc59
-rw-r--r--crawl-ref/source/monstuff.h14
-rw-r--r--crawl-ref/source/mutation.cc178
-rw-r--r--crawl-ref/source/mutation.h9
-rw-r--r--crawl-ref/source/newgame.cc14
-rw-r--r--crawl-ref/source/notes.cc15
-rw-r--r--crawl-ref/source/ouch.cc91
-rw-r--r--crawl-ref/source/player.cc32
-rw-r--r--crawl-ref/source/player.h6
-rw-r--r--crawl-ref/source/religion.cc531
-rw-r--r--crawl-ref/source/religion.h27
-rw-r--r--crawl-ref/source/spells3.cc19
-rw-r--r--crawl-ref/source/spells3.h2
-rw-r--r--crawl-ref/source/spl-cast.cc10
-rw-r--r--crawl-ref/source/xom.cc844
50 files changed, 1704 insertions, 847 deletions
diff --git a/crawl-ref/source/abl-show.cc b/crawl-ref/source/abl-show.cc
index 116e8336a6..d8f50a7997 100644
--- a/crawl-ref/source/abl-show.cc
+++ b/crawl-ref/source/abl-show.cc
@@ -949,7 +949,7 @@ static bool do_ability(const ability_def& abil)
case ABIL_EVOKE_TELEPORTATION: // ring of teleportation
case ABIL_TELEPORTATION: // teleport mut
if (you.mutation[MUT_TELEPORT_AT_WILL] == 3)
- you_teleport2( true, true ); // instant and to new area of Abyss
+ you_teleport_now( true, true ); // instant and to new area of Abyss
else
you_teleport();
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index ea93668845..dfeaefb35c 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -659,7 +659,7 @@ static void handle_wizard_command( void )
break;
case 'X':
- Xom_acts(true, 20, true);
+ xom_acts(abs(you.piety - 100));
break;
case 'z':
@@ -1811,7 +1811,7 @@ static void decrement_durations()
else if (you.duration[DUR_TELEPORT] == 1)
{
// only to a new area of the abyss sometimes (for abyss teleports)
- you_teleport2( true, one_chance_in(5) );
+ you_teleport_now( true, one_chance_in(5) );
you.duration[DUR_TELEPORT] = 0;
}
@@ -2200,9 +2200,9 @@ static void world_reacts()
{
// this is instantaneous
if (player_teleport() > 0 && one_chance_in(100 / player_teleport()))
- you_teleport2( true );
+ you_teleport_now( true );
else if (you.level_type == LEVEL_ABYSS && one_chance_in(30))
- you_teleport2( false, true ); // to new area of the Abyss
+ you_teleport_now( false, true ); // to new area of the Abyss
}
if (env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD)
@@ -3053,9 +3053,8 @@ static void move_player(int move_x, int move_y)
{
struct monsters *mon = &menv[targ_monst];
- // 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)
{
if (swap_places( mon ))
swap = true;
diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc
index 476f566893..ef80105aab 100644
--- a/crawl-ref/source/beam.cc
+++ b/crawl-ref/source/beam.cc
@@ -2090,7 +2090,7 @@ void poison_monster( monsters *monster,
if (new_pois.degree > old_pois.degree)
{
simple_monster_message( monster,
- !old_pois.degree? " looks ill."
+ !old_pois.degree? " is poisoned."
: " looks even sicker." );
}
@@ -3711,7 +3711,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
if (check_mons_resist_magic( mon, beam.ench_power ))
return mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST;
- if (monster_polymorph(mon, RANDOM_MONSTER, 100))
+ if (monster_polymorph(mon, RANDOM_MONSTER))
beam.obvious_effect = true;
return (MON_AFFECTED);
@@ -3744,7 +3744,7 @@ static int affect_monster_enchantment(struct bolt &beam, struct monsters *mon)
if (check_mons_resist_magic( mon, beam.ench_power ))
return mons_immune_magic(mon) ? MON_UNAFFECTED : MON_RESIST;
- if (monster_polymorph(mon, MONS_PULSATING_LUMP, 100))
+ if (monster_polymorph(mon, MONS_PULSATING_LUMP))
beam.obvious_effect = true;
return (MON_AFFECTED);
diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc
index 9f807ede2b..d9ea019a87 100644
--- a/crawl-ref/source/chardump.cc
+++ b/crawl-ref/source/chardump.cc
@@ -542,11 +542,8 @@ static void sdump_religion(const std::string &, std::string & text)
if (!player_under_penance())
{
- if (you.religion != GOD_XOM) // Xom doesn't care
- {
- text += god_prayer_reaction();
- text += "\n";
- }
+ text += god_prayer_reaction();
+ text += "\n";
}
else
{
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index 87dd2c335d..a24e66a01a 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -1386,22 +1386,22 @@ void debug_get_religion(void)
if (specs[0] == '\0')
return;
- int god = -1;
+ god_type god = GOD_NO_GOD;
for (int i = 1; i < NUM_GODS; i++)
{
char name[80];
- strncpy( name, god_name(i), sizeof( name ) );
+ strncpy( name, god_name(static_cast<god_type>(i)), sizeof( name ) );
char *ptr = strstr( strlwr(name), strlwr(specs) );
if (ptr != NULL)
{
- god = i;
+ god = static_cast<god_type>(i);
break;
}
}
- if (god == -1)
+ if (god == GOD_NO_GOD)
mpr( "That god doesn't seem to be taking followers today." );
else
{
diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc
index 3e995593ae..1015ae6594 100644
--- a/crawl-ref/source/decks.cc
+++ b/crawl-ref/source/decks.cc
@@ -144,7 +144,6 @@ static card_type deck_of_punishment[] =
CARD_PANDEMONIUM
};
-#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0]))
#define DECK_WONDERS_SIZE ARRAYSIZE(deck_of_wonders)
#define DECK_SUMMONING_SIZE ARRAYSIZE(deck_of_summoning)
#define DECK_TRICKS_SIZE ARRAYSIZE(deck_of_tricks)
@@ -889,7 +888,7 @@ void card_effect(card_type which_card)
case CARD_TELEPORT_NOW:
mpr( "You have drawn the Portal of Instantaneous Transposition." );
- you_teleport2( true, true ); // in abyss, always to new area
+ you_teleport_now( true, true ); // in abyss, always to new area
break;
case CARD_RAGE:
@@ -913,7 +912,7 @@ void card_effect(card_type which_card)
case CARD_XOM:
mpr("You have drawn the card of Xom!");
- Xom_acts( true, 5 + random2( you.skills[SK_EVOCATIONS] ), true );
+ xom_acts( true, 5 + random2( you.skills[SK_EVOCATIONS] ));
break;
case CARD_SLOW:
diff --git a/crawl-ref/source/defines.h b/crawl-ref/source/defines.h
index c104ae7358..00bae84207 100644
--- a/crawl-ref/source/defines.h
+++ b/crawl-ref/source/defines.h
@@ -301,4 +301,8 @@
// it wants to be used in case labels.
#define CONTROL( xxx ) ((xxx) - 'A' + 1)
+#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0]))
+
+#define MIN(x, y) MINIMUM(x, y)
+
#endif
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index 45ccbcd05f..bf68aec5c8 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -35,6 +35,7 @@
#include "output.h"
#include "player.h"
#include "randart.h"
+#include "religion.h"
#include "spl-util.h"
#include "stuff.h"
#include "travel.h"
@@ -741,9 +742,11 @@ static void armour_wear_effects(const int item_slot)
if (is_random_artefact( arm ))
use_randart( item_slot );
- if (item_cursed( arm )) {
+ if (item_cursed( arm ))
+ {
mpr( "Oops, that feels deathly cold." );
learned_something_new(TUT_YOU_CURSED);
+ xom_is_stimulated(128);
}
if (eq_slot == EQ_SHIELD)
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 2d324c5853..e03fb32164 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -4940,18 +4940,43 @@ static bool print_god_abil_desc( int god, int numpower )
return true;
}
+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.";
+}
+
//---------------------------------------------------------------
//
// describe_god
//
-// Describes all gods. Accessible through altars (by praying), or
-// by the ^ key if player is a worshipper.
+// Describes the player's standing with his deity.
//
//---------------------------------------------------------------
-void describe_god( int which_god, bool give_title )
+std::string describe_favour(god_type which_god)
{
+ if (player_under_penance())
+ {
+ const int penance = you.penance[which_god];
+ return (penance >= 50) ? "Godly wrath is upon you!" :
+ (penance >= 20) ? "You've transgressed heavily! Be penitent!" :
+ (penance >= 5 ) ? "You are under penance."
+ : "You should show more discipline.";
+ }
+ return (which_god == GOD_XOM)?
+ describe_xom_favour() : describe_favour_generic(which_god);
+}
+
+void describe_god( god_type which_god, bool give_title )
+{
const char *description; // mv: tmp string used for printing description
int colour; // mv: colour used for some messages
@@ -5146,8 +5171,7 @@ void describe_god( int which_god, bool give_title )
break;
case GOD_XOM:
- cprintf( (you.experience_level >= 20) ? "Xom's favourite toy"
- : "Toy" );
+ cprintf("Toy");
break;
default:
@@ -5181,31 +5205,7 @@ void describe_god( int which_god, bool give_title )
}
else
{
- 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());
//mv: following code shows abilities given from god (if any)
textcolor(LIGHTGRAY);
diff --git a/crawl-ref/source/describe.h b/crawl-ref/source/describe.h
index e3ba32baf4..9c032f8e7e 100644
--- a/crawl-ref/source/describe.h
+++ b/crawl-ref/source/describe.h
@@ -36,7 +36,7 @@ std::string get_item_description( const item_def &item, bool verbose,
/* ***********************************************************************
* called from: acr - religion
* *********************************************************************** */
-void describe_god( int which_god, bool give_title );
+void describe_god( god_type which_god, bool give_title );
void describe_feature_wide(int x, int y);
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 99b621df93..c5538fcb7a 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -2439,7 +2439,7 @@ static void special_room(int level_number, spec_room &sr)
: OBJ_POTIONS); // 1 in 11
thing_created = items( 1, obj_type, OBJ_RANDOM, true,
- level_number * 3, 250 );
+ level_number * 3, MAKE_ITEM_RANDOM_RACE);
if (thing_created != NON_ITEM)
{
@@ -3458,9 +3458,9 @@ static int vault_grid( vault_placement &place,
|| vgrid == 'Z') ? MAKE_GOOD_ITEM :
(vgrid == '*') ? 5 + (level_number * 2)
: level_number);
-
+
item_made = items( 1, which_class, which_type, true,
- which_depth, spec );
+ which_depth, spec );
if (item_made != NON_ITEM)
{
@@ -3946,16 +3946,14 @@ void place_spec_shop( int level_number,
item_level = level_number + random2((level_number + 1) * 3);
}
- if (one_chance_in(4))
- item_level = MAKE_GOOD_ITEM;
-
// don't generate gold in shops! This used to be possible with
// General Stores (see item_in_shop() below) (GDL)
- while(true)
+ while (true)
{
const int subtype = representative? j : OBJ_RANDOM;
orb = items( 1, item_in_shop(env.shop[i].type), subtype, true,
- item_level, 250 );
+ one_chance_in(4)? MAKE_GOOD_ITEM : item_level,
+ MAKE_ITEM_RANDOM_RACE );
if (orb != NON_ITEM
&& mitm[orb].base_type != OBJ_GOLD
@@ -4781,7 +4779,7 @@ static void labyrinth_level(int level_number)
/* (temp_rand == 8) */ : OBJ_STAVES);
const int treasure_item = items( 1, glopop, OBJ_RANDOM, true,
- level_number * 3, 250 );
+ level_number * 3, MAKE_ITEM_RANDOM_RACE );
if (treasure_item != NON_ITEM)
{
@@ -5070,7 +5068,7 @@ static bool treasure_area(int level_number, unsigned char ta1_x,
continue;
item_made = items( 1, OBJ_RANDOM, OBJ_RANDOM, true,
- random2( level_number * 2 ), 250 );
+ random2( level_number * 2 ), MAKE_ITEM_RANDOM_RACE );
if (item_made != NON_ITEM)
{
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index a76041e600..fb59f24bd5 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -36,6 +36,7 @@
#include "ouch.h"
#include "player.h"
#include "randart.h"
+#include "religion.h"
#include "skills2.h"
#include "spells3.h"
#include "spells4.h"
@@ -154,7 +155,10 @@ void banished(int gate_type, const std::string &who)
down_stairs(true, you.your_level, gate_type); // heh heh
untag_followers(); // safety
-} // end banished()
+
+ if (gate_type == DNGN_ENTER_ABYSS || gate_type == DNGN_ENTER_PANDEMONIUM)
+ xom_is_stimulated(255);
+}
bool forget_spell(void)
{
@@ -297,9 +301,14 @@ void direct_effect(struct bolt &pbolt)
case DMNBM_BRAIN_FEED:
// lose_stat() must come last {dlb}
if (one_chance_in(3) && lose_stat(STAT_INTELLIGENCE, 1))
+ {
mpr("Something feeds on your intellect!");
+ xom_is_stimulated(50);
+ }
else
+ {
mpr("Something tries to feed on your intellect!");
+ }
break;
}
@@ -351,7 +360,7 @@ void mons_direct_effect(struct bolt &pbolt, int i)
else if (check_mons_resist_magic( monster, pbolt.ench_power ))
simple_monster_message(monster, " resists.");
else
- monster_polymorph(monster, RANDOM_MONSTER, 100);
+ monster_polymorph(monster, RANDOM_MONSTER);
break;
}
@@ -1138,12 +1147,11 @@ bool acquirement(object_class_type force_class, int agent)
else
{
randart_properties_t proprt;
-
for (int item_tries = 0; item_tries < 50; item_tries++)
{
// BCR - unique is now used for food quantity.
thing_created = items( unique, class_wanted, type_wanted, true,
- MAKE_GOOD_ITEM, 250 );
+ MAKE_GOOD_ITEM, 250 );
if (thing_created == NON_ITEM)
continue;
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index fd62ec96ba..3f930a509b 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -1532,7 +1532,9 @@ enum item_type_id_state_type // used for values in id[4][50]
enum jewellery_type
{
- RING_REGENERATION, // 0
+ RING_FIRST_RING = 0,
+
+ RING_REGENERATION = RING_FIRST_RING, // 0
RING_PROTECTION,
RING_PROTECTION_FROM_FIRE,
RING_POISON_RESISTANCE,
@@ -1556,7 +1558,12 @@ enum jewellery_type
RING_FIRE,
RING_ICE,
RING_TELEPORT_CONTROL, // 23
- AMU_RAGE = 35, // 35
+
+ NUM_RINGS, // 24, keep as last ring; can overlap
+ // safely with first amulet.
+
+ AMU_FIRST_AMULET = 35,
+ AMU_RAGE = AMU_FIRST_AMULET, // 35
AMU_RESIST_SLOW,
AMU_CLARITY,
AMU_WARDING,
@@ -1566,6 +1573,7 @@ enum jewellery_type
AMU_CONTROLLED_FLIGHT,
AMU_INACCURACY,
AMU_RESIST_MUTATION,
+
NUM_JEWELLERY
};
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index c0465f2f56..065a2961ca 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -154,7 +154,7 @@ public:
virtual void blink() = 0;
virtual void teleport(bool right_now = false, bool abyss_shift = false) = 0;
virtual void poison(actor *attacker, int amount = 1) = 0;
- virtual void sicken(int amount) = 0;
+ virtual bool sicken(int amount) = 0;
virtual void paralyse(int strength) = 0;
virtual void slow_down(int strength) = 0;
virtual void confuse(int strength) = 0;
@@ -434,6 +434,7 @@ public:
std::string name(description_level_type descrip,
bool terse = false, bool ident = false) const;
bool has_spells() const;
+ bool cursed() const;
int book_number() const;
void clear()
@@ -598,7 +599,6 @@ public:
unsigned int gold;
int char_class;
char class_name[30];
- // char speed; // now unused
int time_taken;
char shield_blocks; // number of shield blocks since last action
@@ -773,7 +773,7 @@ public:
int hunger_level() const { return hunger_state; }
void make_hungry(int nutrition, bool silent = true);
void poison(actor *agent, int amount = 1);
- void sicken(int amount);
+ bool sicken(int amount);
void paralyse(int str);
void slow_down(int str);
void confuse(int strength);
@@ -1018,7 +1018,7 @@ public:
int melee_evasion(const actor *attacker) const;
void poison(actor *agent, int amount = 1);
- void sicken(int strength);
+ bool sicken(int strength);
void paralyse(int str);
void slow_down(int str);
void confuse(int strength);
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 80decc8bd1..8eca25a856 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -450,7 +450,10 @@ bool melee_attack::attack()
identify_mimic(def);
if (attacker->fumbles_attack())
+ {
+ xom_is_stimulated(14); // Xom thinks that is funny.
return (false);
+ }
// Allow god to get offended, etc.
attacker->attacking(defender);
@@ -2077,6 +2080,9 @@ int melee_attack::player_to_hit(bool random_factor)
{
if (wpn_skill != SK_FIGHTING)
{
+ if (you.skills[wpn_skill] < 1 && player_in_a_dangerous_place())
+ xom_is_stimulated(14); // Xom thinks that is mildly amusing.
+
your_to_hit += maybe_random2(you.skills[wpn_skill] + 1,
random_factor);
}
diff --git a/crawl-ref/source/files.cc b/crawl-ref/source/files.cc
index 21dfb30a40..2aa69828d7 100644
--- a/crawl-ref/source/files.cc
+++ b/crawl-ref/source/files.cc
@@ -893,7 +893,7 @@ static void grab_followers(std::vector<follower>& followers)
}
}
-void load( int stair_taken, load_mode_type load_mode, bool was_a_labyrinth,
+bool load( int stair_taken, load_mode_type load_mode, bool was_a_labyrinth,
int old_level, branch_type old_branch )
{
std::vector<follower> followers;
@@ -1063,6 +1063,8 @@ void load( int stair_taken, load_mode_type load_mode, bool was_a_labyrinth,
save_level( you.your_level, you.level_type, you.where_are_you );
setup_environment_effects();
+
+ return just_created_level;
} // end load()
void save_level(int level_saved, level_area_type old_ltype,
diff --git a/crawl-ref/source/files.h b/crawl-ref/source/files.h
index 9ac67b5093..112e8e620f 100644
--- a/crawl-ref/source/files.h
+++ b/crawl-ref/source/files.h
@@ -45,7 +45,7 @@ std::string get_savedir_path(const std::string &shortpath);
std::string get_prefs_filename();
-void load( int stair_taken, load_mode_type load_mode, bool was_a_labyrinth,
+bool load( int stair_taken, load_mode_type load_mode, bool was_a_labyrinth,
int old_level, branch_type where_were_you2 );
// last updated 12may2000 {dlb}
diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc
index aa765649c9..dfb90d4591 100644
--- a/crawl-ref/source/food.cc
+++ b/crawl-ref/source/food.cc
@@ -739,27 +739,32 @@ static void eat_chunk( int chunk_effect )
case CE_MUTAGEN_RANDOM:
mpr("This meat tastes really weird.");
mutate(100);
+ xom_is_stimulated(100);
break;
case CE_MUTAGEN_BAD:
mpr("This meat tastes *really* weird.");
give_bad_mutation();
+ xom_is_stimulated(random2(200));
break;
case CE_HCL:
rot_player( 10 + random2(10) );
- disease_player( 50 + random2(100) );
+ if (disease_player( 50 + random2(100) ))
+ xom_is_stimulated(random2(100));
break;
case CE_POISONOUS:
mpr("Yeeuch - this meat is poisonous!");
- poison_player( 3 + random2(4) );
+ if (poison_player( 3 + random2(4) ))
+ xom_is_stimulated(random2(128));
break;
case CE_ROTTEN:
case CE_CONTAMINATED:
mpr("There is something wrong with this meat.");
- disease_player( 50 + random2(100) );
+ if (disease_player( 50 + random2(100) ))
+ xom_is_stimulated(random2(100));
break;
// note that this is the only case that takes time and forces redraw
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index 6def50115d..6dcaad88da 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -651,15 +651,15 @@ static level_area_type str_to_level_area_type(const std::string &s)
return (LEVEL_DUNGEON);
}
-static int str_to_god(const std::string &god)
+static god_type str_to_god(const std::string &god)
{
if (god.empty())
return GOD_NO_GOD;
for (int i = GOD_NO_GOD; i < NUM_GODS; ++i)
{
- if (god_name(i) == god)
- return (i);
+ if (god_name(static_cast<god_type>(i)) == god)
+ return (static_cast<god_type>(i));
}
return (GOD_NO_GOD);
}
@@ -898,7 +898,7 @@ bool scorefile_entry::parse_obsolete_scoreline(const std::string &line)
str = hs_nextint(inbuf);
intel = hs_nextint(inbuf);
dex = hs_nextint(inbuf);
- god = hs_nextint(inbuf);
+ god = static_cast<god_type>(hs_nextint(inbuf));
piety = hs_nextint(inbuf);
penance = hs_nextint(inbuf);
@@ -1014,7 +1014,7 @@ void scorefile_entry::reset()
intel = -1;
dex = -1;
damage = -1;
- god = -1;
+ god = GOD_NO_GOD;
piety = -1;
penance = -1;
wiz_mode = 0;
diff --git a/crawl-ref/source/hiscores.h b/crawl-ref/source/hiscores.h
index a586d5233c..8f2a8f25b5 100644
--- a/crawl-ref/source/hiscores.h
+++ b/crawl-ref/source/hiscores.h
@@ -109,7 +109,7 @@ public:
int str; // final str (useful for nickname)
int intel; // final int
int dex; // final dex (useful for nickname)
- int god; // god
+ god_type god; // god
int piety; // piety
int penance; // penance
char wiz_mode; // character used wiz mode
diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc
index 880eb276cc..9f9004a568 100644
--- a/crawl-ref/source/it_use2.cc
+++ b/crawl-ref/source/it_use2.cc
@@ -153,19 +153,23 @@ bool potion_effect( char pot_eff, int pow )
poison_player( ((pot_eff == POT_POISON) ? 1 + random2avg(5, 2)
: 3 + random2avg(13, 2)) );
+ xom_is_stimulated(128);
}
break;
case POT_SLOWING:
slow_player( 10 + random2(pow) );
+ xom_is_stimulated(64);
break;
case POT_PARALYSIS:
you.paralyse(2 + random2( 6 + you.paralysis ));
+ xom_is_stimulated(64);
break;
case POT_CONFUSION:
confuse_player( 3 + random2(8) );
+ xom_is_stimulated(128);
break;
case POT_INVISIBILITY:
@@ -193,6 +197,7 @@ bool potion_effect( char pot_eff, int pow )
case POT_DEGENERATION:
mpr("There was something very wrong with that liquid!");
lose_stat(STAT_RANDOM, 1 + random2avg(4, 2));
+ xom_is_stimulated(64);
break;
// Don't generate randomly - should be rare and interesting
@@ -200,7 +205,10 @@ bool potion_effect( char pot_eff, int pow )
if (you.is_undead)
mpr( "You feel terrible." );
else
+ {
rot_player( 10 + random2(10) );
+ xom_is_stimulated(64);
+ }
break;
case POT_WATER:
@@ -249,6 +257,7 @@ bool potion_effect( char pot_eff, int pow )
case POT_BERSERK_RAGE:
go_berserk(true);
+ xom_is_stimulated(64);
break;
case POT_CURE_MUTATION:
diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc
index 27368ee5e1..f0809dcb3e 100644
--- a/crawl-ref/source/it_use3.cc
+++ b/crawl-ref/source/it_use3.cc
@@ -822,18 +822,21 @@ void tome_of_power(char sc_read_2)
mpr("A cloud of weird smoke pours from the book's pages!");
big_cloud( random_smoke_type(), KC_YOU,
you.x_pos, you.y_pos, 20, 10 + random2(8) );
+ xom_is_stimulated(16);
return;
case 1:
case 14:
mpr("A cloud of choking fumes pours from the book's pages!");
big_cloud(CLOUD_POISON, KC_YOU,
you.x_pos, you.y_pos, 20, 7 + random2(5));
+ xom_is_stimulated(64);
return;
case 2:
case 13:
mpr("A cloud of freezing gas pours from the book's pages!");
big_cloud(CLOUD_COLD, KC_YOU, you.x_pos, you.y_pos, 20, 8 + random2(5));
+ xom_is_stimulated(64);
return;
case 5:
@@ -862,9 +865,9 @@ void tome_of_power(char sc_read_2)
beam.is_explosion = true;
explosion(beam);
+ xom_is_stimulated(255);
return;
-
case 10:
if (create_monster( MONS_ABOMINATION_SMALL, 6, BEH_HOSTILE,
you.x_pos, you.y_pos, MHITYOU, 250 ) != -1)
@@ -872,6 +875,7 @@ void tome_of_power(char sc_read_2)
mpr("A horrible Thing appears!");
mpr("It doesn't look too friendly.");
}
+ xom_is_stimulated(255);
return;
}
@@ -929,6 +933,7 @@ void skill_manual(char sc_read_2)
{
mpr("The book looks somewhat more worn.");
}
+ xom_is_stimulated(14);
} // end skill_manual()
static bool box_of_beasts(void)
@@ -963,6 +968,7 @@ static bool box_of_beasts(void)
you.x_pos, you.y_pos, MHITYOU, 250 ) != -1)
{
mpr("...and something leaps out!");
+ xom_is_stimulated(14);
ret = true;
}
}
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index ce71ead1b8..afb24beeb7 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -619,7 +619,10 @@ void wield_effects(int item_wield_2, bool showMsgs)
}
if (item_cursed( you.inv[item_wield_2] ))
+ {
mpr("It sticks to your hand!");
+ xom_is_stimulated(64);
+ }
}
if (showMsgs)
@@ -2096,6 +2099,7 @@ void jewellery_wear_effects(item_def &item)
mprf("Oops, that %s feels deathly cold.",
jewellery_is_amulet(item)? "amulet" : "ring");
learned_something_new(TUT_YOU_CURSED);
+ xom_is_stimulated(128);
}
// cursed or not, we know that since we've put the ring on
@@ -2552,7 +2556,9 @@ void zap_wand(void)
return;
}
- if (item_type_known( you.inv[item_slot] ))
+ const bool alreadyknown = item_type_known(you.inv[item_slot]);
+ const bool dangerous = player_in_a_dangerous_place();
+ if (alreadyknown)
{
if (you.inv[item_slot].sub_type == WAND_HASTING
|| you.inv[item_slot].sub_type == WAND_HEALING
@@ -2603,6 +2609,12 @@ void zap_wand(void)
type_zapped = ZAP_NEGATIVE_ENERGY;
if (one_chance_in(17))
type_zapped = ZAP_ENSLAVEMENT;
+ if (dangerous)
+ {
+ // Xom loves it when you use a Wand of Random Effects and
+ // there is a dangerous monster nearby...
+ xom_is_stimulated(256);
+ }
}
beam.source_x = you.x_pos;
@@ -2654,6 +2666,13 @@ void zap_wand(void)
exercise( SK_EVOCATIONS, 1 );
alert_nearby_monsters();
+ if (!alreadyknown && dangerous)
+ {
+ // Xom loves it when you use an unknown wand and there is a
+ // dangerous monster nearby...
+ xom_is_stimulated(256);
+ }
+
you.turn_is_over = true;
} // end zap_wand()
@@ -2727,6 +2746,14 @@ void drink(void)
return;
}
+ const bool alreadyknown = item_type_known(you.inv[item_slot]);
+
+ // The "> 1" part is to reduce the amount of times that Xom is
+ // stimulated when you are a low-level 1 trying your first unknown
+ // potions on monsters.
+ const bool dangerous =
+ player_in_a_dangerous_place() && (you.experience_level > 1);
+
if (potion_effect( you.inv[item_slot].sub_type, 40 ))
{
set_ident_flags( you.inv[item_slot], ISFLAG_IDENT_MASK );
@@ -2739,6 +2766,12 @@ void drink(void)
set_ident_type( you.inv[item_slot].base_type,
you.inv[item_slot].sub_type, ID_TRIED_TYPE );
}
+ if (!alreadyknown && dangerous)
+ {
+ // Xom loves it when you drink an unknown potion and there is
+ // a dangerous monster nearby...
+ xom_is_stimulated(256);
+ }
dec_inv_item_quantity( item_slot, 1 );
you.turn_is_over = true;
@@ -2796,6 +2829,9 @@ bool drink_fountain(void)
: POT_GAIN_INTELLIGENCE);//0.4%
}
+ if (fountain_effect != POT_WATER)
+ xom_is_stimulated(64);
+
potion_effect(fountain_effect, 100);
switch (grd[you.x_pos][you.y_pos])
@@ -3022,6 +3058,7 @@ bool enchant_weapon( int which_stat, bool quiet )
item.plus++;
}
+ xom_is_stimulated(16);
return (true);
}
@@ -3112,6 +3149,7 @@ static bool enchant_armour( void )
do_uncurse_item( item );
you.redraw_armour_class = 1;
+ xom_is_stimulated(16);
return (true);
}
@@ -3238,6 +3276,10 @@ void read_scroll(void)
// Actual removal of scroll done afterwards. -- bwr
}
+ bool alreadyknown = get_ident_type( OBJ_SCROLLS, you.inv[item_slot].sub_type ) == ID_KNOWN_TYPE;
+
+ bool dangerous = player_in_a_dangerous_place();
+
// scrolls of paper are also exempted from this handling {dlb}:
if (scroll_type != SCR_PAPER)
{
@@ -3531,6 +3573,13 @@ void read_scroll(void)
set_ident_type( OBJ_SCROLLS, scroll_type,
(id_the_scroll) ? ID_KNOWN_TYPE : ID_TRIED_TYPE );
+
+ if (!alreadyknown && dangerous)
+ {
+ // Xom loves it when you read an unknown scroll and there is
+ // a dangerous monster nearby...
+ xom_is_stimulated(256);
+ }
} // end read_scroll()
void examine_object(void)
@@ -3559,6 +3608,9 @@ void use_randart(const item_def &item)
{
ASSERT( is_random_artefact( item ) );
+ const bool alreadyknown = item_type_known(item);
+ const bool dangerous = player_in_a_dangerous_place();
+
randart_properties_t proprt;
randart_wpn_properties( item, proprt );
@@ -3575,4 +3627,11 @@ void use_randart(const item_def &item)
if (proprt[RAP_NOISES])
you.special_wield = 50 + proprt[RAP_NOISES];
+
+ if (!alreadyknown && dangerous)
+ {
+ // Xom loves it when you use an unknown random artifact and
+ // there is a dangerous monster nearby...
+ xom_is_stimulated(256);
+ }
}
diff --git a/crawl-ref/source/itemprop.cc b/crawl-ref/source/itemprop.cc
index 81437d49c1..593fcf8e37 100644
--- a/crawl-ref/source/itemprop.cc
+++ b/crawl-ref/source/itemprop.cc
@@ -934,6 +934,11 @@ equipment_type get_armour_slot( const item_def &item )
return (Armour_prop[ Armour_index[item.sub_type] ].slot);
}
+equipment_type get_armour_slot( armour_type arm )
+{
+ return (Armour_prop[ Armour_index[arm] ].slot);
+}
+
bool jewellery_is_amulet( const item_def &item )
{
ASSERT( item.base_type == OBJ_JEWELLERY );
diff --git a/crawl-ref/source/itemprop.h b/crawl-ref/source/itemprop.h
index 98c524b345..5c6ab77bd8 100644
--- a/crawl-ref/source/itemprop.h
+++ b/crawl-ref/source/itemprop.h
@@ -58,7 +58,8 @@ bool armour_is_hide( const item_def &item, bool inc_made = false );
bool armour_not_shiny( const item_def &item );
int armour_str_required( const item_def &arm );
-equipment_type get_armour_slot( const item_def &item );
+equipment_type get_armour_slot( const item_def &item );
+equipment_type get_armour_slot( armour_type arm );
bool jewellery_is_amulet( const item_def &item );
bool check_jewellery_size( const item_def &item, size_type size );
diff --git a/crawl-ref/source/items.cc b/crawl-ref/source/items.cc
index cdaf9f4d97..59b04c9161 100644
--- a/crawl-ref/source/items.cc
+++ b/crawl-ref/source/items.cc
@@ -1119,7 +1119,7 @@ std::string origin_desc(const item_def &item)
break;
default:
if (iorig > GOD_NO_GOD && iorig < NUM_GODS)
- desc += std::string(god_name(iorig))
+ desc += std::string(god_name(static_cast<god_type>(iorig)))
+ " gifted " + article_it(item) + " to you ";
else
// Bug really.
@@ -3044,3 +3044,8 @@ int item_def::book_number() const
base_type == OBJ_STAVES? sub_type + 40 :
-1);
}
+
+bool item_def::cursed() const
+{
+ return (item_cursed(*this));
+}
diff --git a/crawl-ref/source/libdos.cc b/crawl-ref/source/libdos.cc
index dc50480c38..2db3422868 100644
--- a/crawl-ref/source/libdos.cc
+++ b/crawl-ref/source/libdos.cc
@@ -12,6 +12,8 @@
#include <termios.h>
#include <conio.h>
+#if defined(DOS)
+
static bool cursor_is_enabled = true;
void init_libdos()
@@ -88,3 +90,5 @@ int get_number_of_cols()
{
return (80);
}
+
+#endif /* #if defined(DOS) */
diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc
index 3032b5602e..c111aa5251 100644
--- a/crawl-ref/source/libw32c.cc
+++ b/crawl-ref/source/libw32c.cc
@@ -1,3 +1,5 @@
+#if defined(WIN32CONSOLE)
+
/*
* File: libw32c.cc
* Summary: Functions for windows32 console mode support
@@ -977,3 +979,5 @@ int get_number_of_cols()
{
return (80);
}
+
+#endif /* #if defined(WIN32CONSOLE) */
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index f2ec8974e0..0316e1cb7f 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -75,6 +75,7 @@ transfor.o \
travel.o \
tutorial.o \
view.o \
+xom.o \
Kills.o \
mt19937ar.o \
clua.o
diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc
index c920c83325..6bd00913e7 100644
--- a/crawl-ref/source/makeitem.cc
+++ b/crawl-ref/source/makeitem.cc
@@ -844,6 +844,8 @@ int items( int allow_uniques, // not just true-false,
// item_race also gives type of rune!
const dgn_region_list &forbidden)
{
+ const bool make_good_item = (item_level == MAKE_GOOD_ITEM);
+
int temp_rand = 0; // probability determination {dlb}
int range_charges = 0; // for OBJ_WANDS charge count {dlb}
int loopy = 0; // just another loop variable {dlb}
@@ -864,7 +866,7 @@ int items( int allow_uniques, // not just true-false,
return (NON_ITEM);
// cap item_level unless an acquirement-level item {dlb}:
- if (item_level > 50 && item_level != MAKE_GOOD_ITEM)
+ if (item_level > 50 && !make_good_item)
item_level = 50;
// determine base_type for item generated {dlb}:
@@ -1037,7 +1039,7 @@ int items( int allow_uniques, // not just true-false,
ASSERT(!is_fixed_artefact(mitm[p]) && !is_random_artefact(mitm[p]));
- if (item_level == MAKE_GOOD_ITEM
+ if (make_good_item
&& force_type != OBJ_RANDOM
&& (mitm[p].sub_type == WPN_CLUB || mitm[p].sub_type == WPN_SLING))
{
@@ -1215,7 +1217,7 @@ int items( int allow_uniques, // not just true-false,
// if we allow acquirement-type items to be orcish, then
// there's a good chance that we'll just strip them of
// their ego type at the bottom of this function. -- bwr
- if (item_level == MAKE_GOOD_ITEM
+ if (make_good_item
&& get_equip_race( mitm[p] ) == ISFLAG_ORCISH)
{
set_equip_race( mitm[p], ISFLAG_NO_RACE );
@@ -1246,7 +1248,7 @@ int items( int allow_uniques, // not just true-false,
mitm[p].plus2 += race_plus2;
if ((random2(200) <= 50 + item_level
- || item_level == MAKE_GOOD_ITEM
+ || make_good_item
|| is_demonic(mitm[p]))
// nobody would bother enchanting a club
&& mitm[p].sub_type != WPN_CLUB
@@ -1258,7 +1260,7 @@ int items( int allow_uniques, // not just true-false,
do
{
if (random2(300) <= 100 + item_level
- || item_level == MAKE_GOOD_ITEM
+ || make_good_item
|| is_demonic( mitm[p] ))
{
// note: this doesn't guarantee special enchantment
@@ -1605,19 +1607,18 @@ int items( int allow_uniques, // not just true-false,
count++;
}
- while (item_level == MAKE_GOOD_ITEM
+ while (make_good_item
&& mitm[p].special == SPWPN_NORMAL
&& count < 5);
// if acquired item still not ego... enchant it up a bit.
- if (item_level == MAKE_GOOD_ITEM && mitm[p].special == SPWPN_NORMAL)
+ if (make_good_item && mitm[p].special == SPWPN_NORMAL)
{
mitm[p].plus += 2 + random2(3);
mitm[p].plus2 += 2 + random2(3);
}
- const int chance = (item_level == MAKE_GOOD_ITEM) ? 200
- : item_level;
+ const int chance = (make_good_item) ? 200 : item_level;
// odd-looking, but this is how the algorithm compacts {dlb}:
for (loopy = 0; loopy < 4; loopy++)
@@ -1767,7 +1768,7 @@ int items( int allow_uniques, // not just true-false,
else
{
// decide specials:
- if (item_level == MAKE_GOOD_ITEM)
+ if (make_good_item)
temp_rand = random2(150);
else
temp_rand = random2(2000 - 55 * item_level);
@@ -1816,42 +1817,7 @@ int items( int allow_uniques, // not just true-false,
mitm[p].sub_type = force_type;
else
{
- 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);
}
if (mitm[p].sub_type == ARM_HELMET)
@@ -2034,7 +2000,7 @@ int items( int allow_uniques, // not just true-false,
if (50 + item_level >= random2(250)
- || item_level == MAKE_GOOD_ITEM
+ || make_good_item
|| (mitm[p].sub_type == ARM_HELMET
&& get_helmet_type(mitm[p]) == THELM_WIZARD_HAT))
{
@@ -2044,7 +2010,7 @@ int items( int allow_uniques, // not just true-false,
mitm[p].plus += random2(3);
if (30 + item_level >= random2(350)
- && (item_level == MAKE_GOOD_ITEM
+ && (make_good_item
|| (!get_equip_race(mitm[p]) == ISFLAG_ORCISH
|| (mitm[p].sub_type <= ARM_PLATE_MAIL && coinflip()))))
{
@@ -2242,7 +2208,7 @@ int items( int allow_uniques, // not just true-false,
// Make sure you don't get a hide from acquirement (since that
// would be an enchanted item which somehow didn't get converted
// into armour).
- if (item_level == MAKE_GOOD_ITEM)
+ if (make_good_item)
hide2armour(mitm[p]); // what of animal hides? {dlb}
// skin armours + Crystal PM don't get special enchantments
@@ -2583,8 +2549,9 @@ int items( int allow_uniques, // not just true-false,
// otherwise, determine jewellery type {dlb}:
if (force_type == OBJ_RANDOM)
{
- mitm[p].sub_type = (!one_chance_in(4) ? random2(24) // rings
- : AMU_RAGE + random2(10));
+ mitm[p].sub_type =
+ (!one_chance_in(4) ? get_random_ring_type()
+ : get_random_amulet_type());
// Adjusted distribution here -- bwr
if ((mitm[p].sub_type == RING_INVISIBILITY
@@ -2826,10 +2793,16 @@ int items( int allow_uniques, // not just true-false,
default:
mitm[p].base_type = OBJ_GOLD;
- // 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)));
else
quant = 1 + random2avg(19, 2) + random2(item_level);
break;
@@ -3894,3 +3867,84 @@ void give_item(int mid, int level_number) //mv: cleanup+minor changes
give_ammo(mons, level_number, item_race);
give_armour(mons, 1 + level_number / 2);
} // end give_item()
+
+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);
+}
diff --git a/crawl-ref/source/makeitem.h b/crawl-ref/source/makeitem.h
index 62d0ee1db3..d74d572545 100644
--- a/crawl-ref/source/makeitem.h
+++ b/crawl-ref/source/makeitem.h
@@ -18,4 +18,9 @@ void item_colour( item_def &item );
void init_rod_mp(item_def &item);
void give_item(int mid, int level_number);
+jewellery_type get_random_ring_type();
+jewellery_type get_random_amulet_type();
+armour_type get_random_body_armour_type(int level);
+armour_type get_random_armour_type(int item_level);
+
#endif
diff --git a/crawl-ref/source/message.cc b/crawl-ref/source/message.cc
index 3c7b2f31f3..7b13d02917 100644
--- a/crawl-ref/source/message.cc
+++ b/crawl-ref/source/message.cc
@@ -226,8 +226,8 @@ int channel_to_colour( int channel, int param )
case MSGCH_GOD:
case MSGCH_PRAY:
ret = (Options.channels[ channel ] == MSGCOL_DEFAULT)
- ? god_colour( param )
- : god_message_altar_colour( param );
+ ? god_colour( static_cast<god_type>(param) )
+ : god_message_altar_colour( param );
break;
case MSGCH_DURATION:
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 45954cee16..fdae822b50 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -26,8 +26,9 @@
#include <io.h>
#endif
-#include <stdlib.h>
-#include <stdio.h>
+#include <cstdlib>
+#include <cstdio>
+#include <cmath>
#ifdef DOS
#include <conio.h>
@@ -984,7 +985,12 @@ void down_stairs( bool remove_stairs, int old_level, int force_stair )
break;
}
- load(stair_taken, LOAD_ENTER_LEVEL, was_a_labyrinth, old_level, old_where);
+ const bool newlevel =
+ load(stair_taken, LOAD_ENTER_LEVEL, was_a_labyrinth,
+ old_level, old_where);
+
+ if (newlevel)
+ xom_is_stimulated(49);
unsigned char pc = 0;
unsigned char pt = random2avg(28, 3);
@@ -1350,7 +1356,7 @@ void handle_traps(char trt, int i, bool trap_known)
if (scan_randarts(RAP_PREVENT_TELEPORTATION))
mpr("You feel a weird sense of stasis.");
else
- you_teleport2( true );
+ you_teleport_now( true );
break;
case TRAP_AMNESIA:
@@ -1843,8 +1849,8 @@ bool i_feel_safe(bool announce)
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 = 0;
- if ( ystart >= GYM ) yend = 0;
+ if ( xend >= GXM ) xend = GXM;
+ if ( ystart >= GYM ) yend = GYM;
if (in_bounds(you.x_pos, you.y_pos)
&& env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD)
@@ -1883,15 +1889,16 @@ bool i_feel_safe(bool announce)
{
if (announce)
mons.push_back(mon);
- else {
- tutorial_first_monster(*mon);
+ else
+ {
+ tutorial_first_monster(*mon);
return false;
+ }
}
}
}
}
}
- }
if (announce)
{
@@ -2055,6 +2062,112 @@ int player_branch_depth()
return subdungeon_depth(you.where_are_you, you.your_level);
}
+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);
+}
+
////////////////////////////////////////////////////////////////////////////
// Living breathing dungeon stuff.
//
@@ -2131,72 +2244,3 @@ void run_environment_effects()
}
}
}
-
-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;
- }
-}
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 6c82049174..0fa10e8421 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -201,4 +201,6 @@ int str_to_shoptype(const std::string &s);
bool do_autopray();
+bool player_in_a_dangerous_place();
+
#endif
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 0d74cba572..351ee05880 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -2361,10 +2361,14 @@ bool monsters::fumbles_attack(bool verbose)
{
if (floundering() && one_chance_in(4))
{
- if (verbose && !silenced(you.x_pos, you.y_pos)
- && !silenced(x, y))
+ if (verbose)
{
- 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.");
}
return (true);
}
@@ -3384,7 +3388,7 @@ void monsters::apply_enchantment(mon_enchant me, int spd)
if (type == MONS_GLOWING_SHAPESHIFTER
|| random2(1000) < mod_speed( 250, spd ))
{
- monster_polymorph(this, RANDOM_MONSTER, 0);
+ monster_polymorph(this, RANDOM_MONSTER, PPT_SAME);
}
break;
@@ -3392,7 +3396,7 @@ void monsters::apply_enchantment(mon_enchant me, int spd)
if (type == MONS_SHAPESHIFTER
|| random2(1000) < mod_speed( 1000 / ((15 * hit_dice) / 5), spd ))
{
- monster_polymorph(this, RANDOM_MONSTER, 0);
+ monster_polymorph(this, RANDOM_MONSTER, PPT_SAME);
}
break;
@@ -3479,10 +3483,10 @@ kill_category monsters::kill_alignment() const
return (attitude == ATT_FRIENDLY? KC_FRIENDLY : KC_OTHER);
}
-void monsters::sicken(int amount)
+bool monsters::sicken(int amount)
{
if (holiness() != MH_NATURAL || (amount /= 2) < 1)
- return;
+ return (false);
if (!has_ench(ENCH_SICK)
&& mons_near(this) && player_monster_visible(this))
@@ -3492,6 +3496,8 @@ void monsters::sicken(int amount)
}
add_ench(mon_enchant(ENCH_SICK, amount));
+
+ return (true);
}
int monsters::base_speed(int mcls)
@@ -3643,7 +3649,7 @@ void monsters::mutate()
if (holiness() != MH_NATURAL)
return;
- monster_polymorph(this, RANDOM_MONSTER, 100);
+ monster_polymorph(this, RANDOM_MONSTER);
}
bool monsters::is_icy() const
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index bedd380d1c..0923e8cb09 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
+#include <math.h>
#ifdef DOS
#include <conio.h>
@@ -375,7 +376,6 @@ void monster_die(monsters *monster, char killer, int i, bool silent)
if (monster->type == -1)
return;
- int xom_will_act = 0;
int monster_killed = monster_index(monster);
bool death_message =
!silent && mons_near(monster) && player_monster_visible(monster);
@@ -536,15 +536,6 @@ void monster_die(monsters *monster, char killer, int i, bool silent)
// killing triggers tutorial lesson
tutorial_inspect_kill();
- // 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
// prevent summoned creatures from being done_good kills,
// Only affects monsters friendly when created.
if (!created_friendly)
@@ -810,7 +801,7 @@ void monster_die(monsters *monster, char killer, int i, bool silent)
if (monster->type == MONS_SIMULACRUM_SMALL
|| monster->type == MONS_SIMULACRUM_LARGE)
{
- simple_monster_message( monster, " vaporizes!" );
+ simple_monster_message( monster, " vaporises!" );
place_cloud( CLOUD_COLD, monster->x, monster->y,
1 + random2(3), monster->kill_alignment() );
@@ -839,9 +830,6 @@ void monster_die(monsters *monster, char killer, int i, bool silent)
|| killer == KILL_YOU
|| pet_kill);
monster_cleanup(monster);
-
- if ( xom_will_act )
- Xom_acts(true, xom_will_act, false);
} // end monster_die
void monster_cleanup(monsters *monster)
@@ -1013,23 +1001,46 @@ static bool valid_morph( monsters *monster, int new_mclass )
return (monster_habitable_grid(new_mclass, current_tile));
} // end valid_morph()
-// 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 )
{
std::string str_polymon;
int source_power, target_power, relax;
int tries = 1000;
- UNUSED( power );
-
// Used to be mons_power, but that just returns hit_dice
// for the monster class. By using the current hit dice
// the player gets the opportunity to use draining more
// effectively against shapeshifters. -- bwr
source_power = monster->hit_dice;
- relax = 2;
+ relax = 1;
if (targetc == RANDOM_MONSTER)
{
@@ -1044,15 +1055,15 @@ bool monster_polymorph( monsters *monster, int targetc, int power )
target_power = mons_power( targetc );
- if (one_chance_in(100))
+ if (one_chance_in(200))
relax++;
if (relax > 50)
return (simple_monster_message( monster, " shudders." ));
}
while (tries-- && (!valid_morph( monster, targetc )
- || target_power < source_power - relax
- || target_power > source_power + (relax * 3) / 2));
+ || is_poly_power_unsuitable(power, source_power,
+ target_power, relax)));
}
if (!valid_morph( monster, targetc ))
diff --git a/crawl-ref/source/monstuff.h b/crawl-ref/source/monstuff.h
index cc308c6a77..ec98dbb277 100644
--- a/crawl-ref/source/monstuff.h
+++ b/crawl-ref/source/monstuff.h
@@ -14,6 +14,7 @@
#ifndef MONSTUFF_H
#define MONSTUFF_H
+#include "mon-util.h"
// useful macro
#define SAME_ATTITUDE(x) (mons_friendly(x)?BEH_FRIENDLY:BEH_HOSTILE)
@@ -33,12 +34,13 @@ int get_mimic_colour( const monsters *mimic );
* *********************************************************************** */
void alert_nearby_monsters(void);
-
-// 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);
// last updated: 08jun2000 {dlb}
/* ***********************************************************************
diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc
index 81aec01c2f..8db09cdc25 100644
--- a/crawl-ref/source/mutation.cc
+++ b/crawl-ref/source/mutation.cc
@@ -40,6 +40,7 @@
#include "notes.h"
#include "ouch.h"
#include "player.h"
+#include "religion.h"
#include "skills2.h"
#include "stuff.h"
#include "transfor.h"
@@ -1149,27 +1150,68 @@ void display_mutations()
getch();
}
-bool mutate(int which_mutation, bool failMsg)
+static int calc_mutation_amusement_value(int which_mutation)
{
- 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]);
- if (which_mutation >= 2000)
+ switch (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 (which_mutation >= 1000) // must give mutation without failure
- {
+ return (amusement);
+}
+
+bool mutate(int which_mutation, bool failMsg, bool force_mutation,
+ bool demonspawn)
+{
+ int mutat = which_mutation;
+
+ if (demonspawn)
force_mutation = true;
- mutat -= 1000;
- which_mutation -= 1000;
- }
// Undead bodies don't mutate, they fall apart. -- bwr
// except for demonspawn (or other permamutations) in lichform -- haranp
@@ -1241,10 +1283,42 @@ bool mutate(int which_mutation, bool failMsg)
|| you.mutation[mutat] > 13
|| random2(10) >= mutation_rarity[mutat] + you.demon_pow[mutat]);
}
+ else if (which_mutation == 101)
+ {
+ do
+ {
+ mutat = random2(NUM_MUTATIONS);
- 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))
{
return false;
}
@@ -1272,7 +1346,7 @@ bool mutate(int which_mutation, bool failMsg)
mutat = MUT_BREATHE_POISON;
// breathe poison replaces spit poison (so it takes the slot)
- for (i = 0; i < 52; i++)
+ for (int i = 0; i < 52; i++)
{
if (you.ability_letter_table[i] == ABIL_SPIT_POISON)
you.ability_letter_table[i] = ABIL_BREATHE_POISON;
@@ -1461,14 +1535,13 @@ bool mutate(int which_mutation, bool failMsg)
mpr(gain_mutation[mutat][you.mutation[mutat]], MSGCH_MUTATION);
break;
-
case MUT_HOOVES: //jmf: like horns
mpr(gain_mutation[mutat][you.mutation[mutat]], MSGCH_MUTATION);
if (you.equip[EQ_BOOTS] != -1)
{
FixedVector < char, 8 > removed;
- for (i = EQ_WEAPON; i < EQ_RIGHT_RING; i++)
+ for (int i = EQ_WEAPON; i < EQ_RIGHT_RING; i++)
{
removed[i] = 0;
}
@@ -1489,7 +1562,7 @@ bool mutate(int which_mutation, bool failMsg)
{
FixedVector < char, 8 > removed;
- for (i = EQ_WEAPON; i < EQ_RIGHT_RING; i++)
+ for (int i = EQ_WEAPON; i < EQ_RIGHT_RING; i++)
{
removed[i] = 0;
}
@@ -1512,7 +1585,7 @@ bool mutate(int which_mutation, bool failMsg)
FixedVector < char, 8 > removed;
- for (i = EQ_WEAPON; i < EQ_RIGHT_RING; i++)
+ for (int i = EQ_WEAPON; i < EQ_RIGHT_RING; i++)
{
removed[i] = 0;
}
@@ -1605,10 +1678,14 @@ bool mutate(int which_mutation, bool failMsg)
you.mutation[mutat]++;
+ /* amusement value will be 16 * (11-rarity) * Xom's-sense-of-humor */
+ int amusementvalue = calc_mutation_amusement_value(mutat);
+ xom_is_stimulated(amusementvalue);
+
take_note(Note(NOTE_GET_MUTATION, mutat, you.mutation[mutat]));
/* remember, some mutations don't get this far (eg frail) */
return true;
-} // end mutation()
+}
int how_mutated(void)
{
@@ -1659,8 +1736,10 @@ bool delete_mutation(int which_mutation)
return false;
}
while ((you.mutation[mutat] == 0
- && (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))
|| random2(10) >= mutation_rarity[mutat]
|| you.demon_pow[mutat] >= you.mutation[mutat]);
}
@@ -2191,13 +2270,13 @@ bool perma_mutate(int which_mut, char how_much)
{
char levels = 0;
- if (mutate(which_mut + 2000))
+ if (mutate(which_mut, false, true, true))
levels++;
- if (how_much >= 2 && mutate(which_mut + 2000))
+ if (how_much >= 2 && mutate(which_mut, false, true, true))
levels++;
- if (how_much >= 3 && mutate(which_mut + 2000))
+ if (how_much >= 3 && mutate(which_mut, false, true, true))
levels++;
you.demon_pow[which_mut] = levels;
@@ -2205,42 +2284,6 @@ bool perma_mutate(int which_mut, char how_much)
return (levels > 0);
} // end perma_mutate()
-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);
-
- return (mutate(which_good_one, failMsg));
-} // end give_good_mutation()
-
bool give_bad_mutation(bool forceMutation, bool failMsg)
{
int temp_rand = 0; // probability determination {dlb}
@@ -2261,10 +2304,7 @@ bool give_bad_mutation(bool forceMutation, bool failMsg)
(temp_rand == 1) ? MUT_BLURRY_VISION
: MUT_FRAIL);
- if (forceMutation)
- which_bad_one += 1000;
-
- return (mutate(which_bad_one), failMsg);
+ return mutate(which_bad_one, failMsg, forceMutation);
} // end give_bad_mutation()
//jmf: might be useful somewhere (eg Xom or transmigration effect)
diff --git a/crawl-ref/source/mutation.h b/crawl-ref/source/mutation.h
index 771db44c6a..f7f2b27d93 100644
--- a/crawl-ref/source/mutation.h
+++ b/crawl-ref/source/mutation.h
@@ -22,7 +22,8 @@
* called from: acr - decks - effects - fight - food - it_use2 - items -
* mutation - religion - spell - spells
* *********************************************************************** */
-bool mutate(int which_mutation, bool failMsg = true);
+bool mutate(int which_mutation, bool failMsg = true,
+ bool force_mutation = false, bool demonspawn = false);
// last updated 12may2000 {dlb}
@@ -51,12 +52,6 @@ const char *mutation_name( int which_mutat, int level = -1 );
// last updated 12may2000 {dlb}
/* ***********************************************************************
- * called from: religion
- * *********************************************************************** */
-bool give_good_mutation( bool failMsg = true );
-
-// last updated 12may2000 {dlb}
-/* ***********************************************************************
* called from: items - religion
* *********************************************************************** */
bool give_cosmetic_mutation( void );
diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc
index 4d5f9b1a99..9664539d70 100644
--- a/crawl-ref/source/newgame.cc
+++ b/crawl-ref/source/newgame.cc
@@ -4571,7 +4571,6 @@ void give_items_skills()
break;
case JOB_CHAOS_KNIGHT:
- you.piety = 25; // irrelevant for Xom, of course
you.inv[0].quantity = 1;
you.inv[0].base_type = OBJ_WEAPONS;
you.inv[0].sub_type = WPN_SHORT_SWORD;
@@ -4665,9 +4664,20 @@ void give_items_skills()
}
if (you.religion == GOD_XOM)
+ {
you.skills[SK_FIGHTING]++;
- 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;
you.skills[SK_INVOCATIONS] = 2;
+ }
break;
diff --git a/crawl-ref/source/notes.cc b/crawl-ref/source/notes.cc
index 9fe1b9e0b3..3ea3d44edc 100644
--- a/crawl-ref/source/notes.cc
+++ b/crawl-ref/source/notes.cc
@@ -255,16 +255,20 @@ std::string Note::describe( bool when, bool where, bool what ) const
<< spell_title(static_cast<spell_type>(first));
break;
case NOTE_GET_GOD:
- result << "Became a worshipper of " << god_name(first, true);
+ result << "Became a worshipper of "
+ << god_name(static_cast<god_type>(first), true);
break;
case NOTE_LOSE_GOD:
- result << "Fell from the grace of " << god_name(first);
+ result << "Fell from the grace of "
+ << god_name(static_cast<god_type>(first));
break;
case NOTE_MOLLIFY_GOD:
- result << "Was forgiven by " << god_name(first);
+ result << "Was forgiven by "
+ << god_name(static_cast<god_type>(first));
break;
case NOTE_GOD_GIFT:
- result << "Received a gift from " << god_name(first);
+ result << "Received a gift from "
+ << god_name(static_cast<god_type>(first));
break;
case NOTE_ID_ITEM:
result << "Identified " << name;
@@ -288,7 +292,8 @@ std::string Note::describe( bool when, bool where, bool what ) const
result << name << " changed form";
break;
case NOTE_GOD_POWER:
- result << "Acquired " << god_name(first) << "'s "
+ result << "Acquired "
+ << god_name(static_cast<god_type>(first)) << "'s "
<< number_to_ordinal(real_god_power(first, second)+1)
<< " power";
break;
diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc
index 0c3721f596..ae8d6b7c84 100644
--- a/crawl-ref/source/ouch.cc
+++ b/crawl-ref/source/ouch.cc
@@ -62,7 +62,9 @@
#include "itemprop.h"
#include "items.h"
#include "macro.h"
+#include "misc.h"
#include "mon-util.h"
+#include "monstuff.h"
#include "notes.h"
#include "player.h"
#include "randart.h"
@@ -126,6 +128,7 @@ int check_your_resists(int hurted, int flavour)
else if (resist < 0)
{
mpr("It burns terribly!");
+ xom_is_stimulated(200);
hurted *= 15;
hurted /= 10;
}
@@ -141,6 +144,7 @@ int check_your_resists(int hurted, int flavour)
else if (resist < 0)
{
mpr("You feel a terrible chill!");
+ xom_is_stimulated(200);
hurted *= 15;
hurted /= 10;
}
@@ -213,6 +217,7 @@ int check_your_resists(int hurted, int flavour)
else if (resist < 0)
{
mpr("You feel a painful chill!");
+ xom_is_stimulated(200);
hurted *= 13;
hurted /= 10;
}
@@ -229,6 +234,7 @@ int check_your_resists(int hurted, int flavour)
else if (resist < 0)
{
mpr("It burns terribly!");
+ xom_is_stimulated(200);
hurted *= 15;
hurted /= 10;
}
@@ -420,6 +426,7 @@ void item_corrode( int itco )
if (!it_resists)
{
how_rusty--;
+ xom_is_stimulated(64);
if (item.base_type == OBJ_WEAPONS)
item.plus2 = how_rusty;
@@ -538,6 +545,8 @@ static void expose_invent_to_element( beam_type flavour, int strength )
(num_dest > 1) ? "were" : "was" );
break;
}
+
+ xom_is_stimulated((num_dest > 1) ? 32 : 16);
}
}
@@ -602,6 +611,7 @@ void lose_level(void)
take_note(Note(NOTE_XP_LEVEL_CHANGE, you.experience_level, 0, buf));
you.redraw_experience = 1;
+ xom_is_stimulated(255);
} // end lose_level()
void drain_exp(void)
@@ -646,6 +656,7 @@ void drain_exp(void)
if (exp_drained > 0)
{
mpr("You feel drained.");
+ xom_is_stimulated(20);
you.experience -= exp_drained;
you.exp_available -= exp_drained;
@@ -663,6 +674,60 @@ void drain_exp(void)
}
} // end drain_exp()
+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);
+}
+
// death_source should be set to zero for non-monsters {dlb}
void ouch( int dam, int death_source, kill_method_type death_type,
const char *aux )
@@ -688,15 +753,6 @@ void ouch( int dam, int death_source, kill_method_type death_type,
{
switch (you.religion)
{
- case GOD_XOM:
- if (random2(you.hp_max) > you.hp && dam > random2(you.hp)
- && one_chance_in(5))
- {
- simple_god_message( " protects you from harm!" );
- return;
- }
- break;
-
case GOD_ZIN:
case GOD_SHINING_ONE:
case GOD_ELYVILON:
@@ -718,13 +774,20 @@ void ouch( int dam, int death_source, kill_method_type death_type,
// Even if we have low HP messages off, we'll still give a
// big hit warning (in this case, a hit for half our HPs) -- bwr
if (dam > 0 && you.hp_max <= dam * 2)
- mpr( "Ouch! That really hurt!", MSGCH_DANGER );
+ mpr( "Ouch! That really hurt!", MSGCH_DANGER );
- if (you.hp > 0 && Options.hp_warning
- && you.hp <= (you.hp_max * Options.hp_warning) / 100)
+ if (you.hp > 0)
{
- 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;
}
+
take_note(
Note(
NOTE_HP_CHANGE,
@@ -734,8 +797,6 @@ void ouch( int dam, int death_source, kill_method_type death_type,
.death_description(scorefile_entry::DDV_TERSE)
.c_str()) );
- if (you.hp > 0)
- return;
}
#ifdef WIZARD
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index b6eefa1aee..ccb9e67f32 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -2792,9 +2792,8 @@ void level_change(void)
you.hp, you.hp_max, you.magic_points, you.max_magic_points);
take_note(Note(NOTE_XP_LEVEL_CHANGE, you.experience_level, 0, buf));
- if (you.religion == GOD_XOM)
- Xom_acts(true, you.experience_level, true);
-
+ xom_is_stimulated(16);
+
learned_something_new(TUT_NEW_LEVEL);
}
@@ -4221,10 +4220,10 @@ void contaminate_player(int change, bool statusOnly)
(change > 0) ? "more" : "less" );
}
-void poison_player( int amount, bool force )
+bool poison_player( int amount, bool force )
{
if ((!force && player_res_poison()) || amount <= 0)
- return;
+ return false;
const int old_value = you.poisoning;
you.poisoning += amount;
@@ -4238,6 +4237,7 @@ void poison_player( int amount, bool force )
mprf("You are %spoisoned.", (old_value > 0) ? "more " : "" );
learned_something_new(TUT_YOU_POISON);
}
+ return true;
}
void reduce_poison_player( int amount )
@@ -4280,6 +4280,8 @@ void confuse_player( int amount, bool resistable )
// XXX: which message channel for this message?
mprf("You are %sconfused.", (old_value > 0) ? "more " : "" );
learned_something_new(TUT_YOU_ENCHANTED);
+
+ xom_is_stimulated(you.conf - old_value);
}
}
@@ -4392,9 +4394,9 @@ void dec_haste_player( void )
}
}
-void disease_player( int amount )
+bool disease_player( int amount )
{
- you.sicken(amount);
+ return you.sicken(amount);
}
void dec_disease_player( void )
@@ -5111,7 +5113,7 @@ void player::blink()
void player::teleport(bool now, bool abyss_shift)
{
if (now)
- you_teleport2(true, abyss_shift);
+ you_teleport_now(true, abyss_shift);
else
you_teleport();
}
@@ -5127,12 +5129,6 @@ void player::hurt(const actor *agent, int amount)
ASSERT(false);
ouch(amount, 0, KILLED_BY_SOMETHING);
}
-
- if (religion == GOD_XOM && hp <= hp_max / 3
- && one_chance_in(10))
- {
- Xom_acts(true, experience_level, false);
- }
}
void player::drain_stat(int stat, int amount)
@@ -5196,16 +5192,18 @@ kill_category player::kill_alignment() const
return (KC_YOU);
}
-void player::sicken(int amount)
+bool player::sicken(int amount)
{
if (is_undead || amount <= 0)
- return;
+ return (false);
mpr( "You feel ill." );
const int tmp = disease + amount;
disease = (tmp > 210) ? 210 : tmp;
- learned_something_new(TUT_YOU_SICK);
+ learned_something_new(TUT_YOU_SICK);
+
+ return (true);
}
bool player::can_see_invisible() const
diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h
index 9a578f4d7a..2fab29c4a6 100644
--- a/crawl-ref/source/player.h
+++ b/crawl-ref/source/player.h
@@ -386,7 +386,8 @@ const char *get_class_name( int which_job );
* *********************************************************************** */
void contaminate_player(int change, bool statusOnly = false);
-void poison_player( int amount, bool force = false );
+/* @return true iff they were poisoned (false if they are immune) */
+bool poison_player( int amount, bool force = false );
void reduce_poison_player( int amount );
void confuse_player( int amount, bool resistable = true );
@@ -398,7 +399,8 @@ void dec_slow_player();
void haste_player( int amount );
void dec_haste_player();
-void disease_player( int amount );
+/* return true iff they were diseased */
+bool disease_player( int amount );
void dec_disease_player();
void rot_player( int amount );
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 8701400c2a..a88c6081b0 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -50,6 +50,7 @@
#include "makeitem.h"
#include "misc.h"
#include "monplace.h"
+#include "monstuff.h"
#include "mutation.h"
#include "newgame.h"
#include "notes.h"
@@ -66,7 +67,8 @@
#include "tutorial.h"
#include "view.h"
-const char *sacrifice[] = {
+const char *sacrifice[] =
+{
// Zin
" glows silver and disappears.",
// TSO
@@ -257,7 +259,7 @@ const char* god_lose_power_messages[MAX_NUM_GODS][MAX_GOD_ABILITIES] =
void altar_prayer(void);
void dec_penance(int god, int val);
-void divine_retribution(int god);
+void divine_retribution(god_type god);
void inc_penance(int god, int val);
void inc_penance(int val);
@@ -279,7 +281,7 @@ static bool is_good_god(god_type god)
god == GOD_ELYVILON;
}
-void dec_penance(int god, int val)
+void dec_penance(god_type god, int val)
{
if (you.penance[god] > 0)
{
@@ -419,7 +421,7 @@ static void do_god_gift()
&& !grid_destroys_items(grd[you.x_pos][you.y_pos]))
{
int thing_created = NON_ITEM;
- unsigned char gift_type = MISC_DECK_OF_TRICKS;
+ int gift_type = MISC_DECK_OF_TRICKS;
if (random2(200) <= you.piety && one_chance_in(4))
gift_type = MISC_DECK_OF_SUMMONINGS;
@@ -429,7 +431,7 @@ static void do_god_gift()
gift_type = MISC_DECK_OF_POWER;
thing_created = items( 1, OBJ_MISCELLANY, gift_type,
- true, 1, 250 );
+ true, 1, MAKE_ITEM_RANDOM_RACE );
if (thing_created != NON_ITEM)
{
@@ -500,7 +502,7 @@ static void do_god_gift()
int thing_called = random_undead_servant(GOD_YREDELEMNUL);
if (create_monster( thing_called, 0, BEH_FRIENDLY,
you.x_pos, you.y_pos,
- you.pet_target, 250 ) != -1)
+ you.pet_target, MAKE_ITEM_RANDOM_RACE ) != -1)
{
simple_god_message(" grants you an undead servant!");
more();
@@ -567,7 +569,8 @@ static void do_god_gift()
success = acquirement(OBJ_BOOKS, you.religion);
else
{
- int thing_created = items(1, OBJ_BOOKS, gift, true, 1, 250);
+ int thing_created = items(1, OBJ_BOOKS, gift, true, 1,
+ MAKE_ITEM_RANDOM_RACE);
if (thing_created == NON_ITEM)
return;
@@ -684,26 +687,7 @@ void pray()
}
else if (you.religion == GOD_XOM)
{
- 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 ));
-
- // and he's not very nice even then
- int sever = (nice) ? random2( random2( you.experience_level ) )
- : you.experience_level;
-
- // bad results are enforced, good are not
- bool force = !nice;
-
- Xom_acts( nice, 1 + sever, force );
- }
- else
- mpr("Xom ignores you.");
+ mpr("Xom ignores you.");
return;
}
@@ -743,7 +727,7 @@ void pray()
do_god_gift();
} // end pray()
-char *god_name( int which_god, bool long_name ) // mv - rewritten
+const char *god_name( god_type which_god, bool long_name ) // mv - rewritten
{
static char godname_buff[80];
@@ -873,405 +857,11 @@ char *god_name( int which_god, bool long_name ) // mv - rewritten
return (godname_buff);
} // end god_name()
-void god_speaks( int god, const char *mesg )
+void god_speaks( god_type god, const char *mesg )
{
mpr( mesg, MSGCH_GOD, god );
} // end god_speaks()
-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()
-
// This function is the merger of done_good() and naughty().
// Returns true if god was interested (good or bad) in conduct.
bool did_god_conduct( int thing_done, int level )
@@ -1674,8 +1264,12 @@ bool did_god_conduct( int thing_done, int level )
return (ret);
}
-void gain_piety(char pgn)
+void gain_piety(int pgn)
{
+ // Xom uses piety differently...
+ if (you.religion == GOD_XOM)
+ return;
+
// check to see if we owe anything first
if (you.penance[you.religion] > 0)
{
@@ -1750,7 +1344,7 @@ void gain_piety(char pgn)
do_god_gift();
}
-void lose_piety(char pgn)
+void lose_piety(int pgn)
{
int old_piety = you.piety;
@@ -1791,7 +1385,7 @@ void lose_piety(char pgn)
}
}
-static void lugonu_retribution(int god)
+static void lugonu_retribution(god_type god)
{
if (coinflip())
{
@@ -1806,7 +1400,7 @@ static void lugonu_retribution(int god)
simple_god_message("'s wrath finds you!", god);
mpr("Space warps around you!");
if (!one_chance_in(3))
- you_teleport2(false);
+ you_teleport_now(false);
else
random_blink(false);
@@ -1848,7 +1442,7 @@ static void lugonu_retribution(int god)
}
}
-void divine_retribution( int god )
+void divine_retribution( god_type god )
{
ASSERT(god != GOD_NO_GOD);
@@ -1874,14 +1468,8 @@ void divine_retribution( int god )
switch (god)
{
case GOD_XOM:
- {
- // 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));
break;
case GOD_SHINING_ONE:
@@ -2343,7 +1931,7 @@ void divine_retribution( int god )
void excommunication(void)
{
- const int old_god = you.religion;
+ const god_type old_god = you.religion;
take_note(Note(NOTE_LOSE_GOD, old_god));
@@ -2358,7 +1946,7 @@ void excommunication(void)
switch (old_god)
{
case GOD_XOM:
- Xom_acts( false, (you.experience_level * 2), true );
+ xom_acts( false, abs(you.piety - 100) * 2);
inc_penance( old_god, 50 );
break;
@@ -2613,7 +2201,7 @@ void offer_items()
}
}
-void god_pitch(unsigned char which_god)
+void god_pitch(god_type which_god)
{
mprf("You kneel at the altar of %s.", god_name(which_god));
more();
@@ -2660,8 +2248,19 @@ void god_pitch(unsigned char which_god)
//jmf: moved up so god_speaks gives right colour
you.religion = static_cast<god_type>(which_god);
- 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;
+ }
+
set_god_ability_slots(); // remove old god's slots, reserve new god's
#ifdef DGL_WHEREIS
whereis_record();
@@ -2742,7 +2341,7 @@ void handle_god_time(void)
// why we do it this way... it requires only one pass and doesn't
// require an array.
- int which_god = GOD_NO_GOD;
+ god_type which_god = GOD_NO_GOD;
unsigned int count = 0;
for (int i = GOD_NO_GOD; i < NUM_GODS; i++)
@@ -2751,7 +2350,7 @@ void handle_god_time(void)
{
count++;
if (one_chance_in(count))
- which_god = i;
+ which_god = static_cast<god_type>(i);
}
}
@@ -2765,9 +2364,47 @@ void handle_god_time(void)
switch (you.religion)
{
case GOD_XOM:
- 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));
+ }
break;
+ }
case GOD_ZIN: // These gods like long-standing worshippers
case GOD_ELYVILON:
@@ -2831,7 +2468,7 @@ void handle_god_time(void)
} // end handle_god_time()
// yet another wrapper for mpr() {dlb}:
-void simple_god_message(const char *event, int which_deity)
+void simple_god_message(const char *event, god_type which_deity)
{
char buff[ INFO_SIZE ];
@@ -2843,7 +2480,7 @@ void simple_god_message(const char *event, int which_deity)
god_speaks( which_deity, buff );
}
-char god_colour( char god ) //mv - added
+int god_colour( god_type god ) //mv - added
{
switch (god)
{
diff --git a/crawl-ref/source/religion.h b/crawl-ref/source/religion.h
index 5272a1383e..02c85d2494 100644
--- a/crawl-ref/source/religion.h
+++ b/crawl-ref/source/religion.h
@@ -16,24 +16,33 @@
#include "enum.h"
-void simple_god_message( const char *event, int which_deity = GOD_NO_GOD );
+void simple_god_message( const char *event, god_type which_deity = GOD_NO_GOD );
int piety_breakpoint(int i);
-char *god_name(int which_god,bool long_name=false); //mv
+const char *god_name(god_type which_god, bool long_name = false); //mv
void dec_penance(int val);
-void dec_penance(int god, int val);
-void Xom_acts(bool niceness, int sever, bool force_sever);
+void dec_penance(god_type god, int val);
bool did_god_conduct(int thing_done, int pgain);
void excommunication(void);
-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);
void offer_corpse(int corpse);
std::string god_prayer_reaction();
void pray();
void handle_god_time(void);
-char god_colour(char god);
-void god_pitch(unsigned char which_god);
+int god_colour(god_type god);
+void god_pitch(god_type which_god);
int piety_rank(int piety = -1);
void offer_items();
+bool xom_is_nice();
+void xom_is_stimulated(int maxinterestingness);
+void xom_acts(bool niceness, int sever);
+const char *describe_xom_favour();
+
+inline void xom_acts(int sever)
+{
+ xom_acts(xom_is_nice(), sever);
+}
+
#endif
diff --git a/crawl-ref/source/spells3.cc b/crawl-ref/source/spells3.cc
index a3277a4a17..548aa5de9f 100644
--- a/crawl-ref/source/spells3.cc
+++ b/crawl-ref/source/spells3.cc
@@ -40,6 +40,7 @@
#include "mon-util.h"
#include "player.h"
#include "randart.h"
+#include "religion.h"
#include "spells1.h"
#include "spells4.h"
#include "spl-cast.h"
@@ -590,7 +591,7 @@ void you_teleport(void)
return;
} // end you_teleport()
-void you_teleport2( bool allow_control, bool new_abyss_area )
+static bool teleport_player( bool allow_control, bool new_abyss_area )
{
bool is_controlled = (allow_control && !you.conf
&& player_control_teleport()
@@ -599,7 +600,7 @@ void you_teleport2( bool allow_control, bool new_abyss_area )
if (scan_randarts(RAP_PREVENT_TELEPORTATION))
{
mpr("You feel a strange sense of stasis.");
- return;
+ return false;
}
// after this point, we're guaranteed to teleport. Kill the appropriate
@@ -616,7 +617,7 @@ void you_teleport2( bool allow_control, bool new_abyss_area )
{
abyss_teleport( new_abyss_area );
you.pet_target = MHITNOT;
- return;
+ return true;
}
FixedVector < int, 2 > plox;
@@ -693,7 +694,17 @@ void you_teleport2( bool allow_control, bool new_abyss_area )
|| mgrd[you.x_pos][you.y_pos] != NON_MONSTER
|| env.cgrid[you.x_pos][you.y_pos] != EMPTY_CLOUD);
}
-} // 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);
+}
bool entomb(void)
{
diff --git a/crawl-ref/source/spells3.h b/crawl-ref/source/spells3.h
index 067117f979..a93a91c330 100644
--- a/crawl-ref/source/spells3.h
+++ b/crawl-ref/source/spells3.h
@@ -139,7 +139,7 @@ void you_teleport(void);
/* ***********************************************************************
* called from: ability - acr - decks - effects - fight - misc - spells
* *********************************************************************** */
-void you_teleport2( bool allow_control, bool new_abyss_area = false );
+void you_teleport_now( bool allow_control, bool new_abyss_area = false );
#endif
diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc
index 74f17b62c6..9f71de9854 100644
--- a/crawl-ref/source/spl-cast.cc
+++ b/crawl-ref/source/spl-cast.cc
@@ -909,9 +909,6 @@ spret_type your_spells( spell_type spc2, int powc, bool allow_fail )
miscast_effect( sptype, spell_mana(spc2),
spell_fail(spc2) - spfl, 100 );
- if (you.religion == GOD_XOM && random2(75) < spell_mana(spc2))
- Xom_acts(coinflip(), spell_mana(spc2), false);
-
return (SPRET_FAIL);
}
}
@@ -1899,7 +1896,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
/* sp_type is the type of the spell
* mag_pow is overall power of the spell or effect (ie its level)
* mag_fail is the degree to which you failed
- * force_effect forces a certain effect to occur. Currently unused.
+ * force_effect forces a certain severity of effect to occur.
*/
struct bolt beam;
bool failMsg = true;
@@ -2251,7 +2248,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
mpr("Space warps around you!");
if (one_chance_in(3))
- you_teleport2( true );
+ you_teleport_now( true );
else
random_blink( false );
@@ -2284,7 +2281,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break;
case 1:
mpr("Space warps crazily around you!");
- you_teleport2( true );
+ you_teleport_now( true );
ouch(9 + random2avg(17, 2), 0, KILLED_BY_WILD_MAGIC, cause);
potion_effect(POT_CONFUSION, 60);
@@ -3458,6 +3455,7 @@ bool miscast_effect( unsigned int sp_type, int mag_pow, int mag_fail,
break; // end poison
}
+ xom_is_stimulated(spec_effect);
return (true);
} // end miscast_effect()
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
new file mode 100644
index 0000000000..653c1dc5b1
--- /dev/null
+++ b/crawl-ref/source/xom.cc
@@ -0,0 +1,844 @@
+/*
+ * 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;
+}