Esempio n. 1
0
 /**
  * Check if a node is in the main variation of the tree.
  *
  * @param node The node.
  * @return <tt>true</tt>, if the given node is in the main variation, which is the sequence of
  *     nodes starting from the root of the tree and always following the first child.
  */
 public static boolean isInMainVariation(ConstNode node) {
   while (node.getFatherConst() != null) {
     if (node.getFatherConst().getChildConst(0) != node) return false;
     node = node.getFatherConst();
   }
   return true;
 }
Esempio n. 2
0
 /**
  * Get the move number of a node.
  *
  * @param node The node.
  * @return The total number of moves in the sequence of nodes from the root node to the given
  *     node, including the given node.
  */
 public static int getMoveNumber(ConstNode node) {
   int moveNumber = 0;
   while (node != null) {
     if (node.getMove() != null) ++moveNumber;
     node = node.getFatherConst();
   }
   return moveNumber;
 }
Esempio n. 3
0
 /**
  * Get depth of a node.
  *
  * @param node The node.
  * @return The number of nodes in the sequence from the root node to the given node, excluding the
  *     given node (which means that the root node has depth 0).
  */
 public static int getDepth(ConstNode node) {
   int depth = 0;
   while (node.getFatherConst() != null) {
     node = node.getFatherConst();
     ++depth;
   }
   return depth;
 }
Esempio n. 4
0
 /**
  * Get child node containing a certain move.
  *
  * @return null if no such child exists.
  */
 public static ConstNode getChildWithMove(ConstNode node, Move move) {
   for (int i = 0; i < node.getNumberChildren(); ++i) {
     ConstNode child = node.getChildConst(i);
     Move childMove = child.getMove();
     if (childMove != null && childMove.equals(move)) return child;
   }
   return null;
 }
Esempio n. 5
0
 /**
  * Get all children moves.
  *
  * @return Point list containing the move points, not including passes and independent of color.
  */
 public static PointList getChildrenMoves(ConstNode node) {
   PointList moves = new PointList();
   for (int i = 0; i < node.getNumberChildren(); ++i) {
     Move childMove = node.getChildConst(i).getMove();
     if (childMove != null && childMove.getPoint() != null) moves.add(childMove.getPoint());
   }
   return moves;
 }
Esempio n. 6
0
 /** Moves left in main variation. */
 public static int getMovesLeft(ConstNode node) {
   int movesLeft = 0;
   node = node.getChildConst();
   while (node != null) {
     if (node.getMove() != null) ++movesLeft;
     node = node.getChildConst();
   }
   return movesLeft;
 }
Esempio n. 7
0
 /**
  * Check that the time left for a color at a node is known. Returns true, if the last node
  * (including the given one) containing a move of the given color also contains information about
  * the time left after the move for the color. If a previous node with a game info containing time
  * settings exists and no move of the given color was played since then, the function also returns
  * true.
  */
 public static boolean isTimeLeftKnown(ConstNode node, GoColor color) {
   while (node != null) {
     Move move = node.getMove();
     if (move != null && move.getColor() == color) return !Double.isNaN(node.getTimeLeft(color));
     ConstGameInfo info = node.getGameInfoConst();
     if (info != null && info.getTimeSettings() != null) return true;
     node = node.getFatherConst();
   }
   return false;
 }
Esempio n. 8
0
 /**
  * Select a random node in the main variation within a certain depth interval.
  *
  * @param root The root node
  * @param minDepth The minimum depth of the interval (inclusive)
  * @param maxDepth The maximum depth of the interval (inclusive)
  * @return A random node in the given depth interval, null, if there is none.
  */
 public static ConstNode selectRandom(ConstNode root, int minDepth, int maxDepth) {
   ConstNode last = getLast(root);
   int depth = getDepth(last);
   if (depth < minDepth) return null;
   if (depth < maxDepth) maxDepth = depth;
   int idx = minDepth + s_random.nextInt(maxDepth - minDepth + 1);
   ConstNode node = last;
   for (int i = depth; i != idx; --i) node = node.getFatherConst();
   return node;
 }
