summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-09-28 08:27:29 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-09-28 08:27:29 +0000
commit3205c9289fd9ff8bcf739903a49215f75212128e (patch)
tree6a9b4a29e9e8bd96d4e8b87934d17ce84987a8e0 /crawl-ref/source
parentdc3aa32db050e7923a4e802b874fccd997c1d6c6 (diff)
downloadcrawl-ref-3205c9289fd9ff8bcf739903a49215f75212128e.tar.gz
crawl-ref-3205c9289fd9ff8bcf739903a49215f75212128e.zip
crawl_state now keeps track of whether or not the current code is being
executed because of a god's actions, and if so which god (with "actions" not including god-supplied invocations). Currently only used to prevent Xom from being amused/stimulated by his own actions. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2235 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/acr.cc6
-rw-r--r--crawl-ref/source/religion.cc35
-rw-r--r--crawl-ref/source/state.cc102
-rw-r--r--crawl-ref/source/state.h28
-rw-r--r--crawl-ref/source/xom.cc37
5 files changed, 207 insertions, 1 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 2d35510bb4..9a427e6b6f 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1183,6 +1183,8 @@ bool apply_berserk_penalty = false;
*/
static void input()
{
+ crawl_state.clear_god_acting();
+
if (crawl_state.is_replaying_keys() && crawl_state.is_repeating_cmd()
&& kbhit())
{
@@ -1394,6 +1396,8 @@ static void input()
curr_PlaceInfo += delta;
curr_PlaceInfo.assert_validity();
}
+
+ crawl_state.clear_god_acting();
}
static bool toggle_flag( bool* flag, const char* flagname )
@@ -2604,6 +2608,8 @@ static void check_banished()
static void world_reacts()
{
+ crawl_state.clear_god_acting();
+
if (Options.stash_tracking)
stashes.update_visible_stashes(
Options.stash_tracking == STM_ALL?
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 52f3f4b452..abedd6393d 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -542,6 +542,8 @@ static void do_god_gift(bool prayed_for)
if (prayed_for != (you.religion == GOD_ZIN))
return;
+ crawl_state.inc_god_acting();
+
#if DEBUG_DIAGNOSTICS || DEBUG_GIFTS
int old_gifts = you.num_gifts[ you.religion ];
#endif
@@ -816,6 +818,7 @@ static void do_god_gift(bool prayed_for)
mprf(MSGCH_DIAGNOSTICS, "Total number of gifts from this god: %d",
you.num_gifts[ you.religion ] );
#endif
+ crawl_state.dec_god_acting();
}
static bool is_risky_sacrifice(const item_def& item)
@@ -1125,6 +1128,8 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
if (you.religion == GOD_NO_GOD || you.religion == GOD_XOM)
return (false);
+ crawl_state.inc_god_acting();
+
switch (thing_done)
{
case DID_DRINK_BLOOD:
@@ -1581,6 +1586,8 @@ bool did_god_conduct( conduct_type thing_done, int level, const actor *victim )
}
#endif
+ crawl_state.dec_god_acting();
+
return (ret);
}
@@ -1703,6 +1710,8 @@ bool ely_destroy_weapons()
if (you.religion != GOD_ELYVILON)
return false;
+ crawl_state.inc_god_acting();
+
bool success = false;
int i = igrd[you.x_pos][you.y_pos];
while (i != NON_ITEM)
@@ -1745,6 +1754,8 @@ bool ely_destroy_weapons()
mpr("There are no weapons here to destroy!");
}
+ crawl_state.dec_god_acting();
+
return success;
}
@@ -1753,6 +1764,8 @@ void trog_burn_books()
if (you.religion != GOD_TROG)
return;
+ crawl_state.inc_god_acting();
+
int i = igrd[you.x_pos][you.y_pos];
while (i != NON_ITEM)
{
@@ -1863,6 +1876,7 @@ void trog_burn_books()
simple_god_message(" is delighted!", GOD_TROG);
gain_piety(totalpiety);
}
+ crawl_state.dec_god_acting();
}
void lose_piety(int pgn)
@@ -2516,6 +2530,8 @@ void divine_retribution( god_type god )
if (god == you.religion && is_good_god(god) )
return;
+ crawl_state.inc_god_acting(god, true);
+
// Just the thought of retribution (getting this far) mollifies
// the god by at least a point... the punishment might reduce
// penance further.
@@ -2566,6 +2582,7 @@ void divine_retribution( god_type god )
}
}
}
+ crawl_state.dec_god_acting(god);
}
// upon excommunication, (now ex) Beogh adepts lose their orcish followers
@@ -2658,6 +2675,8 @@ bool followers_abandon_you()
// Destroying orcish idols (a.k.a. idols of Beogh) may anger Beogh
void beogh_idol_revenge()
{
+ crawl_state.inc_god_acting(GOD_BEOGH, true);
+
// Beogh watches his charges closely, but for others doesn't always notice
if (you.religion == GOD_BEOGH
|| (you.species == SP_HILL_ORC && coinflip())
@@ -2713,12 +2732,16 @@ void beogh_idol_revenge()
did_god_conduct(DID_ATTACK_FRIEND, 8);
}
}
+
+ crawl_state.dec_god_acting(GOD_BEOGH);
}
void excommunication(void)
{
const god_type old_god = you.religion;
+ crawl_state.inc_god_acting(old_god, true);
+
take_note(Note(NOTE_LOSE_GOD, old_god));
you.duration[DUR_PRAYER] = 0;
@@ -2810,6 +2833,8 @@ void excommunication(void)
inc_penance( old_god, 25 );
break;
}
+
+ crawl_state.dec_god_acting(old_god);
} // end excommunication()
static bool bless_weapon( int god, int brand, int colour )
@@ -2872,6 +2897,8 @@ void altar_prayer(void)
if (you.religion == GOD_XOM)
return;
+ crawl_state.inc_god_acting();
+
// TSO blesses long swords with holy wrath
if (you.religion == GOD_SHINING_ONE
&& !you.num_gifts[GOD_SHINING_ONE]
@@ -2924,6 +2951,8 @@ void altar_prayer(void)
}
offer_items();
+
+ crawl_state.dec_god_acting();
} // end altar_prayer()
static bool god_likes_items(god_type god)
@@ -2970,6 +2999,8 @@ void offer_items()
if (you.religion == GOD_NO_GOD || !god_likes_items(you.religion))
return;
+ crawl_state.inc_god_acting();
+
int num_sacced = 0;
int i = igrd[you.x_pos][you.y_pos];
while (i != NON_ITEM)
@@ -3094,6 +3125,8 @@ void offer_items()
if (num_sacced > 0 && you.religion == GOD_NEMELEX_XOBEH)
show_pure_deck_chances();
#endif
+
+ crawl_state.dec_god_acting();
}
void god_pitch(god_type which_god)
@@ -3117,7 +3150,9 @@ void god_pitch(god_type which_god)
if (which_god == GOD_LUGONU && you.penance[GOD_LUGONU])
{
simple_god_message(" is most displeased with you!", which_god);
+ crawl_state.inc_god_acting(GOD_LUGONU, true);
lugonu_retribution();
+ crawl_state.dec_god_acting(GOD_LUGONU);
return;
}
diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc
index 03cd5817db..25e314eda6 100644
--- a/crawl-ref/source/state.cc
+++ b/crawl-ref/source/state.cc
@@ -240,3 +240,105 @@ void game_state::reset_cmd_again()
prev_cmd_keys.clear();
}
+
+///////////////////////////////////////////////////////////
+// Keeping track of which god is currently doing something
+///////////////////////////////////////////////////////////
+
+god_act_state::god_act_state()
+{
+ reset();
+}
+
+void god_act_state::reset()
+{
+ which_god = GOD_NO_GOD;
+ retribution = false;
+ depth = 0;
+}
+
+bool game_state::is_god_acting() const
+{
+ ASSERT(god_act.depth >= 0);
+ ASSERT(!(god_act.depth > 0 && god_act.which_god == GOD_NO_GOD));
+ ASSERT(!(god_act.depth == 0 && god_act.which_god != GOD_NO_GOD));
+ ASSERT(!(god_act.depth == 0 && god_act_stack.size() > 0));
+
+ return (god_act.depth > 0);
+}
+
+bool game_state::is_god_retribution() const
+{
+ ASSERT(is_god_acting());
+
+ return (god_act.retribution);
+}
+
+god_type game_state::which_god_acting() const
+{
+ return god_act.which_god;
+}
+
+void game_state::inc_god_acting(bool is_retribution)
+{
+ inc_god_acting(you.religion, is_retribution);
+}
+
+void game_state::inc_god_acting(god_type which_god, bool is_retribution)
+{
+ ASSERT(which_god != GOD_NO_GOD);
+
+ if (god_act.which_god != GOD_NO_GOD &&
+ god_act.which_god != which_god)
+ {
+ ASSERT(god_act.depth >= 1);
+
+ god_act_stack.push_back(god_act);
+ god_act.reset();
+ }
+
+ god_act.which_god = which_god;
+ god_act.retribution = is_retribution;
+ god_act.depth++;
+}
+
+void game_state::dec_god_acting()
+{
+ dec_god_acting(you.religion);
+}
+
+void game_state::dec_god_acting(god_type which_god)
+{
+ ASSERT(which_god != GOD_NO_GOD);
+ ASSERT(god_act.depth > 0);
+ ASSERT(god_act.which_god == which_god);
+
+ god_act.depth--;
+
+ if (god_act.depth == 0)
+ {
+ god_act.reset();
+ if (god_act_stack.size() > 0)
+ {
+ god_act = god_act_stack[god_act_stack.size() - 1];
+ god_act_stack.pop_back();
+ ASSERT(god_act.depth >= 1);
+ ASSERT(god_act.which_god != GOD_NO_GOD);
+ ASSERT(god_act.which_god != which_god);
+ }
+ }
+}
+
+void game_state::clear_god_acting()
+{
+ ASSERT(!is_god_acting());
+ ASSERT(god_act_stack.size() == 0);
+
+ god_act.reset();
+}
+
+std::vector<god_act_state> game_state::other_gods_acting() const
+{
+ ASSERT(is_god_acting());
+ return god_act_stack;
+}
diff --git a/crawl-ref/source/state.h b/crawl-ref/source/state.h
index 0f4da3bbbd..8e5a9cc4b5 100644
--- a/crawl-ref/source/state.h
+++ b/crawl-ref/source/state.h
@@ -13,6 +13,20 @@
#ifndef STATE_H
#define STATE_H
+#include "enum.h"
+
+struct god_act_state
+{
+public:
+
+ god_act_state();
+ void reset();
+
+ god_type which_god;
+ bool retribution;
+ int depth;
+};
+
// Track various aspects of Crawl game state.
struct game_state
{
@@ -58,6 +72,9 @@ protected:
void reset_cmd_repeat();
void reset_cmd_again();
+ god_act_state god_act;
+ std::vector<god_act_state> god_act_stack;
+
public:
game_state();
@@ -78,6 +95,17 @@ public:
if (terminal_resize_check)
(*terminal_resize_check)();
}
+
+ bool is_god_acting() const;
+ bool is_god_retribution() const;
+ god_type which_god_acting() const;
+ void inc_god_acting(bool is_retribution = false);
+ void inc_god_acting(god_type which_god, bool is_retribution = false);
+ void dec_god_acting();
+ void dec_god_acting(god_type which_god);
+ void clear_god_acting();
+
+ std::vector<god_act_state> other_gods_acting() const;
};
extern game_state crawl_state;
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index 8293fc4925..ed8b244b5c 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -25,6 +25,7 @@
#include "spells3.h"
#include "spl-cast.h"
#include "spl-util.h"
+#include "state.h"
#include "stuff.h"
#include "view.h"
@@ -113,6 +114,11 @@ void xom_is_stimulated(int maxinterestingness)
{
if (you.religion != GOD_XOM)
return;
+
+ // Xom is not stimulated by his own acts, at least not directly.
+ if (crawl_state.which_god_acting() == GOD_XOM)
+ return;
+
int interestingness = random2(maxinterestingness);
if (interestingness < 12)
return;
@@ -135,6 +141,8 @@ void xom_makes_you_cast_random_spell(int sever)
{
int spellenum = sever;
+ crawl_state.inc_god_acting(GOD_XOM);
+
const int nxomspells = ARRAYSIZE(xom_spells);
if (spellenum >= nxomspells)
spellenum = nxomspells - 1;
@@ -149,6 +157,8 @@ void xom_makes_you_cast_random_spell(int sever)
#endif
your_spells(spell, sever, false);
+
+ crawl_state.dec_god_acting(GOD_XOM);
}
static void xom_make_item(object_class_type base,
@@ -165,11 +175,15 @@ static void xom_make_item(object_class_type base,
return;
}
+ crawl_state.inc_god_acting(GOD_XOM);
+
move_item_to_grid( &thing_created, you.x_pos, you.y_pos );
canned_msg(MSG_SOMETHING_APPEARS);
stop_running();
origin_acquired(mitm[thing_created], GOD_XOM);
+
+ crawl_state.dec_god_acting(GOD_XOM);
}
static object_class_type get_unrelated_wield_class(object_class_type ref)
@@ -197,11 +211,16 @@ static object_class_type get_unrelated_wield_class(object_class_type ref)
(temp_rand == 1) ? OBJ_STAVES :
OBJ_MISCELLANY;
}
+
return (objtype);
}
static bool xom_annoyance_gift(int power)
{
+ // Can't simply use unwind_var because of the way that god act
+ // state is maintained.
+ crawl_state.inc_god_acting(GOD_XOM);
+
if (coinflip() && player_in_a_dangerous_place())
{
const item_def *weapon = you.weapon();
@@ -216,6 +235,7 @@ static bool xom_annoyance_gift(int power)
xom_make_item(weapon->base_type, weapon->sub_type, power * 3);
else
acquirement(weapon->base_type, GOD_XOM);
+ crawl_state.dec_god_acting(GOD_XOM);
return (true);
}
@@ -228,6 +248,7 @@ static bool xom_annoyance_gift(int power)
// A random ring. (Not necessarily a good one.)
god_speaks(GOD_XOM, RANDOM_ELEMENT(xom_try_this));
xom_make_item(OBJ_JEWELLERY, get_random_ring_type(), power * 3);
+ crawl_state.dec_god_acting(GOD_XOM);
return (true);
};
@@ -238,6 +259,7 @@ static bool xom_annoyance_gift(int power)
// you an amulet. Ha ha!
god_speaks(GOD_XOM, RANDOM_ELEMENT(xom_try_this));
xom_make_item(OBJ_JEWELLERY, get_random_amulet_type(), power * 3);
+ crawl_state.dec_god_acting(GOD_XOM);
return (true);
};
@@ -250,6 +272,7 @@ static bool xom_annoyance_gift(int power)
// a ring. Ha ha!
god_speaks(GOD_XOM, RANDOM_ELEMENT(xom_try_this_ring));
xom_make_item(OBJ_JEWELLERY, get_random_ring_type(), power * 3);
+ crawl_state.dec_god_acting(GOD_XOM);
return (true);
}
@@ -266,9 +289,12 @@ static bool xom_annoyance_gift(int power)
acquirement(objtype, GOD_XOM);
else
xom_make_item(objtype, OBJ_RANDOM, power * 3);
+ crawl_state.dec_god_acting(GOD_XOM);
return (true);
}
}
+
+ crawl_state.dec_god_acting(GOD_XOM);
return (false);
}
@@ -276,7 +302,7 @@ 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())
{
@@ -310,7 +336,10 @@ bool xom_gives_item(int power)
(r == 5) ? OBJ_FOOD :
(r == 6) ? OBJ_MISCELLANY :
OBJ_GOLD;
+
+ crawl_state.inc_god_acting(GOD_XOM);
acquirement(objtype, GOD_XOM);
+ crawl_state.dec_god_acting(GOD_XOM);
}
else
{
@@ -397,6 +426,7 @@ static bool xom_is_good(int sever)
// Okay, now for the nicer stuff (note: these things are not
// necessarily nice):
+ crawl_state.inc_god_acting(GOD_XOM);
if (random2(sever) <= 1)
{
temp_rand = random2(4);
@@ -579,6 +609,7 @@ static bool xom_is_good(int sever)
done = true;
}
+ crawl_state.dec_god_acting(GOD_XOM);
return (done);
}
@@ -590,6 +621,8 @@ static bool xom_is_bad(int sever)
bolt beam;
+ crawl_state.inc_god_acting(GOD_XOM);
+
// begin "Bad Things"
while (!done)
{
@@ -778,6 +811,8 @@ static bool xom_is_bad(int sever)
}
}
+ crawl_state.dec_god_acting(GOD_XOM);
+
return (done);
}