/** * 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; }
/** * 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; }
/** 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); }
/** 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; }
/** * 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; }
/** * 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(); } }
/** * 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; }
/** * 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; }
/** * 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; }
/** 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; }
/** * 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; }
/** * 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(); }
/** Find the last node that was still in the main variation. */ public static ConstNode getBackToMainVariation(ConstNode node) { while (!isInMainVariation(node)) node = node.getFatherConst(); return node; }
/** * 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; }
/** Return next variation of this node. */ public static ConstNode getNextVariation(ConstNode node) { ConstNode father = node.getFatherConst(); if (father == null) return null; return father.variationAfter(node); }
/** 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); }
/** * Get node reached by going a number of nodes backward. * * @param node The start node. * @param n The number of moves to go backward. * @return The node reached by going n moves backward or the root node of the tree, if there are * less than n nodes in the sequence before the start node. */ public static ConstNode backward(ConstNode node, int n) { assert n >= 0; for (int i = 0; i < n && node.getFatherConst() != null; ++i) node = node.getFatherConst(); return node; }