Esempio n. 9
0
 /** Return next variation before this node. */
 public static ConstNode getNextEarlierVariation(ConstNode node) {
   ConstNode child = node;
   node = node.getFatherConst();
   while (node != null && node.variationAfter(child) == null) {
     child = node;
     node = node.getFatherConst();
   }
   if (node == null) return null;
   return node.variationAfter(child);
 }
Esempio n. 10
0
 /** Check if a node contains a move and has sibling nodes containing other moves. */
 public static boolean hasSiblingMoves(ConstNode node) {
   ConstNode father = node.getFatherConst();
   if (father == null) return false;
   Move move = node.getMove();
   if (move == null) return false;
   for (int i = 0; i < father.getNumberChildren(); ++i) {
     Move childMove = father.getChildConst(i).getMove();
     if (childMove != null && childMove != move) return true;
   }
   return false;
 }
Esempio n. 11
0
 /**
  * Remove SGF properties for information already contained in game info. This can be used for
  * example, if a SGF reader cannot handle an unknown format of the TM property, puts it into the
  * SGF properties of the node to preserve the information for future saving, but later a
  * well-defined time settings was set in the game information of the node. Handles the following
  * properties: TM (because FF3 allowed an arbitrary text in TM), OT (FF4 allows arbitrary text)
  *
  * @return The cleaned properties, empty properties, if node.getSgfProperties() was null
  */
 public static SgfProperties cleanSgfProps(ConstNode node) {
   SgfProperties props = new SgfProperties(node.getSgfPropertiesConst());
   ConstGameInfo info = node.getGameInfoConst();
   if (info != null) {
     if (info.getTimeSettings() != null) {
       props.remove("OT");
       props.remove("TM");
       props.remove("OM"); // FF3
       props.remove("OP"); // FF3
     }
   }
   return props;
 }
Esempio n. 12
0
 /**
  * Find first node with a certain move number in main variation of a given node.
  *
  * @param node The given node.
  * @param moveNumber The move number of the wanted node.
  * @return The node with the given move number or <code>null</code> if no such node exists.
  */
 public static ConstNode findByMoveNumber(ConstNode node, int moveNumber) {
   int maxMoveNumber = getMoveNumber(node) + getMovesLeft(node);
   if (moveNumber < 0 || moveNumber > maxMoveNumber) return null;
   if (moveNumber <= getMoveNumber(node)) {
     while (node.getFatherConst() != null
         && (getMoveNumber(node) > moveNumber || node.getMove() == null))
       node = node.getFatherConst();
   } else {
     while (node.getChildConst() != null && getMoveNumber(node) < moveNumber)
       node = node.getChildConst();
   }
   return node;
 }
Esempio n. 13
0
 /**
  * Check if game is in cleanup stage. Cleanup stage is after two consecutive pass moves have been
  * played.
  */
 public static boolean isInCleanup(ConstNode node) {
   boolean lastPass = false;
   while (node != null) {
     Move move = node.getMove();
     if (move != null) {
       if (move.getPoint() == null) {
         if (lastPass) return true;
         lastPass = true;
       } else lastPass = false;
     }
     node = node.getFatherConst();
   }
   return false;
 }
Esempio n. 14
0
 /**
  * Get comment, but no more than a maximum number of characters.
  *
  * @return Start of comment, with ellipses appended if trunceted; null, if node has no comment.
  */
 public static String getCommentStart(ConstNode node, boolean firstLineOnly, int maxChar) {
   String comment = node.getComment();
   if (comment == null) return null;
   boolean trimmed = false;
   if (firstLineOnly) {
     int pos = comment.indexOf("\n");
     if (pos >= 0) {
       comment = comment.substring(0, pos);
       trimmed = true;
     }
   }
   if (comment.length() > maxChar) {
     comment = comment.substring(0, maxChar);
     trimmed = true;
   }
   if (trimmed) {
     if (maxChar > 30) {
       // Try to find a cut-off at a space
       int pos = comment.lastIndexOf(' ');
       if (pos > 20) {
         if (comment.charAt(pos) == '.') --pos;
         comment = comment.substring(0, pos);
       }
     }
     comment = comment + "...";
   }
   return comment;
 }
