public static IMctsableGameState calculateGameStateFromNode(MctsNode node) { List <IGameTreeNode> pathInTheGameTree = new List <IGameTreeNode>(); IGameTreeNode currentNode = node; pathInTheGameTree.Add(node); while (currentNode.previousNode != null) { pathInTheGameTree.Insert(0, currentNode.previousNode); currentNode = currentNode.previousNode; } MctsRootNode rootNode = currentNode as MctsRootNode; if (rootNode == null) { throw new InvalidOperationException("CLASS: MctsNode, METHOD: calculateGameStateFromNode - no root node available in game tree!"); } IMctsableGameState gameState = rootNode.initialGameState.duplicate(); pathInTheGameTree.RemoveAt(0); foreach (MctsNode pathNode in pathInTheGameTree) { gameState.makeMove(pathNode.move); } return(gameState); }
public void expandNode() { if (areChildNodesExpanded) { return; } areChildNodesExpanded = true; IMctsableGameState gameState = MctsNode.calculateGameStateFromNode(this); List <IMove> possibleMoves = gameState.getPossibleMoves(); INonDeterministicMove possibleNonDeterministicMove; MctsNode[] childs = new MctsNode[possibleMoves.Count]; for (int i = 0; i < possibleMoves.Count; i++) { possibleNonDeterministicMove = possibleMoves[i] as INonDeterministicMove; if (possibleNonDeterministicMove == null) { childs[i] = new MctsNode(this, possibleMoves[i], possibleMoves[i].nextPlayer); } else { childs[i] = new MctsChanceNode(this, possibleNonDeterministicMove, possibleNonDeterministicMove.nextPlayer, possibleNonDeterministicMove.getChildDistribution()); } } _childNodes = childs; }
public MctsChanceNode(MctsNode previousNode, INonDeterministicMove move, int phasingPlayer, ReadOnlyCollection <double> childDistribution) : base(previousNode, move, phasingPlayer) { if (previousNode == null || move == null || childDistribution == null) { throw new ArgumentNullException("CLASS: MctsChanceNode, CONSTRUCTOR - at least one of the given parameter is null!"); } expandNode(); if (childDistribution.Count != getChildNodes().Count) { throw new ArgumentException("CLASS: MctsChanceNode, CONSTRUCTOR - the number of the given probabilities does not coincide with the number of possible moves!!"); } double checksum = 0; for (int i = 0; i < childDistribution.Count; i++) { if (childDistribution[i] < 0 || childDistribution[i] > 1) { throw new ArgumentException("CLASS: MctsChanceNode, CONSTRUCTOR - invalid given probability!"); } checksum += childDistribution[i]; } if (Math.Abs(checksum - 1.0) > Math.Pow(10, _FLOATING_PRECISSION)) { throw new ArgumentException("CLASS: MctsChanceNode, CONSTRUCTOR - invalid distribution (sum has to be 1)!"); } this.childDistribution = childDistribution; }
public void addResult(GameResult gameResult, MctsNode backpropagatingNode) { if (gameResult == null || backpropagatingNode == null) { throw new ArgumentNullException("CLASS: MctsChanceNode, METHOD: addResult - at least one of the given parameter is null!"); } int indexOfBackpropagatingNode; try { indexOfBackpropagatingNode = getChildNodes().IndexOf(backpropagatingNode); } catch (InvalidOperationException) { throw new InvalidOperationException("CLASS: MctsChanceNode, METHOD: addResult - the child nodes do not have been expanded yet!"); } if (indexOfBackpropagatingNode == -1) { throw new ArgumentException("CLASS: MctsChanceNode, METHOD: addResult - the given backpropagating node is not a child node!"); } playouts++; if (gameResult.winner == move.playerWhoDoesTheMove) { value += childDistribution[indexOfBackpropagatingNode] * (1 + gameResult.relativeVictoryPoints); } }
public MctsNode(MctsNode previousNode, IMove move, int phasingPlayer) { this.move = move; this.previousNode = previousNode; this.phasingPlayer = phasingPlayer; areChildNodesExpanded = false; }
public static MctsNode childSelection(MctsNode node, double explorationConstant) { MctsNode selectedChild = childSelectionService(node, explorationConstant) as MctsNode; if (selectedChild == null) { throw new InvalidOperationException("CLASS: MctsNode, METHOD: childSelection - child selection service returns no mcts node!"); } return(selectedChild); }
public static MctsNode finalChildSelection(MctsRootNode node) { MctsNode selectedChild = finalChildSelectionService(node) as MctsNode; if (selectedChild == null) { throw new InvalidOperationException("CLASS: MctsRootNode, METHOD: finalChildSelection - final child selection service returns no mcts node!"); } return(selectedChild); }
private static BackpropagationContainer mctsSearch(IMctsableGameState gameState, MctsNode node) { if (!node.areChildNodesExpanded) { if (node.playouts == 0) { return(defaultPolicy(gameState)); } node.expandNode(); } MctsNode bestNode = MctsNode.childSelection(node, _DEFAULT_EXPLORATION_CONSTANT); gameState.makeMove(bestNode.move); BackpropagationContainer result; if (!gameState.isGameOver()) { result = mctsSearch(gameState, bestNode); } else { result = new BackpropagationContainer(gameState.getResultOfTheGame(), null); } bestNode.addResult(result.gameResult); bestNode.addResultToAMAFChilds(result); if (result.pathToResult != null) { result.addMoveToPath(bestNode.move); } return(result); }