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;
}