void xrSmoothNodes() { Nodes smoothed; smoothed.reserve(g_nodes.size()); Marks mark; mark.assign(g_nodes.size(),false); int inv_count = 0; for (u32 i=0; i<g_nodes.size(); i++) { vertex& N = g_nodes[i]; Fvector P1,P2,P3,P4,P,REF; int c; // smooth point LF { bool bCorner = false; c=1; N.PointLF(REF); P1.set(REF); if (N.nLeft()!=InvalidNode) { vertex& L = g_nodes[N.nLeft()]; L.PointFR(P); merge(P1); if (L.nForward()!=InvalidNode) { bCorner = true; vertex& C = g_nodes[L.nForward()]; C.PointRB(P); merge(P1); } } if (N.nForward()!=InvalidNode) { vertex& F = g_nodes[N.nForward()]; F.PointBL(P); merge(P1); if ((!bCorner) && (F.nLeft()!=InvalidNode)) { bCorner = true; vertex& C = g_nodes[F.nLeft()]; C.PointRB(P); merge(P1); } } R_ASSERT(c<=4); P1.div(float(c)); } // smooth point FR { bool bCorner = false; c=1; N.PointFR(REF); P2.set(REF); if (N.nForward()!=InvalidNode) { vertex& F = g_nodes[N.nForward()]; F.PointRB(P); merge(P2); if (F.nRight()!=InvalidNode) { bCorner = true; vertex& C = g_nodes[F.nRight()]; C.PointBL(P); merge(P2); } } if (N.nRight()!=InvalidNode) { vertex& R = g_nodes[N.nRight()]; R.PointLF(P); merge(P2); if ((!bCorner) && (R.nForward()!=InvalidNode)) { bCorner = true; vertex& C = g_nodes[R.nForward()]; C.PointBL(P); merge(P2); } } R_ASSERT(c<=4); P2.div(float(c)); } // smooth point RB { bool bCorner = false; c=1; N.PointRB(REF); P3.set(REF); if (N.nRight()!=InvalidNode) { vertex& R = g_nodes[N.nRight()]; R.PointBL(P); merge(P3); if (R.nBack()!=InvalidNode) { bCorner = true; vertex& C = g_nodes[R.nBack()]; C.PointLF(P); merge(P3); } } if (N.nBack()!=InvalidNode) { vertex& B = g_nodes[N.nBack()]; B.PointFR(P); merge(P3); if ((!bCorner) && (B.nRight()!=InvalidNode)) { bCorner = true; vertex& C = g_nodes[B.nRight()]; C.PointLF(P); merge(P3); } } R_ASSERT(c<=4); P3.div(float(c)); } // smooth point BL { bool bCorner = false; c=1; N.PointBL(REF); P4.set(REF); if (N.nBack()!=InvalidNode) { vertex& B = g_nodes[N.nBack()]; B.PointLF(P); merge(P4); if (B.nLeft()!=InvalidNode) { bCorner = true; vertex& C = g_nodes[B.nLeft()]; C.PointFR(P); merge(P4); } } if (N.nLeft()!=InvalidNode) { vertex& L = g_nodes[N.nLeft()]; L.PointRB(P); merge(P4); if ((!bCorner) && (L.nBack()!=InvalidNode)) { bCorner = true; vertex& C = g_nodes[L.nBack()]; C.PointFR(P); merge(P4); } } R_ASSERT(c<=4); P4.div(float(c)); } // align plane Fvector data[4]; data[0]=P1; data[1]=P2; data[2]=P3; data[3]=P4; Fvector vOffs,vNorm,D; vNorm.set(N.Plane.n); vOffs.set(N.Pos); Mgc::OrthogonalPlaneFit( 4,(Mgc::Vector3*)data, *((Mgc::Vector3*)&vOffs), *((Mgc::Vector3*)&vNorm) ); if (vNorm.y<0) vNorm.invert(); // create _new node vertex NEW = N; NEW.Plane.build (vOffs,vNorm); D.set (0,1,0); N.Plane.intersectRayPoint(N.Pos,D,NEW.Pos); // "project" position smoothed.push_back (NEW); // verify placement /* mark[i] = !!ValidNode (NEW); if (!mark[i]) inv_count++;. */ } g_nodes = smoothed; if (inv_count) Msg("%d invalid nodes detected",inv_count); }
int main(int argc, char **argv) { char *file_input = NULL; int c; Node node; Nodes nodes; struct Summary summary; memset(&summary, 0, sizeof(struct Summary)); // options while ((c = getopt(argc, argv, "i:")) != -1) { switch (c) { case 'i': file_input = optarg; break; default: break; } } if (!file_input) { printf("Usage: ./build_tree -i inputs.txt\n"); exit(EXIT_SUCCESS); } // read input file std::ifstream fin(file_input); if (!fin.is_open()) { std::cerr << "open file failure: " << file_input << std::endl; exit(EXIT_FAILURE); } while (!fin.eof()) { std::string uid; std::string balance; if (!std::getline(fin, uid, '\t') || !std::getline(fin, balance, '\n')) { break; } make_user_node(uid.c_str(), atoll(balance.c_str()), &node); nodes.push_back(node); summary.sum += node.sum; } fin.close(); summary.user_count = nodes.size(); // nodes at level 0 should be sorted std::sort(nodes.begin(), nodes.end()); int idx = 0; Nodes parents; parents.reserve(nodes.size()%2 + 1); while (nodes.size() > 1) { if (nodes.size() % 2 == 1) { summary.padding_sum += nodes[nodes.size()-1].sum; nodes.push_back(nodes[nodes.size()-1]); } for (Nodes::iterator it = nodes.begin(); it != nodes.end(); it++) { std::cout << idx++ << "\t" << summary.level << "\t" << it->sum << "\t"; dump_hex(it->hash, 8); std::cout << std::endl; } parents.resize(0); build_parent_nodes(&nodes, &parents); nodes = parents; summary.level++; } std::cout << idx++ << "\t" << summary.level << "\t" << nodes[0].sum << "\t"; dump_hex(nodes[0].hash, 8); std::cout << std::endl; std::cout << "summary:\t" << summary.user_count << "\t" << summary.sum << "\t" << summary.padding_sum << "\t" << summary.level << std::endl; return 0; }
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; }