💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.2 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_BEHAVIOR_TREE_HPP
  20. #define ANTKEEPER_BEHAVIOR_TREE_HPP
  21. #include <functional>
  22. #include <list>
  23. namespace behavior_tree {
  24. /// Behavior tree node return status enumerations.
  25. enum class status
  26. {
  27. failure, ///< Indicates a node's execution failed.
  28. success, ///< Indicates a node's execution succeed.
  29. running ///< Indicates a node's execution has not finished.
  30. };
  31. /**
  32. * Abstract base class for behavior tree nodes.
  33. *
  34. * @tparam T Data type on which nodes operate.
  35. */
  36. template <class T>
  37. struct node
  38. {
  39. /// Data type on which nodes operate.
  40. typedef T context_type;
  41. /**
  42. * Executes a node's functionality and returns its status.
  43. *
  44. * @param context Context data on which the node will operate.
  45. */
  46. virtual status execute(context_type& context) const = 0;
  47. };
  48. /// A node with no children.
  49. template <class T>
  50. using leaf_node = node<T>;
  51. /// A node with exactly one child.
  52. template <class T>
  53. struct decorator_node: node<T>
  54. {
  55. node* child;
  56. };
  57. /// A node that can have one or more children.
  58. template <class T>
  59. struct composite_node: node<T>
  60. {
  61. std::list<node*> children;
  62. };
  63. /// Executes a function on a context and returns the status.
  64. template <class T>
  65. struct action: leaf_node<T>
  66. {
  67. virtual status execute(context_type& context) const final;
  68. typedef std::function<status(context_type&)> function_type;
  69. function_type function;
  70. };
  71. /// Evaluates a boolean condition (predicate) and returns either `status::success` or `status::failure`.
  72. template <class T>
  73. struct condition: leaf_node<T>
  74. {
  75. virtual status execute(context_type& context) const final;
  76. typedef std::function<status(const context_type&)> predicate_type;
  77. predicate_type predicate;
  78. };
  79. /// Executes a child node and returns its inverted status. If the child returns `status::success`, then `status::failure` will be returned. Otherwise if the child returns `status::failure`, then `status::success` will be returned.
  80. template <class T>
  81. struct inverter: decorator_node<T>
  82. {
  83. virtual status execute(context_type& context) const final;
  84. };
  85. /// Attempts to execute a child node `n` times or until the child fails.
  86. template <class T>
  87. struct repeater: decorator_node<T>
  88. {
  89. virtual status execute(context_type& context) const final;
  90. int n;
  91. };
  92. /// Executes a child node and returns `status::success` regardless of the child node status.
  93. template <class T>
  94. struct succeeder: decorator_node<T>
  95. {
  96. virtual status execute(context_type& context) const final;
  97. };
  98. /// Attempts to execute each child node sequentially until one fails. If all children are executed successfully, `status::success` will be returned. Otherwise if any children fail, `status::failure` will be returned.
  99. template <class T>
  100. struct sequence: composite_node<T>
  101. {
  102. virtual status execute(context_type& context) const final;
  103. };
  104. /// Attempts to execute each child node sequentially until one succeeds. If a child succeeds, `status::success` will be returned. Otherwise if all children fail, `status::failure` will be returned.
  105. template <class T>
  106. struct selector: composite_node<T>
  107. {
  108. virtual status execute(context_type& context) const final;
  109. };
  110. template <class T>
  111. status action<T>::execute(context_type& context) const
  112. {
  113. return function(context);
  114. }
  115. template <class T>
  116. status condition<T>::execute(context_type& context) const
  117. {
  118. return (predicate(context)) ? status::success : status::failure;
  119. }
  120. template <class T>
  121. status inverter<T>::execute(context_type& context) const
  122. {
  123. status child_status = child->execute(context);
  124. return (child_status == status::success) ? status::failure : (child_status == status::failure) ? status::success : child_status;
  125. }
  126. template <class T>
  127. status repeater<T>::execute(context_type& context) const
  128. {
  129. status child_status;
  130. for (int i = 0; i < n; ++i)
  131. {
  132. child_status = child->execute(context);
  133. if (child_status == status::failure)
  134. break;
  135. }
  136. return child_status;
  137. }
  138. template <class T>
  139. status succeeder<T>::execute(context_type& context) const
  140. {
  141. child->execute(context);
  142. return status::success;
  143. }
  144. template <class T>
  145. status sequence<T>::execute(context_type& context) const
  146. {
  147. for (const node* child: children)
  148. {
  149. status child_status = child->execute(context);
  150. if (child_status != status::success)
  151. return child_status;
  152. }
  153. return status::success;
  154. }
  155. template <class T>
  156. status selector<T>::execute(context_type& context) const
  157. {
  158. for (const node* child: children)
  159. {
  160. status child_status = child->execute(context);
  161. if (child_status != status::failure)
  162. return child_status;
  163. }
  164. return status::failure;
  165. }
  166. } // namespace behavior_tree
  167. #endif // ANTKEEPER_BEHAVIOR_TREE_HPP