54 #define DBG_NG LOG_STREAM(debug, log_engine) 55 #define LOG_NG LOG_STREAM(info, log_engine) 56 #define ERR_NG LOG_STREAM(err, log_engine) 64 LOG_NG <<
"getting recruit list for side " << side <<
" at location " << recruit_loc <<
"\n";
66 std::set<std::string> local_result;
67 std::set<std::string> global_result;
71 bool leader_in_place =
false;
78 if ( find_it != u_end ) {
79 if ( find_it->can_recruit() && find_it->side() == side &&
84 leader_in_place =
true;
85 local_result.insert(find_it->recruits().begin(),
86 find_it->recruits().end());
88 else if ( find_it->is_visible_to_team(current_team,
false) )
95 if ( !leader_in_place ) {
97 for( ; u != u_end; ++u ) {
99 if ( !(u->can_recruit() && u->side() == side) )
103 if (allow_local && dynamic_cast<game_state&>(*
resources::filter_con).can_recruit_on(*u, recruit_loc)) {
104 leader_in_place=
true;
105 local_result.insert(u->recruits().begin(), u->recruits().end());
107 else if ( !leader_in_place )
108 global_result.insert(u->recruits().begin(), u->recruits().end());
113 std::set<std::string> & result = leader_in_place ? local_result : global_result;
116 const std::set<std::string>& recruit_list = current_team.
recruits();
117 result.insert(recruit_list.begin(), recruit_list.end());
131 std::vector< unit_const_ptr > & result,
132 std::set<std::size_t> * already_added =
nullptr)
144 if ( !already_added || already_added->count(underlying_id) == 0 )
151 result.push_back(recall_unit_ptr);
152 if ( already_added !=
nullptr )
153 already_added->insert(underlying_id);
162 LOG_NG <<
"getting recall list for side " << side <<
" at location " << recall_loc <<
"\n";
164 std::vector<unit_const_ptr > result;
173 bool leader_in_place =
false;
181 if ( find_it->can_recruit() && find_it->side() == side &&
200 std::set<std::size_t> valid_local_recalls;
202 for(; u != u_end; ++u) {
204 if (!(u->can_recruit() && u->side() == side))
210 leader_in_place=
true;
212 add_leader_filtered_recalls(u.
get_shared_ptr(), result, &valid_local_recalls);
216 if ( !leader_in_place )
218 std::set<std::size_t> valid_local_recalls;
222 if(!u->can_recruit() || u->side() != side) {
226 add_leader_filtered_recalls(u.get_shared_ptr(), result, &valid_local_recalls);
249 team& recall_team = (*resources::gameboard).get_team(recaller.
side());
263 if ( !permissible.
valid() )
268 alternative = permissible;
280 const unit &unit_recall)
299 if ( u != u_end && u->side() == side ) {
301 check_unit_recall_location(*u, unit_recall, check_location, alternative);
305 for ( u = units.
begin(); best_result < goal_result && u != u_end; ++u ) {
306 if ( u->side() != side )
311 check_unit_recall_location(*u, unit_recall, check_location, alternative);
314 if ( current_result <= best_result )
316 best_result = current_result;
320 recall_from = u->get_location();
325 recall_location = alternative;
332 LOG_NG <<
"finding recall location for side " << side <<
" and unit " << unit_recall.
id() <<
"\n";
339 LOG_NG <<
"No leaders on side " << side <<
" when recalling " << unit_recall.
id() <<
".\n";
340 return _(
"You do not have a leader to recall with.");
343 LOG_NG <<
"No leader is able to recall " << unit_recall.
id() <<
" on side " << side <<
".\n";
344 return _(
"None of your leaders are able to recall that unit.");
347 LOG_NG <<
"No leader able to recall " << unit_recall.
id() <<
" is on a keep.\n";
348 return _(
"You must have a leader on a keep who is able to recall that unit.");
351 LOG_NG <<
"No vacant castle tiles around a keep are available for recalling " << unit_recall.
id() <<
"; requested location is " << recall_location <<
".\n";
352 return _(
"There are no vacant castle tiles in which to recall the unit.");
356 return std::string();
361 ERR_NG <<
"Unrecognized enum in find_recall_location()" << std::endl;
362 return _(
"An unrecognized error has occurred.");
381 if ( !unit_type.empty() ) {
393 if ( !permissible.
valid() )
398 alternative = permissible;
435 if ( u != u_end && u->side() == side ) {
437 check_unit_recruit_location(*u, check_type, check_location, alternative);
441 for ( u = units.
begin(); best_result < goal_result && u != u_end; ++u ) {
442 if ( u->side() != side )
447 check_unit_recruit_location(*u, check_type, check_location, alternative);
450 if ( current_result <= best_result )
452 best_result = current_result;
456 recruited_from = u->get_location();
461 recruit_location = alternative;
468 LOG_NG <<
"finding recruit location for side " << side <<
"\n";
475 LOG_NG <<
"No leaders on side " << side <<
" when recruiting '" << unit_type <<
"'.\n";
476 return _(
"You do not have a leader to recruit with.");
479 LOG_NG <<
"No leader is able to recruit '" << unit_type <<
"' on side " << side <<
".\n";
480 return _(
"None of your leaders are able to recruit this unit.");
483 LOG_NG <<
"No leader able to recruit '" << unit_type <<
"' is on a keep.\n";
484 return _(
"You must have a leader on a keep who is able to recruit the unit.");
487 LOG_NG <<
"No vacant castle tiles around a keep are available for recruiting '" << unit_type <<
"'; requested location is " << recruit_location <<
".\n";
488 return _(
"There are no vacant castle tiles in which to recruit the unit.");
492 return std::string();
497 ERR_NG <<
"Unrecognized enum in find_recruit_location()" << std::endl;
498 return _(
"An unrecognized error has occurred.");
506 void recruit_checksums(
const unit &new_unit,
bool wml_triggered)
513 config original_checksum_config;
518 const std::string old_checksum = original_checksum_config[
"checksum"];
519 std::stringstream error_msg;
520 error_msg <<
"SYNC: In recruit " << new_unit.
type_id() <<
521 ": has checksum " << checksum <<
522 " while datasource has checksum " << old_checksum <<
"\n";
523 if(old_checksum.empty())
525 error_msg <<
"Original result is \n" << original_checksum_config <<
"\n";
528 new_unit.
write(cfg_unit1);
545 if (leader != units.
end() && leader->can_recruit() &&
546 leader->side() == side &&
dynamic_cast<game_state&
>(*resources::filter_con).
can_recruit_on(*leader, recruit_location))
547 return leader->get_location();
550 for (leader = units.
begin(); leader != units.
end(); ++leader)
551 if (leader->can_recruit() && leader->side() == side &&
553 return leader->get_location();
567 if ( !un_it.
valid() ) {
574 current_loc = un_it->get_location();
586 int min_dist = INT_MAX;
588 for ( unit_itor = units.
begin(); unit_itor != units.
end(); ++unit_itor ) {
591 int dist =
distance_between(unit_itor->get_location(),recruit_loc) - unit_itor->level();
592 if (dist < min_dist) {
594 min_loc = unit_itor->get_location();
598 if (min_dist < INT_MAX) {
617 LOG_NG <<
"placing new unit on location " << recruit_location <<
"\n";
619 u->set_movement(u->total_movement(),
true);
621 u->set_movement(0,
true);
631 find_recruit_leader(u->side(), recruit_location, recruited_from);
632 u->set_location(recruit_location);
641 set_recruit_facing(new_unit_itor, *u, recruit_location, leader_loc);
643 new_unit_itor->set_facing(facing);
648 recruit_checksums(*u, wml_triggered);
652 if(!new_unit_itor.valid()) {
657 const std::string event_name = is_recall ?
"prerecall" :
"prerecruit";
658 LOG_NG <<
"firing " << event_name <<
" event\n";
662 if ( !validate_recruit_iterator(new_unit_itor, current_loc) )
663 return std::tuple(
true, 0,
false);
664 new_unit_itor->set_hidden(
true);
673 new_unit_itor->set_hidden(
false);
682 std::get<0>(res) |= std::get<0>(
actions::get_village(current_loc, new_unit_itor->side(), &std::get<2>(res)));
683 if ( !validate_recruit_iterator(new_unit_itor, current_loc) )
684 return std::tuple(
true, 0,
false);
690 std::get<0>(res) |= clearer.
clear_unit(current_loc, *new_unit_itor);
693 const std::string event_name = is_recall ?
"recall" :
"recruit";
694 LOG_NG <<
"firing " << event_name <<
" event\n";
701 std::get<0>(res) |= std::get<0>(clearer.
fire_events());
702 if ( new_unit_itor.valid() )
753 if (recall->recall_cost() < 0) {
758 res =
place_recruit(recall, loc, from, recall->recall_cost(),
void clear()
Clears the stack of undoable (and redoable) actions.
bool is_keep(const map_location &loc) const
int h() const
Effective map height, in hexes.
static display * get_singleton()
Returns the display object if a display object exists.
void invalidate_game_status()
Function to invalidate the game status displayed on the sidebar.
virtual const unit_map & units() const override
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
This class represents a single unit of a specific type.
const std::string & type_id() const
The id of this unit's type.
bool is_castle(const map_location &loc) const
map_location find_vacant_castle(const unit &leader)
Wrapper for find_vacant_tile() when looking for a vacant castle tile near a leader.
Various functions implementing vision (through fog of war and shroud).
umap_retval_pair_t insert(unit_ptr p)
Inserts the unit pointed to by p into the map.
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.
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.
virtual const gamemap & map() const override
std::tuple< bool, int, bool > place_recruit_result
Recruitment OK, but not at the specified location.
std::string save_id_or_number() const
RECRUIT_CHECK
The possible results of finding a location for recruiting (or recalling).
static config unit_type(const unit *u)
static std::string _(const char *str)
Definitions for the interface to Wesnoth Markup Language (WML).
void redraw_minimap()
Schedule the minimap to be redrawn.
std::shared_ptr< unit > unit_ptr
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...
void recruit_unit(const unit &u)
static unit_ptr create(const config &cfg, bool use_traits=false, const vconfig *vcfg=nullptr)
Initializes a unit from a config.
A single unit type that the player may recruit.
void write(config &cfg, bool write_all=true) const
Serializes the current unit metadata values.
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
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, costs, and slowed.
std::shared_ptr< const unit > unit_const_ptr
This class stores all the data for a single 'side' (in game nomenclature).
game_events::pump_result_t fire_events()
Fires the sighted events that were earlier recorded by fog/shroud clearing.
const std::string & id() const
Gets this unit's id.
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...
filter_context * filter_con
const config & recall_filter() const
Gets the filter constraints upon which units this unit may recall, if able.
Encapsulates the map of the game.
checkup * checkup_instance
map_display and display: classes which take care of displaying the map and game-data on the screen...
void spend_gold(const int amount)
No vacant castle tiles around a leader on a keep.
game_events::manager * game_events
Encapsulates the map of the game.
bool auto_shroud_updates() const
Various functions related to moving units.
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.
unit_iterator find(std::size_t id)
std::shared_ptr< wb::manager > whiteboard
static void process_error(const std::string &msg)
Various functions related to the creation of units (recruits, recalls, and placed units)...
int w() const
Effective map width, in hexes.
pointer get_shared_ptr() const
This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax...
bool fire_event(const ui_event event, std::vector< std::pair< widget *, ui_event >> &event_chain, widget *dispatcher, widget *w, F &&... params)
Helper function for fire_event.
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.
No able leaders are on a keep.
std::string get_checksum(const unit &u)
Gets a checksum for a unit.
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.
bool can_recruit() const
Whether this unit can recruit other units - ie, are they a leader unit.
Define the game's event mechanism.
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.
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.
DIRECTION
Valid directions which can be moved in our hexagonal world.
std::set< std::string > & encountered_units()
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.
void recall_unit(const unit &u)
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.
const std::vector< std::string > & recruits() const
The type IDs of the other units this unit may recruit, if possible.
static DIRECTION get_opposite_dir(DIRECTION d)
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.
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.
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.
const map_location & get_location() const
The current map location this unit is at.
void unit_recruited(const map_location &loc, const map_location &leader_loc)
A variable-expanding proxy for the config class.
Various functions that implement the undoing (and redoing) of in-game commands.
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.
Standard logging facilities (interface).
recall_list_manager & recall_list()
static const map_location & null_location()
Container associating units to locations.
Class to encapsulate fog/shroud clearing and the resultant sighted events.
static lg::log_domain log_engine("engine")
int side() const
The side this unit belongs to.
actions::undo_list * undo_stack
game_events::wml_event_pump & pump()
virtual bool local_checkup(const config &expected_data, config &real_data)=0
Compares data to the results calculated during the original game.
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.
A config object defines a single node in a WML file, with access to child nodes.
This module contains various pathfinding functions and utilities.
std::size_t underlying_id() const
This unit's unique internal ID.
Display units performing various actions: moving, attacking, and dying.
std::size_t find_index(const std::string &unit_id) const
Find the index of a unit by its id.
No leaders able to recall/recruit the given unit/type.
const std::set< std::string > & recruits() const
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.
void show(const std::string &window_id, const t_string &message, const point &mouse, const SDL_Rect &source_rect)
Shows a tip.