StateEvalScore UCTSearch::traverse(UCTNode & node, GameState & currentState) { StateEvalScore playoutVal; _results.totalVisits++; // if we haven't visited this node yet, do a playout if (node.numVisits() == 0) { // update the status of the current state with this node's moves //updateState(node, currentState, !node.hasChildren()); updateState(node, currentState, true); // do the playout playoutVal = currentState.eval(_params.maxPlayer(), _params.evalMethod(), _params.simScript(Players::Player_One), _params.simScript(Players::Player_Two)); _results.nodesVisited++; } // otherwise we have seen this node before else { // update the state for a non-leaf node updateState(node, currentState, false); if (currentState.isTerminal()) { playoutVal = currentState.eval(_params.maxPlayer(), EvaluationMethods::LTD2); } else { // if the children haven't been generated yet if (!node.hasChildren()) { generateChildren(node, currentState); } UCTNode & next = UCTNodeSelect(node); playoutVal = traverse(next, currentState); } } node.incVisits(); if (playoutVal.val() > 0) { node.addWins(1); } else if (playoutVal.val() == 0) { node.addWins(0.5); } return playoutVal; }
void UCTSearch::printSubTreeGraphViz(UCTNode & node, GraphViz::Graph & g, GameState state) { if (node.getNodeType() == SearchNodeType::FirstSimNode && node.hasChildren()) { // don't make any moves if it is a first simnode } else { if (node.getNodeType() == SearchNodeType::SecondSimNode) { state.makeMoves(node.getParent()->getMove()); } state.makeMoves(node.getMove()); state.finishedMoving(); } std::stringstream label; std::stringstream move; for (size_t a(0); a<node.getMove().size(); ++a) { move << node.getMove()[a].moveString() << "\\n"; } if (node.getMove().size() == 0) { move << "root"; } std::string firstSim = SearchNodeType::getName(node.getNodeType()); Unit p1 = state.getUnit(0,0); Unit p2 = state.getUnit(1,0); label << move.str() << "\\nVal: " << node.getUCTVal() << "\\nWins: " << node.numWins() << "\\nVisits: " << node.numVisits() << "\\nChildren: " << node.numChildren() << "\\n" << firstSim << "\\nPtr: " << &node << "\\n---------------" << "\\nFrame: " << state.getTime() << "\\nHP: " << p1.currentHP() << " " << p2.currentHP() << "\\nAtk: " << p1.nextAttackActionTime() << " " << p2.nextAttackActionTime() << "\\nMove: " << p1.nextMoveActionTime() << " " << p2.nextMoveActionTime() << "\\nPrev: " << p1.previousActionTime() << " " << p2.previousActionTime(); std::string fillcolor ("#aaaaaa"); if (node.getPlayer() == Players::Player_One) { fillcolor = "#ff0000"; } else if (node.getPlayer() == Players::Player_Two) { fillcolor = "#00ff00"; } GraphViz::Node n(getNodeIDString(node)); n.set("label", label.str()); n.set("fillcolor", fillcolor); n.set("color", "#000000"); n.set("fontcolor", "#000000"); n.set("style", "filled,bold"); n.set("shape", "box"); g.addNode(n); // recurse for each child for (size_t c(0); c<node.numChildren(); ++c) { UCTNode & child = node.getChild(c); if (child.numVisits() > 0) { GraphViz::Edge edge(getNodeIDString(node), getNodeIDString(child)); g.addEdge(edge); printSubTreeGraphViz(child, g, state); } } }