/// <summary> /// Loads ChessBoard from Forsyth-Edwards Notation<br/> /// ex.:<br/> /// rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1 /// </summary> /// <param name="fen">FEN string to load</param> /// <returns>ChessBoard with according positions</returns> /// <exception cref="ChessArgumentException">Given FEN string didn't match the Regex pattern</exception> public static ChessBoard LoadFromFen(string fen) { var(succeeded, exception) = FenBoardBuilder.TryLoad(fen, out var builder); if (!succeeded && exception is not null) { throw exception; } return(BuildBoardFromFen(builder)); }
/// <summary> /// Tries to load /// ChessBoard from Forsyth-Edwards Notation<br/> /// ex.:<br/> /// rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1 /// </summary> /// <param name="fen">FEN string to load</param> /// <param name="board">Result with loaded board</param> /// <returns>Whether load is succeeded</returns> public static bool TryLoadFromFen(string fen, [NotNullWhen(true)] out ChessBoard?board) { var(succeeded, _) = FenBoardBuilder.TryLoad(fen, out var builder); if (!succeeded) { board = null; return(false); } board = BuildBoardFromFen(builder); return(true); }
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); }