56 #define DBG_NG LOG_STREAM(debug, log_engine)
57 #define LOG_NG LOG_STREAM(info, log_engine)
58 #define ERR_NG LOG_STREAM(err, log_engine)
66 LOG_NG <<
"getting recruit list for side " << side <<
" at location " << recruit_loc;
68 std::set<std::string> local_result;
69 std::set<std::string> global_result;
73 bool leader_in_place =
false;
80 if ( find_it != u_end ) {
81 if ( find_it->can_recruit() && find_it->side() == side &&
86 leader_in_place =
true;
87 local_result.insert(find_it->recruits().begin(),
88 find_it->recruits().end());
90 else if ( find_it->is_visible_to_team(current_team,
false) )
97 if ( !leader_in_place ) {
99 for( ; u != u_end; ++u ) {
101 if ( !(u->can_recruit() && u->side() == side) )
106 leader_in_place=
true;
107 local_result.insert(u->recruits().begin(), u->recruits().end());
109 else if ( !leader_in_place )
110 global_result.insert(u->recruits().begin(), u->recruits().end());
115 std::set<std::string> & result = leader_in_place ? local_result : global_result;
118 const std::set<std::string>& recruit_list = current_team.
recruits();
119 result.insert(recruit_list.begin(), recruit_list.end());
133 std::vector< unit_const_ptr > & result,
134 std::set<std::size_t> * already_added =
nullptr)
145 std::size_t underlying_id =
recall_unit.underlying_id();
146 if ( !already_added || already_added->count(underlying_id) == 0 )
153 result.push_back(recall_unit_ptr);
154 if ( already_added !=
nullptr )
155 already_added->insert(underlying_id);
164 LOG_NG <<
"getting recall list for side " << side <<
" at location " << recall_loc;
166 std::vector<unit_const_ptr > result;
175 bool leader_in_place =
false;
183 if ( find_it->can_recruit() && find_it->side() == side &&
202 std::set<std::size_t> valid_local_recalls;
204 for(; u != u_end; ++u) {
206 if (!(u->can_recruit() && u->side() == side))
212 leader_in_place=
true;
214 add_leader_filtered_recalls(u.
get_shared_ptr(), result, &valid_local_recalls);
218 if ( !leader_in_place )
220 std::set<std::size_t> valid_local_recalls;
224 if(!u->can_recruit() || u->side() != side) {
228 add_leader_filtered_recalls(u.get_shared_ptr(), result, &valid_local_recalls);
251 team& recall_team = (*resources::gameboard).get_team(recaller.
side());
265 if ( !permissible.
valid() )
270 alternative = permissible;
282 const unit &unit_recall)
301 if ( u != u_end && u->side() == side ) {
303 check_unit_recall_location(*u, unit_recall, check_location, alternative);
307 for ( u = units.
begin(); best_result < goal_result && u != u_end; ++u ) {
308 if ( u->side() != side )
313 check_unit_recall_location(*u, unit_recall, check_location, alternative);
316 if ( current_result <= best_result )
318 best_result = current_result;
322 recall_from = u->get_location();
327 recall_location = alternative;
334 LOG_NG <<
"finding recall location for side " << side <<
" and unit " << unit_recall.
id();
341 LOG_NG <<
"No leaders on side " << side <<
" when recalling " << unit_recall.
id() <<
".";
342 return _(
"You do not have a leader to recall with.");
345 LOG_NG <<
"No leader is able to recall " << unit_recall.
id() <<
" on side " << side <<
".";
346 return _(
"None of your leaders are able to recall that unit.");
349 LOG_NG <<
"No leader able to recall " << unit_recall.
id() <<
" is on a keep.";
350 return _(
"You must have a leader on a keep who is able to recall that unit.");
353 LOG_NG <<
"No vacant castle tiles around a keep are available for recalling " << unit_recall.
id() <<
"; requested location is " << recall_location <<
".";
354 return _(
"There are no vacant castle tiles in which to recall the unit.");
358 return std::string();
363 ERR_NG <<
"Unrecognized enum in find_recall_location()";
364 return _(
"An unrecognized error has occurred.");
395 if ( !permissible.
valid() )
400 alternative = permissible;
437 if ( u != u_end && u->side() == side ) {
439 check_unit_recruit_location(*u, check_type, check_location, alternative);
443 for ( u = units.
begin(); best_result < goal_result && u != u_end; ++u ) {
444 if ( u->side() != side )
449 check_unit_recruit_location(*u, check_type, check_location, alternative);
452 if ( current_result <= best_result )
454 best_result = current_result;
458 recruited_from = u->get_location();
463 recruit_location = alternative;
470 LOG_NG <<
"finding recruit location for side " << side;
477 LOG_NG <<
"No leaders on side " << side <<
" when recruiting '" <<
unit_type <<
"'.";
478 return _(
"You do not have a leader to recruit with.");
481 LOG_NG <<
"No leader is able to recruit '" <<
unit_type <<
"' on side " << side <<
".";
482 return _(
"None of your leaders are able to recruit this unit.");
485 LOG_NG <<
"No leader able to recruit '" <<
unit_type <<
"' is on a keep.";
486 return _(
"You must have a leader on a keep who is able to recruit the unit.");
489 LOG_NG <<
"No vacant castle tiles around a keep are available for recruiting '" <<
unit_type <<
"'; requested location is " << recruit_location <<
".";
490 return _(
"There are no vacant castle tiles in which to recruit the unit.");
494 return std::string();
499 ERR_NG <<
"Unrecognized enum in find_recruit_location()";
500 return _(
"An unrecognized error has occurred.");
508 void recruit_checksums(
const unit &new_unit,
bool wml_triggered)
515 config original_checksum_config;
524 checksum_equals = original_checksum_config[
"checksum"] == alternate_checksum;
528 const std::string old_checksum = original_checksum_config[
"checksum"];
529 std::stringstream error_msg;
530 error_msg <<
"SYNC: In recruit " << new_unit.
type_id() <<
531 ": has checksum " << checksum <<
532 " while datasource has checksum " << old_checksum <<
"\n";
533 if(old_checksum.empty())
535 error_msg <<
"Original result is \n" << original_checksum_config <<
"\n";
538 new_unit.
write(cfg_unit1);
555 if (leader != units.
end() && leader->can_recruit() &&
557 return leader->get_location();
560 for (leader = units.
begin(); leader != units.
end(); ++leader)
561 if (leader->can_recruit() && leader->side() == side &&
563 return leader->get_location();
577 if ( !un_it.
valid() ) {
584 current_loc = un_it->get_location();
596 int min_dist = INT_MAX;
598 for ( unit_itor = units.
begin(); unit_itor != units.
end(); ++unit_itor ) {
601 int dist =
distance_between(unit_itor->get_location(),recruit_loc) - unit_itor->level();
602 if (dist < min_dist) {
604 min_loc = unit_itor->get_location();
608 if (min_dist < INT_MAX) {
627 LOG_NG <<
"placing new unit on location " << recruit_location;
629 u->set_movement(u->total_movement(),
true);
631 u->set_movement(0,
true);
641 find_recruit_leader(u->side(), recruit_location, recruited_from);
642 u->set_location(recruit_location);
651 set_recruit_facing(new_unit_itor, *u, recruit_location, leader_loc);
653 new_unit_itor->set_facing(facing);
658 recruit_checksums(*u, wml_triggered);
662 if(!new_unit_itor.
valid()) {
667 const std::string event_name = is_recall ?
"prerecall" :
"prerecruit";
668 LOG_NG <<
"firing " << event_name <<
" event";
672 if ( !validate_recruit_iterator(new_unit_itor, current_loc) )
673 return std::tuple(
true, 0,
false);
674 new_unit_itor->set_hidden(
true);
683 new_unit_itor->set_hidden(
false);
692 std::get<0>(res) |= std::get<0>(
actions::get_village(current_loc, new_unit_itor->side(), &std::get<2>(res)));
693 if ( !validate_recruit_iterator(new_unit_itor, current_loc) )
694 return std::tuple(
true, 0,
false);
700 std::get<0>(res) |= clearer.
clear_unit(current_loc, *new_unit_itor);
703 const std::string event_name = is_recall ?
"recall" :
"recruit";
704 LOG_NG <<
"firing " << event_name <<
" event";
711 std::get<0>(res) |= std::get<0>(clearer.
fire_events());
712 if ( new_unit_itor.
valid() )
763 if (recall->recall_cost() < 0) {
768 res =
place_recruit(recall, loc, from, recall->recall_cost(),
Various functions related to moving units.
Class to encapsulate fog/shroud clearing and the resultant sighted events.
game_events::pump_result_t fire_events()
Fires the sighted events that were earlier recorded by fog/shroud clearing.
bool clear_unit(const map_location &view_loc, team &view_team, std::size_t viewer_id, int sight_range, bool slowed, const movetype::terrain_costs &costs, const map_location &real_loc, const std::set< map_location > *known_units=nullptr, std::size_t *enemy_count=nullptr, std::size_t *friend_count=nullptr, move_unit_spectator *spectator=nullptr, bool instant=true)
Clears shroud (and fog) around the provided location for view_team based on sight_range,...
void add_recall(const unit_const_ptr u, const map_location &loc, const map_location &from, int orig_village_owner, bool time_bonus)
Adds a recall to the undo stack.
void clear()
Clears the stack of undoable (and redoable) actions.
void add_recruit(const unit_const_ptr u, const map_location &loc, const map_location &from, int orig_village_owner, bool time_bonus)
Adds a recruit to the undo stack.
virtual bool local_checkup(const config &expected_data, config &real_data)=0
Compares data to the results calculated during the original game.
A config object defines a single node in a WML file, with access to child nodes.
int village_owner(const map_location &loc) const
Given the location of a village, will return the 1-based number of the team that currently owns it,...
void redraw_minimap()
Schedule the minimap to be redrawn.
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
void invalidate_game_status()
Function to invalidate the game status displayed on the sidebar.
static display * get_singleton()
Returns the display object if a display object exists.
virtual const unit_map & units() const override
virtual const gamemap & map() const override
game_events::wml_event_pump & pump()
pump_result_t fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
bool can_recruit_on(const map_location &leader_loc, const map_location &recruit_loc, int side) const
Checks to see if a leader at leader_loc could recruit on recruit_loc.
int w() const
Effective map width.
int h() const
Effective map height.
Encapsulates the map of the game.
bool is_castle(const map_location &loc) const
bool is_keep(const map_location &loc) const
statistics_t & statistics()
unit_ptr extract_if_matches_id(const std::string &unit_id, int *pos=nullptr)
Find a unit by id, and extract from this object if found.
std::size_t find_index(const std::string &unit_id) const
Find the index of a unit by its id.
static void process_error(const std::string &msg)
void recall_unit(const unit &u)
void recruit_unit(const unit &u)
static bool undo_blocked()
This class stores all the data for a single 'side' (in game nomenclature).
bool auto_shroud_updates() const
std::string save_id_or_number() const
void spend_gold(const int amount)
recall_list_manager & recall_list()
const std::set< std::string > & recruits() const
Container associating units to locations.
unit_iterator find(std::size_t id)
umap_retval_pair_t insert(unit_ptr p)
Inserts the unit pointed to by p into the map.
A single unit type that the player may recruit.
This class represents a single unit of a specific type.
static unit_ptr create(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Initializes a unit from a config.
A variable-expanding proxy for the config class.
static lg::log_domain log_engine("engine")
Various functions related to the creation of units (recruits, recalls, and placed units).
static std::string _(const char *str)
void write(config &cfg, bool write_all=true) const
Serializes the current unit metadata values.
@ version_1_16_or_older
Included some of the flavortext from weapon specials.
const std::vector< std::string > & recruits() const
The type IDs of the other units this unit may recruit, if possible.
const config & recall_filter() const
Gets the filter constraints upon which units this unit may recall, if able.
const std::string & type_id() const
The id of this unit's type.
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
const std::string & id() const
Gets this unit's id.
int side() const
The side this unit belongs to.
const map_location & get_location() const
The current map location this unit is at.
T end(const std::pair< T, T > &p)
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Standard logging facilities (interface).
std::string find_recruit_location(const int side, map_location &recruit_location, map_location &recruited_from, const std::string &unit_type)
Finds a location on which to place a unit.
void recruit_unit(const unit_type &u_type, int side_num, const map_location &loc, const map_location &from, bool show, bool use_undo)
Recruits a unit of the given type for the given side.
RECRUIT_CHECK check_recall_location(const int side, map_location &recall_location, map_location &recall_from, const unit &unit_recall)
Checks if there is a location on which to recall unit_recall.
const std::set< std::string > get_recruits(int side, const map_location &recruit_loc)
Gets the recruitable units from a side's leaders' personal recruit lists who can recruit on or from a...
place_recruit_result place_recruit(unit_ptr u, const map_location &recruit_location, const map_location &recruited_from, int cost, bool is_recall, map_location::DIRECTION facing, bool show, bool fire_event, bool full_movement, bool wml_triggered)
Place a unit into the game.
RECRUIT_CHECK
The possible results of finding a location for recruiting (or recalling).
@ RECRUIT_OK
Recruitment OK, but not at the specified location.
@ RECRUIT_NO_VACANCY
No able leaders are on a keep.
@ RECRUIT_NO_ABLE_LEADER
No leaders exist.
@ RECRUIT_ALTERNATE_LOCATION
No vacant castle tiles around a leader on a keep.
@ RECRUIT_NO_KEEP_LEADER
No leaders able to recall/recruit the given unit/type.
RECRUIT_CHECK check_recruit_location(const int side, map_location &recruit_location, map_location &recruited_from, const std::string &unit_type)
Checks if there is a location on which to place a recruited unit.
game_events::pump_result_t actor_sighted(const unit &target, const std::vector< int > *cache)
Fires sighted events for the sides that can see target.
bool recall_unit(const std::string &id, team ¤t_team, const map_location &loc, const map_location &from, map_location::DIRECTION facing, bool show, bool use_undo)
Recalls the unit with the indicated ID for the provided team.
game_events::pump_result_t get_village(const map_location &loc, int side, bool *action_timebonus, bool fire_event)
Makes it so the village at the given location is owned by the given side.
std::vector< unit_const_ptr > get_recalls(int side, const map_location &recall_loc)
Gets the recallable units for a side, restricted by that side's leaders' personal abilities to recall...
std::string find_recall_location(const int side, map_location &recall_location, map_location &recall_from, const unit &unit_recall)
Finds a location on which to recall unit_recall.
std::tuple< bool, int, bool > place_recruit_result
void pump()
Process all events currently in the queue.
void show(const std::string &window_id, const t_string &message, const point &mouse, const SDL_Rect &source_rect)
Shows a tip.
bool fire_event(const ui_event event, const std::vector< std::pair< widget *, ui_event >> &event_chain, widget *dispatcher, widget *w, F &&... params)
Helper function for fire_event.
map_location find_vacant_castle(const unit &leader)
Wrapper for find_vacant_tile() when looking for a vacant castle tile near a leader.
std::set< std::string > & encountered_units()
game_events::manager * game_events
actions::undo_list * undo_stack
play_controller * controller
filter_context * filter_con
std::shared_ptr< wb::manager > whiteboard
void unit_recruited(const map_location &loc, const map_location &leader_loc)
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
This module contains various pathfinding functions and utilities.
std::shared_ptr< const unit > unit_const_ptr
std::shared_ptr< unit > unit_ptr
Define the game's event mechanism.
static config unit_type(const unit *u)
Encapsulates the map of the game.
DIRECTION
Valid directions which can be moved in our hexagonal world.
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
static const map_location & null_location()
static DIRECTION get_opposite_dir(DIRECTION d)
pointer get_shared_ptr() const
This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax...
checkup * checkup_instance
Display units performing various actions: moving, attacking, and dying.
Various functions that implement the undoing (and redoing) of in-game commands.
std::string get_checksum(const unit &u, backwards_compatibility::unit_checksum_version version)
Gets a checksum for a unit.
Various functions implementing vision (through fog of war and shroud).