player through the walls. Don't use pathfinding to target other monsters, only the player! Monsters of different intelligence have different limits on the distance they may travel to circumvent an obstacle, i.e. zombies will only use a range of 2, whereas highly intelligent monsters can expertly find their way through (transparent) labyrinths, though there's a chance they'll forget their target if they don't see it, so for very long and winding paths it's likely they don't ever arrive.
Will probably affect performance, though I did test on entire levels turned transparent with Vitrification and things seemed to run more or less smoothly.
Ideally, monsters should also be able to move around other obstacles that don't affect visibility (such as water, lava, or statues) but that is currently not possible.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5700 c06c8d41-db1a-0410-9941-cceddc491573
LH4OYDEWEON5QNUCM74R7MNBJDP7O4XRETY74ZMYSXUXYQV427PAC
3OFG2YD2UOHC6UA7H7LWKOWCNFFSTDOXAA6L3KC335OF5RV3YOYQC
EMOBSWJHHB4V6WVMZL7JCF2V3KZN454Z6NS346OKFPMBNO24EJDQC
Q5YUZONIIPGRWOIQNL6DHRGLKF4V3K5XSZCBH2SL7DP4WPLDNOSQC
AM7QPHDAWNXHLUEVUHVRHG2RO2DOIEFFU4GV3DCIROW6O5HW7H4AC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
P5TRGRH7XMQSPCZKM5IEEO34TY6WMLGHHX7BU6Y453JFRXLUR2VQC
PSCYVKJ7DGXAL3V5U4O6AJTRV6Q3N3SHQWAZ73VIPRTE4W64F2XAC
PFEJ4LMDNEKLMGRCMWQ7EIRVU4JMYGICI4G7X4WVWOROVXQCBZ7QC
LFBNFE3PZBXTR2ROPKYPARUWLJAYWAKGTS7VBWADZWVVSJ5CLX6AC
LTX72QGIPNUGWQN5ULPOMFCOPZTK7472DQY4AYX5WM3WHSUVXI5QC
22ORIULMB2NHLFZNJFK2AF275Q6XBKOBE4ZRMOADY64VK5FAUUSQC
Y4NA3JSN63RLATF4NNBPSR5CWF5Z7UEMWCGVX4B6NOAR47CGM4GQC
7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC
WQLOHSNCA3VOMDJF6IINJYKSYVYZEBPJJWBB33QSNE4RP5HEXPMAC
4GYZYBY7FFORRNPIEFTV4ZM2C7Z6D2KTQOM537ZCC2YBXT2TNSHAC
RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC
TDAVD56MGLFSMJLPLSYLEVW7MBRMT7V5BNII4TRWVDIHH47CD2OAC
TAG_MINOR_PIETY = 2, // Added piety_hysteresis
TAG_MINOR_QUIVER = 3, // Added quiver
TAG_MINOR_MAPMARK = 4, // Added sizes to map markers
TAG_MINOR_MONNAM = 5, // Monsters get individual names
TAG_MINOR_MONBASE = 6, // Zombie base monster gets its own field.
TAG_MINOR_FPICKUP = 7, // Added pickup option for allied monsters.
TAG_MINOR_MPATROL = 8, // Added monster patrol points.
TAG_MINOR_PATHFIND = 9, // Added monster pathfinding.
TAG_MINOR_VERSION = 9 // Current version
TAG_MINOR_PIETY = 2, // Added piety_hysteresis
TAG_MINOR_QUIVER = 3, // Added quiver
TAG_MINOR_MAPMARK = 4, // Added sizes to map markers
TAG_MINOR_MONNAM = 5, // Monsters get individual names
TAG_MINOR_MONBASE = 6, // Zombie base monster gets its own field.
TAG_MINOR_FPICKUP = 7, // Added pickup option for allied monsters.
TAG_MINOR_MPATROL = 8, // Added monster patrol points.
TAG_MINOR_PATHFIND = 9, // Added monster pathfinding.
TAG_MINOR_TRTARGET = 10, // Added travel target.
TAG_MINOR_VERSION = 10 // Current version
if (proxPlayer && !trans_wall_block)
{
if (travelling && mon->travel_target != MTRAV_PATROL)
{
mon->travel_path.clear();
mon->travel_target = MTRAV_NONE;
}
}
else if (proxPlayer && trans_wall_block
&& (mon->travel_target != MTRAV_UNREACHABLE
|| one_chance_in(8)))
{
#ifdef DEBUG_PATHFIND
mprf("%s: Player out of reach! What now?",
mon->name(DESC_PLAIN).c_str());
#endif
// If we're already on our way, do nothing.
if (travelling && mon->travel_target == MTRAV_PLAYER)
{
#ifdef DEBUG_PATHFIND
mpr("Already travelling...");
#endif
int len = mon->travel_path.size();
coord_def targ = mon->travel_path[len - 1];
if (grid_see_grid(targ.x, targ.y, you.x_pos, you.y_pos)
&& !trans_wall_blocking(targ.x, targ.y))
{
#ifdef DEBUG_PATHFIND
mpr("Target still valid...");
#endif
// Current target still valid?
if (mon->x == mon->travel_path[0].x
&& mon->y == mon->travel_path[0].y)
{
// Get next waypoint.
mon->travel_path.erase(
mon->travel_path.begin() );
if (!mon->travel_path.empty())
{
mon->target_x = mon->travel_path[0].x;
mon->target_y = mon->travel_path[0].y;
break;
}
}
else if (grid_see_grid(mon->x, mon->y,
mon->travel_path[0].x,
mon->travel_path[0].y,
can_move))
{
mon->target_x = mon->travel_path[0].x;
mon->target_y = mon->travel_path[0].y;
break;
}
}
}
// Use pathfinding to find a (new) path to the player.
const int dist = grid_distance(mon->x, mon->y,
you.x_pos, you.y_pos);
#ifdef DEBUG_PATHFIND
mprf("Need to calculate a path... (dist = %d)", dist);
#endif
const bool native =
mons_is_native_in_branch(mon, you.where_are_you);
int range = 0;
switch (mons_intel(mon->type))
{
case I_PLANT:
range = 2;
break;
case I_INSECT:
range = 3;
break;
case I_ANIMAL:
range = 5;
break;
case I_NORMAL:
range = 10;
break;
default:
// Highly intelligent monsters can find their way
// anywhere.
range = 0;
break;
}
if (range && native)
range += 3;
if (range > 0 && dist > range)
{
mon->travel_target = MTRAV_UNREACHABLE;
#ifdef DEBUG_PATHFIND
mprf("Distance too great, don't attempt pathfinding! (%s)",
mon->name(DESC_PLAIN).c_str());
#endif
}
else
{
#ifdef DEBUG_PATHFIND
mprf("Need a path for %s from (%d, %d) to (%d, %d), "
"max. dist = %d",
mon->name(DESC_PLAIN).c_str(), mon->x, mon->y,
you.x_pos, you.y_pos, range);
#endif
monster_pathfind mp;
if (range > 0)
mp.set_range(range);
if (mp.start_pathfind(mon, coord_def(you.x_pos,
you.y_pos)))
{
mon->travel_path = mp.calc_waypoints();
if (!mon->travel_path.empty())
{
// Okay then, we found a path. Let's use it!
mon->target_x = mon->travel_path[0].x;
mon->target_y = mon->travel_path[0].y;
mon->travel_target = MTRAV_PLAYER;
break;
}
else
{
#ifdef DEBUG_PATHFIND
mpr("No path found!");
#endif
mon->travel_target = MTRAV_UNREACHABLE;
}
}
else
{
#ifdef DEBUG_PATHFIND
mpr("No path found!");
#endif
mon->travel_target = MTRAV_UNREACHABLE;
}
}
}