IDType UCTSearch::getPlayerToMove(UCTNode & node, const GameState & state) const { const IDType whoCanMove(state.whoCanMove()); // if both players can move if (whoCanMove == Players::Player_Both) { // pick the first move based on our policy const IDType policy(_params.playerToMoveMethod()); const IDType maxPlayer(_params.maxPlayer()); // the max player always chooses at the root if (isRoot(node)) { return maxPlayer; } // the type of node this is const IDType nodeType = node.getNodeType(); // the 2nd player in a sim move is always the enemy of the first if (nodeType == SearchNodeType::FirstSimNode) { return state.getEnemy(node.getPlayer()); } // otherwise use our policy to see who goes first in a sim move state else { if (policy == SparCraft::PlayerToMove::Alternate) { return state.getEnemy(node.getPlayer()); } else if (policy == SparCraft::PlayerToMove::Not_Alternate) { return node.getPlayer(); } else if (policy == SparCraft::PlayerToMove::Random) { return rand() % 2; } // we should never get to this state System::FatalError("UCT Error: Nobody can move for some reason"); return Players::Player_None; } } else { return whoCanMove; } }
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); } } }