Exemplo n.º 1
0
        private static Bitboard[] InitializeKnightAttacksOrMoves()
        {
            var result = new Bitboard[ChessConstants.SquareCount];

            for (var squareIndex = 0; squareIndex < ChessConstants.SquareCount; squareIndex++)
            {
                var square      = new Square(squareIndex);
                var moveSquares = ChessHelper.GetKnightMoveSquares(square);
                var bitboard    = new Bitboard(moveSquares);
                result[squareIndex] = bitboard;
            }

            return(result);
        }
Exemplo n.º 2
0
        private static bool TryCreateInternal(
            [NotNull] string fen,
            out string errorDetails,
            out StandardGamePosition result)
        {
            if (fen.IsNullOrWhiteSpace())
            {
                errorDetails = "The FEN cannot be empty.";
                result       = null;
                return(false);
            }

            var fenSnippets = fen
                              .Trim()
                              .Split(ChessConstants.FenSnippetSeparator.AsArray(), StringSplitOptions.None);

            if (fenSnippets.Length != ChessConstants.FenSnippetCount)
            {
                errorDetails = "Invalid FEN format.";
                result       = null;
                return(false);
            }

            var piecePositionFen = fenSnippets[0];

            if (!PiecePosition.TryCreate(piecePositionFen, out var piecePosition))
            {
                errorDetails = "Invalid position of pieces.";
                result       = null;
                return(false);
            }

            var activeSideSnippet = fenSnippets[1];

            if (!ChessConstants.FenSnippetToGameSideMap.TryGetValue(activeSideSnippet, out var activeSide))
            {
                errorDetails = "Invalid active side.";
                result       = null;
                return(false);
            }

            var castlingOptions        = CastlingOptions.None;
            var castlingOptionsSnippet = fenSnippets[2];

            if (castlingOptionsSnippet != ChessConstants.NoneCastlingOptionsFenSnippet)
            {
                var castlingOptionsSnippetSet = OmnifactotumCollectionExtensions.ToHashSet(castlingOptionsSnippet);
                foreach (var optionChar in castlingOptionsSnippetSet)
                {
                    if (!ChessConstants.FenCharCastlingOptionMap.TryGetValue(optionChar, out var option))
                    {
                        errorDetails = "Invalid castling options.";
                        result       = null;
                        return(false);
                    }

                    castlingOptions |= option;
                }
            }

            EnPassantCaptureInfo2?enPassantCaptureInfo = null;
            var enPassantCaptureTargetSnippet          = fenSnippets[3];

            if (enPassantCaptureTargetSnippet != ChessConstants.NoEnPassantCaptureFenSnippet)
            {
                const string InvalidEnPassant = "Invalid en-passant.";

                var captureSquare = Square.TryFromAlgebraic(enPassantCaptureTargetSnippet);
                if (!captureSquare.HasValue)
                {
                    errorDetails = InvalidEnPassant;
                    result       = null;
                    return(false);
                }

                var enPassantInfo =
                    ChessConstants.GameSideToDoublePushInfoMap.Values.SingleOrDefault(
                        obj => obj.CaptureTargetRank == captureSquare.Value.Rank);

                if (enPassantInfo is null)
                {
                    errorDetails = InvalidEnPassant;
                    result       = null;
                    return(false);
                }

                enPassantCaptureInfo = new EnPassantCaptureInfo2(
                    captureSquare.Value,
                    new Square(captureSquare.Value.File, enPassantInfo.EndRank));
            }

            var halfMovesBy50MoveRuleSnippet = fenSnippets[4];

            if (!ChessHelper.TryParseInt(halfMovesBy50MoveRuleSnippet, out var halfMovesBy50MoveRule) ||
                halfMovesBy50MoveRule < 0)
            {
                errorDetails = "Invalid half move counter for the 50 move rule.";
                result       = null;
                return(false);
            }

            var fullMoveIndexSnippet = fenSnippets[5];

            if (!ChessHelper.TryParseInt(fullMoveIndexSnippet, out var fullMoveIndex) || fullMoveIndex <= 0)
            {
                errorDetails = "Invalid move index.";
                result       = null;
                return(false);
            }

            result = new StandardGamePosition(
                piecePosition,
                activeSide,
                fullMoveIndex,
                castlingOptions,
                enPassantCaptureInfo,
                halfMovesBy50MoveRule);

            errorDetails = null;
            return(true);
        }