Esempio n. 15
0
 /**
  * Get nodes in path from a given node to the root node.
  *
  * @param node The node
  * @param result The resulting path. Passed as an argument to allow reusing an array list. It will
  *     be cleared before it is used.
  */
 public static void getPathToRoot(ConstNode node, ArrayList<ConstNode> result) {
   result.clear();
   while (node != null) {
     result.add(node);
     node = node.getFatherConst();
   }
 }
Esempio n. 16
0
 /**
  * Find next node with a comment in the iteration through complete tree.
  *
  * @param node The current node in the iteration.
  * @return The next node in the iteration through the complete tree after the current node that
  *     has a comment.
  */
 public static ConstNode findNextComment(ConstNode node) {
   node = nextNode(node);
   while (node != null) {
     if (node.hasComment()) return node;
     node = nextNode(node);
   }
   return null;
 }
Esempio n. 17
0
 /** Nodes left in main variation. */
 public static int getNodesLeft(ConstNode node) {
   int nodesLeft = 0;
   while (node != null) {
     ++nodesLeft;
     node = node.getChildConst();
   }
   return nodesLeft;
 }
Esempio n. 18
0
 /**
  * Get a text representation of the variation to a certain node. The string contains the number of
  * the child for each node with more than one child in the path from the root node to this node.
  * The childs are counted starting with 1 and the numbers are separated by colons.
  */
 public static String getVariationString(ConstNode node) {
   ArrayList<String> list = new ArrayList<String>();
   while (node != null) {
     ConstNode father = node.getFatherConst();
     if (father != null && father.getNumberChildren() > 1) {
       int index = father.getChildIndex(node) + 1;
       list.add(0, Integer.toString(index));
     }
     node = father;
   }
   StringBuilder result = new StringBuilder(list.size() * 3);
   for (int i = 0; i < list.size(); ++i) {
     result.append(list.get(i));
     if (i < list.size() - 1) result.append('.');
   }
   return result.toString();
 }
Esempio n. 19
0
 /**
  * Get node reached by going a number of nodes forward.
  *
  * @param node The start node.
  * @param n The number of moves to go forward.
  * @return The node reached by going n moves forward following the main variaton (always the first
  *     child) or the last node in this variation, if it has less than n nodes.
  */
 public static ConstNode forward(ConstNode node, int n) {
   assert n >= 0;
   for (int i = 0; i < n; ++i) {
     ConstNode child = node.getChildConst();
     if (child == null) break;
     node = child;
   }
   return node;
 }
Esempio n. 20
0
 /**
  * Get first node of a given variation. Searches the node that can be reached from the root node
  * by taking the children defined by the integers in the variation string for nodes with more than
  * one child.
  *
  * @param root The root node of the tree.
  * @param variation The variation string (e.g. "1.1.3.1.5").
  * @return The first node of the given variation, or the root node, if the variation string is
  *     empty, or <code>null</code>, if the variation string is invalid or does not specify a node
  *     in the given tree.
  */
 public static ConstNode findByVariation(ConstNode root, String variation) {
   if (variation.trim().equals("")) return root;
   String[] tokens = StringUtil.split(variation, '.');
   int[] n = new int[tokens.length];
   for (int i = 0; i < tokens.length; ++i) {
     try {
       n[i] = Integer.parseInt(tokens[i]) - 1;
       if (n[i] < 0) return null;
     } catch (NumberFormatException e) {
       return null;
     }
   }
   ConstNode node = root;
   for (int i = 0; i < n.length; ++i) {
     while (node.getNumberChildren() <= 1) {
       node = node.getChildConst();
       if (node == null) return null;
     }
     if (n[i] >= node.getNumberChildren()) return null;
     node = node.getChildConst(n[i]);
   }
   return node;
 }
Esempio n. 21
0
 /** Return previous variation before this node. */
 public static ConstNode getPreviousEarlierVariation(ConstNode node) {
   ConstNode child = node;
   node = node.getFatherConst();
   while (node != null && node.variationBefore(child) == null) {
     child = node;
     node = node.getFatherConst();
   }
   if (node == null) return null;
   node = node.variationBefore(child);
   if (node == null) return null;
   while (hasSubtree(node)) node = node.getChildConst(node.getNumberChildren() - 1);
   return node;
 }
