(C++)  1.1.0
A multi-platform, modular, universal engine for embedding advanced AI in games.
Planner.hh
1 #ifndef GRAIL_PLANNER_H
2 #define GRAIL_PLANNER_H
3 
4 #include "WorldState/WorldState.hh"
5 #include "Action/Action.hh"
6 #include "../../GrailData/DebugInfo/PlannerSnapshots.h"
7 
8 #include <functional>
9 #include <memory>
10 #include <vector>
11 #include <queue>
12 #include <map>
13 
14 namespace grail
15 {
16  namespace planning
17  {
18  using ConditionFunction = std::function<bool(const WorldState&)>;
19  using PlannerHeuristic = std::function<double(const WorldState&, const std::vector<ConditionFunction>&)>;
20 
22  class Planner
23  {
24  public:
25  struct Config
26  {
27  Config() noexcept {}
28  PlannerHeuristic heuristic = nullptr;
29  std::size_t iterationLimit = 500;
30  int maxPlanLength = -1;
31  double maxPlanCost = -1;
32  std::size_t initialNodeCapacity = 128;
33  };
34 
35  struct AbstractPlan
36  {
37  std::vector<Action> actions{};
38  float totalCost = 0.0f;
39  };
40 
41  Planner(MemoryPool& memory);
42  Planner(MemoryPool& memory, const WorldState& initialState, const Config& config = Config{});
43 
44  void SetIterationLimit(std::size_t iterationLimit);
45  void SetMaxPlanLength(int maxLength);
46  void SetMaxPlanCost(double maxCost);
47  void SetHeuristic(PlannerHeuristic heuristic);
48  void ResetConfig(const Config& config);
49 
52  void PushCondition(ConditionFunction condition);
53  AbstractPlan GetPartialPlan() const;
54  PlannerIterationSnapshot GetPlanSnapshot(std::size_t goalNodeIndex, std::size_t iteration) const;
55  void Iterate(std::size_t iterationCount) noexcept;
56  void IterateWithSnapshot(std::size_t iterationCount, PlannerReasonerSnapshot& snapshot, std::size_t minDebugSnapshotIteration = 0, std::size_t maxDebugSnapshotIteration = std::numeric_limits<std::size_t>::max()) noexcept;
57  void SetPlanFoundCallback(const std::function<void(const AbstractPlan&)> callbackFunction);
58  void SetPlanningFailedCallback(const std::function<void()> callbackFunction);
59  void Reset(const WorldState& initialState);
60  bool IsComputing() const;
61  //REVIEW: dox comments would be nice for the particular methods above
62 
63  private:
64  //helper structs start
65  struct Edge;
66  struct Node
67  {
68  WorldState state;
69  int depth = 0;
70  double score = 0;
71  double distanceFromGoal = std::numeric_limits<double>::max();
72  std::shared_ptr<Edge> pathEdge = nullptr;
73 
74  Node(Node&& other) noexcept;
75  Node(const WorldState& state);
76  Node(WorldState&& state);
77  Node& operator=(Node&& other) noexcept;
78  };
79 
80  struct Edge
81  {
82  Edge(std::size_t sourceIndex, std::size_t destinationIndex, Action&& action);
83  Edge(Edge&& otherEdge) = default;
84 
85  std::size_t sourceIndex = 0;
86  std::size_t destinationIndex = 0;
87  Action action;
88  };
89 
90  struct EdgePriority
91  {
92  EdgePriority(const std::shared_ptr<Edge>& edge, double dijkstraScore, double aStarScore);
93 
94  std::shared_ptr<Edge> edge;
95  double dijkstraScore;
96  double aStarScore;
97  };
98 
99  class EdgePriorityComparer
100  {
101  public:
102  bool operator() (const EdgePriority& one, const EdgePriority& other)
103  {
104  return one.aStarScore > other.aStarScore;
105  }
106  };
107  //helper structs end
108 
109  void AddNode(Node&& node);
110  bool IsGoalAchieved(const WorldState& state) const;
111 
112  WorldState initialState;
113  Config plannerConfig = {};
114 
115  std::vector<ConditionFunction> goalConditions = {};
116  std::function<void(const AbstractPlan&)> onPlanFound = nullptr;
117  std::function<void()> onPlanningFailed = nullptr;
118 
119  //cached data for iterative approach
120  std::size_t nextNodeIndex = 0;
121  std::size_t nodeClosestToGoalIndex = std::numeric_limits<std::size_t>::max();
122  std::size_t lastChosenNodeIndex = std::numeric_limits<std::size_t>::max();
123  int maxNodeDepth = 0;
124  std::priority_queue<EdgePriority, std::vector<EdgePriority>, EdgePriorityComparer> edges{};
125  std::vector<Node> generatedNodes{};
126  std::vector<std::size_t> closedNodeIndices{};
127  std::size_t currentIteration = 0;
128  bool isPlanningFinished = true;
129  MemoryPool& memory;
130  };
131  }
132 }
133 #endif //GRAIL_PLANNER_H
The MemoryPool class - preallocated memory container for optimization issues.
Definition: MemoryPool.hh:74
Definition: Action.hh:11
The main class responsible for finding paths in plan space.
Definition: Planner.hh:23
void PushCondition(ConditionFunction condition)
Definition: Planner.cpp:58
A class representing planner world state.
Definition: WorldState.hh:15
Definition: PlannerSnapshots.h:50
Definition: PlannerSnapshots.h:70
Definition: Planner.hh:26