Exemple #1
0
        public static void GetFenSnippet([NotNull] this PiecePosition position, [NotNull] StringBuilder resultBuilder)
        {
            if (position is null)
            {
                throw new ArgumentNullException(nameof(position));
            }

            if (resultBuilder is null)
            {
                throw new ArgumentNullException(nameof(resultBuilder));
            }

            var emptySquareCount = new ValueContainer <int>(0);

            void WriteEmptySquareCount()
            {
                //// ReSharper disable once InvertIf
                if (emptySquareCount.Value > 0)
                {
                    resultBuilder.Append(emptySquareCount.Value);
                    emptySquareCount.Value = 0;
                }
            }

            for (var rank = ChessConstants.RankCount - 1; rank >= 0; rank--)
            {
                if (rank < ChessConstants.RankCount - 1)
                {
                    resultBuilder.Append(ChessConstants.FenRankSeparator);
                }

                for (var file = 0; file < ChessConstants.FileCount; file++)
                {
                    var square = new Square(file, rank);
                    var piece  = position[square];
                    if (piece == Piece.None)
                    {
                        emptySquareCount.Value++;
                        continue;
                    }

                    WriteEmptySquareCount();
                    var fenChar = piece.GetFenChar();
                    resultBuilder.Append(fenChar);
                }

                WriteEmptySquareCount();
            }
        }
Exemple #2
0
        public bool IsSamePosition(StandardGamePosition other)
        {
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            if (other is null)
            {
                return(false);
            }

            return(ZobristKey == other.ZobristKey &&
                   CastlingOptions == other.CastlingOptions &&
                   ActiveSide == other.ActiveSide &&
                   EnPassantCaptureInfo == other.EnPassantCaptureInfo &&
                   PiecePosition.IsSamePosition(other.PiecePosition));
        }
Exemple #3
0
 public override string ToString() => PiecePosition.GetFenSnippet();
Exemple #4
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);
        }