int UltimateTicTacToeMontecarloAI::expand(int leafIndex, Nodes& nodes, int const player) const { Node& node = nodes[leafIndex]; node.children.reserve(maxChildren); Moves options = movementOptions(node.board, node.previousMove); int turn = node.previousMove > 0 ? otherPlayer(node.board.grids.at(node.previousMove)) : player; int mostPromisingChildIndex = -1; int mostPromisingChildScore = 0; while(node.children.size() < maxChildren && !options.empty()) { Move move = options.takeAt(qrand() % options.size()); int childIndex = nodes.size(); node.children.append(childIndex); Board newBoard(node.board); nodes.append( Node {0, 1, playMove(newBoard, move, turn), move, leafIndex, Node::Children()}); int score = scoreBoard(nodes.last().board, player); if(score > mostPromisingChildScore || mostPromisingChildIndex < 0) { mostPromisingChildIndex = childIndex; mostPromisingChildScore = score; } } return mostPromisingChildIndex; }
int UltimateTicTacToeMontecarloAI::realThink(const UltimateTicTacToeMontecarloAI::Board &board, const int previousMove, const int player) const { //printBoard(board); if(maxIterations == 0) { Moves options = movementOptions(board, previousMove); return options.at(qrand() % options.size()); } //qint64 now = QDateTime::currentMSecsSinceEpoch(); //qDebug() << "c: " << c << ", maxIterations: " << maxIterations << ", maxChildren: " <<maxChildren; Nodes nodes; nodes.reserve(maxIterations * maxChildren); nodes.append(Node { 0, 1, board, previousMove, -1, Node::Children() }); int i; for(i = 0; i < maxIterations; ++i) { int leafIndex = select(nodes); Node const& leaf = nodes.at(leafIndex); GameState leafState = gameState(leaf.board, player); if(leafState == GameState::WIN) { /* qDebug() << "---"; printBoard(leaf.board); */ break; } else if(leafState == GameState::LOSE) { backpropagate(leafIndex, nodes, -10); } else if(leafState == GameState::TIE) { backpropagate(leafIndex, nodes, -5); } else if(leafState == GameState::UNRESOLVED) { int nodeIndex = expand(leafIndex, nodes, player); Node const& node = nodes.at(nodeIndex); int score = simulate(node.board, node.previousMove, player); backpropagate(nodeIndex, nodes, score); } } //qDebug() << "Found solution in " << i + 1 << " iterations"; Node const& root = nodes.at(0); int bestChildIndex = pickBestChild(root, nodes, false); Node const& bestChild = nodes.at(bestChildIndex); //qDebug() << "AI took " << (QDateTime::currentMSecsSinceEpoch() - now) << " ms"; /*for(int childIndex : root.children) { Node const& child = nodes.at(childIndex); qDebug() << child.previousMove << ":" << child.v << child.n; }*/ //qDebug() << bestChild.previousMove / 9 << bestChild.previousMove %9; return bestChild.previousMove; }