If the patrol point gets out of sight, zombies don't even attempt to get back. Instead they become confused (not literally, though) and reset their patrol point to 0 (if hostile, thus stop patrolling) or to their current position (to continue "waiting" if friendly). Also, while patrolling, if they reach their target there's a 50% chance of not moving this turn, and 50% the next turn, etc. Especially the latter needs testing. If it looks too stupid even for zombies I'll take it out again.
These changes should also help to make patrolling a bit more efficient because for stupid monsters we have:
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5335 c06c8d41-db1a-0410-9941-cceddc491573
22ORIULMB2NHLFZNJFK2AF275Q6XBKOBE4ZRMOADY64VK5FAUUSQC
K2RBO245UPBDAGMUUMB5EPUNKBDMQ2FM4HLCTTF6Y7ILWW2XVSDQC
UCEAWJ4I6AEFR64SSUFQSX6Q62JGLMJQ5BOO5MQSV3XIE7KAS6CQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
W6IY6LF3MREPXC23AAKA2BJNUCJYCSOWY55DIWJWFLUEE2Y3LGNQC
EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC
P5TRGRH7XMQSPCZKM5IEEO34TY6WMLGHHX7BU6Y453JFRXLUR2VQC
LTX72QGIPNUGWQN5ULPOMFCOPZTK7472DQY4AYX5WM3WHSUVXI5QC
H7AOW4T4Q7AKOXREMK6ZXN3GK6A4I24ICE6VTROMJ5Y3LX47TSDAC
PMCHUVWMCDXOWGXB4SWMBXFGHJYZG7KZ34SE33HFUGHPQYP3LYEAC
BMHUBADDGIOZRVN4P3O5QKIDUYD4RFWBS7MP5X6LZWAYHUBRVD2QC
G5WLU3B4MR3ZDJLGR6OHNIMLZXGQS2EWBJ5YYY5J2GWM6DTD44BAC
6TEISZD7HYSSL24EOKIBNURU66KGSQX7B7SNAHBP4DQSAOTGH2MQC
void monster_los::set_monster(monsters *mon)
{
mons = mon;
if (gridx != mons->x)
gridx = mons->x;
if (gridy != mons->y)
gridy = mons->y;
}
void monster_los::set_los_centre(int x, int y)
{
if (!in_bounds(x, y))
return;
gridx = x;
gridy = y;
}
void monster_los::set_los_range(int r)
{
ASSERT (r >= 1 && r <= LOS_RADIUS);
range = r;
}
}
void monster_los::set_monster(monsters *mon)
{
mons = mon;
if (gridx != mons->x)
gridx = mons->x;
if (gridy != mons->y)
gridy = mons->y;
}
void monster_los::set_los_centre(int x, int y)
{
if (!in_bounds(x, y))
return;
gridx = x;
gridy = y;
int patrol_x = mon->patrol_point.x;
int patrol_y = mon->patrol_point.y;
const int intel = mons_intel(mon->type);
// Zombies will occasionally just stand around.
// This does not mean that they don't move every second turn. Rather,
// once they reach their chosen target, there's a 50% chance they'll
// just remain there until next turn when this function is called
// again.
if (intel == I_PLANT && coinflip())
return (true);
const int patrol_x = mon->patrol_point.x;
const int patrol_y = mon->patrol_point.y;
// If there's no chance we'll find the patrol point, quit right away.
if (grid_distance(mon->x, mon->y, patrol_x, patrol_y) > 2*LOS_RADIUS)
return (false);
const bool patrol_seen = mon->mon_see_grid(patrol_x, patrol_y,
habitat2grid(mons_habitat(mon)));
monster_los lm;
lm.set_monster(mon);
lm.fill_los_field();
bool patrol_seen = lm.in_sight(patrol_x, patrol_y);
if (intel == I_PLANT && !patrol_seen)
{
// Really stupid monsters won't even try to get back into the
// patrol zone.
return (false);
}
// While the patrol point is in easy reach, monsters of insect/plant
// intelligence will only use a range of 5 (distance from the patrol point).
// Otherwise, try to get back using the full LOS.
const int rad = (intel >= I_ANIMAL || !patrol_seen)? LOS_RADIUS : 5;
const bool is_smart = (intel >= I_NORMAL);
// Note: This can take us into a position where the target
// cannot be easily reached (e.g. blocked by a wall) and the
// patrol point is out of sight, too. Such a case will be
// handled below, though it might take a while until a monster
// gets out of a deadlock.
// Only smart monsters will even attempt to move out of the
// patrol area.
// NOTE: Either of these can take us into a position where the
// target cannot be easily reached (e.g. blocked by a wall)
// and the patrol point is out of sight, too. Such a case
// will be handled below, though it might take a while until
// a monster gets out of a deadlock. (5% chance per turn.)
if (one_chance_in(++count_grids))
if (intel == I_PLANT && pos_x == patrol_x && pos_y == patrol_y)
{
// Slightly greater chance to simply head for the centre.
count_grids += 3;
if (random2(count_grids) < 3)
set_target = true;
}
else if (one_chance_in(++count_grids))
set_target = true;
if (set_target)
// it's time to head back.
mon->target_x = mon->patrol_point.x;
mon->target_y = mon->patrol_point.y;
// do one of the following:
// * set current position as new patrol point
// * forget about patrolling
// * head back to patrol point
if (mons_intel(mon->type) == I_PLANT)
{
// Really stupid monsters forget where they're
// supposed to be.
if (mons_friendly(mon))
{
// Your ally was told to wait, and wait it will!
// (Though possibly not where you told it to.)
mon->patrol_point = coord_def(mon->x, mon->y);
}
else
{
// Stop patrolling.
mon->patrol_point = coord_def(0, 0);
}
}
else
{
// It's time to head back!
// Ideally, smart monsters should be able to use
// 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;
}