protected TsumegoProblem(string name, SgfGameTree tree, StoneColor colorToPlay) { this.Name = name; this.SgfGameTree = tree; this.ColorToPlay = colorToPlay; this.InitialTree = SpawnThisProblem(); }
/// <summary> /// Creates a tsumego problem from the contents of an SGF file downloaded from online-go.com using /// the Ruby downloader. /// </summary> /// <param name="data">The contents of an SGF file.</param> /// <returns></returns> public static TsumegoProblem CreateFromSgfText(string data) { SgfParser parser = new SgfParser(); var collection = parser.Parse(data); SgfGameTree sgfTree = collection.GameTrees.First(); string problemName = ""; StoneColor playerToPlay = StoneColor.None; foreach (var node in sgfTree.Sequence) { if (node["GN"] != null) { problemName = node["GN"].Value <string>(); } if (node["PL"] != null) { SgfColor sgfColor = node["PL"].Value <SgfColor>(); switch (sgfColor) { case SgfColor.Black: playerToPlay = StoneColor.Black; break; case SgfColor.White: playerToPlay = StoneColor.White; break; } } } return(new TsumegoProblem(problemName, sgfTree, playerToPlay)); }
/// <summary> /// Converts a game tree /// </summary> /// <param name="tree">SGF game tree</param> /// <returns>Game tree root</returns> private GameTree ConvertTree(SgfGameTree tree) { var boardSizeInt = tree.GetPropertyInSequence("SZ")?.Value <int>() ?? 19; if (boardSizeInt == 0) { boardSizeInt = 19; } GameBoardSize boardSize = new GameBoardSize(boardSizeInt); var converted = ConvertBranch(tree, boardSize); var ruleset = new ChineseRuleset(boardSize); // Post-processing converted.ForAllDescendants((node) => node.Branches, node => { if (node.Parent == null) { node.FillBoardStateOfRoot(boardSize, ruleset); } else { node.FillBoardState(ruleset); } }); var gameTree = new GameTree(new ChineseRuleset(boardSize), boardSize, converted); gameTree.LastNode = gameTree.GameTreeRoot; return(gameTree); }
/// <summary> /// Serializes a SGF Game tree /// </summary> /// <param name="gameTree">Game tree</param> /// <returns>Serialized game tree</returns> private string SerializeGameTree([NotNull] SgfGameTree gameTree) { if (gameTree == null) { throw new ArgumentNullException(nameof(gameTree)); } StringBuilder builder = new StringBuilder(); if (_createNewlines) { builder.AppendLine(); } builder.Append('('); builder.Append(SerializeSequence(gameTree.Sequence)); foreach (var child in gameTree.Children) { builder.Append(SerializeGameTree(child)); } builder.Append(')'); if (_createNewlines) { builder.AppendLine(); } return(builder.ToString()); }
/// <summary> /// Parses a SGF game tree /// </summary> /// <param name="input">Input</param> /// <param name="inputPosition">Current input position</param> /// <returns>SGF game tree</returns> private SgfGameTree ParseGameTree(string input, ref int inputPosition) { if (input[inputPosition] != '(') { throw new SgfParseException($"No gameTree node found on input position {inputPosition}"); } inputPosition++; SkipInputWhitespace(input, ref inputPosition); //parse sequence SgfSequence sequence = ParseSequence(input, ref inputPosition); SkipInputWhitespace(input, ref inputPosition); //parse children List <SgfGameTree> children = new List <SgfGameTree>(); while (inputPosition < input.Length && input[inputPosition] == '(') { SgfGameTree child = ParseGameTree(input, ref inputPosition); children.Add(child); SkipInputWhitespace(input, ref inputPosition); } //check proper ending of the game tree if (inputPosition == input.Length || input[inputPosition] != ')') { throw new SgfParseException($"SGF gameTree was not properly terminated with ) at {inputPosition}"); } inputPosition++; return(new SgfGameTree(sequence, children)); }
/// <summary> /// Finds all available game info in the SGF game tree /// </summary> /// <param name="tree">Tree</param> /// <returns>Game info</returns> private GameInfo FindGameInfo(SgfGameTree tree) { var gameInfoSearcher = new SgfGameInfoSearcher(tree); var sgfGameInfo = gameInfoSearcher.GetGameInfo(); return(sgfGameInfo.ToGameInfo()); }
/// <summary> /// Parses a SGF collection /// </summary> /// <param name="input">Input</param> /// <returns>SGF collection</returns> private SgfCollection ParseCollection(string input) { if (string.IsNullOrWhiteSpace(input)) { throw new SgfParseException("Input SGF empty"); } int inputPosition = 0; SkipInputWhitespace(input, ref inputPosition); List <SgfGameTree> gameTrees = new List <SgfGameTree>(); while (inputPosition < input.Length) { if (input[inputPosition] != '(') { throw new SgfParseException($"SGF Root does not begin with ( at {inputPosition}"); } SgfGameTree tree = ParseGameTree(input, ref inputPosition); gameTrees.Add(tree); SkipInputWhitespace(input, ref inputPosition); } SgfCollection collection = new SgfCollection(gameTrees); return(collection); }
/// <summary> /// Counts the number of moves in the primary timeline of a SGF game tree /// </summary> /// <param name="gameTree">SGF game tree</param> /// <returns>Number of moves</returns> private int CountPrimaryLineMoves(SgfGameTree gameTree) { if (gameTree == null) { return(0); } int moveCount = 0; var currentNode = gameTree; while (currentNode != null) { foreach (var node in currentNode.Sequence) { //black move if (node.Properties.ContainsKey("B")) { moveCount++; } //white move if (node.Properties.ContainsKey("W")) { moveCount++; } } currentNode = currentNode.Children.FirstOrDefault(); } return(moveCount); }
private void StartAnalysis(LibraryItemViewModel item, SgfGameTree sgfGameTree) { SgfToGameTreeConverter converter = new SgfToGameTreeConverter(sgfGameTree); var conversionResult = converter.Convert(); var bundle = new AnalyzeOnlyViewModel.NavigationBundle(item, conversionResult.GameTree, conversionResult.GameInfo); Mvx.RegisterSingleton(bundle); ShowViewModel <AnalyzeOnlyViewModel>(); }
/// <summary> /// Converter for a game tree /// </summary> /// <param name="gameTree">SGF Game Tree</param> public SgfToGameTreeConverter(SgfGameTree gameTree) { _inputTree = gameTree; }
/// <summary> /// Converts a SGF tree branch to GameTreeNode /// </summary> /// <param name="branch">Branch</param> /// <returns>Game tree node</returns> private GameTreeNode ConvertBranch(SgfGameTree branch, GameBoardSize boardSize) { GameTreeNode root = null; GameTreeNode current = null; foreach (var node in branch.Sequence) { GameTreeNode newNode = null; if (node["W"] != null) { SgfPoint point = node["W"].Value <SgfPoint>(); //add white move newNode = new GameTreeNode(Move.PlaceStone(StoneColor.White, Position.FromSgfPoint(point, boardSize))); } else if (node["B"] != null) { SgfPoint point = node["B"].Value <SgfPoint>(); //add black move newNode = new GameTreeNode(Move.PlaceStone(StoneColor.Black, Position.FromSgfPoint(point, boardSize))); } else { //add non-move newNode = new GameTreeNode(Move.NoneMove); } if (node["AW"] != null) { //add white moves var property = node["AW"]; var pointRectangles = property.SimpleValues <SgfPointRectangle>(); newNode.AddWhite.AddRange(GetPositionsFromPointRectangles(pointRectangles, boardSize)); } if (node["AB"] != null) { var property = node["AB"]; var pointRectangles = property.SimpleValues <SgfPointRectangle>(); newNode.AddBlack.AddRange(GetPositionsFromPointRectangles(pointRectangles, boardSize)); } if (node["C"] != null) { var property = node["C"]; var comment = property.Value <string>(); newNode.Comment = comment; } // Fill in all markup properties ParseAndFillMarkupProperties(node, newNode, boardSize); if (current == null) { root = newNode; } else { current.Branches.AddNode(newNode); } current = newNode; } //create root if none were found if (root == null) { root = new GameTreeNode(Move.NoneMove); current = root; } //add branches foreach (var child in branch.Children) { var rootOfBranch = ConvertBranch(child, boardSize); current.Branches.AddNode(rootOfBranch); } return(root); }