summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/enum.h3
-rw-r--r--crawl-ref/source/mon-util.h2
-rw-r--r--crawl-ref/source/monplace.cc5
-rw-r--r--crawl-ref/source/monstuff.cc87
-rw-r--r--crawl-ref/source/traps.cc1
5 files changed, 89 insertions, 9 deletions
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 14581e94a0..bbdfad70a9 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -2789,7 +2789,8 @@ enum montravel_target_type
MTRAV_NONE = 0,
MTRAV_PLAYER, // Travelling to reach the player.
MTRAV_PATROL, // Travelling to reach the patrol point.
- MTRAV_UNREACHABLE // Not travelling because player is unreachable.
+ MTRAV_UNREACHABLE, // Not travelling because player is unreachable.
+ MTRAV_EXIT // Travelling to reach a level exit.
};
#ifdef WIZARD
diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h
index 7b00dee43e..ce71eccfa7 100644
--- a/crawl-ref/source/mon-util.h
+++ b/crawl-ref/source/mon-util.h
@@ -646,7 +646,7 @@ mon_attitude_type mons_attitude(const monsters *m);
bool mons_behaviour_perceptible(const monsters *mon);
bool mons_is_native_in_branch(const monsters *monster,
- const branch_type branch);
+ const branch_type branch = you.where_are_you);
bool mons_is_god_gift(const monsters *mon, god_type god = you.religion);
bool mons_is_chaotic(const monsters *mon);
bool mons_is_poisoner(const monsters *mon);
diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc
index 2a54fae689..01a7cf4f8c 100644
--- a/crawl-ref/source/monplace.cc
+++ b/crawl-ref/source/monplace.cc
@@ -2635,7 +2635,7 @@ bool monster_pathfind::traversable(coord_def p)
// at home in this branch.
if (grd(p) == DNGN_SECRET_DOOR && mons_friendly(mons)
&& (mons_intel(mons->type) < I_NORMAL
- || !mons_is_native_in_branch(mons, you.where_are_you)))
+ || !mons_is_native_in_branch(mons)))
{
return (false);
}
@@ -2696,8 +2696,7 @@ int monster_pathfind::travel_cost(coord_def npos)
bool knows_trap = (!mons_friendly(mons)
|| grd(npos) != DNGN_UNDISCOVERED_TRAP
|| mons_intel(mons->type) >= I_NORMAL
- && mons_is_native_in_branch(mons,
- you.where_are_you));
+ && mons_is_native_in_branch(mons));
trap_type tt = env.trap[trap].type;
if (tt == TRAP_ALARM || tt == TRAP_ZOT)
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)))
diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc
index 1434640c19..d399ae7cd1 100644
--- a/crawl-ref/source/traps.cc
+++ b/crawl-ref/source/traps.cc
@@ -928,7 +928,6 @@ dungeon_feature_type trap_category(trap_type type)
// Returns index of the trap for a given (x,y) coordinate pair {dlb}
int trap_at_xy(int which_x, int which_y)
{
-
for (int which_trap = 0; which_trap < MAX_TRAPS; which_trap++)
{
if (env.trap[which_trap].x == which_x