summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/xom.cc
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-03-29 12:43:34 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-03-29 12:43:34 +0000
commit996361d167065bc29bef5da248e3d18bd0d9cbab (patch)
treebac3e756a6c0a8d10988563761cdb297652cd9c6 /crawl-ref/source/xom.cc
parent262fc856ccb0dbc4462aa71cfb7f56d81cd9b03d (diff)
downloadcrawl-ref-996361d167065bc29bef5da248e3d18bd0d9cbab.tar.gz
crawl-ref-996361d167065bc29bef5da248e3d18bd0d9cbab.zip
* When Xom decides to cast Magic Mapping or send you on a teleportation
journey, use a random sample of level grids as a guesstimate of the explored portion of the level, and reduce chances for mostly explored levels. * Don't attempt to cast spells you wouldn't be able to cast (e.g. the transformations for undead). * Tweak random uselessness messages as per FR 2595700. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@9565 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/xom.cc')
-rw-r--r--crawl-ref/source/xom.cc146
1 files changed, 123 insertions, 23 deletions
diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc
index 673630344b..0626b35b5f 100644
--- a/crawl-ref/source/xom.cc
+++ b/crawl-ref/source/xom.cc
@@ -33,6 +33,7 @@ REVISION("$Rev$");
#include "spells1.h"
#include "spells2.h"
#include "spells3.h"
+#include "spl-book.h"
#include "spl-cast.h"
#include "spl-mis.h"
#include "spl-util.h"
@@ -209,6 +210,20 @@ void xom_is_stimulated(int maxinterestingness, xom_message_type message_type,
force_message);
}
+void xom_is_stimulated(int maxinterestingness, const std::string& message,
+ bool force_message)
+{
+ if (you.religion != GOD_XOM)
+ return;
+
+ const char *message_array[6];
+
+ for (int i = 0; i < 6; ++i)
+ message_array[i] = message.c_str();
+
+ _xom_is_stimulated(maxinterestingness, message_array, force_message);
+}
+
void xom_tick()
{
// Xom semi-randomly drifts your piety.
@@ -249,15 +264,30 @@ void xom_tick()
tension <= 20 ? 4
: 5);
- // During tension, Xom may briefly forget about being bored.
- if (_xom_is_bored() && x_chance_in_y(chance-1, 4))
+ // If Xom is bored the chances for Xom acting are reversed.
+ if (you.gift_timeout == 0 && x_chance_in_y(5-chance,5))
{
- you.gift_timeout += random2(chance*20);
+ xom_acts(abs(you.piety - MAX_PIETY/2), tension);
+ return;
+ }
+ else if (you.gift_timeout <= 1 && x_chance_in_y(chance-1, 4))
+ {
+ // During tension, Xom may briefly forget about being bored.
+ const int interest = random2(chance*15);
+ if (interest > 0)
+ {
+ if (interest < 25)
+ simple_god_message(" is interested.");
+ else
+ simple_god_message(" is intrigued.");
+
+ you.gift_timeout += interest;
#if defined(DEBUG_RELIGION) || defined(DEBUG_XOM)
- mprf(MSGCH_DIAGNOSTICS,
- "tension %d (chance: %d) -> increase interest to %d",
- tension, chance, you.gift_timeout);
+ mprf(MSGCH_DIAGNOSTICS,
+ "tension %d (chance: %d) -> increase interest to %d",
+ tension, chance, you.gift_timeout);
#endif
+ }
}
if (x_chance_in_y(chance, 5))
@@ -265,21 +295,63 @@ void xom_tick()
}
}
-void xom_is_stimulated(int maxinterestingness, const std::string& message,
- bool force_message)
+// Picks 100 random grids from the level and checks whether they've been
+// marked as seen (explored) or known (mapped). If seen_only is true
+// grids only "seen" via magic mapping don't count.
+// Returns the estimated percentage value of exploration.
+static int _exploration_estimate(bool seen_only = false)
{
- if (you.religion != GOD_XOM)
- return;
+ int seen = 0;
+ int total = 0;
+ int tries = 0;
+ do
+ {
+ tries++;
+ coord_def pos = random_in_bounds();
+ if (!seen_only && is_terrain_known(pos) || is_terrain_seen(pos))
+ {
+ seen++;
+ total++;
+ continue;
+ }
- const char *message_array[6];
+ bool open = true;
+ if (grid_is_solid(grd(pos)) && grd(pos) != DNGN_CLOSED_DOOR)
+ {
+ open = false;
+ for (adjacent_iterator ai(pos); ai; ++ai)
+ {
+ if (map_bounds(*ai) && (!grid_is_opaque(grd(*ai))
+ || grd(*ai) == DNGN_CLOSED_DOOR))
+ {
+ open = true;
+ break;
+ }
+ }
+ }
+ if (open)
+ total++;
+ }
+ while (total < 100 && tries < 1000);
- for (int i = 0; i < 6; ++i)
- message_array[i] = message.c_str();
+#ifdef DEBUG_XOM
+ mprf(MSGCH_DIAGNOSTICS,
+ "exploration estimate (%s): %d out of %d grids seen",
+ seen_only ? "explored" : "mapped", seen, total);
+#endif
- _xom_is_stimulated(maxinterestingness, message_array, force_message);
+ // If we didn't get any qualifying grids, there are probably so few
+ // of them you've already seen them all.
+ if (total == 0)
+ return 100;
+
+ if (total < 100)
+ seen *= 100/total;
+
+ return (seen);
}
-static void _xom_makes_you_cast_random_spell(int sever, int tension)
+static bool _xom_makes_you_cast_random_spell(int sever, int tension)
{
int spellenum = sever;
@@ -297,7 +369,19 @@ static void _xom_makes_you_cast_random_spell(int sever, int tension)
const int nxomspells = ARRAYSZ(_xom_nontension_spells);
spellenum = std::min(nxomspells, spellenum);
spell = _xom_nontension_spells[random2(spellenum)];
+
+ if (spell == SPELL_MAGIC_MAPPING)
+ {
+ // If the level is already mostly explored, there's
+ // a chance we might try something else.
+ const int explored = _exploration_estimate();
+ if (explored > 80 && x_chance_in_y(explored, 100))
+ return (false);
+ }
}
+ // Don't attempt to cast spells the undead cannot memorise.
+ if (you_cannot_memorise(spell))
+ return (false);
god_speaks(GOD_XOM, _get_xom_speech("spell effect").c_str());
@@ -308,6 +392,7 @@ static void _xom_makes_you_cast_random_spell(int sever, int tension)
#endif
your_spells(spell, sever, false);
+ return (true);
}
static void _try_brand_switch(const int item_index)
@@ -1261,10 +1346,7 @@ static bool _xom_is_good(int sever, int tension)
// There are a lot less non-tension spells than tension ones,
// so use them more rarely.
if (tension > 0 || one_chance_in(3))
- {
- _xom_makes_you_cast_random_spell(sever, tension);
- done = true;
- }
+ done = _xom_makes_you_cast_random_spell(sever, tension);
}
else if (x_chance_in_y(4, sever))
done = _xom_confuse_monsters(sever);
@@ -1288,8 +1370,15 @@ static bool _xom_is_good(int sever, int tension)
_xom_give_item(sever);
done = true;
}
- else if (x_chance_in_y(11, sever) && (you.level_type != LEVEL_ABYSS))
+ else if (x_chance_in_y(11, sever) && you.level_type != LEVEL_ABYSS)
{
+ // This is not very interesting if the level is already fully
+ // explored (presumably cleared). Even then, it may occasionally
+ // happen.
+ const int explored = _exploration_estimate(true);
+ if (explored >= 80 && x_chance_in_y(explored, 120))
+ return (false);
+
// The Xom teleportation train takes you on instant teleportation
// to a few random areas, stopping randomly but most likely in
// an area that is not dangerous to you.
@@ -1679,7 +1768,8 @@ static void _get_hand_type(std::string &hand, bool &can_plural)
hand_vec.push_back("mandible");
plural_vec.push_back(true);
}
- else if (you.species != SP_MUMMY || transform_changed_physiology())
+ else if (you.species != SP_MUMMY && !player_mutation_level(MUT_BEAK)
+ || transform_changed_physiology())
{
hand_vec.push_back("nose");
plural_vec.push_back(false);
@@ -1962,9 +2052,19 @@ static bool _xom_is_bad(int sever, int tension)
badness = 2;
done = true;
}
- else if ((!nasty || coinflip())
- && x_chance_in_y(7, sever) && you.level_type != LEVEL_ABYSS)
+ else if (x_chance_in_y(7, sever) && you.level_type != LEVEL_ABYSS)
{
+ // This is not particularly exciting if the level is already fully
+ // explored (presumably cleared). If Xom is feeling nasty this
+ // is likelier to happen if the level is unexplored.
+ const int explored = _exploration_estimate(true);
+ if (nasty && explored >= 50 && coinflip()
+ || explored >= 80 + random2(20))
+ {
+ done = false;
+ continue;
+ }
+
// The Xom teleportation train takes you on instant
// teleportation to a few random areas, stopping if either
// an area is dangerous to you or randomly.