42 #define ERR_PF LOG_STREAM(err, log_engine)
68 const bool do_shroud = shroud_check && shroud_check->
uses_shroud();
69 std::set<map_location> pending_tiles_to_check, tiles_checked;
70 pending_tiles_to_check.insert(loc);
72 for (
int distance = 0; distance < 50; ++distance) {
73 if (pending_tiles_to_check.empty())
76 std::set<map_location> tiles_checking;
77 tiles_checking.swap(pending_tiles_to_check);
82 if ( do_shroud && shroud_check->
shrouded(loc) )
86 const bool pass_check_and_unreachable = pass_check
94 if (pass_check_and_unreachable && distance > 10)
continue;
96 if (units.
find(loc) == units.
end() && !pass_check_and_unreachable)
return loc;
104 if (tiles_checked.find(loc) == tiles_checked.end() &&
105 tiles_checking.find(loc) == tiles_checking.end())
107 pending_tiles_to_check.insert(loc);
111 tiles_checked.swap(tiles_checking);
124 nullptr, &(*resources::teams)[leader.
side()-1]);
139 team const &viewing_team,
bool see_all)
144 for (
int i = 0;
i != 6; ++
i)
162 struct findroute_node {
171 findroute_node(
int moves,
int turns,
const map_location &prev_loc,
unsigned search_count)
175 , search_num(search_count)
185 bool operator<(
const findroute_node& o)
const {
186 return turns_left > o.turns_left ||
187 (turns_left == o.turns_left && moves_left > o.moves_left);
194 struct findroute_indexer {
198 findroute_indexer(
int a,
int b) : w(a), h(b) { }
200 int operator()(
int x,
int y)
const {
201 if ( x < 0 || w <= x || y < 0 || h <= y )
207 return (*
this)(loc.
x, loc.
y);
218 struct findroute_comp {
219 const std::vector<findroute_node>&
nodes;
222 findroute_comp(
const std::vector<findroute_node>&
n) : nodes(n) { }
224 bool operator()(
int l,
int r)
const {
225 return nodes[
r] < nodes[
l];
271 const unit * teleporter,
const team * current_team,
272 const unit * skirmisher,
const team * viewing_team,
273 const std::map<map_location, int> * jamming_map=
nullptr,
278 const bool see_all = viewing_team ==
nullptr;
281 if ( viewing_team ==
nullptr )
290 static std::vector<findroute_node>
nodes;
291 static unsigned search_counter = 0;
295 if ( search_counter == 0 ) {
300 nodes.resize(map.
w() * map.
h());
301 findroute_comp node_comp(nodes);
302 findroute_indexer
index(map.
w(), map.
h());
307 if (
full_cost_map->size() !=
static_cast<unsigned>(map.
w() * map.
h()) )
312 (*full_cost_map)[
index(origin)].second += 1;
317 int xmin = origin.
x, xmax = origin.
x, ymin = origin.
y, ymax = origin.
y;
321 assert(
index(origin) >= 0);
322 nodes[
index(origin)] = findroute_node(moves_left, turns_left,
326 std::vector<int> hexes_to_process(1,
index(origin));
328 while ( !hexes_to_process.empty() ) {
330 const int cur_index = hexes_to_process.front();
332 const findroute_node& current = nodes[cur_index];
334 std::pop_heap(hexes_to_process.begin(), hexes_to_process.end(), node_comp);
335 hexes_to_process.pop_back();
338 std::vector<map_location> adj_locs(6);
341 std::set<map_location> allowed_teleports;
343 adj_locs.insert(adj_locs.end(), allowed_teleports.begin(), allowed_teleports.end());
345 for (
int i = adj_locs.size()-1;
i >= 0; --
i ) {
348 const int next_index =
index(next_hex);
349 if ( next_index < 0 ) {
351 if ( edges !=
nullptr )
352 edges->insert(next_hex);
355 findroute_node &
next = nodes[next_index];
362 if ( next.search_num == search_counter )
369 int cost = costs.
cost(map[next_hex], slowed);
371 const std::map<map_location, int>::const_iterator jam_it =
372 jamming_map->find(next_hex);
373 if ( jam_it != jamming_map->end() )
374 cost += jam_it->second;
378 next.moves_left = current.moves_left - cost;
379 next.turns_left = current.turns_left;
380 if ( next.moves_left < 0 ) {
383 next.moves_left = max_moves - cost;
385 if ( next.moves_left < 0 || next.turns_left < 0 ) {
387 if ( edges !=
nullptr )
388 edges->insert(next_hex);
392 if ( current_team ) {
397 if ( edges !=
nullptr )
398 edges->insert(next_hex);
402 if ( skirmisher && next.moves_left > 0 &&
403 enemy_zoc(*current_team, next_hex, *viewing_team, see_all) &&
413 int summed_cost = (turns_left - next.turns_left + 1) * max_moves - next.moves_left;
415 (*full_cost_map)[next_index].second += 1;
419 next.search_num = search_counter;
422 hexes_to_process.push_back(next_index);
423 std::push_heap(hexes_to_process.begin(), hexes_to_process.end(), node_comp);
427 if ( next_hex.x < xmin )
429 else if ( xmax < next_hex.x )
431 if ( next_hex.y < ymin )
433 else if ( ymax < next_hex.y )
446 destinations.reserve(nb_dest);
447 for (
int x = xmin;
x <= xmax; ++
x) {
448 for (
int y = ymin;
y <= ymax; ++
y)
450 const findroute_node &
n = nodes[
index(
x,
y)];
451 if ( n.search_num == search_counter ) {
453 {
map_location(
x,
y), n.prev, n.moves_left + n.turns_left*max_moves };
454 destinations.push_back(s);
463 size_t sz = v.size(),
pos = 0;
466 if (v[
pos + sz / 2].
curr < loc) {
468 sz = sz - sz / 2 - 1;
471 return v.begin() +
pos;
476 const_iterator
i =
lower_bound(const_cast<dest_vect &>(*
this), loc), i_end =
end();
477 if (i != i_end && i->curr != loc) i = i_end;
484 if (i != i_end && i->curr == loc)
return;
495 std::vector<map_location>
path;
496 if (!j->prev.valid()) {
497 path.push_back(j->curr);
499 const_iterator
i = j;
503 path.push_back(i->curr);
504 }
while (i->prev.valid());
506 std::reverse(path.begin(), path.end());
529 bool allow_teleport,
const team &viewing_team,
530 int additional_turns,
bool see_all,
bool ignore_units)
534 if (u.
side() < 1 || u.
side() >
int(teams.size())) {
541 allow_teleport ? &u :
nullptr,
542 ignore_units ?
nullptr : &teams[u.
side()-1],
543 force_ignore_zoc ?
nullptr : &u,
544 see_all ?
nullptr : &viewing_team);
566 const std::map<map_location, int>& jamming_map)
569 const int sight_range = viewer.
vision();
591 const std::map<map_location, int>& jamming_map)
596 find_routes(loc, view_costs, slowed, sight_range, sight_range, 0,
618 const int jamming_range = jammer.
jamming();
624 0,
destinations,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
645 const team& unit_team = (*resources::teams)[u.
side()-1];
648 std::vector<map_location>::const_iterator
i = rt.
steps.begin();
650 for (; i !=rt.
steps.end(); ++
i) {
651 bool last_step = (i+1 == rt.
steps.end());
659 if (last_step || zoc || move_cost > movement) {
673 if (last_step)
break;
676 if(move_cost > movement) {
681 zoc =
enemy_zoc(unit_team, *(i + 1), viewing_team)
687 movement -= move_cost;
696 bool ignore_unit,
bool ignore_defense,
bool see_all)
697 :
unit_(u), viewing_team_(t), teams_(teams),
map_(map),
698 movement_left_(
unit_.movement_left()),
699 total_movement_(
unit_.total_movement()),
700 ignore_unit_(ignore_unit), ignore_defense_(ignore_defense),
716 VALIDATE(terrain_cost >= 1,
_(
"Terrain with a movement cost less than 1 encountered."));
722 int other_unit_subcost = 0;
724 const unit *other_unit =
739 other_unit_subcost = 1;
746 int remaining_movement =
movement_left_ -
static_cast<int>(so_far);
747 if (remaining_movement < 0)
757 if (remaining_movement < terrain_cost) {
758 move_cost += remaining_movement;
767 move_cost += remaining_movement;
770 move_cost += terrain_cost;
781 return move_cost + (defense_subcost + other_unit_subcost) / 10000.0;
785 : movement_type_(mt), movement_left_(movement_left),
786 total_movement_(total_movement), viewing_team_(t),
map_(map)
802 int remaining_movement =
movement_left_ -
static_cast<int>(so_far);
803 if (remaining_movement < 0)
808 if (remaining_movement < terrain_cost) {
809 move_cost += remaining_movement;
812 move_cost += terrain_cost;
851 bool allow_teleport,
const team &viewing_team,
852 bool see_all,
bool ignore_units)
853 :force_ignore_zoc_(force_ignore_zoc), allow_teleport_(allow_teleport),
854 viewing_team_(viewing_team), see_all_(see_all), ignore_units_(ignore_units)
857 cost_map = std::vector<std::pair<int, int> >(map.
w() * map.
h(), std::make_pair(-1, 0));
866 bool allow_teleport,
const team &viewing_team,
867 bool see_all,
bool ignore_units)
868 :force_ignore_zoc_(force_ignore_zoc), allow_teleport_(allow_teleport),
869 viewing_team_(viewing_team), see_all_(see_all), ignore_units_(ignore_units)
872 cost_map = std::vector<std::pair<int, int> >(map.
w() * map.
h(), std::make_pair(-1, 0));
882 if (u.
side() < 1 || u.
side() >
int(teams.size())) {
912 unit u(*ut, side,
false);
927 assert(
cost_map.size() ==
static_cast<unsigned>(map.
w() * map.
h()));
930 return std::make_pair(-1, 0);
int total_movement() const
Stores a set of terrain costs (for movement, vision, or "jamming").
virtual const unit_map & units() const
const map_location & get_location() const
marked_route mark_route(const plain_route &rt)
Add marks on a route rt assuming that the unit located at the first hex of rt travels along it...
std::vector< std::pair< int, int > > cost_map
std::pair< int, int > get_pair_at(int x, int y) const
Accessor for the cost/reach-amount pairs.
emergency_path_calculator(const unit &u, const gamemap &map)
bool get_state(const std::string &state) const
map_location find_vacant_castle(const unit &leader)
Wrapper for find_vacant_tile() when looking for a vacant castle tile near a leader.
static paths::dest_vect::iterator lower_bound(paths::dest_vect &v, const map_location &loc)
bool shrouded(const map_location &loc) const
virtual double cost(const map_location &loc, const double so_far) const
int movement_cost(const t_translation::t_terrain &terrain) const
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
bool owns_village(const map_location &loc) const
static const int UNREACHABLE
Magic value that signifies a hex is unreachable.
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
bool is_village(const map_location &loc) const
map_location find_vacant_tile(const map_location &loc, VACANT_TILE_TYPE vacancy, const unit *pass_check, const team *shroud_check, const game_board *board)
Function that will find a location on the board that is as near to loc as possible, but which is unoccupied by any units.
bool is_enemy(int n) const
const_iterator find(const map_location &) const
GLint GLint GLint GLint GLint GLint y
The basic "size" of the unit - flying, small land, large land, etc.
void add_unit(const unit &u, bool use_max_moves=true)
Adds a units cost map to cost_map (increments the elements in cost_map)
bool get_ability_bool(const std::string &tag_name, const map_location &loc) const
Returns true if the unit is currently under effect by an ability with this given TAG NAME...
virtual ~jamming_path()
Default destructor.
int movement_cost(const t_translation::t_terrain &terrain, bool slowed=false) const
Returns the cost to move through the indicated terrain.
double get_average_cost_at(int x, int y) const
Accessor for the costs.
int defense_modifier(const t_translation::t_terrain &terrain) const
std::vector< team > const & teams_
terrain_costs & get_jamming()
static double getNoPathValue()
GLdouble GLdouble GLdouble b
static std::vector< team > *& teams
bool contains(const map_location &) const
team const & viewing_team_
This class stores all the data for a single 'side' (in game nomenclature).
static UNUSEDNOWARN std::string _(const char *str)
virtual double cost(const map_location &loc, const double so_far) const
GLsizei const char ** path
std::vector< map_location > steps
virtual double cost(const map_location &loc, const double so_far) const
bool const ignore_defense_
std::vector< team > * teams
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
move_type_path_calculator(const movetype &mt, int movement_left, int total_movement, const team &t, const gamemap &map)
Structure which holds a single route between one location and another.
static void find_routes(const map_location &origin, const movetype::terrain_costs &costs, bool slowed, int moves_left, int max_moves, int turns_left, paths::dest_vect &destinations, std::set< map_location > *edges, const unit *teleporter, const team *current_team, const unit *skirmisher, const team *viewing_team, const std::map< map_location, int > *jamming_map=nullptr, std::vector< std::pair< int, int > > *full_cost_map=nullptr)
Creates a list of routes that a unit can traverse from the provided location.
unit * get_visible_unit(const map_location &loc, const team ¤t_team, bool see_all=false)
const bool allow_teleport_
static lg::log_domain log_engine("engine")
int w() const
Effective map width.
terrain_costs & get_vision()
vision_path(const unit &viewer, map_location const &loc, const std::map< map_location, int > &jamming_map)
Construct a list of seen hexes for a unit.
GLboolean GLboolean GLboolean GLboolean a
dummy_path_calculator(const unit &u, const gamemap &map)
Encapsulates the map of the game.
virtual ~vision_path()
Default destructor.
full_cost_map(const unit &u, bool force_ignore_zoc, bool allow_teleport, const team &viewing_team, bool see_all=true, bool ignore_units=true)
Constructs a cost-map.
Structure which holds a single route and marks for special events.
static const map_location & null_location()
int movement_left() const
Returns how far a unit can move this turn (zero if incapacitated).
static const ::config * terrain
The terrain used to create the cache.
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
virtual double cost(const map_location &loc, const double so_far) const
terrain_costs & get_movement()
bool invisible(const map_location &loc, bool see_all=true) const
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Encapsulates the map of the game.
virtual ~paths()
Virtual destructor (default processing).
int h() const
Effective map height.
Ordered vector of possible destinations.
void set_location(const map_location &loc)
To be called by unit_map or for temporary units only.
static bool operator<(const placing_info &a, const placing_info &b)
Structure which uses find_routes() to build a cost map This maps each hex to a the movements a unit w...
const team & viewing_team_
GLint GLint GLint GLint GLint x
shortest_path_calculator(const unit &u, const team &t, const std::vector< team > &teams, const gamemap &map, bool ignore_unit=false, bool ignore_defense_=false, bool see_all=false)
bool fogged(const map_location &loc) const
const bool force_ignore_zoc_
GLdouble GLdouble GLdouble r
bool is_castle(const map_location &loc) const
int cost(const t_translation::t_terrain &terrain, bool slowed=false) const
Returns the cost associated with the given terrain.
virtual const gamemap & map() const
bool on_board(const map_location &loc) const
Tell if a location is on the map.
bool find(E event, F functor)
Tests whether an event handler is available.
const movetype & movement_type() const
int const total_movement_
std::set< map_location > edges
The edges are the non-destination hexes bordering the destinations.
Standard logging facilities (interface).
const int total_movement_
Object which contains all the possible locations a unit can move to, with associated best routes to t...
Container associating units to locations.
const movetype & movement_type_
utf8::string & insert(utf8::string &str, const size_t pos, const utf8::string &insert)
Insert a UTF-8 string at the specified position.
size_t viewing_team() const
The viewing team is the team currently viewing the game.
unit_iterator find(size_t id)
int get_cost_at(int x, int y) const
Accessor for the costs.
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units)
std::vector< map_location > get_path(const const_iterator &) const
Returns the path going from the source point (included) to the destination point j (excluded)...
const std::vector< findroute_node > & nodes
team const & viewing_team_
This module contains various pathfinding functions and utilities.
bool enemy_zoc(team const ¤t_team, map_location const &loc, team const &viewing_team, bool see_all)
Determines if a given location is in an enemy zone of control.
void insert(const map_location &)
jamming_path(const unit &jammer, map_location const &loc)
Construct a list of jammed hexes for a unit.
void get_adjacents(std::set< map_location > &adjacents, map_location loc) const