Esempio n. 22
0
 /** Return a string containing information and statistics of the subtree of a node. */
 public static String treeInfo(ConstNode node) {
   int numberNodes = 0;
   int numberTerminal = 0;
   int moreThanOneChild = 0;
   int maxDepth = 0;
   int maxChildren = 0;
   double averageDepth = 0;
   double averageChildren = 0;
   double averageChildrenInner = 0;
   int rootDepth = getDepth(node);
   while (node != null) {
     ++numberNodes;
     int numberChildren = node.getNumberChildren();
     int depth = getDepth(node) - rootDepth;
     assert depth >= 0;
     if (depth > maxDepth) maxDepth = depth;
     if (numberChildren > maxChildren) maxChildren = numberChildren;
     if (numberChildren == 0) ++numberTerminal;
     else averageChildrenInner += numberChildren;
     if (numberChildren > 1) ++moreThanOneChild;
     averageDepth += depth;
     averageChildren += numberChildren;
     node = nextNode(node, rootDepth);
   }
   int numberInner = numberNodes - numberTerminal;
   averageDepth /= numberNodes;
   averageChildren /= numberNodes;
   averageChildrenInner /= Math.max(numberInner, 1);
   NumberFormat format = StringUtil.getNumberFormat(3);
   format.setMinimumFractionDigits(3);
   StringBuilder buffer = new StringBuilder();
   appendInfo(buffer, "Nodes", numberNodes);
   appendInfo(buffer, "Terminal", numberTerminal);
   appendInfo(buffer, "Inner", numberInner);
   appendInfo(buffer, "AvgDepth", format.format(averageDepth));
   appendInfo(buffer, "MaxDepth", maxDepth);
   appendInfo(buffer, "AvgChildren", format.format(averageChildren));
   appendInfo(buffer, "AvgChildrenInner", format.format(averageChildrenInner));
   appendInfo(buffer, "MaxChildren", maxChildren);
   appendInfo(buffer, "MoreThanOneChild", moreThanOneChild);
   return buffer.toString();
 }
Esempio n. 23
0
 private static void restoreTimeLeft(ConstNode node, Clock clock, GoColor color) {
   double timeLeft = node.getTimeLeft(color);
   int movesLeft = node.getMovesLeft(color);
   if (!Double.isNaN(timeLeft)) clock.setTimeLeft(color, (long) (timeLeft * 1000), movesLeft);
 }
Esempio n. 24
0
 /**
  * Check if the comment of the current node contains a pattern.
  *
  * @param node The node to check.
  * @param pattern The pattern.
  * @return <tt>true</tt>, if the current node has a comment and a match for the pattern is found
  *     in the comment.
  */
 public static boolean commentContains(ConstNode node, Pattern pattern) {
   String comment = node.getComment();
   return (comment != null && pattern.matcher(comment).find());
 }
