summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monstuff.cc
diff options
context:
space:
mode:
authorharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-02 13:42:17 +0000
committerharanp <haranp@c06c8d41-db1a-0410-9941-cceddc491573>2009-01-02 13:42:17 +0000
commit654f48b0e2c49245a1983fbeff889c99fa651d57 (patch)
treef0a890a75ecb9f19557cc15be49509a6ef5b0d4e /crawl-ref/source/monstuff.cc
parent1fa85b4ecc24308a1c4b565522062a7cfeda3809 (diff)
downloadcrawl-ref-654f48b0e2c49245a1983fbeff889c99fa651d57.tar.gz
crawl-ref-654f48b0e2c49245a1983fbeff889c99fa651d57.zip
Fix monster blinks not respecting their preferred habitat.
Fixes [2482177]. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8115 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/monstuff.cc')
-rw-r--r--crawl-ref/source/monstuff.cc74
1 files changed, 65 insertions, 9 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index d0ebed5742..9759f977e6 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -1983,22 +1983,78 @@ bool monster_polymorph(monsters *monster, monster_type targetc,
return (player_messaged);
}
-bool monster_blink(monsters *monster)
+// If the returned value is mon.pos(), then nothing was found.
+static coord_def _random_monster_nearby_habitable_space(const monsters& mon,
+ bool allow_adjacent,
+ bool respect_los)
{
- coord_def near;
-
+ const bool respect_sanctuary = mons_wont_attack(&mon);
+
+ coord_def target;
+ int tries;
{
- unwind_var<env_show_grid> visible_grid( env.show );
- losight(env.show, grd, monster->pos(), true);
+ // Save LOS, because we're going to clobber it with monster LOS.
+ unwind_var<env_show_grid> visible_grid(env.show);
- if (!random_near_space(monster->pos(), near,
- false, true,
- !mons_wont_attack(monster)))
+ // Do the clobbering.
+ losight(env.show, grd, mon.pos(), true);
+
+ for (tries = 0; tries < 150; ++tries)
{
- return (false);
+ const coord_def delta(random2(14), random2(14));
+
+ // Check that we don't get something too close to the
+ // starting point.
+ if (delta.origin())
+ continue;
+
+ if (delta.rdist() == 1 && !allow_adjacent)
+ continue;
+
+ // Update target.
+ target = delta + mon.pos();
+
+ // Check that the target is valid and survivable.
+ if (!in_bounds(target))
+ continue;
+
+ if (!monster_habitable_grid(&mon, grd(target)))
+ continue;
+
+ if (respect_sanctuary && is_sanctuary(target))
+ continue;
+
+ // Check that we didn't go through clear walls.
+ if (num_feats_between(target, mon.pos(),
+ DNGN_CLEAR_ROCK_WALL,
+ DNGN_CLEAR_PERMAROCK_WALL,
+ true, true) > 0)
+ {
+ continue;
+ }
+
+ // Note that this uses the clobbered LOS!
+ if (respect_los && !see_grid(target))
+ continue;
+
+ // Survived everything, break out (with a good value of target.)
+ break;
}
}
+ if (tries == 150)
+ target = mon.pos();
+
+ return (target);
+}
+
+bool monster_blink(monsters *monster)
+{
+ coord_def near = _random_monster_nearby_habitable_space(*monster, false,
+ true);
+ if (near == monster->pos())
+ return (false);
+
mons_clear_trapping_net(monster);
const coord_def oldplace = monster->pos();