50 ret.order.target = target->
index;
54 ret.location = target;
60 auto moved_probe = probe;
61 moved_probe.
tile = target;
95 return (a <= 0 && b <= 0 && c <= 0 && d <= 0)
96 || (a >= 0 && b >= 0 && c >= 0 && d >= 0);
157 maybe_insert_vertex(initial_vertex);
168 if (constraint && !constraint->is_allowed(v)) {
191 insert.fuel_left = probe.fuel;
192 }
else if (probe.fuel <= 1) {
211 insert.health = probe.hp;
214 insert.moved =
false;
215 insert.paradropped =
false;
219 if (insert.waypoints < waypoints.size()
220 && insert.location == waypoints[insert.waypoints]) {
228 const auto [begin, end] = best_vertices.equal_range(v.
location);
229 bool do_insert =
true;
230 for (
auto it = begin; it != end; ) {
231 const bool comparable = it->second->comparable(insert);
232 if (comparable && *it->second > insert) {
234 it = best_vertices.erase(it);
236 }
else if (comparable) {
249 std::make_unique<detail::vertex>(insert));
295 move_cost = probe.utype->unknown_move_cost;
302 move_cost = std::min(move_cost, probe.moves_left);
308 next.moves_left -= move_cost;
309 next.parent = &source;
311 next.order.dir = dir;
312 maybe_insert_vertex(next);
328 next.parent = &source;
330 maybe_insert_vertex(next);
352 maybe_insert_vertex(next);
363 if (transport !=
nullptr
371 next.loaded = transport;
372 maybe_insert_vertex(next);
389 if (probe.transporter !=
nullptr) {
392 probe.transporter)) {
396 maybe_insert_vertex(next);
404 {ACTION_TRANSPORT_DISEMBARK1, ACTION_TRANSPORT_DISEMBARK2}) {
413 next.loaded =
nullptr;
421 maybe_insert_vertex(next);
441 if (!probe.paradropped
449 sq_radius *= sq_radius;
453 auto tile = probe.tile;
469 && (!
game.
info.paradrop_to_transport
499 next.paradropped =
true;
501 next.loaded =
nullptr;
502 maybe_insert_vertex(next);
524 if (target->terrain ==
nullptr) {
532 if (!
tile_city(target) && unit_list_size(target->units) == 0) {
537 const bool can_not_move =
540 const bool one_action_may_be_legal =
549 if (one_action_may_be_legal) {
554 next.is_final =
true;
555 next.parent = &source;
557 next.order.dir = dir;
558 maybe_insert_vertex(next);
580 it != best_vertices.end()
581 && !(!queue.empty() && *it->second > queue.top())) {
586 while (!queue.empty()) {
588 const auto v = queue.top();
601 const auto [begin, end] = best_vertices.equal_range(v.location);
602 const auto it = std::find_if(
603 begin, end, [&v](
const auto &pair) {
return *pair.second == v; });
612 auto parent = it->second.get();
615 attempt_move(*parent);
616 attempt_full_mp(*parent);
617 attempt_load(*parent);
618 attempt_unload(*parent);
619 attempt_paradrop(*parent);
620 attempt_action_move(*parent);
633 best_vertices.clear();
634 while (!queue.empty()) {
637 insert_initial_vertex();
660 unit, detail::vertex{
init, nullptr}))
679 std::unique_ptr<step_constraint> &&constraint)
681 m_d->constraint = std::move(constraint);
693 if (
m_d->waypoints.empty() || location !=
m_d->waypoints.back()) {
694 m_d->waypoints.push_back(location);
709 if (
m_d->waypoints.empty()) {
713 m_d->waypoints.pop_back();
729 m_d->best_vertices.clear();
730 while (!
m_d->queue.empty()) {
733 m_d->insert_initial_vertex();
747 if (
m_d->unit.stay) {
754 auto ret = std::vector<path>();
755 ret.reserve(
m_d->best_vertices.size());
757 for (
const auto &[
_, end] :
m_d->best_vertices) {
764 auto steps = std::vector<path::step>();
765 for (
auto vertex = end.get(); vertex->parent !=
nullptr;
766 vertex = vertex->parent) {
767 steps.push_back(*vertex);
770 ret.emplace_back(std::vector<path::step>(steps.rbegin(), steps.rend()));
782 if (
m_d->unit.stay) {
802 auto steps = std::vector<path::step>();
803 for (
auto vertex = it->second.get(); vertex->parent !=
nullptr;
804 vertex = vertex->parent) {
805 steps.push_back(*vertex);
808 return path(std::vector<path::step>(steps.rbegin(), steps.rend()));
818 path_finder::storage_type::const_iterator
820 std::size_t num_waypoints)
const
822 auto best = map.end();
823 for (
auto it = map.begin(); it != map.end(); ++it) {
825 if (it->second->waypoints == num_waypoints &&
reached(*it->second)) {
827 if (best == map.end() || *best->second > *it->second) {
848 path_finder::storage_type::const_iterator
850 std::size_t num_waypoints)
const
852 auto best = map.end();
854 for (
auto it = begin; it != end; ++it) {
856 if (it->second->waypoints == num_waypoints &&
reached(*it->second)) {
858 if (best == map.end() || *best->second > *it->second) {
bool is_action_enabled_unit_on_unit(const action_id wanted_action, const struct unit *actor_unit, const struct unit *target_unit)
Returns TRUE if actor_unit can do wanted_action to target_unit as far as action enablers are concerne...
struct extra_type * action_tgt_tile_extra(const struct unit *actor, const struct tile *target_tile, bool accept_all_actions)
Find an extra to target for an action at the specified tile.
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
Find a unit to target for an action at the specified tile.
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
Find a city to target for an action on the specified tile.
struct tile * action_tgt_tile(struct unit *actor, struct tile *target, const struct extra_type *target_extra, bool accept_all_actions)
Returns the tile iff it, from the point of view of the owner of the actor unit, looks like a target t...
bool is_action_enabled_unit_on_tile(const action_id wanted_action, const struct unit *actor_unit, const struct tile *target_tile, const struct extra_type *target_extra)
Returns TRUE if actor_unit can do wanted_action to the target_tile as far as action enablers are conc...
struct action * action_by_number(action_id act_id)
Return the action with the given id.
struct city * is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Is there an friendly city on this tile?
bool reached(const detail::vertex &vertex) const override
Checks if a vertex should be considered as being at the destination.
Abstraction for path finding destinations.
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 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.
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.
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.
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.
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.
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
std::multimap< const tile *, std::unique_ptr< detail::vertex > > storage_type
The type of the underlying storage, exposed through destination.
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 is a succession of moves and actions to go from one location to another.
bool reached(const detail::vertex &vertex) const override
Checks if a vertex should be considered as being at the destination.
const tile * m_destination
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.
bool is_allowed(const path::step &step) const override
Whether a step should be used in the search.
void unit_restore_hitpoints(struct unit *punit)
add hitpoints to the unit, hp_gain_coord returns the amount to add united nations will speed up the p...
#define fc_assert_ret_val(condition, val)
#define adjc_dir_iterate(nmap, center_tile, itr_tile, dir_itr)
#define circle_dxyr_iterate(nmap, center_tile, sq_radius, _tile, dx, dy, dr)
#define adjc_iterate(nmap, center_tile, itr_tile)
#define circle_dxyr_iterate_end
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
#define adjc_dir_iterate_end
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Return TRUE iff the unit can "exist" at this location.
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
This tile is native to unit.
int unit_move_rate(const struct unit *punit)
This function calculates the move rate of the unit.
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Return whether we could find a suitable transporter for given unit at 'ptile'.
bool unit_can_move_to_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *dst_tile, bool igzoc, bool enter_enemy_city)
Returns whether the unit can move from its current tile to the destination tile.
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Return TRUE iff the unit can "survive" at this location.
bool is_unit_being_refueled(const struct unit *punit)
Is unit being refueled in its current position.
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players have peace, cease-fire, or armistice.
struct packet_game_info info
A vertex in the path-finding graph.
vertex child_for_action(action_id action, const unit &probe, tile *target)
Creates a vertex starting from this one and executing an action.
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...
vertex * parent
The previous vertex, if any.
static vertex from_unit(const unit &unit)
Creates a vertex representing the state of a unit.
bool operator==(const vertex &other) const
Equality comparator.
unit * loaded
The unit we are loaded in.
int turns
How many turns it takes to get there.
int waypoints
How many waypoints we have visited so far.
int health
How many HP the unit has left.
unit_order order
The order to come here.
tile * location
Where we are.
bool moved
Whether we moved this turn (for HP recovery)
int fuel_left
How much fuel the unit has left.
bool paradropped
Whether we paradropped this turn.
int moves_left
How many move fragments the unit has left.
bool is_final
Whether this vertex can have children.
enum unit_activity activity
struct unit::@76::@78 client
struct unit * transporter
const struct unit_type * utype
enum known_type tile_get_known(const struct tile *ptile, const struct player *pplayer)
Return a known_type enumeration value for the tile.
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
struct unit * transporter_for_unit(const struct unit *pcargo)
Find the best transporter at the given location for the unit.
int unit_pays_mp_for_action(const struct action *paction, const struct unit *punit)
Returns the amount of movement points successfully performing the specified action will consume in th...
struct unit * is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Returns true if the tile contains an allied unit and only allied units.
struct unit * is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Is there an non-allied unit on this tile?
struct unit * transporter_for_unit_at(const struct unit *pcargo, const struct tile *ptile)
Find the best transporter at the given location for the unit.
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Returns TRUE iff successfully performing the specified action always will move the actor unit of the ...
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Return TRUE iff units of the given type can do the specified generalized (ruleset defined) action ena...
#define utype_fuel(ptype)