/// <summary> /// Initializes a new instance of the <see cref="CastlingInfo"/> class /// using the specified parameters. /// </summary> internal CastlingInfo( CastlingType castlingType, [NotNull] GameMove kingMove, [NotNull] GameMove rookMove, [NotNull] params Square[] emptySquares) { castlingType.EnsureDefined(); if (kingMove is null) { throw new ArgumentNullException(nameof(kingMove)); } if (emptySquares is null) { throw new ArgumentNullException(nameof(emptySquares)); } if (kingMove.From.Rank != kingMove.To.Rank || Math.Abs(kingMove.From.SquareIndex - kingMove.To.SquareIndex) != 2) { throw new ArgumentException( $@"Invalid castling move '{kingMove.ToUciNotation()}'.", nameof(kingMove)); } CastlingType = castlingType; CastlingSide = castlingType.GetSide(); Option = castlingType.ToOption(); KingMove = kingMove; RookMove = rookMove ?? throw new ArgumentNullException(nameof(rookMove)); EmptySquares = emptySquares.AsReadOnly(); PassedSquare = new Square((kingMove.From.SquareIndex + kingMove.To.SquareIndex) / 2); GameSide = Option.IsAnySet(CastlingOptions.WhiteMask) ? GameSide.White : GameSide.Black; }
public static string ToUciNotation([NotNull] this GameMove move) { if (move is null) { throw new ArgumentNullException(nameof(move)); } var isPromotion = move.PromotionResult != PieceType.None; var chars = new[] { move.From.FileChar, move.From.RankChar, move.To.FileChar, move.To.RankChar, isPromotion ? char.ToLowerInvariant(move.PromotionResult.GetFenChar()) : '\0' }; return(new string(chars, 0, isPromotion ? chars.Length : chars.Length - 1)); }
internal GameMoveData([NotNull] GameMove move, GameMoveFlags moveFlags) { Move = move ?? throw new ArgumentNullException(nameof(move)); MoveFlags = moveFlags; }
internal static string GetStandardAlgebraicNotationInternal( [NotNull] this GameBoard board, [NotNull] GameMove move, [NotNull] out GameBoard nextBoard) { if (board is null) { throw new ArgumentNullException(nameof(board)); } if (move is null) { throw new ArgumentNullException(nameof(move)); } if (!board.ValidMoves.TryGetValue(move, out var moveFlags)) { throw new ArgumentException($@"Invalid move {move} for the board '{board.GetFen()}'.", nameof(move)); } var resultBuilder = new StringBuilder(); if (moveFlags.IsKingCastling()) { var castlingInfo = board.CheckCastlingMove(move).EnsureNotNull(); var isKingSide = (castlingInfo.Option & CastlingOptions.KingSideMask) != 0; resultBuilder.Append(isKingSide ? "O-O" : "O-O-O"); } else { var pieceType = board[move.From].GetPieceType(); switch (pieceType) { case PieceType.None: throw new InvalidOperationException( $@"Invalid move {move} for the board '{board.GetFen()}': no piece at the source square."); case PieceType.Pawn: { if (moveFlags.IsAnyCapture()) { resultBuilder.Append(move.From.FileChar); } break; } case PieceType.Knight: case PieceType.King: case PieceType.Bishop: case PieceType.Rook: case PieceType.Queen: { resultBuilder.Append(pieceType.GetFenChar()); var competitorSquares = board .ValidMoves .Keys .Where(obj => obj != move && obj.To == move.To && board[obj.From].GetPieceType() == pieceType) .Select(obj => obj.From) .ToArray(); if (competitorSquares.Length != 0) { var onSameFile = competitorSquares.Any(square => square.File == move.From.File); var onSameRank = competitorSquares.Any(square => square.Rank == move.From.Rank); if (onSameFile) { if (onSameRank) { resultBuilder.Append(move.From.FileChar); } resultBuilder.Append(move.From.RankChar); } else { resultBuilder.Append(move.From.FileChar); } } break; } default: throw pieceType.CreateEnumValueNotImplementedException(); } if (moveFlags.IsAnyCapture()) { resultBuilder.Append(ChessConstants.CaptureChar); } resultBuilder.Append(move.To); } if (moveFlags.IsPawnPromotion()) { resultBuilder.Append(ChessConstants.PromotionPrefixChar); resultBuilder.Append(move.PromotionResult.GetFenChar()); } nextBoard = board.MakeMove(move); if (nextBoard.State == GameState.Checkmate) { resultBuilder.Append("#"); } else if (nextBoard.State.IsCheck()) { resultBuilder.Append("+"); } return(resultBuilder.ToString()); }
public static string ToStandardAlgebraicNotation([NotNull] this GameMove move, [NotNull] GameBoard board) => GetStandardAlgebraicNotation(board, move);
public static string GetStandardAlgebraicNotation([NotNull] this GameBoard board, [NotNull] GameMove move) { return(GetStandardAlgebraicNotationInternal(board, move, out _)); }