many FRs on Sourceforge.
When standing at the end of a corridor, monsters of animal intelligence or higher may swarm out to semi-surround you rather than block the entrance for all monsters behind them.
Example:
####. .rgo@ ####.
will now within two turns change to
which is obviously much smarter. The same logic applies to friendly monsters who presumably form a semicircle around you to protect you.
Also, hostile monsters will even move out of the way if the next monster farther down the corridor has a ranged attack (think centaurs).
This does not yet work for diagonals (but I'm working on that one), and also does not handle monsters stepping out of a corridor to surround non-allied monsters (though this should be easy enough to add).
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7445 c06c8d41-db1a-0410-9941-cceddc491573
IA6EPF5ZQE6276Q4JSUKBSXHX5ODRY5I5UK7LXH4MQEDG36P6PZAC
SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC
TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC
3OFG2YD2UOHC6UA7H7LWKOWCNFFSTDOXAA6L3KC335OF5RV3YOYQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
DK362IHKSDADMUPD35NOTKM4WESQM37KG2PNOJRV2FGELDWULYPQC
247OW5JFN34ZV3GRVHRE25AXLLISUBPOX5YRGUE64BCM2V7QNEHAC
PM65H4V4GNPVIJFUQW57DC3VDB7TRUUNXKVZONQKEFZSK3AXX5GQC
}
}
static bool _allied_monster_at(monsters *mon, coord_def a, coord_def b,
coord_def c)
{
std::vector<coord_def> pos;
pos.push_back(mon->pos() + a);
pos.push_back(mon->pos() + b);
pos.push_back(mon->pos() + c);
for (unsigned int i = 0; i < pos.size(); i++)
{
if (!in_bounds(pos[i]))
continue;
if (mgrd(pos[i]) == NON_MONSTER)
continue;
if (mons_is_stationary(&menv[mgrd(pos[i])]))
return (false);
if (mons_aligned(monster_index(mon), mgrd(pos[i])))
return (true);
}
return (false);
}
static bool _ranged_allied_monster_in_dir(monsters *mon, coord_def p)
{
coord_def pos = mon->pos();
for (int i = 1; i <= LOS_RADIUS; i++)
{
pos += p;
if (!in_bounds(pos))
break;
if (mgrd(pos) == NON_MONSTER)
continue;
if (mons_aligned(monster_index(mon), mgrd(pos)))
{
monsters *m = &menv[mgrd(pos)];
if (mons_has_ranged_attack(m) || mons_has_ranged_spell(m))
return (true);
}
break;
}
const coord_def newpos(monster->pos() + mmov);
FixedArray < bool, 3, 3 > good_move;
for (int count_x = 0; count_x < 3; count_x++)
for (int count_y = 0; count_y < 3; count_y++)
{
const int targ_x = monster->pos().x + count_x - 1;
const int targ_y = monster->pos().y + count_y - 1;
// Bounds check - don't consider moving out of grid!
if (!in_bounds(targ_x, targ_y))
{
good_move[count_x][count_y] = false;
continue;
}
good_move[count_x][count_y] =
_mon_can_move_to_pos(monster, coord_def(count_x-1, count_y-1));
}
// The monster is moving in your direction, to attack or protect you.
if (newpos == you.pos() && mons_intel(monster) >= I_ANIMAL
&& !mons_is_confused(monster) && !mons_is_caught(monster)
&& !monster->has_ench(ENCH_BERSERK))
{
if (mmov.y == 0)
{
if (!good_move[1][0] && !good_move[1][2]
&& (good_move[mmov.x+1][0] || good_move[mmov.x+1][2])
&& (_allied_monster_at(monster, coord_def(-mmov.x, -1),
coord_def(-mmov.x, 0),
coord_def(-mmov.x, 1))
|| mons_intel(monster) >= I_NORMAL
&& !mons_wont_attack(monster)
&& _ranged_allied_monster_in_dir(monster,
coord_def(-mmov.x, 0))))
{
if (good_move[mmov.x+1][0])
mmov.y = -1;
if (good_move[mmov.x+1][2] && (mmov.y == 0 || coinflip()))
mmov.y = 1;
}
}
else if (mmov.x == 0)
{
if (!good_move[0][1] && !good_move[2][1]
&& (good_move[0][mmov.y+1] || good_move[2][mmov.y+1])
&& (_allied_monster_at(monster, coord_def(-1, -mmov.y),
coord_def(0, -mmov.y),
coord_def(1, -mmov.y))
|| mons_intel(monster) >= I_NORMAL
&& !mons_wont_attack(monster)
&& _ranged_allied_monster_in_dir(monster,
coord_def(0, -mmov.y))))
{
if (good_move[0][mmov.y+1])
mmov.x = -1;
if (good_move[2][mmov.y+1] && (mmov.x == 0 || coinflip()))
mmov.x = 1;
}
}