示例#1
0
        /// <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 _));
 }