protected virtual GameCreationData FenStringToGameCreationData(string fen) { Dictionary <char, Piece> fenMappings = FenMappings; string[] parts = fen.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (!AllowedFenPartsLength.Contains(parts.Length)) { throw new ArgumentException("The FEN string has too much, or too few, parts."); } Piece[][] board = new Piece[8][]; string[] rows = parts[0].Split('/'); if (!ValidFenBoardRows.Contains(rows.Length)) { throw new ArgumentException("The board in the FEN string has an invalid number of rows."); } GameCreationData data = new GameCreationData(); data.Board = InterpretBoardOfFen(parts[0]); if (parts[1] == "w") { data.WhoseTurn = Player.White; } else if (parts[1] == "b") { data.WhoseTurn = Player.Black; } else { throw new ArgumentException("Expected `w` or `b` for the active player in the FEN string."); } if (parts[2].Contains("K")) { data.CanWhiteCastleKingSide = true; } else { data.CanWhiteCastleKingSide = false; } if (parts[2].Contains("Q")) { data.CanWhiteCastleQueenSide = true; } else { data.CanWhiteCastleQueenSide = false; } if (parts[2].Contains("k")) { data.CanBlackCastleKingSide = true; } else { data.CanBlackCastleKingSide = false; } if (parts[2].Contains("q")) { data.CanBlackCastleQueenSide = true; } else { data.CanBlackCastleQueenSide = false; } if (parts[3] == "-") { data.EnPassant = null; } else { Position ep = new Position(parts[3]); if ((data.WhoseTurn == Player.White && (ep.Rank != 6 || !(data.Board[3][(int)ep.File] is Pawn))) || (data.WhoseTurn == Player.Black && (ep.Rank != 3 || !(data.Board[4][(int)ep.File] is Pawn)))) { throw new ArgumentException("Invalid en passant field in FEN."); } data.EnPassant = ep; } int halfmoveClock; if (int.TryParse(parts[4], out halfmoveClock)) { data.HalfMoveClock = halfmoveClock; } else { throw new ArgumentException("Halfmove clock in FEN is invalid."); } int fullMoveNumber; if (int.TryParse(parts[5], out fullMoveNumber)) { data.FullMoveNumber = fullMoveNumber; } else { throw new ArgumentException("Fullmove number in FEN is invalid."); } return(data); }
protected virtual GameCreationData FenStringToGameCreationData(string fen) { Dictionary <char, ChessPiece> fenMappings = FenMappings; string[] parts = fen.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (!AllowedFenPartsLength.Contains(parts.Length)) { throw new ArgumentException("The FEN string has too much, or too few, parts."); } ChessPiece[][] board = new ChessPiece[8][]; string[] rows = parts[0].Split('/'); if (rows.Length != 8) { throw new ArgumentException("The board in the FEN string does not have 8 rows."); } GameCreationData data = new GameCreationData(); for (int i = 0; i < 8; i++) { string row = rows[i]; ChessPiece[] currentRow = new ChessPiece[8] { null, null, null, null, null, null, null, null }; int j = 0; foreach (char c in row) { if (char.IsDigit(c)) { j += (int)char.GetNumericValue(c); continue; } if (!fenMappings.ContainsKey(c)) { throw new ArgumentException("The FEN string contains an unknown piece."); } currentRow[j] = fenMappings[c]; j++; } if (j != 8) { throw new ArgumentException("Not enough pieces provided for a row in the FEN string."); } board[i] = currentRow; } data.Board = board; if (parts[1] == "w") { data.WhoseTurn = ChessPlayer.White; } else if (parts[1] == "b") { data.WhoseTurn = ChessPlayer.Black; } else { throw new ArgumentException("Expected `w` or `b` for the active player in the FEN string."); } if (parts[2].Contains('K')) { data.CanWhiteCastleKingSide = true; } else { data.CanWhiteCastleKingSide = false; } if (parts[2].Contains('Q')) { data.CanWhiteCastleQueenSide = true; } else { data.CanWhiteCastleQueenSide = false; } if (parts[2].Contains('k')) { data.CanBlackCastleKingSide = true; } else { data.CanBlackCastleKingSide = false; } if (parts[2].Contains('q')) { data.CanBlackCastleQueenSide = true; } else { data.CanBlackCastleQueenSide = false; } if (parts[3] == "-") { data.EnPassant = null; } else { BoardPosition ep = new BoardPosition(parts[3]); if ((data.WhoseTurn == ChessPlayer.White && (ep.Rank != 6 || !(data.Board[3][(int)ep.File] is Pawn))) || (data.WhoseTurn == ChessPlayer.Black && (ep.Rank != 3 || !(data.Board[4][(int)ep.File] is Pawn)))) { throw new ArgumentException("Invalid en passant field in FEN."); } data.EnPassant = ep; } if (int.TryParse(parts[4], out int halfmoveClock)) { data.HalfMoveClock = halfmoveClock; } else { throw new ArgumentException("Halfmove clock in FEN is invalid."); } if (int.TryParse(parts[5], out int fullMoveNumber)) { data.FullMoveNumber = fullMoveNumber; } else { throw new ArgumentException("Fullmove number in FEN is invalid."); } return(data); }