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(); } }
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)); }
public override string ToString() => PiecePosition.GetFenSnippet();
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); }