Freeciv21
Develop your civilization from humble roots to a global empire
path_finder.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2022 Louis Moureaux
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 
4 #pragma once
5 
6 #include "path.h"
7 #include "unit.h"
8 
9 #include <map>
10 #include <memory>
11 #include <optional>
12 #include <queue>
13 #include <set>
14 #include <utility>
15 
16 struct tile;
17 
18 namespace freeciv {
19 
20 class path;
21 
22 namespace detail {
23 
31 struct vertex : public path::step {
32  // Ancestor information, needed to build a path. Invalid for the first
33  // tile.
35 
36  static vertex from_unit(const unit &unit);
37 
38  vertex child_for_action(action_id action, const unit &probe, tile *target);
39 
40  bool comparable(const vertex &other) const;
41  void fill_probe(unit &probe) const;
42 
43  bool operator==(const vertex &other) const;
44  bool operator>(const vertex &other) const;
45 };
46 } // namespace detail
47 
48 class destination;
49 class step_constraint;
50 
55 class path_finder {
56  friend class destination;
57 
58 public:
62  using storage_type =
63  std::multimap<const tile *, std::unique_ptr<detail::vertex>>;
64 
65 private:
67  public:
68  explicit path_finder_private(const unit *unit,
69  const detail::vertex &init);
70  ~path_finder_private() = default;
71 
72  const ::unit unit;
73  const detail::vertex
75 
76  std::unique_ptr<step_constraint> constraint = nullptr;
77 
78  // Storage for Dijkstra's algorithm.
79  // In most cases, a single vertex will be stored for a given tile. There
80  // are situations, however, where more vertices are needed. This is for
81  // instance the case for fueled units: a path in 5 turns leading to a
82  // tile with 3 fuel left cannot be compared to a path in 1 turn leading
83  // to the same tile with only one fuel left (since we don't know how much
84  // fuel will be needed to reach the target). In such a case, the tile is
85  // mapped to several vertices.
87  std::priority_queue<detail::vertex, std::vector<detail::vertex>,
88  std::greater<>>
90 
91  // Waypoints are tiles we must use in our path
92  std::vector<const tile *> waypoints;
93 
94  void insert_initial_vertex();
95  void maybe_insert_vertex(const detail::vertex &v);
96 
98  const detail::vertex &v) const;
99 
100  void attempt_move(detail::vertex &source);
101  void attempt_full_mp(detail::vertex &source);
102  void attempt_load(detail::vertex &source);
103  void attempt_unload(detail::vertex &source);
104  void attempt_paradrop(detail::vertex &source);
105  void attempt_action_move(detail::vertex &source);
106 
107  bool run_search(const destination &destination, bool full = false);
108  void reset();
109  };
110 
111 public:
112  explicit path_finder(const unit *unit);
113  explicit path_finder(const unit *unit, const path::step &init);
114  virtual ~path_finder();
115 
116  inline path_finder &operator=(path_finder &&other);
117 
118  void set_constraint(std::unique_ptr<step_constraint> &&constraint);
119 
120  void push_waypoint(const tile *location);
121  bool pop_waypoint();
122 
123  void unit_changed(const unit &unit);
124 
125  std::vector<path> find_all(const destination &destination);
126  std::optional<path> find_path(const destination &destination);
127 
128 private:
129  std::unique_ptr<path_finder_private> m_d;
130 };
131 
136 {
137  m_d = std::move(other.m_d);
138  return *this;
139 }
140 
148 class destination {
149 public:
150  friend class path_finder;
152 
156  virtual ~destination() {}
157 
158 protected:
162  virtual bool reached(const detail::vertex &vertex) const = 0;
163 
164  virtual path_finder::storage_type::const_iterator
166  std::size_t num_waypoints) const;
167 };
168 
174 public:
180  {
181  fc_assert(destination != nullptr);
182  }
183 
188 
189 protected:
190  bool reached(const detail::vertex &vertex) const override;
191  path_finder::storage_type::const_iterator
193  std::size_t num_waypoints) const override;
194 
195 private:
197 };
198 
203 public:
207  explicit allied_city_destination(const player *allied_with)
208  : m_player(allied_with)
209  {
210  fc_assert(m_player != nullptr);
211  }
212 
217 
218 protected:
219  bool reached(const detail::vertex &vertex) const override;
220 
221 private:
222  const player *m_player;
223 };
224 
231 public:
235  explicit refuel_destination(const unit &unit) : m_unit(unit) {}
236 
241 
242 protected:
243  bool reached(const detail::vertex &vertex) const override;
244 
245 private:
247 };
248 
259 public:
261  virtual ~step_constraint() = default;
262 
267  virtual bool is_allowed(const path::step &step) const = 0;
268 };
269 
275 public:
278 
281 
282  bool is_allowed(const path::step &step) const override;
283 
284 private:
285  const player *m_player;
286 };
287 
288 } // namespace freeciv
A path finding destination that accepts any allied city.
Definition: path_finder.h:202
bool reached(const detail::vertex &vertex) const override
Checks if a vertex should be considered as being at the destination.
allied_city_destination(const player *allied_with)
Constructor.
Definition: path_finder.h:207
Abstraction for path finding destinations.
Definition: path_finder.h:148
virtual path_finder::storage_type::const_iterator find_best(const path_finder::storage_type &map, std::size_t num_waypoints) const
Returns an iterator to the best vertex that is a destination vertex.
virtual ~destination()
Destructor.
Definition: path_finder.h:156
virtual bool reached(const detail::vertex &vertex) const =0
Checks if a vertex should be considered as being at the destination.
void reset()
Resets the state of the path finder.
bool run_search(const destination &destination, bool full=false)
Runs the path finding seach until the stopping condition is met (the destination tile is reached).
void attempt_action_move(detail::vertex &source)
Opens vertices corresponding to attempts to do ORDER_ACTION_MOVE from the source vertex.
void insert_initial_vertex()
Inserts the initial vertex, from which the search will be started.
std::unique_ptr< step_constraint > constraint
Definition: path_finder.h:76
void attempt_load(detail::vertex &source)
Opens vertices corresponding to attempts to load into a transport from the source vertex.
void attempt_move(detail::vertex &source)
Opens vertices corresponding to attempts to do ORDER_MOVE from the source vertex.
void attempt_paradrop(detail::vertex &source)
Opens vertices corresponding to attempts to unload from a transport at the source vertex.
std::priority_queue< detail::vertex, std::vector< detail::vertex >, std::greater<> > queue
Definition: path_finder.h:89
bool is_reached(const destination &destination, const detail::vertex &v) const
Checks if a vertex is at the destination, taking waypoints into account.
void attempt_unload(detail::vertex &source)
Opens vertices corresponding to attempts to unload from a transport at the source vertex.
const detail::vertex initial_vertex
The starting point in the search graph.
Definition: path_finder.h:74
const ::unit unit
A unit used to probe whether moves are valid.
Definition: path_finder.h:72
std::vector< const tile * > waypoints
Definition: path_finder.h:92
path_finder_private(const unit *unit, const detail::vertex &init)
Constructor.
void maybe_insert_vertex(const detail::vertex &v)
Saves a new vertex for further processing if it is better than the current vertex at the same locatio...
void attempt_full_mp(detail::vertex &source)
Opens vertices corresponding to attempts to do ORDER_FULL_MP from the source vertex.
A path is a succession of moves and actions to go from one location to another.
Definition: path_finder.h:55
bool pop_waypoint()
Removes the last added waypoint.
void set_constraint(std::unique_ptr< step_constraint > &&constraint)
Sets a constraint to limit the number of steps considered when trying to find a path.
virtual ~path_finder()
Destructor.
path_finder & operator=(path_finder &&other)
Move-assignment operator.
Definition: path_finder.h:135
std::vector< path > find_all(const destination &destination)
Runs the path finding algorithm, searching for all paths leading to the destination.
void unit_changed(const unit &unit)
Notifies the path finder that some unit died or changed state.
std::unique_ptr< path_finder_private > m_d
Definition: path_finder.h:129
std::multimap< const tile *, std::unique_ptr< detail::vertex > > storage_type
The type of the underlying storage, exposed through destination.
Definition: path_finder.h:63
void push_waypoint(const tile *location)
Adds a waypoint to the path finding.
path_finder(const unit *unit)
Constructs a path_finder for the given unit.
std::optional< path > find_path(const destination &destination)
Runs the path finding algorithm.
A path finding destination that accepts any tile where one can refuel or, for units with HP loss,...
Definition: path_finder.h:230
refuel_destination(const unit &unit)
Constructor.
Definition: path_finder.h:235
bool reached(const detail::vertex &vertex) const override
Checks if a vertex should be considered as being at the destination.
~refuel_destination()
Destructor.
Definition: path_finder.h:240
Allows one to limit the scope a path finding search.
Definition: path_finder.h:258
virtual bool is_allowed(const path::step &step) const =0
Whether a step should be used in the search.
virtual ~step_constraint()=default
Destructor.
A path finding destination that accepts any path leading to a specific tile.
Definition: path_finder.h:173
tile_destination(const tile *destination)
Constructor.
Definition: path_finder.h:178
const tile * m_destination
Definition: path_finder.h:196
~tile_destination()
Destructor.
Definition: path_finder.h:187
bool reached(const detail::vertex &vertex) const override
Checks if a vertex should be considered as being at the destination.
path_finder::storage_type::const_iterator find_best(const path_finder::storage_type &map, std::size_t num_waypoints) const override
Returns an iterator to the best vertex that is a destination vertex.
A constraint that restricts the search to tiles known by the player.
Definition: path_finder.h:274
bool is_allowed(const path::step &step) const override
Whether a step should be used in the search.
tile_known_constraint(const player *player)
Constructor.
Definition: path_finder.h:277
~tile_known_constraint()=default
Destructor.
int action_id
Definition: fc_types.h:306
#define fc_assert(condition)
Definition: log.h:89
bool init
Definition: mapimg.cpp:328
Definition: path.cpp:10
int step
Definition: specpq.h:83
A vertex in the path-finding graph.
Definition: path_finder.h:31
vertex child_for_action(action_id action, const unit &probe, tile *target)
Creates a vertex starting from this one and executing an action.
Definition: path_finder.cpp:43
void fill_probe(unit &probe) const
Ensures that probe reflects the properties of this vertex.
bool operator>(const vertex &other) const
Defines an ordering for the priority queue.
bool comparable(const vertex &other) const
Checks whether two vertices are comparable, which is the case when one of them is unambiguously "bett...
Definition: path_finder.cpp:77
vertex * parent
The previous vertex, if any.
Definition: path_finder.h:34
static vertex from_unit(const unit &unit)
Creates a vertex representing the state of a unit.
Definition: path_finder.cpp:27
bool operator==(const vertex &other) const
Equality comparator.
Definition: player.h:231
Definition: tile.h:42
Definition: unit.h:134