Ember
Loading...
Searching...
No Matches
BehaviorTree.h
Go to the documentation of this file.
1#pragma once
2
14
15#include "BlackboardEntry.h"
16#include "Node.h"
17#include <functional>
18#include <memory>
19#include <unordered_map>
20#include <vector>
21
22namespace EmberCore {
23
29 struct Comment {
31 bool before_node; // true if comment appears before node, false if after
32 };
33
34 // Map node ID -> comments associated with that node
35 std::unordered_map<size_t, std::vector<Comment>> node_comments;
36
37 // Document-level comments (header, footer)
38 std::vector<EmberCore::String> header_comments;
39 std::vector<EmberCore::String> footer_comments;
40
41 // Formatting hints
42 int indent_size = 4;
43 bool use_tabs = false;
44};
45
55 public:
59 enum class ExecutionState {
60 Idle, // Not running
61 Running, // Currently executing
62 Paused, // Execution paused
63 Completed, // Finished successfully
64 Failed // Finished with failure
65 };
66
71 bool is_valid = true;
72 std::vector<EmberCore::String> errors;
73 std::vector<EmberCore::String> warnings;
74
75 void AddError(const EmberCore::String &error) {
76 errors.push_back(error);
77 is_valid = false;
78 }
79
80 void AddWarning(const EmberCore::String &warning) { warnings.push_back(warning); }
81 };
82
83 public:
88 explicit BehaviorTree(const EmberCore::String &name = "Behavior Tree");
89
94
95 // Tree structure management
96 void SetRootNode(std::unique_ptr<Node> root);
97 void SetRootNode(std::shared_ptr<Node> root); // New: shared_ptr support
98 Node *GetRootNode() const { return root_node_ ? root_node_.get() : root_node_shared_.get(); }
99 std::shared_ptr<Node> GetRootNodeShared() const { return root_node_shared_; } // New: shared access
100 bool HasRootNode() const { return root_node_.get() || root_node_shared_.get(); }
101
102 // Tree properties
103 const EmberCore::String &GetName() const { return name_; }
104 void SetName(const EmberCore::String &name) { name_ = name; }
105
107 void SetDescription(const EmberCore::String &description) { description_ = description; }
108
109 // Tree statistics
110 size_t GetNodeCount() const;
111 size_t GetMaxDepth() const;
112 std::vector<Node *> GetAllNodes();
113 std::vector<const Node *> GetAllNodes() const;
114
115 // Node operations
116 Node *FindNodeById(size_t id) const;
117 Node *FindNodeByName(const EmberCore::String &name) const;
118 std::vector<Node *> FindNodesByType(Node::Type type) const;
119
120 // Tree manipulation
121 bool AddNode(std::unique_ptr<Node> node, Node *parent = nullptr);
122 bool RemoveNode(size_t node_id);
123 bool MoveNode(size_t node_id, Node *new_parent);
124 std::unique_ptr<Node> ExtractNode(size_t node_id);
125
126 // Tree validation
128 bool IsValid() const { return Validate().is_valid; }
129 bool HasCycles() const;
130
131 // Tree execution state
134
135 // Tree operations
136 void Clear();
137 std::unique_ptr<BehaviorTree> Clone() const;
138 void Reset(); // Reset all node states to default
139
140 // Blackboard management
141 void AddBlackboard(std::unique_ptr<Blackboard> blackboard);
143 const Blackboard *GetBlackboard(const EmberCore::String &id) const;
144 bool HasBlackboard(const EmberCore::String &id) const;
145 void RemoveBlackboard(const EmberCore::String &id);
146 const std::map<EmberCore::String, std::unique_ptr<Blackboard>> &GetBlackboards() const { return blackboards_; }
147 size_t GetBlackboardCount() const { return blackboards_.size(); }
148 void ClearBlackboards();
149
150 // Serialization
153
154 // File operations
155 bool SaveToFile(const EmberCore::String &filename) const;
156 bool LoadFromFile(const EmberCore::String &filename);
157
158 // Visitor pattern
159 void TraverseNodes(std::function<void(Node *)> visitor);
160 void TraverseNodes(std::function<void(const Node *)> visitor) const;
161 void TraversePreOrder(std::function<void(Node *)> visitor);
162 void TraversePostOrder(std::function<void(Node *)> visitor);
163
164 // Events and callbacks
165 using NodeChangeCallback = std::function<void(Node *, const EmberCore::String &change_type)>;
166 using TreeChangeCallback = std::function<void(const EmberCore::String &change_type)>;
167
170
171 // Debug utilities
172 void PrintTree() const;
174 std::unordered_map<Node::Type, size_t> GetNodeTypeStatistics() const;
175
176 // Tree metadata
177 void SetMetadata(const EmberCore::String &key, const EmberCore::String &value);
179 void RemoveMetadata(const EmberCore::String &key);
180 const std::unordered_map<EmberCore::String, EmberCore::String> &GetAllMetadata() const { return metadata_; }
181
182 // XML metadata (for comment/formatting preservation)
184 const XMLMetadata &GetXMLMetadata() const { return xml_metadata_; }
185
186 protected:
187 // Internal helper methods
188 void NotifyNodeChange(Node *node, const EmberCore::String &change_type);
189 void NotifyTreeChange(const EmberCore::String &change_type);
190 void UpdateNodeIndex();
191 Node *FindNodeRecursive(Node *current, std::function<bool(const Node *)> predicate) const;
192 void CollectNodesRecursive(Node *current, std::vector<Node *> &nodes);
193 void CollectNodesRecursive(const Node *current, std::vector<const Node *> &nodes) const;
194
195 private:
196 // Core tree data
197 std::unique_ptr<Node> root_node_;
198 std::shared_ptr<Node> root_node_shared_; // New: for shared ownership
202
203 // Node lookup optimization
204 std::unordered_map<size_t, Node *> node_index_;
205
206 // Metadata storage
207 std::unordered_map<EmberCore::String, EmberCore::String> metadata_;
208
209 // XML metadata (comments and formatting)
211
212 // Blackboard storage
213 std::map<EmberCore::String, std::unique_ptr<Blackboard>> blackboards_;
214
215 // Event callbacks
218
219 // Helper methods
220 ValidationResult ValidateNode(const Node *node, std::vector<const Node *> &visited) const;
221 void BuildNodeIndex(Node *node);
222};
223
224// Utility functions
229std::unique_ptr<BehaviorTree> CreateSampleTree();
230
234std::unique_ptr<BehaviorTree> CreateEmptyTree(const EmberCore::String &name = "New Tree");
235
239std::unique_ptr<BehaviorTree> MergeTrees(const BehaviorTree &tree1, const BehaviorTree &tree2);
240} // namespace BehaviorTreeUtils
241
242} // namespace EmberCore
Represents a complete behavior tree data structure.
const EmberCore::String & GetDescription() const
Blackboard * GetBlackboard(const EmberCore::String &id)
size_t GetBlackboardCount() const
std::map< EmberCore::String, std::unique_ptr< Blackboard > > blackboards_
ExecutionState GetExecutionState() const
std::shared_ptr< Node > GetRootNodeShared() const
std::shared_ptr< Node > root_node_shared_
std::unique_ptr< Node > root_node_
void TraverseNodes(std::function< void(Node *)> visitor)
size_t GetNodeCount() const
std::vector< Node * > GetAllNodes()
Node * GetRootNode() const
std::unordered_map< size_t, Node * > node_index_
void TraversePostOrder(std::function< void(Node *)> visitor)
EmberCore::String GetMetadata(const EmberCore::String &key) const
const std::map< EmberCore::String, std::unique_ptr< Blackboard > > & GetBlackboards() const
EmberCore::String Serialize() const
EmberCore::String description_
bool HasBlackboard(const EmberCore::String &id) const
std::unordered_map< Node::Type, size_t > GetNodeTypeStatistics() const
void SetMetadata(const EmberCore::String &key, const EmberCore::String &value)
size_t GetMaxDepth() const
std::function< void(Node *, const EmberCore::String &change_type)> NodeChangeCallback
void AddBlackboard(std::unique_ptr< Blackboard > blackboard)
EmberCore::String name_
void BuildNodeIndex(Node *node)
ExecutionState
Tree execution states.
XMLMetadata & GetXMLMetadata()
bool Deserialize(const EmberCore::String &data)
bool RemoveNode(size_t node_id)
EmberCore::String GetTreeStructure() const
void CollectNodesRecursive(Node *current, std::vector< Node * > &nodes)
ValidationResult ValidateNode(const Node *node, std::vector< const Node * > &visited) const
void SetExecutionState(ExecutionState state)
bool SaveToFile(const EmberCore::String &filename) const
void RemoveBlackboard(const EmberCore::String &id)
std::function< void(const EmberCore::String &change_type)> TreeChangeCallback
bool MoveNode(size_t node_id, Node *new_parent)
void SetDescription(const EmberCore::String &description)
BehaviorTree(const EmberCore::String &name="Behavior Tree")
Constructor.
ValidationResult Validate() const
bool LoadFromFile(const EmberCore::String &filename)
bool AddNode(std::unique_ptr< Node > node, Node *parent=nullptr)
std::unique_ptr< Node > ExtractNode(size_t node_id)
std::unique_ptr< BehaviorTree > Clone() const
const XMLMetadata & GetXMLMetadata() const
const EmberCore::String & GetName() const
void TraversePreOrder(std::function< void(Node *)> visitor)
void SetRootNode(std::unique_ptr< Node > root)
ExecutionState execution_state_
std::unordered_map< EmberCore::String, EmberCore::String > metadata_
void SetName(const EmberCore::String &name)
const std::unordered_map< EmberCore::String, EmberCore::String > & GetAllMetadata() const
void SetTreeChangeCallback(TreeChangeCallback callback)
TreeChangeCallback tree_change_callback_
std::vector< Node * > FindNodesByType(Node::Type type) const
void NotifyTreeChange(const EmberCore::String &change_type)
Node * FindNodeById(size_t id) const
NodeChangeCallback node_change_callback_
Node * FindNodeByName(const EmberCore::String &name) const
void NotifyNodeChange(Node *node, const EmberCore::String &change_type)
void RemoveMetadata(const EmberCore::String &key)
void SetNodeChangeCallback(NodeChangeCallback callback)
Node * FindNodeRecursive(Node *current, std::function< bool(const Node *)> predicate) const
Represents a blackboard containing multiple entries.
Represents a node in a behavior tree structure.
Definition Node.h:20
Type
Node types for behavior tree classification.
Definition Node.h:25
std::unique_ptr< BehaviorTree > CreateSampleTree()
Create a sample behavior tree for testing.
std::unique_ptr< BehaviorTree > CreateEmptyTree(const EmberCore::String &name="New Tree")
Create an empty behavior tree with basic structure.
std::unique_ptr< BehaviorTree > MergeTrees(const BehaviorTree &tree1, const BehaviorTree &tree2)
Merge two behavior trees.
Main types header for EmberCore.
std::string String
Framework-agnostic string type.
Definition String.h:14
void AddError(const EmberCore::String &error)
void AddWarning(const EmberCore::String &warning)
std::vector< EmberCore::String > errors
std::vector< EmberCore::String > warnings
Stores XML-specific metadata for preserving comments and formatting.
std::unordered_map< size_t, std::vector< Comment > > node_comments
std::vector< EmberCore::String > header_comments
std::vector< EmberCore::String > footer_comments