| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2014 Guy Allard
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "Parallel.h"
- #include "console/engineAPI.h"
- using namespace BadBehavior;
- //------------------------------------------------------------------------------
- // Parallel node
- //------------------------------------------------------------------------------
- IMPLEMENT_CONOBJECT(Parallel);
- Parallel::Parallel()
- : mReturnPolicy(REQUIRE_ALL)
- {
- }
- ImplementEnumType( ParallelReturnPolicy,
- "@brief The policy to use when determining the return status of a parallel node.\n\n"
- "@ingroup AI\n\n")
- { Parallel::REQUIRE_ALL, "REQUIRE_ALL", "Will return success if all children succeed.\n"
- "Will terminate and return failure if one child fails \n"},
- { Parallel::REQUIRE_NONE, "REQUIRE_NONE", "Will return success even if all children fail.\n" },
- { Parallel::REQUIRE_ONE, "REQUIRE_ONE", "Will terminate and return success when one child succeeds.\n" },
- EndImplementEnumType;
- void Parallel::initPersistFields()
- {
- addGroup( "Behavior" );
- addField( "returnPolicy", TYPEID< Parallel::ParallelPolicy >(), Offset(mReturnPolicy, Parallel),
- "@brief The policy to use when deciding the return status for the parallel sequence.");
- endGroup( "Behavior" );
- Parent::initPersistFields();
- }
- Task *Parallel::createTask(SimObject &owner, BehaviorTreeRunner &runner)
- {
- return new ParallelTask(*this, owner, runner);
- }
- //------------------------------------------------------------------------------
- // Parallel Task
- //------------------------------------------------------------------------------
- ParallelTask::ParallelTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
- : Parent(node, owner, runner),
- mHasSuccess(false),
- mHasFailure(false)
- {
- }
- void ParallelTask::onInitialize()
- {
- Parent::onInitialize();
- mHasSuccess = mHasFailure = false;
- if(mBranches.empty())
- {
- for (VectorPtr<Task*>::iterator i = mChildren.begin(); i != mChildren.end(); ++i)
- {
- mBranches.push_back(BehaviorTreeBranch(*i));
- }
- }
- else
- {
- for (Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it)
- {
- it->reset();
- }
- }
- }
- Task* ParallelTask::update()
- {
- bool hasRunning = false, hasSuspended = false, hasResume = false;
- for (Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it)
- {
- Status s = it->getStatus();
- if(s == INVALID || s == RUNNING || s == RESUME)
- {
- s = it->update();
- switch(it->getStatus())
- {
- case SUCCESS:
- mHasSuccess = true;
- break;
- case FAILURE:
- mHasFailure = true;
- break;
- case RUNNING:
- hasRunning = true;
- break;
- case SUSPENDED:
- hasSuspended = true;
- break;
- case RESUME:
- hasResume = true;
- break;
- }
- }
- }
- switch(static_cast<Parallel *>(mNodeRep)->getReturnPolicy())
- {
- // REQUIRE_NONE
- // returns SUCCESS when all children have finished irrespective of their return status.
- case Parallel::REQUIRE_NONE:
- mStatus = hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : SUCCESS ) );
- break;
-
- // REQUIRE_ONE
- // terminates and returns SUCCESS when any of its children succeed
- // returns FAILURE if no children succeed
- case Parallel::REQUIRE_ONE:
- mStatus = mHasSuccess ? SUCCESS : ( hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : FAILURE ) ) );
- break;
- // REQUIRE_ALL
- // returns SUCCESS if all of its children succeed.
- // terminates and returns failure if any of its children fail
- case Parallel::REQUIRE_ALL:
- mStatus = mHasFailure ? FAILURE : ( hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : SUCCESS ) ) );
- break;
- }
- mIsComplete = (mStatus != RUNNING && mStatus != SUSPENDED && mStatus != RESUME);
- return NULL;
- }
- Status ParallelTask::getStatus()
- {
- if(mStatus == SUSPENDED)
- {
- // need to check if the parallel is still suspended.
- // A parallel will only report SUSPENDED when all of its children are suspended
- for(Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it)
- {
- switch(it->getStatus())
- {
- case RUNNING:
- return RUNNING;
- case RESUME:
- return RESUME;
- }
- }
- }
- return mStatus;
- }
|