const Node* explore(const State& startState, TerminationChecker& terminationChecker) { ++iterationCounter; clearOpenList(); openList.reorder(fComparator); Planner::incrementGeneratedNodeCount(); Node*& startNode = nodes[startState]; if (startNode == nullptr) { startNode = nodePool->construct(Node{nullptr, startState, Action(), 0, domain.heuristic(startState), true}); } else { startNode->g = 0; startNode->action = Action(); startNode->predecessors.clear(); startNode->parent = nullptr; } startNode->iteration = iterationCounter; addToOpenList(*startNode); while (!terminationChecker.reachedTermination() && openList.isNotEmpty()) { Node* const currentNode = popOpenList(); if (domain.isGoal(currentNode->state)) { return currentNode; } terminationChecker.notifyExpansion(); expandNode(currentNode); } return openList.top(); }
void RxDev::showContextMenu_availableNodes(const QPoint&point){ QMenu contextMenu_availableNodes; QModelIndex index(ui->treeView_availableNodes->indexAt(point)); //menuPoint_availableNodes = point; //const QModelIndex index = ui->treeView_availableNodes->selectionModel()->currentIndex(); QModelIndex seekRoot = index; if(index.isValid()){ while(seekRoot.parent() != QModelIndex()) { seekRoot = seekRoot.parent(); } contextMenu_availableNodes.addAction(tr("view/edit Specfile"),this, SLOT(openSpecFile())); contextMenu_availableNodes.addAction(tr("expand"),this, SLOT(expandNode())); contextMenu_availableNodes.addAction(tr("collapse"),this, SLOT(collapseNode())); contextMenu_availableNodes.addSeparator(); contextMenu_availableNodes.addAction(tr("expand all"),this, SLOT(expandAll())); contextMenu_availableNodes.addAction(tr("collapse all"),this, SLOT(collapseAll())); contextMenu_availableNodes.exec(ui->treeView_availableNodes->viewport()->mapToGlobal(point)); } }
//returns true if there were no prob creating a path //error only occur if there's something wrong with the parameter //can (and will) return true even if there is no way to the destination bool PathPlanner::Planning(int start[2], int goal[2]) { if(!inBounds(start) || !inBounds(goal)) return false; std::vector<Path> pathList; Path init(0,computeHeuristic(start[0],start[1],goal[0],goal[1])); init.nodes.push_back(&nodeMap[start[0]][start[1]]); nodeMap[start[0]][start[1]].state = FRONTIER; pathList.push_back(init); Path newpath; Path toexpand; Node* lastnode; while(pathList.size() != 0 ) { std::sort(pathList.begin(),pathList.end()); toexpand = pathList.back(); pathList.pop_back(); if(toexpand.nodes.back() == &nodeMap[goal[0]][goal[1]]) { path = toexpand; return true; } lastnode = toexpand.nodes.back(); if( lastnode->state != EXPLORED) { //bottom expandNode(toexpand,&pathList,0,1,3,goal); //right expandNode(toexpand,&pathList,1,0,3,goal); // left expandNode(toexpand,&pathList,-1,0,3,goal); //top expandNode(toexpand,&pathList,0,-1,3,goal); //top-left expandNode(toexpand,&pathList,-1,-1,4,goal); //top-right expandNode(toexpand,&pathList,1,-1,4,goal); //bottom-left expandNode(toexpand,&pathList,-1,1,4,goal); //bottom-right expandNode(toexpand,&pathList,1,1,4,goal); toexpand.nodes.back()->state = EXPLORED; } } return false; }
Node* explore(const State& startState, TerminationChecker& terminationChecker) { ++iterationCounter; clearOpenList(); openList.reorder(fComparator); Planner::incrementGeneratedNodeCount(); Node*& startNode = nodes[startState]; if (startNode == nullptr) { startNode = nodePool->construct(Node{nullptr, startState, Action(), 0, domain.heuristic(startState), true}); } else { startNode->g = 0; startNode->action = Action(); startNode->predecessors.clear(); startNode->parent = nullptr; } startNode->iteration = iterationCounter; addToOpenList(*startNode); Node* currentNode = startNode; checkSafeNode(currentNode); while (!terminationChecker.reachedTermination() && !domain.isGoal(currentNode->state)) { // if (domain.safetyPredicate(currentNode->state)) { // try to find nodes which lead to safety // currentNode = popOpenList(); // terminationChecker.notifyExpansion(); // expandNode(currentNode); // } // // if (currentNode == startNode) { // if we can't just do LSS-LRTA* // while (!terminationChecker.reachedTermination() && !domain.isGoal(currentNode->state)) { // currentNode = popOpenList(); // terminationChecker.notifyExpansion(); // expandNode(currentNode); // } // } Node* const currentNode = popOpenList(); if (domain.isGoal(currentNode->state)) { return currentNode; } terminationChecker.notifyExpansion(); expandNode(currentNode); } return openList.top(); }
void Astar::execute() { do { std::set<Node>::iterator it = std::min_element(openList.begin(), openList.end(), Node::CompareCostWithHeuristic()); Node currentNode = *it; openList.erase(it); if (isGoalNode(currentNode)) { pathFound = true; lastNode = currentNode; return; } else { currentNode.setPaint(CLOSED); closedList.insert(currentNode); } expandNode(currentNode); } while (not openList.empty()); pathFound = false; }
std::vector<SearchNode*>* AStar::searchPath(SearchNode* start, SearchNode* goal){ queue.clear(); currentIteration++; currentGoal = goal; //put start in the queue start->computeHeuristic(currentGoal); start->g=0; start->f=start->h; start->expanded = false; start->iteration = currentIteration; queue.push(start->f, start); //while queue front != goal while(queue.empty()==false){ SearchNode* n = queue.pop(); if(n->iteration == currentIteration && n->expanded){ continue; } else { if(n==currentGoal){ // std::cerr<<"PATH FOUND"<<std::endl; std::vector<SearchNode*>* result = new std::vector<SearchNode*>(); SearchNode* s = n; while(s!=NULL){ result->push_back(s); s = s->getPredecessor(); } return result; } else { expandNode(n); } } } std::cerr<<"search finished w/o result"<<std::endl; return NULL; }
bool Pathfinder::pathfind(std::vector<PathfindingAction>& path) { #if 0 pout << "Actor " << actor->getObjId(); if (targetitem) { pout << " pathfinding to item: "; targetitem->dumpInfo(); } else { pout << " pathfinding to (" << targetx << "," << targety << "," << targetz << ")" << std::endl; } #endif #ifdef DEBUG if (actor->getObjId() == visualdebug_actor) { RenderSurface* screen = GUIApp::get_instance()->getScreen(); screen->BeginPainting(); if (targetitem) drawbox(targetitem); else drawdot(targetx, targety, targetz, 2, 0xFF0000FF); screen->EndPainting(); } #endif path.clear(); PathNode* startnode = new PathNode(); startnode->state = start; startnode->cost = 0; startnode->parent = 0; startnode->depth = 0; startnode->stepsfromparent = 0; nodelist.push_back(startnode); nodes.push(startnode); unsigned int expandednodes = 0; const unsigned int NODELIMIT_MIN = 30; //! constant const unsigned int NODELIMIT_MAX = 200; //! constant bool found = false; Uint32 starttime = SDL_GetTicks(); while (expandednodes < NODELIMIT_MAX && !nodes.empty() && !found) { PathNode* node = nodes.top(); nodes.pop(); #if 0 pout << "Trying node: (" << node->state.x << "," << node->state.y << "," << node->state.z << ") target=(" << targetx << "," << targety << "," << targetz << ")" << std::endl; #endif if (checkTarget(node)) { // done! // find path length PathNode* n = node; unsigned int length = 0; while (n->parent) { n = n->parent; length++; } #if 0 pout << "Pathfinder: path found (length = " << length << ")" << std::endl; #endif unsigned int i = length; if (length > 0) length++; // add space for final 'stand' action path.resize(length); // now backtrack through the nodes to assemble the final animation while (node->parent) { PathfindingAction action; action.action = node->state.lastanim; action.direction = node->state.direction; action.steps = node->stepsfromparent; path[--i] = action; #if 0 pout << "anim = " << node->state.lastanim << ", dir = " << node->state.direction << ", steps = " << node->stepsfromparent << std::endl; #endif //TODO: check how turns work //TODO: append final 'stand' animation node = node->parent; } if (length) { if (node->state.combat) path[length-1].action = Animation::combatStand; else path[length-1].action = Animation::stand; path[length-1].direction = path[length-2].direction; } expandtime = SDL_GetTicks() - starttime; return true; } expandNode(node); expandednodes++; if(expandednodes >= NODELIMIT_MIN && ((expandednodes) % 5) == 0) { Uint32 elapsed_ms = SDL_GetTicks() - starttime; if(elapsed_ms > 350) break; } } expandtime = SDL_GetTicks() - starttime; #if 0 static sint32 pfcalls = 0; static sint32 pftotaltime = 0; pfcalls++; pftotaltime += expandtime; pout << "maxout average = " << (pftotaltime / pfcalls) << "ms." << std::endl; #endif return false; }
int AStarPath::pathFind() { if(!checkUnitBorders(destX/8, destY/8) && distance <=20) { int newDestX = destX/8 + (rand()%3-1), newDestY = destY/8 + (rand()%3-1); bool help = true; for(int i=0; i<distance; i++) { newDestX += (rand()%3-1), newDestY += (rand()%3-1); if(checkUnitBorders(newDestX, newDestY)) { this->destX = newDestX*8; this->destY = newDestY*8; help = false; } } std::cout << help << std::endl; if(help) return 0; } // Creating a map object we search our path in. You move an unit from // a start coordinate tuple, given in pixels to a destination tuple, // also given in pixels. The map is designed as 64x64 pixel tiles, but // that's too unaccurate for a pathfinding algorithm. So I choiced 8x8 // pixels, to be good enough. // As maps are currently sized at 110x110 tiles, which is not possible // to change. We need an graph with 880x880 nodes. // Because most nodes of your graph won't even be touched, these won't // be initialized at start. //map.resize(880); // The only two points which will be needed in each pathfinding call // are the start and destination nodes, so we are initializing them map[this->startX/8][this->startY/8] = new Node(this->startX/8,this->startY/8,0,0); map[this->destX/8][this->destY/8] = new Node(this->destX/8,this->destY/8,0,0); // The open list is a list of each object we are going to look at. // At the beginning, only the start node is in this list. open_list.push_back(map[this->startX/8][this->startY/8]); // Main loop for the algorithm, when this terminates, you have // either a found path or there is none existing. bool found = false; while(!found) { // If open_list is totally empty, we removed each object which is in // it, therefore, there is no path to destination because we looked // at every node. if(open_list.empty() || closed_list.size() >= 3000) { found = true; return 0; } // We are looking for the shortest path, so the neighbor nodes with lowest // distance, equals to highest priority, will get checked fist. // TODO: This can be optimized by remembering the point we're at and only looking for direct neighbours. int indexMin = 0; for(int i=open_list.size()-1; i>=0; i--) { if(open_list[indexMin]->getPriority() >= open_list[i]->getPriority()) { indexMin = i; } } //std::cout << "Current: " << open_list[indexMin]->getX() << "/" << open_list[indexMin]->getY() << std::endl; //std::cout << "Destination: " << this->destX << "/" << this->destY << std::endl; //std::cout << "openListSize: " << open_list.size() << std::endl; //std::cout << "closedListSize: " << closed_list.size() << std::endl; //std::cout << "empty? " << open_list.empty() << std::endl; // The current node will be set to the node which was found as the // one with highest priority. Node* currentNode = open_list[indexMin]; // As we are looking at this node now, we will erase it from open list. open_list.erase(open_list.begin()+indexMin); // Euclid distance to destination // If distance arg is set, unit will only move until a range, so we // need to calculate range to destination to get a value to compare to. float toDest = getDistance(currentNode->getX()*8, currentNode->getY()*8, destX, destY); // If currentNode is the destination point, we're done with the algorithm. if(currentNode == map[destX/8][destY/8] || toDest <= distance) { found = true; Node* n = currentNode; bool help = true; // We are going back though each node we walked though while finding the path // using the getPredecessor() method, which provides a pointer to the previous // node in the path. This way, we go back from destination to the start while // writing the fastest path in a final_list queue. while(help) { final_list.push(n); n = map[n->getX()][n->getY()]; n = n->getPredecessor(); if(n == map[startX/8][startY/8]) { final_list.push(n); help = false; } else if(n == NULL) { help = false; } } return 1; } // We are expanding the current node. This means, we are searching // for neighbour nodes which we should look at and add them to // the open list. expandNode(currentNode); // As we went though all things we can do with this current node, // we can add it to the closed list. This one won't get touched // any more. It's like a blacklist of nodes. closed_list.push_back(currentNode); } return 0; // This should never happen }
// a non-recursive and hopefully somewhat parallel algorithm based on alpha beta float exploreTree(Node *node, int depth) { exploreSubTreeCount = 0; // the frontier / current list of nodes that need to be explored / nodes at the current level // TODO: many of these lists are probably redundant - get rid of some later Node *currentPVNode = NULL; Node *nextPVNode = NULL; Node *currentCutNodes = NULL; Node *nextCutNodes = NULL; Node *currentAllNodes = NULL; Node *nextAllNodes = NULL; int nCutNodes = 0, nAllNodes = 0; int nNextCutNodes = 0, nNextAllNodes = 0; // full frontier Node **fullCurrentFrontier = NULL; Node **fullNextFrontier = NULL; int nCurr, nNext; // 1. PV based initial tree generation node->nodeType = PV_NODE; // the root is always a PV node currentPVNode = node; fullCurrentFrontier = &node; nCurr = 1; bool isMaxLevel = true; for (int i = 0; i < depth - 1; i++) { // explore the frontier nodes // figure out total no. of childs that need to be explored for all frontier nodes nNext = 0; for (int j=0; j<nCurr; j++) { int childsToExplore = 0; switch (fullCurrentFrontier[j]->nodeType) { case PV_NODE: case ALL_NODE: childsToExplore = fullCurrentFrontier[j]->nChildren; break; case CUT_NODE: childsToExplore = 1; break; } nNext += childsToExplore; } // allocate memory for the next frontier fullNextFrontier = (Node**) malloc (nNext * sizeof(Node *)); int index = 0; // fill in the next frontier for (int j=0; j<nCurr; j++) { switch (fullCurrentFrontier[j]->nodeType) { case PV_NODE: for (int k = 0; k < fullCurrentFrontier[j]->nChildren; k++) { Node *curNode = &(fullCurrentFrontier[j]->children[k]); if (index == 0) // first child of PV node is PV node curNode->nodeType = PV_NODE; else // others are CUT nodes curNode->nodeType = CUT_NODE; fullNextFrontier[index++] = curNode; } fullCurrentFrontier[j]->nChildsExplored = fullCurrentFrontier[j]->nChildren; break; case ALL_NODE: for (int k = 0; k < fullCurrentFrontier[j]->nChildren; k++) { Node *curNode = &(fullCurrentFrontier[j]->children[k]); curNode->nodeType = CUT_NODE; // child of ALL node is cut node fullNextFrontier[index++] = curNode; } fullCurrentFrontier[j]->nChildsExplored = fullCurrentFrontier[j]->nChildren; break; case CUT_NODE: { fullCurrentFrontier[j]->nChildsExplored = 1; fullCurrentFrontier[j]->children[0].nodeType = ALL_NODE; fullNextFrontier[index++] = &(fullCurrentFrontier[j]->children[0]); } } // Ankan - not known yet, but initialize with first child fullCurrentFrontier[j]->best = &(fullCurrentFrontier[j]->children[0]); fullCurrentFrontier[j]->bestChild = 0; } assert(index == nNext); // go to next depth, set current = next if (i!=0) free (fullCurrentFrontier); nCurr = nNext; fullCurrentFrontier = fullNextFrontier; isMaxLevel = !isMaxLevel; } // when generating the last level evaluate all ALL nodes at the level just above the CUT node leaves // for depth 5 search, we need to do a MAX reduction (see modern gpu's segmented reduction example when implementing parallel version) fullNextFrontier = (Node**) malloc (nCurr * sizeof(Node *)); bool *expectedMore = (bool*) malloc (nCurr * sizeof(bool)); float *currentNodeVals = (float *) malloc(nCurr * sizeof(float)); for (int i=0;i<nCurr;i++) { Node *curNode = fullCurrentFrontier[i]; curNode->nodeVal = isMaxLevel ? -INF : INF; if(curNode->nodeType == PV_NODE || curNode->nodeType == ALL_NODE) { for (int k = 0; k < curNode->nChildren; k++) { if (isMaxLevel) { if (curNode->children[k].nodeVal > curNode->nodeVal) { curNode->nodeVal = curNode->children[k].nodeVal; curNode->best = &curNode->children[k]; curNode->bestChild = k; } } else { if (curNode->children[k].nodeVal < curNode->nodeVal) { curNode->nodeVal = curNode->children[k].nodeVal; curNode->best = &curNode->children[k]; curNode->bestChild = k; } } } fullNextFrontier[i] = curNode; currentNodeVals[i] = curNode->nodeVal; curNode->nChildsExplored = curNode->nChildren; expectedMore[i] = isMaxLevel ? false : true; } else { curNode->best = &curNode->children[0]; curNode->bestChild = 0; curNode->nChildsExplored = 1; curNode->children[0].nodeType = ALL_NODE; fullNextFrontier[i] = &curNode->children[0]; currentNodeVals[i] = fullNextFrontier[i]->nodeVal; expectedMore[i] = isMaxLevel ? true : false; } fullNextFrontier[i]->numChildrenAtFrontier = 1; fullNextFrontier[i]->frontierOffset = i; } free (fullCurrentFrontier); fullCurrentFrontier = fullNextFrontier; float *minScan = (float *) malloc (sizeof(float) * nCurr); float *maxScan = (float *) malloc (sizeof(float) * nCurr); bool *ignored = (bool *)malloc(sizeof(bool) * nCurr); memset(ignored, 0, sizeof(bool) * nCurr); float curMin, curMax; curMin = curMax = currentNodeVals[0]; // init. with value of PV node int nRejected = 0; int nExpnded = 0; // propogate frontier offsets from leafs up the tree int count; int start = propogateFrontierOffsets(node, &count); assert(start == 0 && count == nCurr); int iterations = 0; do { iterations++; nRejected = 0; nExpnded = 0; // ignore all nodes to the left of bestNow for (int i = 0; i < nCurr; i++) { ignored[i] = true; // Unnecessary and expensive. TODO: figure out better way bool found = false; Node *bestNow = node; while (bestNow->children) { bestNow = bestNow->best; if (bestNow == fullCurrentFrontier[i]) { found = true; } } if (found) { curMin = curMax = bestNow->nodeVal; break; } } for (int i = 1; i < nCurr; i++) { // all nodes that are explored here must be ALL nodes assert(fullCurrentFrontier[i]->nodeType = ALL_NODE || fullCurrentFrontier[i]->nChildsExplored == fullCurrentFrontier[i]->nChildren); if (ignored[i]) continue; minScan[i] = curMin; maxScan[i] = curMax; // this node was expected to be less than the PV node value if (expectedMore[i] == false) { if (currentNodeVals[i] <= curMin) { // reject this branch (i.e, no need to evaluate any more siblings) nRejected++; ignored[i] = true; } if (currentNodeVals[i] > curMax) { curMax = currentNodeVals[i]; // need to evaluate more siblings of this node expandNode(fullCurrentFrontier, currentNodeVals, i, curMax, NULL, ignored); nExpnded++; } } else //if (expectedMore[i]) { if (currentNodeVals[i] >= curMax) { // reject this branch (i.e, no need to evaluate any more siblings of this node) nRejected++; ignored[i] = true; } if (currentNodeVals[i] < curMin) { curMin = currentNodeVals[i]; // need to evaluate more siblings of this node expandNode(fullCurrentFrontier, currentNodeVals, i, curMin, NULL, ignored); nExpnded++; } } } } while (nExpnded); printf("\nFrontier Nodes: %d, main loop iterations: %d, explore subtree count: %d", nCurr, iterations, exploreSubTreeCount); printf("\nExplore Tree found value: %f\n", node->nodeVal); free (fullCurrentFrontier); return node->nodeVal; }
// starts exploring a node as if it's a CUT node with cutVal as the value to check against // returns either cutVal if a better value couldn't be found, or value of the best found node otherwise // works only on CUT and ALL nodes, no node is marked as PV node by this function float exploreSubTree(Node *node, float cutVal) { exploreSubTreeCount++; // isMaxLevel is true if node's *parent* is a MAX level bool isMaxLevel = !node->isMaxNode; if (node->children == NULL) { // leaf node return isMaxLevel ? max(cutVal, node->nodeVal) : min(cutVal, node->nodeVal); } // full frontier Node **fullCurrentFrontier = NULL; Node **fullNextFrontier = NULL; // only for the last level float *currentNodeVals; int nCurr, nNext; // treat passed-in node as CUT node node->nodeType = CUT_NODE; fullCurrentFrontier = &node; nCurr = 1; bool currentIsMaxLevel = !isMaxLevel; int subDepth = 0; while (1) { bool secondLastLevel = false; secondLastLevel = (fullCurrentFrontier[0]->children[0].children == NULL); // explore the frontier nodes // figure out total no. of childs that need to be explored for all frontier nodes nNext = 0; for (int j=0; j<nCurr; j++) { switch (fullCurrentFrontier[j]->nodeType) { case ALL_NODE: // if it's the second last level, we will explore all ALL nodes and find the best immediately nNext += secondLastLevel ? 1 : fullCurrentFrontier[j]->nChildren; break; case CUT_NODE: nNext++; break; } } // no more child nodes, we are at leaves.. if (nNext == 0) break; // allocate memory for the next frontier fullNextFrontier = (Node**) malloc (nNext * sizeof(Node *)); if (secondLastLevel) { assert(nCurr == nNext); currentNodeVals = (float *)malloc(nNext * sizeof(float)); } int index = 0; // fill in the next frontier for (int j=0; j<nCurr; j++) { switch (fullCurrentFrontier[j]->nodeType) { case ALL_NODE: if (secondLastLevel) { Node * curNode = fullCurrentFrontier[j]; curNode->nodeVal = curNode->isMaxNode ? -INF : INF; for (int k = 0; k < curNode->nChildren; k++) { if (curNode->isMaxNode) { if (curNode->children[k].nodeVal > curNode->nodeVal) { curNode->nodeVal = curNode->children[k].nodeVal; curNode->best = &curNode->children[k]; curNode->bestChild = k; } } else { if (curNode->children[k].nodeVal < curNode->nodeVal) { curNode->nodeVal = curNode->children[k].nodeVal; curNode->best = &curNode->children[k]; curNode->bestChild = k; } } } if (secondLastLevel) currentNodeVals[index] = curNode->nodeVal; fullNextFrontier[index++] = curNode; curNode->nChildsExplored = curNode->nChildren; } else { for (int k = 0; k < fullCurrentFrontier[j]->nChildren; k++) { Node *curNode = &(fullCurrentFrontier[j]->children[k]); curNode->nodeType = CUT_NODE; // child of ALL node is cut node fullNextFrontier[index++] = curNode; } fullCurrentFrontier[j]->nChildsExplored = fullCurrentFrontier[j]->nChildren; fullCurrentFrontier[j]->best = &(fullCurrentFrontier[j]->children[0]); } break; case CUT_NODE: { fullCurrentFrontier[j]->nChildsExplored = 1; fullCurrentFrontier[j]->best = &(fullCurrentFrontier[j]->children[0]); fullCurrentFrontier[j]->children[0].nodeType = ALL_NODE; fullNextFrontier[index] = &(fullCurrentFrontier[j]->children[0]); if (secondLastLevel) { currentNodeVals[index] = fullNextFrontier[index]->nodeVal; fullCurrentFrontier[j]->nodeVal = currentNodeVals[index]; } index++; } } if (secondLastLevel) { fullNextFrontier[j]->numChildrenAtFrontier = 1; fullNextFrontier[j]->frontierOffset = j; } } // go to next depth, set current = next if (subDepth != 0) free (fullCurrentFrontier); nCurr = nNext; fullCurrentFrontier = fullNextFrontier; subDepth++; currentIsMaxLevel = !currentIsMaxLevel; if (secondLastLevel) break; } int count; int start = propogateFrontierOffsets(node, &count); assert(start == 0 && count == nCurr); float *minScan = (float *)malloc(sizeof(float) * nCurr); float *maxScan = (float *)malloc(sizeof(float) * nCurr); bool *ignored = (bool *)malloc(sizeof(bool) * nCurr); memset(ignored, 0, sizeof(bool) * nCurr); float curMin, curMax; curMin = curMax = cutVal; // init. with cut val float computedVal = isMaxLevel ? -INF : INF; int nRejected; int nExpnded; do { nRejected = 0; nExpnded = 0; curMin = curMax = cutVal; for (int i = 0; i < nCurr; i++) { // all nodes that are explored here must be ALL nodes assert(fullCurrentFrontier[i]->nodeType = ALL_NODE || fullCurrentFrontier[i]->nChildsExplored == fullCurrentFrontier[i]->nChildren); if (ignored[i]) continue; minScan[i] = curMin; maxScan[i] = curMax; // this node was expected to be less than the PV node value if (isMaxLevel) { if (currentNodeVals[i] <= curMin) { // reject this branch (i.e, no need to evaluate any more siblings) nRejected++; ignored[i] = true; } if (currentNodeVals[i] > curMax) { curMax = currentNodeVals[i]; // need to evaluate more siblings of this node if (expandNode(fullCurrentFrontier, currentNodeVals, i, curMax, node, ignored)) nExpnded++; computedVal = currentNodeVals[i]; } } else //if (!isMaxLevel) { if (currentNodeVals[i] >= curMax) { // reject this branch (i.e, no need to evaluate any more siblings of this node) nRejected++; ignored[i] = true; } if (currentNodeVals[i] < curMin) { curMin = currentNodeVals[i]; // need to evaluate more siblings of this node if(expandNode(fullCurrentFrontier, currentNodeVals, i, curMin, node, ignored)) nExpnded++; computedVal = currentNodeVals[i]; } } } // the loop is done when nothing gets expanded anymore } while (nExpnded); return isMaxLevel ? max(cutVal, computedVal) : min(cutVal, computedVal); }