summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-02 11:16:08 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-12-02 11:16:08 +0000
commit29d2d1be7e3d8ef6096100e6c51f1dde66f3a028 (patch)
treeb87b12baa3908a374a9fffb1a34cc00f2eeed643
parent8bc4633d7abb19284ab90ee5b7fff09948748b84 (diff)
downloadcrawl-ref-29d2d1be7e3d8ef6096100e6c51f1dde66f3a028.tar.gz
crawl-ref-29d2d1be7e3d8ef6096100e6c51f1dde66f3a028.zip
Implemented "flee towards/into walls" behaviour for rock worms. It
isn't very sophisticated, especially if there's friendly monsters between the worm and the nearest wall, but it's a srart. Added rock worms to the Lair and the Dungeon with the same depth and rarity as trapdoor spiders. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7721 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/enum.h1
-rw-r--r--crawl-ref/source/mon-pick.cc4
-rw-r--r--crawl-ref/source/monstuff.cc129
3 files changed, 123 insertions, 11 deletions
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 08bd09a537..9ab78972e6 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -3001,6 +3001,7 @@ enum montravel_target_type
MTRAV_PLAYER, // Travelling to reach the player.
MTRAV_PATROL, // Travelling to reach the patrol point.
MTRAV_SIREN, // Sirens travelling towards deep water.
+ MTRAV_WALL, // Earthworms travelling towards a wall.
MTRAV_UNREACHABLE // Not travelling because target is unreachable.
};
diff --git a/crawl-ref/source/mon-pick.cc b/crawl-ref/source/mon-pick.cc
index 4f2efd9004..3ba5edfdbe 100644
--- a/crawl-ref/source/mon-pick.cc
+++ b/crawl-ref/source/mon-pick.cc
@@ -661,6 +661,7 @@ int mons_standard_level(int mcls)
case MONS_WRAITH:
case MONS_UNSEEN_HORROR:
case MONS_TRAPDOOR_SPIDER:
+ case MONS_ROCK_WORM:
return 14;
case MONS_ARMOUR_MIMIC:
@@ -948,6 +949,7 @@ int mons_standard_rare(int mcls)
case MONS_EYE_OF_DRAINING:
case MONS_TRAPDOOR_SPIDER:
+ case MONS_ROCK_WORM:
return 33;
case MONS_GIANT_SLUG:
@@ -1385,6 +1387,7 @@ int mons_lair_level(int mcls)
case MONS_OKLOB_PLANT:
case MONS_WYVERN:
case MONS_TRAPDOOR_SPIDER:
+ case MONS_ROCK_WORM:
mlev += 7;
break;
@@ -1522,6 +1525,7 @@ int mons_lair_rare(int mcls)
case MONS_YELLOW_WASP:
case MONS_BUTTERFLY:
case MONS_TRAPDOOR_SPIDER:
+ case MONS_ROCK_WORM:
return 5;
case MONS_GIANT_SPORE:
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index c4fa1b663a..cfa15e4d09 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1633,9 +1633,6 @@ static bool _valid_morph( monsters *monster, int new_mclass )
|| new_mclass == MONS_PLAYER_GHOST
|| new_mclass == MONS_PANDEMONIUM_DEMON
- // Monsters still under development
- || new_mclass == MONS_ROCK_WORM
-
// Other poly-unsuitable things.
|| new_mclass == MONS_ROYAL_JELLY
|| new_mclass == MONS_ORB_GUARDIAN
@@ -2985,6 +2982,101 @@ static bool _find_siren_water_target(monsters *mon)
return (false);
}
+static bool _find_wall_target(monsters *mon)
+{
+ ASSERT(mons_wall_shielded(mon));
+
+ if (mon->travel_target == MTRAV_WALL)
+ {
+ coord_def targ_pos(mon->travel_path[mon->travel_path.size() - 1]);
+
+ // Target grid might have changed since we started, like if the
+ // player destroys the wall the monster wants to hide in.
+ if (grid_is_solid(targ_pos)
+ && monster_habitable_grid(mon, grd(targ_pos)))
+ {
+ // Wall is still good.
+#ifdef DEBUG_PATHFIND
+ mprf("%s target is (%d, %d), dist = %d",
+ mon->name(DESC_PLAIN, true).c_str(),
+ targ_pos.x, targ_pos.y, (int) (mon->pos() - targ_pos).rdist());
+#endif
+ return (true);
+ }
+
+ mon->travel_path.clear();
+ mon->travel_target = MTRAV_NONE;
+ }
+
+ monster_los lm;
+ lm.set_monster(mon);
+ lm.set_los_range(LOS_RADIUS);
+ lm.fill_los_field();
+
+ int best_dist = INT_MAX;
+ bool best_closer_to_player = false;
+ coord_def best_target;
+
+ for (radius_iterator ri(mon->pos(), LOS_RADIUS, true, false);
+ ri; ++ri)
+ {
+ if (!grid_is_solid(*ri)
+ || monster_habitable_grid(mon, grd(*ri)))
+ {
+ continue;
+ }
+
+ int dist = (mon->pos() - *ri).rdist();
+ bool closer_to_player = false;
+ if (dist > (you.pos() - *ri).rdist())
+ closer_to_player = true;
+
+ if (dist < best_dist)
+ {
+ best_dist = dist;
+ best_closer_to_player = closer_to_player;
+ best_target = *ri;
+ }
+ else if (best_closer_to_player && !closer_to_player
+ && dist == best_dist)
+ {
+ best_closer_to_player = false;
+ best_target = *ri;
+ }
+ }
+
+ if (best_dist == INT_MAX || !in_bounds(best_target))
+ return (false);
+
+ monster_pathfind mp;
+#ifdef WIZARD
+ // Remove old highlighted areas to make place for the new ones.
+ for (rectangle_iterator ri(1); ri; ++ri)
+ env.map(*ri).property &= ~(FPROP_HIGHLIGHT);
+#endif
+
+ if (mp.init_pathfind(mon, best_target))
+ {
+ mon->travel_path = mp.calc_waypoints();
+
+ if (!mon->travel_path.empty())
+ {
+#ifdef WIZARD
+ for (unsigned int i = 0; i < mon->travel_path.size(); i++)
+ env.map(mon->travel_path[i]).property |= FPROP_HIGHLIGHT;
+#endif
+#ifdef DEBUG_PATHFIND
+ mprf("Found a path to (%d, %d)", best_target.x, best_target.y);
+#endif
+ // Okay then, we found a path. Let's use it!
+ mon->target = mon->travel_path[0];
+ mon->travel_target = MTRAV_WALL;
+ return (true);
+ }
+ }
+ return (false);
+}
+
// Returns true if further handling neeeded.
static bool _handle_monster_travelling(monsters *mon,
const dungeon_feature_type can_move)
@@ -3223,6 +3315,16 @@ static void _handle_behaviour(monsters *mon)
return;
}
+ if (mons_wall_shielded(mon) && grid_is_solid(mon->pos()))
+ {
+ // Monster is safe, so it's behaviour can be simplified to fleeing.
+ if (mon->behaviour == BEH_CORNERED || mon->behaviour == BEH_PANIC
+ || isScared)
+ {
+ mon->behaviour = BEH_FLEE;
+ }
+ }
+
const dungeon_feature_type can_move =
(mons_amphibious(mon)) ? DNGN_DEEP_WATER : DNGN_SHALLOW_WATER;
@@ -3624,18 +3726,13 @@ static void _handle_behaviour(monsters *mon)
// possible to get a 'CORNERED' event, at which point
// we can jump back to WANDER if the foe isn't present.
- // XXX: If a monster can move through solid grids, then it
- // should preferentially flee towards the nearest solid grid
- // it can move through. It will be (mostly) safe as soon as
- // it enters the wall, and even if it isn't, once it moves
- // again it will be on the other side of the wall and likely
- // beyond the reach of the player.
-
if (isFriendly)
{
// Special-cased below so that it will flee *towards* you.
mon->target = you.pos();
}
+ else if (mons_wall_shielded(mon) && _find_wall_target(mon))
+ ; // Wall target found.
else if (proxFoe)
{
// Special-cased below so that it will flee *from* the
@@ -3681,6 +3778,16 @@ static void _handle_behaviour(monsters *mon)
mon->foe = new_foe;
}
+
+ if (mon->travel_target == MTRAV_WALL && grid_is_solid(mon->pos()))
+ {
+ if (mon->behaviour == BEH_FLEE)
+ {
+ // Monster is safe, so stay put.
+ mon->target.set(mon->pos().x, mon->pos().y);
+ mon->foe = MHITNOT;
+ }
+ }
}
static bool _mons_check_set_foe(monsters *mon, const coord_def& p,
@@ -4007,7 +4114,7 @@ static void _handle_movement(monsters *monster)
mmov.x = (delta.x > 0) ? 1 : ((delta.x < 0) ? -1 : 0);
mmov.y = (delta.y > 0) ? 1 : ((delta.y < 0) ? -1 : 0);
- if (mons_is_fleeing(monster)
+ if (mons_is_fleeing(monster) && monster->travel_target != MTRAV_WALL
&& (!mons_friendly(monster)
|| monster->target != you.pos()))
{