Parallel.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2014 Guy Allard
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "Parallel.h"
  23. #include "console/engineAPI.h"
  24. using namespace BadBehavior;
  25. //------------------------------------------------------------------------------
  26. // Parallel node
  27. //------------------------------------------------------------------------------
  28. IMPLEMENT_CONOBJECT(Parallel);
  29. Parallel::Parallel()
  30. : mReturnPolicy(REQUIRE_ALL)
  31. {
  32. }
  33. ImplementEnumType( ParallelReturnPolicy,
  34. "@brief The policy to use when determining the return status of a parallel node.\n\n"
  35. "@ingroup AI\n\n")
  36. { Parallel::REQUIRE_ALL, "REQUIRE_ALL", "Will return success if all children succeed.\n"
  37. "Will terminate and return failure if one child fails \n"},
  38. { Parallel::REQUIRE_NONE, "REQUIRE_NONE", "Will return success even if all children fail.\n" },
  39. { Parallel::REQUIRE_ONE, "REQUIRE_ONE", "Will terminate and return success when one child succeeds.\n" },
  40. EndImplementEnumType;
  41. void Parallel::initPersistFields()
  42. {
  43. addGroup( "Behavior" );
  44. addField( "returnPolicy", TYPEID< Parallel::ParallelPolicy >(), Offset(mReturnPolicy, Parallel),
  45. "@brief The policy to use when deciding the return status for the parallel sequence.");
  46. endGroup( "Behavior" );
  47. Parent::initPersistFields();
  48. }
  49. Task *Parallel::createTask(SimObject &owner, BehaviorTreeRunner &runner)
  50. {
  51. return new ParallelTask(*this, owner, runner);
  52. }
  53. //------------------------------------------------------------------------------
  54. // Parallel Task
  55. //------------------------------------------------------------------------------
  56. ParallelTask::ParallelTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
  57. : Parent(node, owner, runner),
  58. mHasSuccess(false),
  59. mHasFailure(false)
  60. {
  61. }
  62. void ParallelTask::onInitialize()
  63. {
  64. Parent::onInitialize();
  65. mHasSuccess = mHasFailure = false;
  66. if(mBranches.empty())
  67. {
  68. for (VectorPtr<Task*>::iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  69. {
  70. mBranches.push_back(BehaviorTreeBranch(*i));
  71. }
  72. }
  73. else
  74. {
  75. for (Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it)
  76. {
  77. it->reset();
  78. }
  79. }
  80. }
  81. Task* ParallelTask::update()
  82. {
  83. bool hasRunning = false, hasSuspended = false, hasResume = false;
  84. for (Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it)
  85. {
  86. Status s = it->getStatus();
  87. if(s == INVALID || s == RUNNING || s == RESUME)
  88. {
  89. s = it->update();
  90. switch(it->getStatus())
  91. {
  92. case SUCCESS:
  93. mHasSuccess = true;
  94. break;
  95. case FAILURE:
  96. mHasFailure = true;
  97. break;
  98. case RUNNING:
  99. hasRunning = true;
  100. break;
  101. case SUSPENDED:
  102. hasSuspended = true;
  103. break;
  104. case RESUME:
  105. hasResume = true;
  106. break;
  107. }
  108. }
  109. }
  110. switch(static_cast<Parallel *>(mNodeRep)->getReturnPolicy())
  111. {
  112. // REQUIRE_NONE
  113. // returns SUCCESS when all children have finished irrespective of their return status.
  114. case Parallel::REQUIRE_NONE:
  115. mStatus = hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : SUCCESS ) );
  116. break;
  117. // REQUIRE_ONE
  118. // terminates and returns SUCCESS when any of its children succeed
  119. // returns FAILURE if no children succeed
  120. case Parallel::REQUIRE_ONE:
  121. mStatus = mHasSuccess ? SUCCESS : ( hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : FAILURE ) ) );
  122. break;
  123. // REQUIRE_ALL
  124. // returns SUCCESS if all of its children succeed.
  125. // terminates and returns failure if any of its children fail
  126. case Parallel::REQUIRE_ALL:
  127. mStatus = mHasFailure ? FAILURE : ( hasResume ? RESUME : ( hasRunning ? RUNNING : ( hasSuspended ? SUSPENDED : SUCCESS ) ) );
  128. break;
  129. }
  130. mIsComplete = (mStatus != RUNNING && mStatus != SUSPENDED && mStatus != RESUME);
  131. return NULL;
  132. }
  133. Status ParallelTask::getStatus()
  134. {
  135. if(mStatus == SUSPENDED)
  136. {
  137. // need to check if the parallel is still suspended.
  138. // A parallel will only report SUSPENDED when all of its children are suspended
  139. for(Vector<BehaviorTreeBranch>::iterator it = mBranches.begin(); it != mBranches.end(); ++it)
  140. {
  141. switch(it->getStatus())
  142. {
  143. case RUNNING:
  144. return RUNNING;
  145. case RESUME:
  146. return RESUME;
  147. }
  148. }
  149. }
  150. return mStatus;
  151. }