find the nearest exit, and disappear once they reach it. There's a new travel target, MTRAV_EXIT.
Notes:
This is currently very simplistic. The monsters still don't use pathfinding, so if they're blocked, they'll just stand there again.
With shaft traps, the monsters shouldn't try to go directly to the target, since they can't disappear at the same time they fall through to another level.
With teleport traps, they should only go to them when all paths to exits are blocked, and they shouldn't disappear when they hit them. There may also be issues if a monster hits one and reappears nearby, since it won't be far enough outside the player's LOS to disappear.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5935 c06c8d41-db1a-0410-9941-cceddc491573
F4FAPEZ5P5CPHZIHUSRYULB3LY4LOJCUC7DZAYVL77LFFBUBCUNAC
CKUQML2VZN6MF7U72JIFOU4LELG4H2E4NRZDOZYDGCWNPHFLOTEQC
VEVPRVWGRHRKBBUTO64ELK3NPZANUQI3ZZ7F23YXJQLKIORUW3HQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
SXUKGEXMGRRN6UO2GJW4HSVU5TSUNUHIHBMMF7CAG7QMLKZYWTKQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
LH4OYDEWEON5QNUCM74R7MNBJDP7O4XRETY74ZMYSXUXYQV427PAC
NW6P7VRKBFBQ2FRDZBXN7APJZPYC4SYCIA3MOOE2KZGX43IXNK2AC
D7SLVLRNCYCBDYYRANHDG3JYEF25CFCSUY5FMF5KXVD5D4UZSDDAC
Q5YUZONIIPGRWOIQNL6DHRGLKF4V3K5XSZCBH2SL7DP4WPLDNOSQC
}
}
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);
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);
}
// 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;
}