static void _move_stair(coord_def stair_pos, bool away)
{
ASSERT(stair_pos != you.pos());
dungeon_feature_type feat = grd(stair_pos);
ASSERT(grid_stair_direction(feat) != CMD_NO_CMD);
coord_def begin, towards;
if (away)
{
begin = you.pos();
towards = stair_pos;
}
else
{
// Can't move towards player if it's already adjacent.
if (adjacent(you.pos(), stair_pos))
return;
begin = stair_pos;
towards = you.pos();
}
ray_def ray;
if (!find_ray(begin, towards, ray))
{
mpr("Couldn't find ray between player and stairs.", MSGCH_ERROR);
return;
}
// Don't start off under the player.
if (away)
ray.advance();
bool found_stairs = false;
int past_stairs = 0;
while ( in_bounds(ray.pos()) && see_grid(ray.pos())
&& !grid_is_solid(ray.pos()) && ray.pos() != you.pos() )
{
if (ray.pos() == stair_pos)
found_stairs = true;
if (found_stairs)
past_stairs++;
ray.advance();
}
past_stairs--;
if (!away && grid_is_solid(ray.pos()))
// Transparent wall between stair and player.
return;
if (away && !found_stairs)
{
if (grid_is_solid(ray.pos()))
// Transparent wall between stair and player.
return;
mpr("Ray didn't cross stairs.", MSGCH_ERROR);
}
if (away && past_stairs <= 0)
// Stairs already at edge, can't move further away.
return;
if (!in_bounds(ray.pos()) || ray.pos() == you.pos())
ray.regress();
while (!see_grid(ray.pos()) || grd(ray.pos()) != DNGN_FLOOR)
{
ray.regress();
if (!in_bounds(ray.pos()) || ray.pos() == you.pos()
|| ray.pos() == stair_pos)
{
// No squares in path are a plain floor.
return;
}
}
ASSERT(stair_pos != ray.pos());
std::string stair_str =
feature_description(stair_pos, false, DESC_CAP_THE, false);
mprf("%s slides %s you!", stair_str.c_str(),
away ? "away from" : "towards");
// Animate stair moving.
const feature_def &feat_def = get_feature_def(feat);
bolt beam;