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