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; }
Move bestMove(const Moves& moves) { if (!moves.empty()) { return *min_element(moves.begin(), moves.end()); } else { return Move(Cost::infinity()); } }
Moves MoveGenerator::generateRemove(const Board& old, QChar color) const { Moves result; for(int i=0; i<23; ++i) { if(old.getManAt(i) == color) { if(!old.closeMill(i)) { // DO NOT use old.makeChild // next is a semi-finished product of a move Board next = old; next.setManAt(i, 'x'); result.push_back(next); } } } if(result.empty()) // no possible remove result.push_back(old); return result; }