Chessistics/chessistics-engine/Rules/MoveValidator.cs
Samuel Bouchet 8918140114 Phase 5: Dame (Queen) piece and network levels 7-8
Dame (Queen):
- Moves 1-2 cells in all 8 directions (orthogonal + diagonal)
- Social status 7 (highest — priority over all other pieces)
- Deep burgundy color, letter "D"
- Rare and powerful, forces strategic placement choices

Levels:
- Level 7 "La Dame Blanche": 10x10, walled arena with central fortress,
  1 queen available as a logistics superweapon
- Level 8 "Le Grand Reseau": 12x10, 4 productions + 4 demands,
  two vertical wall corridors, 2 queens, full network challenge

GDD updated with Dame section and status hierarchy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:24:14 +02:00

82 lines
2.7 KiB
C#

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<Coords> 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<Coords> GetSlidingMoves(
Coords start, (int dc, int dr)[] directions, int maxRange, BoardState board)
{
var result = new List<Coords>();
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<Coords> GetKnightMoves(Coords start, BoardState board)
{
var result = new List<Coords>();
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;
}
}