using Theriapolis.Core.Util;
namespace Theriapolis.Core.Rules.Combat;
///
/// Tactical-tile line-of-sight via Bresenham. The caller supplies a
/// "blocked at (x, y)?" predicate so this helper stays free of a hard
/// dependency on TacticalChunk / WorldState — Phase 5 M4 tests use a flat
/// arena (always-clear); M5 plugs in the live tactical-tile sampler.
///
public static class LineOfSight
{
///
/// True if a straight line from to
/// traverses only un-blocked tiles. Endpoints
/// themselves are NOT consulted — only the intermediate tiles.
///
public static bool HasLine(Vec2 from, Vec2 to, System.Func isBlockedAt)
{
int x0 = (int)System.Math.Floor(from.X);
int y0 = (int)System.Math.Floor(from.Y);
int x1 = (int)System.Math.Floor(to.X);
int y1 = (int)System.Math.Floor(to.Y);
int dx = System.Math.Abs(x1 - x0);
int dy = System.Math.Abs(y1 - y0);
int sx = x0 < x1 ? 1 : -1;
int sy = y0 < y1 ? 1 : -1;
int err = dx - dy;
int x = x0, y = y0;
while (true)
{
// Skip the endpoint itself
if (!(x == x0 && y == y0) && !(x == x1 && y == y1))
{
if (isBlockedAt(x, y)) return false;
}
if (x == x1 && y == y1) return true;
int e2 = 2 * err;
if (e2 > -dy) { err -= dy; x += sx; }
if (e2 < dx) { err += dx; y += sy; }
}
}
/// Convenience: always-clear arena. Used by combat-duel and most M4 tests.
public static readonly System.Func AlwaysClear = (_, _) => false;
}