Example #1
0
    /// <summary>
    /// Parses Move object into Standard Algebraic Notation move-string
    /// </summary>
    /// <param name="move">Move to parse</param>
    /// <returns>Parsed Move in SAN</returns>
    /// <exception cref="ArgumentNullException">Given move was null or didn't have valid positions values</exception>
    public string ParseToSan(Move move)
    {
        var(succeeded, exception) = SanBuilder.TryParse(this, move, out var san);

        if (!succeeded && exception is not null)
        {
            throw exception;
        }

        return(san !);
    }
Example #2
0
    /// <summary>
    /// Parses San-notated move into Move object<br/>
    /// Long algebraic notation is also acceptable
    /// </summary>
    /// <param name="san">San-notated move to parse</param>
    /// <param name="resetSan">Whether SAN needs to be regenerated</param>
    /// <returns>Parsed Move object</returns>
    /// <exception cref="ChessArgumentException">Given San-notated move didn't match the Regex pattern</exception>
    /// <exception cref="ChessSanNotFoundException">Given San-notated move is not valid for current board positions</exception>
    /// <exception cref="ChessSanTooAmbiguousException">Given San-notated move is too ambiguous between multiple moves</exception>
    public Move ParseFromSan(string san, bool resetSan = false)
    {
        var(succeeded, exception) = SanBuilder.TryParse(this, san, out var move, resetSan);

        if (!succeeded && exception is not null)
        {
            throw exception;
        }

        return(move !);
    }
Example #3
0
    public static (bool succeeded, ChessException?exception) TryLoad(string pgn, out ChessBoard?board)
    {
        board = new();

        var headersMatches = Regexes.regexHeaders.Matches(pgn);

        if (headersMatches.Count > 0)
        {
            // Extracting headers
            for (int i = 0; i < headersMatches.Count; i++)
            {
                // [Black "Geras1mleo"]
                // Groups[1] = Black
                // Groups[2] = Geras1mleo
                board.headers.Add(headersMatches[i].Groups[1].Value,
                                  headersMatches[i].Groups[2].Value);
            }
        }

        // San move can occur in header ex. in nickname of player => remove headers from string
        pgn = Regexes.regexHeaders.Replace(pgn, "");

        // Loading fen if exist
        if (board.headers.TryGetValue("FEN", out var fen))
        {
            var(succeeded, exception) = FenBoardBuilder.TryLoad(fen, out board.FenBuilder);

            if (!succeeded)
            {
                board = null;
                return(false, exception);
            }

            board.pieces = board.FenBuilder.Pieces;

            board.HandleKingChecked();
            board.HandleEndGame();

            if (board.IsEndGame)
            {
                return(true, null);
            }
        }

        // Remove all alternatives
        pgn = Regexes.regexAlternatives.Replace(pgn, "");

        // Remove all comments
        pgn = Regexes.regexComments.Replace(pgn, "");

        // Todo Save Alternative moves(bracnhes) and Comments for moves

        var movesMatches = Regexes.regexSanMoves.Matches(pgn);

        // Execute all found moves
        for (int i = 0; i < movesMatches.Count; i++)
        {
            var(succeeded, exception) = SanBuilder.TryParse(board, movesMatches[i].Value, out var move, true);

            if (!succeeded)
            {
                board = null;
                return(false, exception);
            }

            // If san parsing succeeded => move is valid

            board.executedMoves.Add(move);
            board.DropPieceToNewPosition(move);
            board.moveIndex = board.executedMoves.Count - 1;
        }


        board.HandleKingChecked();
        board.HandleEndGame();

        // If not actual end game but game is in fact ended => someone resigned
        if (!board.IsEndGame)
        {
            if (pgn.Contains("1-0"))
            {
                board.Resign(PieceColor.Black);
            }

            else if (pgn.Contains("0-1"))
            {
                board.Resign(PieceColor.White);
            }

            else if (pgn.Contains("1/2-1/2"))
            {
                board.Draw();
            }
        }

        return(true, null);
    }
Example #4
0
 /// <summary>
 /// Tries to
 /// parse Move object into Standard Algebraic Notation move-string
 /// </summary>
 /// <param name="move">Move to parse</param>
 /// <param name="san">Result with parsed SAN-string</param>
 /// <returns>Whether convertion succeeded</returns>
 public bool TryParseToSan(Move move, [NotNullWhen(true)] out string?san)
 {
     return(SanBuilder.TryParse(this, move, out san).succeeded);
 }
Example #5
0
 /// <summary>
 /// Tries to
 /// parse San-notated move into Move object<br/>
 /// Long algebraic notation is also acceptable
 /// </summary>
 /// <param name="san">San-notated move to parse</param>
 /// <param name="move">Result with parsed Move object</param>
 /// <param name="resetSan">Whether SAN needs to be regenerated</param>
 /// <returns>Whether convert succeeded</returns>
 public bool TryParseFromSan(string san, [NotNullWhen(true)] out Move?move, bool resetSan = false)
 {
     return(SanBuilder.TryParse(this, san, out move, resetSan).succeeded);
 }