Esempio n. 25
0
 /**
  * Return a string containing information about a node. The string contains a listing of the data
  * stored in the node (like moves or setup stones) and properties of the node in the tree (like
  * depth or variation).
  */
 public static String nodeInfo(ConstNode node) {
   StringBuilder buffer = new StringBuilder(128);
   buffer.append("NodeProperties:\n");
   appendInfo(buffer, "Depth", getDepth(node));
   appendInfo(buffer, "Children", node.getNumberChildren());
   if (node.getMove() != null) {
     appendInfo(buffer, "Move", node.getMove().toString());
     appendInfo(buffer, "MoveNumber", getMoveNumber(node));
   }
   appendInfo(buffer, "Variation", getVariationString(node));
   ConstPointList black = node.getSetup(BLACK);
   if (black.size() > 0) appendInfo(buffer, "AddBlack", black);
   ConstPointList white = node.getSetup(WHITE);
   if (white.size() > 0) appendInfo(buffer, "AddWhite", white);
   ConstPointList empty = node.getSetup(EMPTY);
   if (empty.size() > 0) appendInfo(buffer, "AddEmpty", empty);
   if (node.getPlayer() != null) appendInfo(buffer, "Player", node.getPlayer().toString());
   if (!Double.isNaN(node.getTimeLeft(BLACK)))
     appendInfo(buffer, "TimeLeftBlack", node.getTimeLeft(BLACK));
   if (node.getMovesLeft(BLACK) >= 0)
     appendInfo(buffer, "MovesLeftBlack", node.getMovesLeft(BLACK));
   if (!Double.isNaN(node.getTimeLeft(WHITE)))
     appendInfo(buffer, "TimeLeftWhite", node.getTimeLeft(WHITE));
   if (node.getMovesLeft(WHITE) >= 0)
     appendInfo(buffer, "MovesLeftWhite", node.getMovesLeft(WHITE));
   appendInfoComment(buffer, node);
   for (MarkType type : EnumSet.allOf(MarkType.class)) {
     ConstPointList marked = node.getMarkedConst(type);
     if (marked != null && marked.size() > 0) appendInfo(buffer, "Marked " + type, marked);
   }
   Map<GoPoint, String> labels = node.getLabelsUnmodifiable();
   if (labels != null && !labels.isEmpty()) {
     StringBuilder labelsBuffer = new StringBuilder();
     boolean isFirst = true;
     for (Map.Entry<GoPoint, String> entry : labels.entrySet()) {
       if (!isFirst) labelsBuffer.append(' ');
       isFirst = false;
       GoPoint point = entry.getKey();
       String value = entry.getValue();
       labelsBuffer.append(point);
       labelsBuffer.append(':');
       labelsBuffer.append(value);
     }
     appendInfo(buffer, "Labels", labelsBuffer.toString());
   }
   if (!Float.isNaN(node.getValue())) appendInfo(buffer, "Value", Float.toString(node.getValue()));
   ConstGameInfo info = node.getGameInfoConst();
   if (info != null) {
     buffer.append("GameInfo:\n");
     for (StringInfo type : EnumSet.allOf(StringInfo.class)) {
       String s = info.get(type);
       if (s != null) appendInfo(buffer, type.toString(), s);
     }
     for (StringInfoColor type : EnumSet.allOf(StringInfoColor.class)) {
       String s = info.get(type, BLACK);
       if (s != null) appendInfo(buffer, type.toString() + "[B]", s);
       s = info.get(type, WHITE);
       if (s != null) appendInfo(buffer, type.toString() + "[W]", s);
     }
     if (info.getHandicap() != 0) appendInfo(buffer, "HANDICAP", info.getHandicap());
     if (info.getKomi() != null) appendInfo(buffer, "KOMI", info.getKomi().toString());
     if (info.getTimeSettings() != null)
       appendInfo(buffer, "TIMESETTINGS", info.getTimeSettings().toString());
   }
   ConstSgfProperties sgfProperties = node.getSgfPropertiesConst();
   if (sgfProperties != null) {
     buffer.append("SgfProperties:\n");
     for (String key : sgfProperties.getKeys()) {
       StringBuilder values = new StringBuilder();
       for (int i = 0; i < sgfProperties.getNumberValues(key); ++i) {
         values.append('[');
         values.append(sgfProperties.getValue(key, i));
         values.append(']');
       }
       appendInfo(buffer, key, values.toString());
     }
   }
   return buffer.toString();
 }
Esempio n. 26
0
 /** Get next node for iteration through complete tree. */
 public static ConstNode nextNode(ConstNode node) {
   ConstNode child = node.getChildConst();
   if (child != null) return child;
   return getNextEarlierVariation(node);
 }
Esempio n. 27
0
 /** Return previous variation of this node. */
 public static ConstNode getPreviousVariation(ConstNode node) {
   ConstNode father = node.getFatherConst();
   if (father == null) return null;
   return father.variationBefore(node);
 }
Esempio n. 28
0
 /**
  * Check if node is root node and has no children.
  *
  * @param node The node to check.
  * @return <tt>true</tt>, if the node has no father node and no children.
  */
 public static boolean isRootWithoutChildren(ConstNode node) {
   return (!node.hasFather() && !node.hasChildren());
 }
Esempio n. 29
0
 /**
  * Get the root node.
  *
  * @param node The node.
  * @return The root node of the tree that the given node belongs to.
  */
 public static ConstNode getRoot(ConstNode node) {
   while (node.getFatherConst() != null) node = node.getFatherConst();
   return node;
 }
Esempio n. 30
0
 /** Subtree of node contains at least one node with 2 or more children. */
 public static boolean hasSubtree(ConstNode node) {
   while (node != null && node.getNumberChildren() < 2) node = node.getChildConst();
   return (node != null);
 }