Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
Planner.cpp
Go to the documentation of this file.
1
2
3#include "Planner.h"
4
5namespace Divide::goap
6{
7
8int Planner::calculateHeuristic(const WorldState& now, const WorldState& goal) const {
9 return now.distanceTo(goal);
10}
11
13 // insert maintaining sort order
14 auto it = eastl::lower_bound(begin(open_),
15 end(open_),
16 n);
17 open_.emplace(it, MOV(n));
18}
19
21 assert(!open_.empty());
22 closed_.push_back( MOV(open_.front()));
23 open_.erase(std::begin(open_));
24
25 return closed_.back();
26}
27
28bool Planner::memberOfClosed(const WorldState& ws) const {
29 if (std::find_if(std::begin(closed_), std::end(closed_), [&](const Node& n) { return n.ws_ == ws; }) == std::end(closed_)) {
30 return false;
31 }
32 return true;
33}
34
36 return std::find_if(std::begin(open_), std::end(open_), [&](const Node& n) { return n.ws_ == ws; });
37}
38
39void Planner::printOpenList(string& output) const
40{
41 for (const auto& n : open_)
42 {
43 output.append(n.toString());
44 output.append("\n");
45 }
46}
47
48void Planner::printClosedList(string& output) const
49{
50 for (const auto& n : closed_)
51 {
52 output.append( n.toString() );
53 output.append( "\n" );
54 }
55}
56
58 if (start.meetsGoal(goal)) {
59 //throw std::runtime_error("Planner cannot plan when the start state and the goal state are the same!");
60 return vector<const Action*>();
61 }
62
63 // Feasible we'd re-use a planner, so clear out the prior results
64 open_.clear();
65 closed_.clear();
66 known_nodes_.clear();
67
68 Node starting_node(start, 0, calculateHeuristic(start, goal), 0, nullptr);
69
70 // TODO figure out a more memory-friendly way of doing this...
71 known_nodes_[starting_node.id_] = starting_node;
72 open_.push_back( MOV(starting_node));
73
74 //int iters = 0;
75 while (open_.size() > 0) {
76 //++iters;
77 //std::cout << "\n-----------------------\n";
78 //std::cout << "Iteration " << iters << std::endl;
79
80 // Look for Node with the lowest-F-score on the open list. Switch it to closed,
81 // and hang onto it -- this is our latest node.
82 Node& current(popAndClose());
83
84 //std::cout << "Open list\n";
85 //printOpenList();
86 //std::cout << "Closed list\n";
87 //printClosedList();
88 //std::cout << "\nCurrent is " << current << std::endl;
89
90 // Is our current state the goal state? If so, we've found a path, yay.
91 if (current.ws_.meetsGoal(goal)) {
92 vector<const Action*> the_plan;
93 do {
94 the_plan.push_back(current.action_);
95 current = known_nodes_.at(current.parent_id_);
96 } while (current.parent_id_ != 0);
97 return the_plan;
98 }
99
100 // Check each node REACHABLE from current
101 for (const auto& action : actions) {
102 if (action->eligibleFor(current.ws_)) {
103 WorldState possibility = action->actOn(current.ws_);
104 //std::cout << "Hmm, " << action.name() << " could work..." << "resulting in " << possibility << std::endl;
105
106 // Skip if already closed
107 if (memberOfClosed(possibility)) {
108 //std::cout << "...but that one's closed out.\n";
109 continue;
110 }
111
112 auto needle = memberOfOpen(possibility);
113 if (needle==end(open_)) { // not a member of open list
114 // Make a new node, with current as its parent, recording G & H
115 Node found(possibility, current.g_ + action->cost(), calculateHeuristic(possibility, goal), current.id_, action);
116 known_nodes_[found.id_] = found;
117
118 // Add it to the open list (maintaining sort-order therein)
119 addToOpenList( MOV(found));
120 } else { // already a member of the open list
121 // check if the current G is better than the recorded G
122 if ((current.g_ + action->cost()) < needle->g_) {
123 //std::cout << "My path is better\n";
124 needle->parent_id_ = current.id_; // make current its parent
125 needle->g_ = current.g_ + action->cost(); // recalc G & H
126 needle->h_ = calculateHeuristic(possibility, goal);
127 eastl::sort(begin(open_), end(open_)); // resort open list to account for the new F
128 // sorting likely invalidates the iterator, but we don't need it anymore
129 }
130 }
131 }
132 }
133 }
134
135 // If there's nothing left to evaluate, then we have no possible path left
136 //throw std::runtime_error("A* planner could not find a path from start to goal");
137 return vector<const Action*>();
138}
139
140} //namespace Divide::goap
#define MOV(...)
vector< Node > closed_
Definition: Planner.h:23
void printOpenList(Divide::string &output) const
Definition: Planner.cpp:39
void printClosedList(Divide::string &output) const
Definition: Planner.cpp:48
bool memberOfClosed(const WorldState &ws) const
Definition: Planner.cpp:28
void addToOpenList(Node &&node)
Definition: Planner.cpp:12
int calculateHeuristic(const WorldState &now, const WorldState &goal) const
Definition: Planner.cpp:8
vector< const Action * > plan(const WorldState &start, const WorldState &goal, const vector< const Action * > &actions)
Definition: Planner.cpp:57
Node & popAndClose()
Definition: Planner.cpp:20
hashMap< I32, Node > known_nodes_
A master lookup table of ID-to-Node; useful during the action replay.
Definition: Planner.h:20
vector< Node > open_
Definition: Planner.h:22
vector< goap::Node >::iterator memberOfOpen(const WorldState &ws)
Definition: Planner.cpp:35
eastl::vector< Type > vector
Definition: Vector.h:42
const Action * action_
Definition: Node.h:25
I32 parent_id_
Definition: Node.h:22
WorldState ws_
Definition: Node.h:20
int distanceTo(const WorldState &goal_state) const
Definition: WorldState.cpp:44
bool meetsGoal(const WorldState &goal_state) const
Definition: WorldState.cpp:29