using Chessistics.Engine.Model; namespace Chessistics.Engine.Rules; public static class MoveValidator { private static readonly (int dc, int dr)[] OrthogonalDirs = [(0, 1), (0, -1), (1, 0), (-1, 0)]; private static readonly (int dc, int dr)[] DiagonalDirs = [(1, 1), (1, -1), (-1, 1), (-1, -1)]; private static readonly (int dc, int dr)[] AllDirs = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]; private static readonly (int dc, int dr)[] KnightOffsets = [ (1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1, 2) ]; public static IReadOnlyList GetLegalEndCells(PieceKind kind, Coords start, BoardState board) { if (!board.IsOnBoard(start) || board.GetCell(start) == CellType.Wall) return []; return kind switch { PieceKind.Pawn => GetSlidingMoves(start, OrthogonalDirs, 1, board), PieceKind.Rook => GetSlidingMoves(start, OrthogonalDirs, 2, board), PieceKind.Bishop => GetSlidingMoves(start, DiagonalDirs, 2, board), PieceKind.Knight => GetKnightMoves(start, board), PieceKind.Queen => GetSlidingMoves(start, AllDirs, 2, board), _ => [] }; } public static bool IsLegalPlacement(PieceKind kind, Coords start, Coords end, BoardState board) { return GetLegalEndCells(kind, start, board).Contains(end); } private static IReadOnlyList GetSlidingMoves( Coords start, (int dc, int dr)[] directions, int maxRange, BoardState board) { var result = new List(); foreach (var (dc, dr) in directions) { for (int dist = 1; dist <= maxRange; dist++) { var target = new Coords(start.Col + dc * dist, start.Row + dr * dist); if (!board.IsOnBoard(target)) break; if (board.GetCell(target) == CellType.Wall) break; // Only walls block the path. Other pieces do NOT block during edit. // Collisions are detected at runtime during simulation. result.Add(target); } } return result; } private static IReadOnlyList GetKnightMoves(Coords start, BoardState board) { var result = new List(); foreach (var (dc, dr) in KnightOffsets) { var target = new Coords(start.Col + dc, start.Row + dr); if (!board.IsOnBoard(target)) continue; if (board.GetCell(target) == CellType.Wall) continue; result.Add(target); } return result; } }