public bool IsPositionValidToMoveTo(PiecePosition position, Func <Piece, bool> isFoundPieceValid) { return(position.IsValid() && isFoundPieceValid(GetPiece(position))); }
private List <ChessMoveInfo> FilterOutInvalidKingMoves(Player player, List <ChessMoveInfo> uncheckedKingMoves, int forwardMotion) { var validKingMoves = new List <ChessMoveInfo>(); if (!uncheckedKingMoves.Any()) { return(validKingMoves); } var opponent = player.ToOppositePlayer(); var opponentMoves = CalculateValidMoves(opponent, filterOutInvalidKingMoves: false); foreach (var potentialKingMove in uncheckedKingMoves) { if (!potentialKingMove.IsCastling) { var pieceToCapture = potentialKingMove.MoveSteps.First().PieceToCapture; if (!pieceToCapture.IsNone()) { // If the king would capture a piece with his move, then we cannot use the current valid moves of the opponent to verify // this king move, as said valid moves would be altered after the piece is captured. Hence, we need to pretend to make // the move and then recalculate the opponent's moves in order to verify whether the king would be in check or not. MovesEngine.TryMakeDummyMove <ChessBoard, ChessMoveInfo, ChessBoardState>(this, potentialKingMove, tempBoard => { var opponentMovesAfterKingMove = tempBoard.CalculateValidMoves(opponent, filterOutInvalidKingMoves: false); var kingIsInCheckAfterMove = opponentMovesAfterKingMove.Any(move => move.WouldCaptureKing); if (!kingIsInCheckAfterMove) { validKingMoves.Add(potentialKingMove); } }, shouldBeValid: false); } else { var kingMoveDestination = potentialKingMove.MoveSteps.First().NewPosition; if (!opponentMoves.Any(move => move.MoveSteps.First().PieceToMove.Type != PieceType.Pawn && move.MoveSteps.First().NewPosition.Equals(kingMoveDestination))) { // There is no move that would cause the opponent's piece to land on this new position of the king, // so it is likely that this king move won't result on a check. However, we still have to look for // pawns, as they move differently to capture pieces than they do to advance. var upLeftPosition = new PiecePosition(kingMoveDestination.HorizontalPosition + forwardMotion, kingMoveDestination.VerticalPosition + forwardMotion); var upLeftPiece = upLeftPosition.IsValid() ? GetPiece(upLeftPosition) : null; if (!upLeftPiece.IsNone() && upLeftPiece.Type == PieceType.Pawn && upLeftPiece.Player == opponent) { // After this potential king move, the piece in front of the king and to his left would be an opponent's pawn, // so this move isn't allowed for the king because it would result in a check continue; } var upRightPosition = new PiecePosition(kingMoveDestination.HorizontalPosition - forwardMotion, kingMoveDestination.VerticalPosition + forwardMotion); var upRightPiece = upRightPosition.IsValid() ? GetPiece(upRightPosition) : null; if (!upRightPiece.IsNone() && upRightPiece.Type == PieceType.Pawn && upRightPiece.Player == opponent) { // After this potential king move, the piece in front of the king and to his right would be an opponent's pawn, // so this move isn't allowed for the king because it would result in a check continue; } validKingMoves.Add(potentialKingMove); } } } else { // The castling move can only be made if the king is not currently in check var kingIsInCheck = opponentMoves.Any(move => move.WouldCaptureKing); if (!kingIsInCheck) { validKingMoves.Add(potentialKingMove); } } } return(validKingMoves); }