Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
BehaviorTree.h
Go to the documentation of this file.
1/**
2 * @file BehaviorTree.h
3 * @brief Data-driven behavior tree system for AI decision making
4 * @author Nicolas Chereau
5 * @date 2025
6 * @version 2.0
7 *
8 * @details
9 * This file implements a behavior tree system for creating complex AI behaviors.
10 * Behavior trees are hierarchical structures that make decisions based on conditions
11 * and execute actions based on those decisions.
12 *
13 * Key features:
14 * - Composite nodes: Selector (OR), Sequence (AND)
15 * - Decorator nodes: Inverter, Repeater
16 * - Condition nodes: State checking (health, target, etc.)
17 * - Action nodes: Behaviors (move, attack, patrol, etc.)
18 * - JSON-based tree definitions
19 * - Per-entity tree execution
20 *
21 * @note Behavior Tree purpose: Data-driven behavior tree system for AI decision making.
22 *
23 * @example
24 * @code
25 * // Load behavior tree from JSON
26 * BehaviorTree::LoadTreeForEntity(npcEntity, "Blueprints/BehaviorTrees/Patrol.json");
27 *
28 * // Update tree each frame
29 * BehaviorTree::UpdateEntity(npcEntity, deltaTime);
30 * @endcode
31 */
32
33#pragma once
34
35#include "../ECS_Entity.h"
36#include "../vector.h"
37#include <vector>
38#include <string>
39#include <cstdint>
40#include <map>
41
42// Forward declarations
44
45/**
46 * @enum BTNodeType
47 * @brief Behavior tree node types
48 *
49 * Defines the different types of nodes that can exist in a behavior tree.
50 */
51enum class BTNodeType : uint8_t
52{
53 Selector = 0, ///< OR node - succeeds if any child succeeds
54 Sequence, ///< AND node - succeeds if all children succeed
55 Condition, ///< Leaf node - checks a condition
56 Action, ///< Leaf node - performs an action
57 Inverter, ///< Decorator - inverts child result
58 Repeater ///< Decorator - repeats child N times
59};
60
61/**
62 * @enum BTStatus
63 * @brief Behavior tree node execution status
64 *
65 * Represents the current state of a behavior tree node.
66 */
67enum class BTStatus : uint8_t
68{
69 Idle = 0, ///< Node waiting for execution (not yet started)
70 Running = 1, ///< Node is currently executing
71 Success = 2, ///< Node completed successfully
72 Failure = 3, ///< Node failed
73 Aborted = 4 ///< Node execution interrupted (e.g., entity destroyed)
74};
75
76/**
77 * @enum BTConditionType
78 * @brief Built-in condition types for behavior trees
79 *
80 * Predefined conditions that can be checked during tree execution.
81 */
83{
84 TargetVisible = 0, ///< Can see target entity
85 TargetInRange, ///< Target within specified range
86 HealthBelow, ///< Health below threshold
87 HasMoveGoal, ///< Movement goal is set
88 CanAttack, ///< Attack is available
89 HeardNoise, ///< Detected noise
90 // NEW: Wander behavior conditions
91 IsWaitTimerExpired, ///< Wait timer expired?
92 HasNavigableDestination, ///< Navigable destination chosen?
93 HasValidPath, ///< Valid path calculated?
94 HasReachedDestination, ///< Reached destination?
95 // Catalog aliases for better readability
96 HasTarget = TargetVisible, ///< Alias for HasTarget condition
97 IsTargetInAttackRange = TargetInRange ///< Alias for range check
98};
99
100/**
101 * @enum BTActionType
102 * @brief Built-in action types for behavior trees
103 *
104 * Predefined actions that can be executed during tree execution.
105 */
107{
108 SetMoveGoalToLastKnownTargetPos = 0, ///< Move to last seen target position
109 SetMoveGoalToTarget, ///< Move towards current target
110 SetMoveGoalToPatrolPoint, ///< Move to next patrol waypoint
111 MoveToGoal, ///< Execute movement to goal
112 AttackIfClose, ///< Attack if in range
113 PatrolPickNextPoint, ///< Select next patrol point
114 ClearTarget, ///< Clear current target
115 Idle, ///< Do nothing
116 // NEW: Wander behavior actions
117 WaitRandomTime, ///< Initialize random timer (param1=min, param2=max)
118 ChooseRandomNavigablePoint, ///< Choose navigable point (param1=searchRadius, param2=maxAttempts)
119 RequestPathfinding, ///< Request pathfinding to moveGoal via MoveIntent
120 FollowPath, ///< Follow the path (check progression)
121 // Catalog aliases for better readability
122 MoveTo = MoveToGoal, ///< Alias for MoveTo action
123 AttackMelee = AttackIfClose ///< Alias for melee attack
124};
125
126/**
127 * @struct BTNode
128 * @brief Represents a single node in a behavior tree
129 *
130 * Can be a composite, decorator, condition, or action node.
131 * Stores node type, parameters, and child references.
132 */
133struct BTNode
134{
136 uint32_t id = 0; ///< Unique node ID within tree
137
138 // For composite nodes (Selector, Sequence)
139 std::vector<uint32_t> childIds; ///< IDs of child nodes
140
141 // For condition nodes
143 std::string conditionTypeString; ///< Condition type as string (for flexible conditions like CheckBlackboardValue)
144 float conditionParam = 0.0f; ///< Generic parameter for conditions
145
146 // For action nodes
148 float actionParam1 = 0.0f; ///< Generic parameter 1 for actions
149 float actionParam2 = 0.0f; ///< Generic parameter 2 for actions
150
151 // For decorator nodes
153 int repeatCount = 1; // For Repeater decorator
154
155 // Debug info
156 std::string name;
157
158 // Flexible parameters (for new condition/action types that need structured data)
159 std::map<std::string, std::string> stringParams; ///< String parameters
160 std::map<std::string, int> intParams; ///< Integer parameters
161 std::map<std::string, float> floatParams; ///< Float parameters
162
163 // Helper methods for parameter access
164 std::string GetParameterString(const std::string& key, const std::string& defaultValue = "") const
165 {
166 auto it = stringParams.find(key);
167 return (it != stringParams.end()) ? it->second : defaultValue;
168 }
169
170 int GetParameterInt(const std::string& key, int defaultValue = 0) const
171 {
172 auto it = intParams.find(key);
173 return (it != intParams.end()) ? it->second : defaultValue;
174 }
175
176 float GetParameterFloat(const std::string& key, float defaultValue = 0.0f) const
177 {
178 auto it = floatParams.find(key);
179 return (it != floatParams.end()) ? it->second : defaultValue;
180 }
181};
182
183/**
184 * @struct BTValidationMessage
185 * @brief Validation message for behavior tree structure checking
186 */
188{
189 enum class Severity : uint8_t
190 {
191 Info = 0,
192 Warning = 1,
193 Error = 2
194 };
195
198 std::string message;
199};
200
201// --- Behavior Tree Asset ---
203{
204 uint32_t id = 0; // Unique tree ID
205 std::string name;
206 std::vector<BTNode> nodes;
208
209 // Helper: get node by ID
211 {
212 for (auto& node : nodes)
213 {
214 if (node.id == nodeId)
215 return &node;
216 }
217 return nullptr;
218 }
219
220 const BTNode* GetNode(uint32_t nodeId) const
221 {
222 for (const auto& node : nodes)
223 {
224 if (node.id == nodeId)
225 return &node;
226 }
227 return nullptr;
228 }
229
230 // Validation methods
231 std::vector<BTValidationMessage> ValidateTreeFull() const;
232 bool DetectCycle(uint32_t startNodeId) const;
233
234 // Editor CRUD operations
235 uint32_t AddNode(BTNodeType type, const std::string& name, const Vector& position);
236 bool RemoveNode(uint32_t nodeId);
237 bool ConnectNodes(uint32_t parentId, uint32_t childId);
238 bool DisconnectNodes(uint32_t parentId, uint32_t childId);
240};
241
242// --- Behavior Tree Manager ---
243// Singleton manager for loading and caching behavior tree assets
245{
246public:
248 {
250 return instance;
251 }
252
253 // Load a behavior tree from JSON file
254 bool LoadTreeFromFile(const std::string& filepath, uint32_t treeId);
255
256 // Reload a behavior tree from JSON file (hot-reload support)
257 bool ReloadTree(uint32_t treeId);
258
259 // Validate a behavior tree structure
260 bool ValidateTree(const BehaviorTreeAsset& tree, std::string& errorMessage) const;
261
262 // Get a loaded tree by ID
263 const BehaviorTreeAsset* GetTree(uint32_t treeId) const;
264
265 // Clear all loaded trees
266 void Clear();
267
268 // NEW: Get tree ID from path (for prefab instantiation)
269 uint32_t GetTreeIdFromPath(const std::string& treePath) const;
270
271 // NEW: Check if tree is already loaded by path
272 bool IsTreeLoadedByPath(const std::string& treePath) const;
273
274 // NEW: Get loaded tree by path
275 const BehaviorTreeAsset* GetTreeByPath(const std::string& treePath) const;
276
277 // NEW: Enhanced lookup that tries multiple strategies
278 const BehaviorTreeAsset* GetTreeByAnyId(uint32_t treeId) const;
279
280 // NEW: Get tree path from ID (reverse lookup)
281 std::string GetTreePathFromId(uint32_t treeId) const;
282
283 // NEW: Debug method to list all loaded trees
284 void DebugPrintLoadedTrees() const;
285
286private:
288 std::vector<BehaviorTreeAsset> m_trees;
289
290 // NEW: Registry to map file paths to tree IDs
291 std::map<std::string, uint32_t> m_pathToIdMap;
292};
293
294// --- Behavior Tree Execution ---
295// Execute a single node of a behavior tree
297
298// Execute built-in condition nodes
300
301// Execute built-in action nodes
302BTStatus ExecuteBTAction(BTActionType actionType, float param1, float param2, EntityID entity, AIBlackboard_data& blackboard);
BTStatus ExecuteBTAction(BTActionType actionType, float param1, float param2, EntityID entity, AIBlackboard_data &blackboard)
BTActionType
Built-in action types for behavior trees.
@ SetMoveGoalToTarget
Move towards current target.
@ SetMoveGoalToLastKnownTargetPos
Move to last seen target position.
@ WaitRandomTime
Initialize random timer (param1=min, param2=max)
@ AttackMelee
Alias for melee attack.
@ MoveToGoal
Execute movement to goal.
@ ClearTarget
Clear current target.
@ PatrolPickNextPoint
Select next patrol point.
@ ChooseRandomNavigablePoint
Choose navigable point (param1=searchRadius, param2=maxAttempts)
@ AttackIfClose
Attack if in range.
@ MoveTo
Alias for MoveTo action.
@ Idle
Do nothing.
@ SetMoveGoalToPatrolPoint
Move to next patrol waypoint.
@ RequestPathfinding
Request pathfinding to moveGoal via MoveIntent.
@ FollowPath
Follow the path (check progression)
BTStatus ExecuteBTNode(const BTNode &node, EntityID entity, AIBlackboard_data &blackboard, const BehaviorTreeAsset &tree)
BTStatus
Behavior tree node execution status.
@ Success
Node completed successfully.
@ Running
Node is currently executing.
@ Aborted
Node execution interrupted (e.g., entity destroyed)
@ Failure
Node failed.
@ Idle
Node waiting for execution (not yet started)
BTNodeType
Behavior tree node types.
@ Action
Leaf node - performs an action.
@ Selector
OR node - succeeds if any child succeeds.
@ Sequence
AND node - succeeds if all children succeed.
@ Inverter
Decorator - inverts child result.
@ Condition
Leaf node - checks a condition.
@ Repeater
Decorator - repeats child N times.
BTConditionType
Built-in condition types for behavior trees.
@ HasValidPath
Valid path calculated?
@ CanAttack
Attack is available.
@ IsWaitTimerExpired
Wait timer expired?
@ HeardNoise
Detected noise.
@ TargetVisible
Can see target entity.
@ HasMoveGoal
Movement goal is set.
@ IsTargetInAttackRange
Alias for range check.
@ HasTarget
Alias for HasTarget condition.
@ HasNavigableDestination
Navigable destination chosen?
@ HealthBelow
Health below threshold.
@ HasReachedDestination
Reached destination?
@ TargetInRange
Target within specified range.
BTStatus ExecuteBTCondition(BTConditionType condType, float param, EntityID entity, const AIBlackboard_data &blackboard)
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
std::uint64_t EntityID
Definition ECS_Entity.h:21
bool LoadTreeFromFile(const std::string &filepath, uint32_t treeId)
std::string GetTreePathFromId(uint32_t treeId) const
void DebugPrintLoadedTrees() const
uint32_t GetTreeIdFromPath(const std::string &treePath) const
const BehaviorTreeAsset * GetTree(uint32_t treeId) const
static BehaviorTreeManager & Get()
std::vector< BehaviorTreeAsset > m_trees
bool IsTreeLoadedByPath(const std::string &treePath) const
bool ValidateTree(const BehaviorTreeAsset &tree, std::string &errorMessage) const
std::map< std::string, uint32_t > m_pathToIdMap
bool ReloadTree(uint32_t treeId)
BehaviorTreeManager()=default
const BehaviorTreeAsset * GetTreeByPath(const std::string &treePath) const
const BehaviorTreeAsset * GetTreeByAnyId(uint32_t treeId) const
Represents a single node in a behavior tree.
std::map< std::string, int > intParams
Integer parameters.
std::string conditionTypeString
Condition type as string (for flexible conditions like CheckBlackboardValue)
std::vector< uint32_t > childIds
IDs of child nodes.
float GetParameterFloat(const std::string &key, float defaultValue=0.0f) const
BTConditionType conditionType
Condition type (enum)
std::string GetParameterString(const std::string &key, const std::string &defaultValue="") const
float actionParam1
Generic parameter 1 for actions.
std::string name
uint32_t decoratorChildId
BTActionType actionType
Action type.
int GetParameterInt(const std::string &key, int defaultValue=0) const
float actionParam2
Generic parameter 2 for actions.
std::map< std::string, std::string > stringParams
String parameters.
int repeatCount
BTNodeType type
Node type.
std::map< std::string, float > floatParams
Float parameters.
float conditionParam
Generic parameter for conditions.
Validation message for behavior tree structure checking.
uint32_t AddNode(BTNodeType type, const std::string &name, const Vector &position)
const BTNode * GetNode(uint32_t nodeId) const
bool RemoveNode(uint32_t nodeId)
std::vector< BTValidationMessage > ValidateTreeFull() const
bool ConnectNodes(uint32_t parentId, uint32_t childId)
uint32_t GenerateNextNodeId() const
std::vector< BTNode > nodes
BTNode * GetNode(uint32_t nodeId)
bool DetectCycle(uint32_t startNodeId) const
bool DisconnectNodes(uint32_t parentId, uint32_t childId)