EBTStatus SelectorLoopTask::update(Agent* pAgent, EBTStatus childStatus) { BEHAVIAC_UNUSED_VAR(pAgent); BEHAVIAC_UNUSED_VAR(childStatus); //checking the preconditions and take the first action tree uint32_t index = (uint32_t)-1; for (uint32_t i = 0; i < this->m_children.size(); ++i) { WithPreconditionTask* pSubTree = (WithPreconditionTask*)this->m_children[i]; BEHAVIAC_ASSERT(WithPreconditionTask::DynamicCast(pSubTree)); BehaviorTask* pPrecondTree = pSubTree->PreconditionNode(); EBTStatus status = pPrecondTree->exec(pAgent); if (status == BT_SUCCESS) { index = i; break; } } //clean up the current ticking action tree if (index != (uint32_t)-1) { if (this->m_activeChildIndex != CompositeTask::InvalidChildIndex) { WithPreconditionTask* pCurrentSubTree = (WithPreconditionTask*)this->m_children[this->m_activeChildIndex]; BEHAVIAC_ASSERT(WithPreconditionTask::DynamicCast(pCurrentSubTree)); BehaviorTask* pCurrentActionTree = pCurrentSubTree->Action(); WithPreconditionTask* pSubTree = (WithPreconditionTask*)this->m_children[index]; BEHAVIAC_ASSERT(WithPreconditionTask::DynamicCast(pSubTree)); BehaviorTask* pActionTree = pSubTree->Action(); if (pCurrentActionTree != pActionTree) { pCurrentActionTree->abort(pAgent); pCurrentSubTree->abort(pAgent); this->m_activeChildIndex = index; } } for (uint32_t i = 0; i < this->m_children.size(); ++i) { WithPreconditionTask* pSubTree = (WithPreconditionTask*)this->m_children[i]; BEHAVIAC_ASSERT(WithPreconditionTask::DynamicCast(pSubTree)); //dummy ticking so that the designer knows it is updating EBTStatus statusDummy = pSubTree->exec(pAgent); BEHAVIAC_ASSERT(statusDummy == BT_RUNNING); BEHAVIAC_UNUSED_VAR(statusDummy); //when i < index, the precondition is failure, so to continue if (i < index) { continue; } if (i > index) { BehaviorTask* pPreconditionTree = pSubTree->PreconditionNode(); EBTStatus status = pPreconditionTree->exec(pAgent); //to search for the first one whose precondition is success if (status != BT_SUCCESS) { continue; } } BehaviorTask* pActionTree = pSubTree->Action(); EBTStatus status = pActionTree->exec(pAgent); if (status == BT_RUNNING) { this->m_activeChildIndex = index; } else { pActionTree->reset(pAgent); if (status == BT_FAILURE || status == BT_INVALID) { //THE ACTION failed, to try the next one continue; } } BEHAVIAC_ASSERT(status == BT_RUNNING || status == BT_SUCCESS); return status; } } return BT_FAILURE; }
EBTStatus SelectorLoopTask::update(Agent* pAgent, EBTStatus childStatus) { BEHAVIAC_UNUSED_VAR(pAgent); BEHAVIAC_UNUSED_VAR(childStatus); int idx = -1; if (childStatus != BT_RUNNING) { BEHAVIAC_ASSERT(this->m_activeChildIndex != CompositeTask::InvalidChildIndex); if (childStatus == BT_SUCCESS) { return BT_SUCCESS; } else if (childStatus == BT_FAILURE) { //the next for starts from (idx + 1), so that it starts from next one after this failed one idx = this->m_activeChildIndex; } else { BEHAVIAC_ASSERT(false); } } //checking the preconditions and take the first action tree uint32_t index = (uint32_t) - 1; for (uint32_t i = (idx + 1); i < this->m_children.size(); ++i) { WithPreconditionTask* pSubTree = (WithPreconditionTask*)this->m_children[i]; BEHAVIAC_ASSERT(WithPreconditionTask::DynamicCast(pSubTree)); pSubTree->SetIsUpdatePrecondition(true); EBTStatus status = pSubTree->exec(pAgent); pSubTree->SetIsUpdatePrecondition(false); if (status == BT_SUCCESS) { index = i; break; } } //clean up the current ticking action tree if (index != (uint32_t) - 1) { if (this->m_activeChildIndex != CompositeTask::InvalidChildIndex && this->m_activeChildIndex != (int)index) { WithPreconditionTask* pCurrentSubTree = (WithPreconditionTask*)this->m_children[this->m_activeChildIndex]; BEHAVIAC_ASSERT(WithPreconditionTask::DynamicCast(pCurrentSubTree)); pCurrentSubTree->abort(pAgent); } for (uint32_t i = index; i < this->m_children.size(); ++i) { WithPreconditionTask* pSubTree = (WithPreconditionTask*)this->m_children[i]; BEHAVIAC_ASSERT(WithPreconditionTask::DynamicCast(pSubTree)); if (i > index) { pSubTree->SetIsUpdatePrecondition(true); EBTStatus status = pSubTree->exec(pAgent); pSubTree->SetIsUpdatePrecondition(false); //to search for the first one whose precondition is success if (status != BT_SUCCESS) { continue; } } EBTStatus s = pSubTree->exec(pAgent); if (s == BT_RUNNING) { this->m_activeChildIndex = i; } else { //pActionTree->reset(pAgent); if (s == BT_FAILURE) { //THE ACTION failed, to try the next one continue; } } BEHAVIAC_ASSERT(s == BT_RUNNING || s == BT_SUCCESS); return s; } } return BT_FAILURE; }