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.cc141
1 files changed, 129 insertions, 12 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index 137838824a..589a3da109 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -2351,9 +2351,10 @@ static void _handle_behaviour(monsters *mon)
bool isSmart = (mons_intel(mon->type) > I_ANIMAL);
bool isScared = mon->has_ench(ENCH_FEAR);
bool isMobile = !mons_is_stationary(mon);
+ bool travelling = mon->is_travelling();
bool patrolling = mon->is_patrolling();
- // check for confusion -- early out.
+ // Check for confusion -- early out.
if (mon->has_ench(ENCH_CONFUSION))
{
mon->target_x = 10 + random2(GXM - 10);
@@ -2515,7 +2516,7 @@ static void _handle_behaviour(monsters *mon)
break;
}
- // foe gone out of LOS?
+ // Foe gone out of LOS?
if (!proxFoe)
{
if (patrolling)
@@ -2575,8 +2576,7 @@ static void _handle_behaviour(monsters *mon)
break;
}
- // hack: smarter monsters will
- // tend to pursue the player longer.
+ // Hack: smarter monsters will tend to pursue the player longer.
int memory = 0;
switch (mons_intel(monster_index(mon)))
{
@@ -2648,10 +2648,102 @@ static void _handle_behaviour(monsters *mon)
// wandering monsters at least appear to have some sort of
// attention span. -- bwr
if (mon->x == mon->target_x && mon->y == mon->target_y
- || one_chance_in(20)
- || testbits( mon->flags, MF_BATTY ))
+ || !travelling && (one_chance_in(20)
+ || testbits( mon->flags, MF_BATTY )))
{
- if (patrolling)
+ bool need_target = true;
+ if (travelling)
+ {
+#ifdef DEBUG_PATHFIND
+ mprf("Monster %s reached target (%d, %d)",
+ mon->name(DESC_PLAIN).c_str(),
+ mon->target_x, mon->target_y);
+#endif
+ need_target = false;
+ if (mon->x == mon->travel_path[0].x
+ && mon->y == mon->travel_path[0].y)
+ {
+ // Hey, we reached our first waypoint!
+ mon->travel_path.erase( mon->travel_path.begin() );
+ if (mon->travel_path.empty())
+ need_target = true;
+
+ mon->target_x = mon->travel_path[0].x;
+ mon->target_y = mon->travel_path[0].y;
+#ifdef DEBUG_PATHFIND
+ mprf("Next waypoint: (%d, %d)",
+ mon->target_x, mon->target_y);
+#endif
+ }
+ else
+ {
+ // Apparently we got sidetracked a bit.
+ // Check the waypoints vector backwards and pick the
+ // first waypoint we can see.
+
+ // XXX: Note that this might still not be the best
+ // thing to do since another path might be even
+ // *closer* to our actual target now.
+
+ dungeon_feature_type can_move;
+ if (mons_amphibious(mons_is_zombified(mon) ?
+ mon->base_monster : mon->type))
+ {
+ can_move = DNGN_DEEP_WATER;
+ }
+ else
+ can_move = DNGN_SHALLOW_WATER;
+
+
+ int erase = -1; // Erase how many waypoints?
+ for (unsigned int i = mon->travel_path.size() - 1;
+ i >= 0; i--)
+ {
+ if (grid_see_grid(mon->x, mon->y,
+ mon->travel_path[i].x,
+ mon->travel_path[i].y, can_move))
+ {
+ mon->target_x = mon->travel_path[i].x;
+ mon->target_y = mon->travel_path[i].y;
+ erase = i;
+ break;
+ }
+ }
+
+ if (erase != -1)
+ {
+ // Erase all waypoints that came earlier:
+ // we don't need them anymore.
+ while (0 < erase--)
+ {
+ mon->travel_path.erase(
+ mon->travel_path.begin() );
+ }
+ }
+ else
+ {
+ // We can't reach our old path from our current
+ // position, so calculate a new path instead.
+ monster_pathfind mp;
+ if (mp.start_pathfind(mon, mon->patrol_point, true))
+ {
+ mon->travel_path = mp.calc_waypoints();
+ if (!mon->travel_path.empty())
+ {
+ mon->target_x = mon->travel_path[0].x;
+ mon->target_y = mon->travel_path[0].y;
+ }
+ }
+ else
+ {
+ mon->travel_path.clear();
+ need_target = true;
+ }
+ }
+ }
+ }
+
+ if (need_target && patrolling)
{
if (!_choose_random_patrol_target_grid(mon))
{
@@ -2685,14 +2777,39 @@ static void _handle_behaviour(monsters *mon)
// pathfinding to find the way back, and animals
// could decide to stop patrolling if the path
// was too long.
-
- mon->target_x = mon->patrol_point.x;
- mon->target_y = mon->patrol_point.y;
+ monster_pathfind mp;
+ if (mp.start_pathfind(mon, mon->patrol_point, true))
+ {
+ mon->travel_path = mp.calc_waypoints();
+ if (!mon->travel_path.empty())
+ {
+ mon->target_x = mon->travel_path[0].x;
+ mon->target_y = mon->travel_path[0].y;
+ }
+ }
+ else
+ {
+ // Stop patrolling.
+ mon->patrol_point = coord_def(0, 0);
+ }
}
}
+ else
+ {
+#ifdef DEBUG_PATHFIND
+ mprf("Monster %s (pp: %d, %d) is now patrolling to (%d, %d)",
+ mon->name(DESC_PLAIN).c_str(),
+ mon->patrol_point.x, mon->patrol_point.y,
+ mon->target_x, mon->target_y);
+#endif
+ }
}
- else
+ else if (need_target)
{
+#ifdef DEBUG_PATHFIND
+ if (!testbits( mon->flags, MF_BATTY ))
+ mprf("Monster is wandering randomly.");
+#endif
mon->target_x = 10 + random2(GXM - 10);
mon->target_y = 10 + random2(GYM - 10);
}
@@ -2742,7 +2859,7 @@ static void _handle_behaviour(monsters *mon)
if (isHealthy)
new_beh = BEH_SEEK;
- // foe gone out of LOS?
+ // Foe gone out of LOS?
if (!proxFoe)
{
if ((isFriendly || proxPlayer) && !isNeutral && !patrolling)