BEHAVIOR_STATUS SequentialNode::execute(void* agent) { if (currentPosition == -1) //starting out { init(agent); currentPosition = 0; } if (children.size() == 0) return BT_SUCCESS; BehaviorTreeNode* currentTask = children.at(currentPosition); BEHAVIOR_STATUS result = currentTask->execute(agent); while(result == BT_SUCCESS) { if (currentPosition == children.size()-1) //finished last task { currentPosition = -1; //indicate we are not running anything return BT_SUCCESS; } else { currentPosition++; currentTask = children.at(currentPosition); result = currentTask->execute(agent); } } if (result == BT_FAILURE) currentPosition = -1; return result; }
BEHAVIOR_STATUS CNodePriorityInterrupt::execute(void* agent) { if (children.size() == 0) return BT_SUCCESS; if (currentPosition == -1) init(agent); // Nodo que vamos a comprobar a continuación int checkedNode = 0; BEHAVIOR_STATUS status; BehaviorTreeNode* currentlyRunningNode; while (checkedNode < children.size()) //keep trying children until one doesn't fail { currentlyRunningNode = children.at(checkedNode); status = currentlyRunningNode->execute(agent); if (status == BT_FAILURE) { // Si el nodo falla al ejecutarse lo reiniciamos y pasamos al siguiente currentlyRunningNode->init(agent); checkedNode++; } else { // Si el nodo actual se ejecuta tenemos que comprobar si se ha interrumpido // la ejecución de otro nodo menos prioritario, para poder reinicializarlo. // El último nodo no ejecutado se almacena en currentPosition. // Tendremos que comprobar si tiene menos prioridad, es decir, si su índice // es mayor que el que ocupa el que acabamos de ejecutar con éxito. if (checkedNode < currentPosition) children.at(currentPosition)->init(agent); // Si el nodo ha terminado con éxito, el selector también termina con éxito if (status == BT_SUCCESS) { // Además, dejamos inicializado el nodo que acaba de terminar para la próxima vuelta currentlyRunningNode->init(agent); currentPosition = 0; return BT_SUCCESS; } else { // Sólo queda que el status sea BT_RUNNING // En este caso actualizamos el nodo actual por si ha cambiado currentPosition = checkedNode; return BT_RUNNING; } //assert(!"BT in an unsupported state"); } } // Si ha llegado al final de la lista de nodos y todos han fallado el selector // tendrá también que fallar currentPosition = 0; return BT_FAILURE; }
BEHAVIOR_STATUS ParallelNode::execute(void* agent) { if (childrenStatus == NULL) init(agent); // go through all children and update the childrenStatus for (unsigned int i = 0 ; i<children.size(); i++) { BehaviorTreeNode* node = children[i]; if ((*childrenStatus)[node] == BT_RUNNING) { BEHAVIOR_STATUS status = node->execute(agent); if (status == BT_FAILURE) { if (failPolicy == FAIL_ON_ONE) { init(agent); return BT_FAILURE; } else { (*childrenStatus)[node] = BT_FAILURE; } } if (status == BT_SUCCESS) (*childrenStatus)[node] = BT_SUCCESS; } if ((*childrenStatus)[node] == BT_FAILURE && failPolicy == FAIL_ON_ALL) //theoretically the failPolicy check is not needed { BEHAVIOR_STATUS status = node->execute(agent); (*childrenStatus)[node] = status; } } //look through the childrenStatus and see if we have met any of our end conditions ChildrenStatusMap::iterator iter; bool sawSuccess = false; bool sawAllFails = true; bool sawAllSuccess = true; for (iter = childrenStatus->begin(); iter != childrenStatus->end() ; iter++) { switch((*iter).second) { case BT_SUCCESS: //can't instantly return success for succeedOnOne policy if failOnOne is also true, because failOnOne overrides succeedOnOne if (succeedPolicy == SUCCEED_ON_ONE && failPolicy != FAIL_ON_ONE) { init(agent); return BT_SUCCESS; } sawSuccess = true; sawAllFails = false; break; case BT_FAILURE: if (failPolicy == FAIL_ON_ONE) { init(agent); return BT_FAILURE; } sawAllSuccess = false; break; case BT_RUNNING: sawAllFails = false; sawAllSuccess = false; //optimization for early exit if (failPolicy == FAIL_ON_ALL && succeedPolicy == SUCCEED_ON_ALL) { return BT_RUNNING; } break; } } if (failPolicy == FAIL_ON_ALL && sawAllFails) { init(agent); return BT_FAILURE; } else if ((succeedPolicy == SUCCEED_ON_ALL && sawAllSuccess) || (succeedPolicy == SUCCEED_ON_ONE && sawSuccess)) { init(agent); return BT_SUCCESS; } else { return BT_RUNNING; } }