From 94a02ff6849436d9496c70a0f16c21666dae8e4e Mon Sep 17 00:00:00 2001 From: Janis Date: Mon, 23 Mar 2026 21:42:21 +0100 Subject: [PATCH] feat: implement GameRules with isInCheck, legalMoves, gameStatus Co-Authored-By: Claude Sonnet 4.6 --- .../de/nowchess/chess/logic/GameRules.scala | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/modules/core/src/main/scala/de/nowchess/chess/logic/GameRules.scala b/modules/core/src/main/scala/de/nowchess/chess/logic/GameRules.scala index da42ea5..c788651 100644 --- a/modules/core/src/main/scala/de/nowchess/chess/logic/GameRules.scala +++ b/modules/core/src/main/scala/de/nowchess/chess/logic/GameRules.scala @@ -8,10 +8,35 @@ enum PositionStatus: object GameRules: /** True if `color`'s king is under attack on this board. */ - def isInCheck(board: Board, color: Color): Boolean = false + def isInCheck(board: Board, color: Color): Boolean = + board.pieces + .collectFirst { case (sq, p) if p.color == color && p.pieceType == PieceType.King => sq } + .exists { kingSq => + board.pieces.exists { case (sq, piece) => + piece.color != color && + MoveValidator.legalTargets(board, sq).contains(kingSq) + } + } /** All (from, to) moves for `color` that do not leave their own king in check. */ - def legalMoves(board: Board, color: Color): Set[(Square, Square)] = Set.empty + def legalMoves(board: Board, color: Color): Set[(Square, Square)] = + board.pieces + .collect { case (from, piece) if piece.color == color => from } + .flatMap { from => + MoveValidator.legalTargets(board, from) + .filter { to => + val (newBoard, _) = board.withMove(from, to) + !isInCheck(newBoard, color) + } + .map(to => from -> to) + } + .toSet /** Position status for the side whose turn it is (`color`). */ - def gameStatus(board: Board, color: Color): PositionStatus = PositionStatus.Normal + def gameStatus(board: Board, color: Color): PositionStatus = + val moves = legalMoves(board, color) + val inCheck = isInCheck(board, color) + if moves.isEmpty && inCheck then PositionStatus.Mated + else if moves.isEmpty then PositionStatus.Drawn + else if inCheck then PositionStatus.InCheck + else PositionStatus.Normal