summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monstuff.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/monstuff.cc')
-rw-r--r--crawl-ref/source/monstuff.cc87
1 files changed, 84 insertions, 3 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 866b7dbcb4..f84d4c9037 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -2405,6 +2405,68 @@ static void _mark_neighbours_player_unreachable(monsters *mon)
}
}
+static void _mons_find_level_exits(const monsters *mon,
+ std::vector<coord_def> &e,
+ int range = -1)
+{
+ if (range == -1)
+ range = LOS_RADIUS;
+
+ // Sweep every square within range.
+ for (radius_iterator ri(mon->pos(), range, true, false); ri; ++ri)
+ {
+ // All types of stairs.
+ if (is_stair(grd(*ri)))
+ e.push_back(*ri);
+
+ // Teleportation and shaft traps: only known traps if the
+ // monster isn't native to the branch, or all traps if it is.
+ trap_type tt = trap_type_at_xy((*ri).x, (*ri).y);
+ if ((tt == TRAP_TELEPORT || tt == TRAP_SHAFT)
+ && (grd[(*ri).x][(*ri).y] != DNGN_UNDISCOVERED_TRAP
+ || mons_is_native_in_branch(mon)))
+ {
+ e.push_back(*ri);
+ }
+
+ // Any place the monster can submerge.
+ if (monster_can_submerge(mon, grd(*ri)))
+ e.push_back(*ri);
+ }
+}
+
+static bool _mons_find_nearest_level_exit(const monsters *mon,
+ coord_def &e)
+{
+ std::vector<coord_def> level_exits;
+
+ _mons_find_level_exits(mon, level_exits);
+
+ e.x = -1;
+ e.y = -1;
+
+ int old_dist = -1;
+
+ for (unsigned int i = 0; i < level_exits.size(); ++i)
+ {
+ int dist = distance(mon->x, mon->y, level_exits[i].x,
+ level_exits[i].y);
+
+ if (old_dist == -1 || old_dist >= dist)
+ {
+ if (old_dist == dist && coinflip())
+ continue;
+
+ old_dist = dist;
+
+ e.x = level_exits[i].x;
+ e.y = level_exits[i].y;
+ }
+ }
+
+ return (old_dist != -1);
+}
+
static void _make_mons_leave_level(monsters *mon)
{
if (mons_is_leaving(mon))
@@ -2834,8 +2896,7 @@ static void _handle_behaviour(monsters *mon)
#ifdef DEBUG_PATHFIND
mprf("Need to calculate a path... (dist = %d)", dist);
#endif
- const bool native =
- mons_is_native_in_branch(mon, you.where_are_you);
+ const bool native = mons_is_native_in_branch(mon);
int range = 0;
switch (mons_intel(mon->type))
@@ -3241,6 +3302,26 @@ static void _handle_behaviour(monsters *mon)
_make_mons_leave_level(mon);
return;
}
+
+ // If the monster isn't travelling toward an exit, make it
+ // start doing so.
+ if (mon->travel_target != MTRAV_EXIT)
+ {
+ coord_def e;
+ if (_mons_find_nearest_level_exit(mon, e))
+ {
+ mon->foe = MHITNOT;
+ mon->target_x = e.x;
+ mon->target_y = e.y;
+ mon->travel_target = MTRAV_EXIT;
+ }
+ }
+ // If it is, and it's on the exit, make it leave the level.
+ else if (mon->x == mon->target_x && mon->y == mon->target_y)
+ {
+ _make_mons_leave_level(mon);
+ return;
+ }
break;
case BEH_FLEE:
@@ -6546,7 +6627,7 @@ static bool _is_trap_safe(const monsters *monster, const int trap_x,
// * very intelligent monsters can be assumed to have a high T&D skill
// (or have memorised part of the dungeon layout ;) )
if (intel >= I_NORMAL && mechanical
- && (mons_is_native_in_branch(monster, you.where_are_you)
+ && (mons_is_native_in_branch(monster)
|| monster->attitude == ATT_FRIENDLY
&& player_knows_trap
|| intel >= I_HIGH && one_chance_in(3)))