private void ProcessBestMove(string line, bool tryToPlay) { try { Move bestMove = NotationUtils.ParseMoveString(Board, line.Split(';')[0]); TargetPiece = bestMove.PieceName; TargetPosition = bestMove.Position; TargetMove = bestMove; } catch (Exception) { TargetPiece = PieceName.INVALID; } if (tryToPlay && CurrentTurnIsEngineAI && CurrentGameSettings.GameMode == GameMode.Play && null != TargetMove) { if (TargetMove.IsPass) { SendCommandInternal("pass"); } else { SendCommandInternal("play {0}", NotationUtils.ToBoardSpaceMoveString(Board, TargetMove)); } } }
private void Play(string moveString) { if (null == _gameBoard) { throw new NoBoardException(); } if (_gameBoard.GameIsOver) { throw new GameIsOverException(); } Move move = null; try { move = NotationUtils.ParseMoveString(_gameBoard, moveString); } catch (Exception) { throw new InvalidMoveException(move); } NotationUtils.TryNormalizeBoardSpaceMoveString(moveString, out moveString); _gameBoard.Play(move, moveString); StopPonder(); ConsoleOut(_gameBoard.ToGameString()); }
public void Parse(string s) { if (string.IsNullOrWhiteSpace(s)) { throw new ArgumentNullException(nameof(s)); } s = s.Trim(); string[] vals = s.Split('\t'); Board = GameBoard.ParseGameString(vals[0]); InvalidMoveString = vals[1]; InvalidMove = NotationUtils.ParseMoveString(Board, vals[1]); }
public void Parse(string s) { if (string.IsNullOrWhiteSpace(s)) { throw new ArgumentNullException(nameof(s)); } s = s.Trim(); string[] vals = s.Split('\t'); Board = GameBoard.ParseGameString(vals[0]); ValidMoveStrings = vals[1].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); ValidMoves = new Move[ValidMoveStrings.Length]; for (int i = 0; i < ValidMoveStrings.Length; i++) { ValidMoves[i] = NotationUtils.ParseMoveString(Board, ValidMoveStrings[i]); } }
public static GameRecording LoadSGF(Stream inputStream, string fileName = null) { if (null == inputStream) { throw new ArgumentNullException(nameof(inputStream)); } GameMetadata metadata = new GameMetadata(); List <string> moveList = new List <string>(); Dictionary <string, Stack <string> > backupPositions = new Dictionary <string, Stack <string> >(); string rawResult = ""; bool lastMoveCompleted = true; bool whiteTurn = true; using (StreamReader sr = new StreamReader(inputStream)) { string line = null; while ((line = sr.ReadLine()) != null) { line = line.Trim(); if (!string.IsNullOrWhiteSpace(line)) { // Line has contents Match m = null; if ((m = Regex.Match(line, @"SU\[(.*)\]")).Success) { metadata.SetTag("GameType", m.Groups[1].Value.ToUpper().Replace("HIVE", EnumUtils.NoExpansionsString).Replace("-", "+")); } else if ((m = Regex.Match(line, @"EV\[(.*)\]")).Success) { metadata.SetTag("Event", m.Groups[1].Value); } else if ((m = Regex.Match(line, @"PC\[(.*)\]")).Success) { metadata.SetTag("Site", m.Groups[1].Value); } else if ((m = Regex.Match(line, @"RO\[(.*)\]")).Success) { metadata.SetTag("Round", m.Groups[1].Value); } else if ((m = Regex.Match(line, @"DT\[(.+)\]")).Success) { string rawDate = m.Groups[1].Value; metadata.SetTag("SgfDate", rawDate); rawDate = Regex.Replace(rawDate, @"(\D{3}) (\D{3}) (\d{2}) (\d{2}):(\d{2}):(\d{2}) (.{3,}) (\d{4})", @"$1 $2 $3 $4:$5:$6 $8"); if (DateTime.TryParseExact(rawDate, SgfDateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsed)) { metadata.SetTag("Date", parsed.ToString("yyyy.MM.dd")); } else { foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.AllCultures)) { if (DateTime.TryParseExact(rawDate, SgfDateFormats, ci, DateTimeStyles.None, out parsed)) { metadata.SetTag("Date", parsed.ToString("yyyy.MM.dd")); break; } } } } else if ((m = Regex.Match(line, @"P0\[id ""(.*)""\]")).Success) { metadata.SetTag("White", m.Groups[1].Value); } else if ((m = Regex.Match(line, @"P1\[id ""(.*)""\]")).Success) { metadata.SetTag("Black", m.Groups[1].Value); } else if ((m = Regex.Match(line, @"RE\[(.+)\]")).Success) { rawResult = m.Groups[1].Value; metadata.SetTag("SgfResult", m.Groups[1].Value); } else if ((m = Regex.Match(line, @"GN\[(.+)\]")).Success) { metadata.SetTag("SgfGameName", m.Groups[1].Value); } else if ((m = Regex.Match(line, @"((move (w|b))|(dropb)|(pdropb)) ([a-z0-9]+) ([a-z] [0-9]+) ([a-z0-9\\\-\/\.]*)", RegexOptions.IgnoreCase)).Success) { // Initial parse string movingPiece = m.Groups[m.Groups.Count - 3].Value.ToLower(); string destination = m.Groups[m.Groups.Count - 1].Value.ToLower().Replace("\\\\", "\\"); string backupPos = m.Groups[m.Groups.Count - 2].Value; // Remove unnecessary numbers movingPiece = movingPiece.Replace("m1", "m").Replace("l1", "l").Replace("p1", "p"); destination = destination.Replace("m1", "m").Replace("l1", "l").Replace("p1", "p"); // Add missing color indicator if (movingPiece == "b1" || movingPiece == "b2" || !(movingPiece.StartsWith("b") || movingPiece.StartsWith("w"))) { movingPiece = (whiteTurn ? "w" : "b") + movingPiece; } // Fix missing destination if (destination == ".") { if (moveList.Count == 0) { destination = ""; } else { destination = backupPositions[backupPos].Peek(); } } // Remove move that wasn't commited if (!lastMoveCompleted) { moveList.RemoveAt(moveList.Count - 1); } moveList.Add(string.Format("{0} {1}", movingPiece, destination)); foreach (Stack <string> stack in backupPositions.Values) { if (stack.Count > 0 && stack.Peek() == movingPiece) { stack.Pop(); break; } } if (!backupPositions.ContainsKey(backupPos)) { backupPositions.Add(backupPos, new Stack <string>()); } backupPositions[backupPos].Push(movingPiece); lastMoveCompleted = false; } else if ((m = Regex.Match(line, @"P(0|1)\[[0-9]+ pass\]")).Success) { moveList.Add(NotationUtils.BoardSpacePass); lastMoveCompleted = false; } else if ((m = Regex.Match(line, @"P(0|1)\[[0-9]+ done\]")).Success) { lastMoveCompleted = true; whiteTurn = !whiteTurn; } else if ((m = Regex.Match(line, @"P(0|1)\[[0-9]+ resign\]")).Success) { rawResult = m.Groups[1].Value == "0" ? BoardState.BlackWins.ToString() : BoardState.WhiteWins.ToString(); } } } } GameBoard gameBoard = new GameBoard(metadata.GameType); foreach (string moveString in moveList) { Move move = null; try { move = NotationUtils.ParseMoveString(gameBoard, moveString); } catch (Exception ex) { throw new Exception(string.Format("Unable to parse '{0}'.", moveString), ex); } gameBoard.TrustedPlay(move, NotationUtils.NormalizeBoardSpaceMoveString(moveString)); } // Set result if (rawResult.Contains(metadata.White)) { metadata.SetTag("Result", BoardState.WhiteWins.ToString()); } else if (rawResult.Contains(metadata.Black)) { metadata.SetTag("Result", BoardState.BlackWins.ToString()); } else if (rawResult == "The game is a draw") { metadata.SetTag("Result", BoardState.Draw.ToString()); } else if (Enum.TryParse(rawResult, out BoardState parsed)) { metadata.SetTag("Result", parsed.ToString()); } else { metadata.SetTag("Result", gameBoard.BoardState.ToString()); } return(new GameRecording(gameBoard, GameRecordingSource.SGF, metadata) { FileName = fileName?.Trim() }); }
public static GameRecording LoadPGN(Stream inputStream, string fileName = null) { if (null == inputStream) { throw new ArgumentNullException(nameof(inputStream)); } GameMetadata metadata = new GameMetadata(); List <string> moveList = new List <string>(); string rawResult = ""; string multiLineCommentary = null; using (StreamReader sr = new StreamReader(inputStream, Encoding.ASCII)) { string line = null; while ((line = sr.ReadLine()) != null) { line = line.Trim(); if (null != multiLineCommentary) { // Line is part of multiline commentary multiLineCommentary += Environment.NewLine + line; if (multiLineCommentary.EndsWith("}")) { // End of multiline commentary metadata.SetMoveCommentary(moveList.Count, multiLineCommentary); multiLineCommentary = null; } } else if (line.StartsWith("[") && line.EndsWith("]")) { // Line is a tag KeyValuePair <string, string> kvp = ParsePGNTag(line); if (kvp.Key == "Result") { rawResult = kvp.Value; } else { metadata.SetTag(kvp.Key, kvp.Value); } } else if (line.StartsWith("{") && line.EndsWith("}")) { // Line is a single line of commentary metadata.SetMoveCommentary(moveList.Count, line); } else if (line.StartsWith("{") && null == multiLineCommentary) { multiLineCommentary = line; } else if (!string.IsNullOrWhiteSpace(line)) { // Line is a move or result if (Enum.TryParse(line, out BoardState lineResult)) { rawResult = lineResult.ToString(); } else { // Not a result, add as moveString moveList.Add(line.TrimStart('.', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0')); } } } } GameBoard gameBoard = new GameBoard(metadata.GameType); foreach (string moveString in moveList) { Move move = null; try { move = NotationUtils.ParseMoveString(gameBoard, moveString); } catch (Exception ex) { throw new Exception(string.Format("Unable to parse '{0}'.", moveString), ex); } gameBoard.TrustedPlay(move, moveString); } // Set result if (Enum.TryParse(rawResult, out BoardState result)) { metadata.SetTag("Result", result.ToString()); } else { metadata.SetTag("Result", gameBoard.BoardState.ToString()); } return(new GameRecording(gameBoard, GameRecordingSource.PGN, metadata) { FileName = fileName?.Trim() }); }