Atoms Crowd  7.0.0
BehaviourTreeContext.h
1 #pragma once
2 // ===========================================================================
3 // Copyright (c) 2015 Toolchefs Ltd. All rights reserved.
4 //
5 // Use of this software is subject to the terms of the Toolchefs license
6 // agreement provided at the time of installation or download, or which
7 // otherwise accompanies this software in either electronic or hard copy form.
8 // ===========================================================================
9 
10 #include <Atoms/Globals.h>
11 #include <Atoms/BehaviourTree/Behaviour.h>
12 #include <Atoms/BehaviourTree/Blackboard.h>
13 #include <Atoms/BehaviourTree/BlackboardValue.h>
14 #include <Atoms/AgentGroup.h>
15 #include <Atoms/Agent.h>
16 #include <vector>
17 #include <deque>
18 
19 namespace Atoms
20 {
21  class BehaviourTree;
22 
23  class ATOMS_EXPORT BehaviourTreeContext
24  {
25  public:
26 
27  struct ChildState
28  {
29  unsigned short index;
30  unsigned short state;
31  };
32 
34  {
35  Behaviour::State state;
36  unsigned short childIndex;
37  unsigned short childState;
38  };
39 
41  {
42  public:
43  AgentScopeLock(Atoms::Agent* ag) : agent(ag) {
44  if (agent) { agent->lock(); }
45  }
47  {
48  if (agent) { agent->unlock(); }
49  }
50  Atoms::Agent* agent;
51  };
52 
53  const unsigned short nullIndex = 0;
54 
56 
58 
60 
61  void setTree(BehaviourTree* bt);
62 
63  bool start();
64 
65  bool start(const std::string& name);
66 
67  bool start(unsigned short index);
68 
69  void abort(unsigned short index);
70 
71  bool isRunning() const;
72 
73  void stop();
74 
75  Behaviour::Status tick();
76 
77  void updateParent(Behaviour* behaviour, Behaviour::State& current);
78  void dirtyUpdateParent(Behaviour* behaviour, Behaviour::State& current);
79 
80  template <class T>
81  T* allocateMemory() {
82  return new T();
83  }
84 
85  template <class T>
86  void releaseMemory(T* data) {
87  delete data;
88  }
89 
90  std::string behaviourName(unsigned short index) const;
91 
92  template <class T>
93  inline T& getBlackboardValue(BlackboardValue<T>& value);
94 
95  template <class T>
96  inline std::vector<T>& getBlackboardValue(BlackboardValue<std::vector<T>>& value);
97 
98  template <class T>
99  inline bool setBlackboardValue(const BlackboardValue<T>& value);
100 
101  template <class T>
102  inline bool setBlackboardValue(const BlackboardValue<std::vector<T>>& value);
103 
104  AtomsPtr<AtomsCore::Metadata> getBlackboardValueFromName(const std::string& name) const;
105 
106  AtomsPtr<AtomsCore::Metadata> getBlackboardValueFromPosition(const BlackboardEntryPosition& position) const;
107 
108  void cacheMetadata(Atoms::BlackboardEntryPosition& position);
109 
110  void unCacheMetadata(Atoms::BlackboardEntryPosition& position);
111 
112  void lock();
113 
114  void unlock();
115 
116  public:
117 
118  BlackboardInstance blackboardInstance;
119 
120  BehaviourTree* tree;
121 
122  AgentGroup* agentGroup;
123 
124  Agent* agent;
125 
126  std::mutex* mutex;
127 
128  std::deque<BehaviourStackState> m_activeBehaviours;
129 
130  std::vector<Behaviour::State> m_activeStack;
131 
132  std::vector<BehaviourStackState> m_aborted;
133 
134  std::vector<BehaviourStackState> m_started;
135 
136  std::vector<unsigned short> m_successBehaviours;
137  std::vector<unsigned short> m_failureBehaviours;
138 
139  unsigned short tickCount;
140 
141  double tickTime;
142 
143  unsigned int seed;
144 
145  bool debug;
146 
147  bool isLocked;
148  };
149 
150 
151  template <class T>
152  inline T& BehaviourTreeContext::getBlackboardValue(BlackboardValue<T>& value)
153  {
154  if (value.position.valueIndex == -1)
155  {
156  return value.value;
157  }
158 
159  auto* sourceboard = &blackboardInstance;
160  if (value.position.parentIndex > 0)
161  {
162  for (short i = 0; i < value.position.parentIndex; ++i)
163  {
164  if (!sourceboard)
165  {
166  break;
167  }
168 
169  sourceboard = sourceboard->parent;
170  }
171  }
172 
173  // Not value found on the blackboard
174  if (!sourceboard || sourceboard->size() <= value.position.valueIndex)
175  {
176  return value.value;
177  }
178 
179  auto& entry = sourceboard->blackboard->entry(value.position.valueIndex);
180  auto& instanceEntry = sourceboard->entry(value.position.valueIndex);
181  if (entry.flags != Atoms::BlackboardEntry::Flags::LinkMetadata)
182  {
183  if (instanceEntry && instanceEntry->typeId() == AtomsCore::MetadataImpl<T>::staticTypeId())
184  {
185  auto metaPtr = static_cast<AtomsCore::MetadataImpl<T>*>(instanceEntry.get());
186  return metaPtr->get();
187  }
188  else
189  {
190  return value.value;
191  }
192  }
193 
194  if (!agent)
195  return value.value;
196 
197  auto agentMeta = agent->metadata().getTypedEntry<AtomsCore::MetadataImpl<T>>(entry.name);
198  if (!agentMeta)
199  return value.value;
200 
201  return agentMeta->get();
202  }
203 
204  template <>
205  inline AtomsPtr<AtomsCore::Metadata>& BehaviourTreeContext::getBlackboardValue<AtomsPtr<AtomsCore::Metadata>>(BlackboardMetadataValue& value)
206  {
207  if (value.position.valueIndex == -1)
208  {
209  return value.value;
210  }
211 
212  auto* sourceboard = &blackboardInstance;
213  if (value.position.parentIndex > 0)
214  {
215  for (short i = 0; i < value.position.parentIndex; ++i)
216  {
217  if (!sourceboard)
218  {
219  break;
220  }
221 
222  sourceboard = sourceboard->parent;
223  }
224  }
225 
226  // Not value found on the blackboard
227  if (!sourceboard || sourceboard->size() <= value.position.valueIndex)
228  {
229  return value.value;
230  }
231 
232  auto& entry = sourceboard->blackboard->entry(value.position.valueIndex);
233  auto& instanceEntry = sourceboard->entry(value.position.valueIndex);
234  if (entry.flags != Atoms::BlackboardEntry::Flags::LinkMetadata)
235  {
236  if (instanceEntry)
237  {
238  return instanceEntry;
239  }
240  else
241  {
242  return value.value;
243  }
244  }
245 
246  if (!agent)
247  return value.value;
248 
249  auto agentMeta = agent->metadata().data().find(entry.name);
250  if (agentMeta == agent->metadata().data().end())
251  return value.value;
252 
253  return agentMeta->second;
254  }
255 
256  template <class T>
257  inline std::vector<T>& BehaviourTreeContext::getBlackboardValue(BlackboardValue<std::vector<T>>& value)
258  {
259  if (value.position.valueIndex == -1)
260  {
261  return value.value;
262  }
263 
264  auto* sourceboard = &blackboardInstance;
265  if (value.position.parentIndex > 0)
266  {
267  for (short i = 0; i < value.position.parentIndex; ++i)
268  {
269  if (!sourceboard)
270  {
271  break;
272  }
273 
274  sourceboard = sourceboard->parent;
275  }
276  }
277 
278  // Not value found on the blackboard
279  if (!sourceboard || sourceboard->size() <= value.position.valueIndex)
280  {
281  return value.value;
282  }
283 
284  auto& entry = sourceboard->blackboard->entry(value.position.valueIndex);
285  auto& instanceEntry = sourceboard->entry(value.position.valueIndex);
286  if (entry.flags != Atoms::BlackboardEntry::Flags::LinkMetadata)
287  {
288  if (instanceEntry && instanceEntry->typeId() == AtomsCore::TypedArrayMetadata<T>::staticTypeId())
289  {
290  auto metaPtr = static_cast<AtomsCore::TypedArrayMetadata<T>*>(instanceEntry.get());
291  return metaPtr->get();
292  }
293  else
294  {
295  return value.value;
296  }
297  }
298 
299  if (!agent)
300  return value.value;
301 
302  auto agentMeta = agent->metadata().getTypedEntry<AtomsCore::TypedArrayMetadata<T>>(entry.name);
303  if (!agentMeta)
304  return value.value;
305 
306  return agentMeta->get();
307  }
308 
309  template <class T>
310  inline bool BehaviourTreeContext::setBlackboardValue(const BlackboardValue<T>& value)
311  {
312  if (value.position.valueIndex == -1)
313  {
314  return false;
315  }
316 
317  auto* sourceboard = &blackboardInstance;
318  if (value.position.parentIndex > 0)
319  {
320  for (short i = 0; i < value.position.parentIndex; ++i)
321  {
322  if (!sourceboard)
323  {
324  break;
325  }
326 
327  sourceboard = sourceboard->parent;
328  }
329  }
330 
331  // Not value found on the blackboard
332  if (!sourceboard || sourceboard->size() <= value.position.valueIndex)
333  {
334  return false;
335  }
336 
337  auto& entry = sourceboard->blackboard->entry(value.position.valueIndex);
338  auto& instanceEntry = sourceboard->entry(value.position.valueIndex);
339  if (entry.flags != Atoms::BlackboardEntry::Flags::LinkMetadata)
340  {
341  if (instanceEntry && instanceEntry->typeId() == AtomsCore::MetadataImpl<T>::staticTypeId())
342  {
343  static_cast<AtomsCore::MetadataImpl<T>*>(instanceEntry.get())->set(value.value);
344  return true;
345  }
346  return false;
347  }
348 
349  if (!agent)
350  return false;
351 
352  auto agentMeta = agent->metadata().getEntry(entry.name);
353  if (agentMeta && agentMeta->typeId() == AtomsCore::MetadataImpl<T>::staticTypeId())
354  {
355  static_cast<AtomsCore::MetadataImpl<T>*>(agentMeta.get())->set(value.value);
356  return true;
357  }
358  return false;
359  }
360 
361  template <>
362  inline bool BehaviourTreeContext::setBlackboardValue<AtomsPtr<AtomsCore::Metadata>>(const BlackboardMetadataValue& value)
363  {
364  if (value.position.valueIndex == -1)
365  {
366  return false;
367  }
368 
369  auto* sourceboard = &blackboardInstance;
370  if (value.position.parentIndex > 0)
371  {
372  for (short i = 0; i < value.position.parentIndex; ++i)
373  {
374  if (!sourceboard)
375  {
376  break;
377  }
378 
379  sourceboard = sourceboard->parent;
380  }
381  }
382 
383  // Not value found on the blackboard
384  if (!sourceboard || sourceboard->size() <= value.position.valueIndex)
385  {
386  return false;
387  }
388 
389  auto& entry = sourceboard->blackboard->entry(value.position.valueIndex);
390  auto& instanceEntry = sourceboard->entry(value.position.valueIndex);
391  if (entry.flags != Atoms::BlackboardEntry::Flags::LinkMetadata)
392  {
393  if (instanceEntry && instanceEntry->typeId() == value.value->typeId())
394  {
395  instanceEntry->copy(value.value.get());
396  }
397  else
398  {
399  instanceEntry = value.value->clone();
400  }
401  return true;
402  }
403 
404  if (!agent)
405  return false;
406 
407  auto agentMeta = agent->metadata().getEntry(entry.name);
408  if (agentMeta && agentMeta->typeId() == value.value->typeId())
409  {
410  agentMeta->copy(value.value.get());
411  return true;
412  }
413  return false;
414  }
415 
416  template <class T>
417  inline bool BehaviourTreeContext::setBlackboardValue(const BlackboardValue<std::vector<T>>& value)
418  {
419  if (value.position.valueIndex == -1)
420  {
421  return false;
422  }
423 
424  auto* sourceboard = &blackboardInstance;
425  if (value.position.parentIndex > 0)
426  {
427  for (short i = 0; i < value.position.parentIndex; ++i)
428  {
429  if (!sourceboard)
430  {
431  break;
432  }
433 
434  sourceboard = sourceboard->parent;
435  }
436  }
437 
438  // Not value found on the blackboard
439  if (!sourceboard || sourceboard->size() <= value.position.valueIndex)
440  {
441  return false;
442  }
443 
444  auto& entry = sourceboard->blackboard->entry(value.position.valueIndex);
445  auto& instanceEntry = sourceboard->entry(value.position.valueIndex);
446  if (entry.flags != Atoms::BlackboardEntry::Flags::LinkMetadata)
447  {
448  if (instanceEntry && instanceEntry->typeId() == AtomsCore::TypedArrayMetadata<T>::staticTypeId())
449  {
450  static_cast<AtomsCore::TypedArrayMetadata<T>*>(instanceEntry.get())->set(value.value);
451  return true;
452  }
453  return false;
454  }
455 
456  if (!agent)
457  return false;
458 
459  auto agentMeta = agent->metadata().getEntry(entry.name);
460  if (agentMeta && agentMeta->typeId() == AtomsCore::TypedArrayMetadata<T>::staticTypeId())
461  {
462  static_cast<AtomsCore::TypedArrayMetadata<T>*>(agentMeta.get())->set(value.value);
463  return true;
464  }
465  return false;
466  }
467 }
Agent.
Definition: Agent.h:44
AtomsCore::MapMetadata & metadata()
Gets the agent metadata map.
Definition: Agent.impl.h:32
Definition: Behaviour.h:21
Definition: BehaviourTreeContext.h:41
Definition: BehaviourTreeContext.h:24
Definition: BehaviourTree.h:27
AtomsPtr< Metadata > getEntry(const Key &key)
Get an entry.
AtomsPtr< T > getTypedEntry(const Key &key)
Get a typed entry.
Definition: MapMetadata.impl.h:4
Metadata template class.
Definition: MetadataImpl.h:158
T & get()
Get reference.
Definition: MetadataImpl.impl.h:88
T value() const
Get value.
Definition: MetadataImpl.impl.h:76
Metadata template class.
Definition: TypedArrayMetadata.h:160
std::vector< T > & get()
Get reference.
Definition: TypedArrayMetadata.Impl.h:92
std::vector< T > value() const
Get value.
Definition: TypedArrayMetadata.Impl.h:80
Atoms namespace.
Definition: Agent.h:29
Definition: Behaviour.h:34
Definition: BehaviourTreeContext.h:34
Definition: BehaviourTreeContext.h:28
Definition: BlackboardValue.h:21