55 #define DBG_NG LOG_STREAM(debug, log_engine) 56 #define LOG_NG LOG_STREAM(info, log_engine) 57 #define ERR_NG LOG_STREAM(err, log_engine) 65 LOG_NG <<
"getting recruit list for side " << side <<
" at location " << recruit_loc;
67 std::set<std::string> local_result;
68 std::set<std::string> global_result;
72 bool leader_in_place =
false;
79 if ( find_it != u_end ) {
80 if ( find_it->can_recruit() && find_it->side() == side &&
85 leader_in_place =
true;
86 local_result.insert(find_it->recruits().begin(),
87 find_it->recruits().end());
89 else if ( find_it->is_visible_to_team(current_team,
false) )
96 if ( !leader_in_place ) {
98 for( ; u != u_end; ++u ) {
100 if ( !(u->can_recruit() && u->side() == side) )
104 if (allow_local && dynamic_cast<game_state&>(*
resources::filter_con).can_recruit_on(*u, recruit_loc)) {
105 leader_in_place=
true;
106 local_result.insert(u->recruits().begin(), u->recruits().end());
108 else if ( !leader_in_place )
109 global_result.insert(u->recruits().begin(), u->recruits().end());
114 std::set<std::string> & result = leader_in_place ? local_result : global_result;
117 const std::set<std::string>& recruit_list = current_team.
recruits();
118 result.insert(recruit_list.begin(), recruit_list.end());
132 std::vector< unit_const_ptr > & result,
133 std::set<std::size_t> * already_added =
nullptr)
145 if ( !already_added || already_added->count(underlying_id) == 0 )
152 result.push_back(recall_unit_ptr);
153 if ( already_added !=
nullptr )
154 already_added->insert(underlying_id);
163 LOG_NG <<
"getting recall list for side " << side <<
" at location " << recall_loc;
165 std::vector<unit_const_ptr > result;
174 bool leader_in_place =
false;
182 if ( find_it->can_recruit() && find_it->side() == side &&
201 std::set<std::size_t> valid_local_recalls;
203 for(; u != u_end; ++u) {
205 if (!(u->can_recruit() && u->side() == side))
211 leader_in_place=
true;
213 add_leader_filtered_recalls(u.
get_shared_ptr(), result, &valid_local_recalls);
217 if ( !leader_in_place )
219 std::set<std::size_t> valid_local_recalls;
223 if(!u->can_recruit() || u->side() != side) {
227 add_leader_filtered_recalls(u.get_shared_ptr(), result, &valid_local_recalls);
250 team& recall_team = (*resources::gameboard).get_team(recaller.
side());
264 if ( !permissible.
valid() )
269 alternative = permissible;
281 const unit &unit_recall)
300 if ( u != u_end && u->side() == side ) {
302 check_unit_recall_location(*u, unit_recall, check_location, alternative);
306 for ( u = units.
begin(); best_result < goal_result && u != u_end; ++u ) {
307 if ( u->side() != side )
312 check_unit_recall_location(*u, unit_recall, check_location, alternative);
315 if ( current_result <= best_result )
317 best_result = current_result;
321 recall_from = u->get_location();
326 recall_location = alternative;
333 LOG_NG <<
"finding recall location for side " << side <<
" and unit " << unit_recall.
id();
340 LOG_NG <<
"No leaders on side " << side <<
" when recalling " << unit_recall.
id() <<
".";
341 return _(
"You do not have a leader to recall with.");
344 LOG_NG <<
"No leader is able to recall " << unit_recall.
id() <<
" on side " << side <<
".";
345 return _(
"None of your leaders are able to recall that unit.");
348 LOG_NG <<
"No leader able to recall " << unit_recall.
id() <<
" is on a keep.";
349 return _(
"You must have a leader on a keep who is able to recall that unit.");
352 LOG_NG <<
"No vacant castle tiles around a keep are available for recalling " << unit_recall.
id() <<
"; requested location is " << recall_location <<
".";
353 return _(
"There are no vacant castle tiles in which to recall the unit.");
357 return std::string();
362 ERR_NG <<
"Unrecognized enum in find_recall_location()";
363 return _(
"An unrecognized error has occurred.");
382 if ( !unit_type.empty() ) {
394 if ( !permissible.
valid() )
399 alternative = permissible;
436 if ( u != u_end && u->side() == side ) {
438 check_unit_recruit_location(*u, check_type, check_location, alternative);
442 for ( u = units.
begin(); best_result < goal_result && u != u_end; ++u ) {
443 if ( u->side() != side )
448 check_unit_recruit_location(*u, check_type, check_location, alternative);
451 if ( current_result <= best_result )
453 best_result = current_result;
457 recruited_from = u->get_location();
462 recruit_location = alternative;
469 LOG_NG <<
"finding recruit location for side " << side;
476 LOG_NG <<
"No leaders on side " << side <<
" when recruiting '" << unit_type <<
"'.";
477 return _(
"You do not have a leader to recruit with.");
480 LOG_NG <<
"No leader is able to recruit '" << unit_type <<
"' on side " << side <<
".";
481 return _(
"None of your leaders are able to recruit this unit.");
484 LOG_NG <<
"No leader able to recruit '" << unit_type <<
"' is on a keep.";
485 return _(
"You must have a leader on a keep who is able to recruit the unit.");
488 LOG_NG <<
"No vacant castle tiles around a keep are available for recruiting '" << unit_type <<
"'; requested location is " << recruit_location <<
".";
489 return _(
"There are no vacant castle tiles in which to recruit the unit.");
493 return std::string();
498 ERR_NG <<
"Unrecognized enum in find_recruit_location()";
499 return _(
"An unrecognized error has occurred.");
507 void recruit_checksums(
const unit &new_unit,
bool wml_triggered)
514 config original_checksum_config;
523 checksum_equals = original_checksum_config[
"checksum"] == alternate_checksum;
527 const std::string old_checksum = original_checksum_config[
"checksum"];
528 std::stringstream error_msg;
529 error_msg <<
"SYNC: In recruit " << new_unit.
type_id() <<
530 ": has checksum " << checksum <<
531 " while datasource has checksum " << old_checksum <<
"\n";
532 if(old_checksum.empty())
534 error_msg <<
"Original result is \n" << original_checksum_config <<
"\n";
537 new_unit.
write(cfg_unit1);
554 if (leader != units.
end() && leader->can_recruit() &&
555 leader->side() == side &&
dynamic_cast<game_state&
>(*resources::filter_con).
can_recruit_on(*leader, recruit_location))
556 return leader->get_location();
559 for (leader = units.
begin(); leader != units.
end(); ++leader)
560 if (leader->can_recruit() && leader->side() == side &&
562 return leader->get_location();
576 if ( !un_it.
valid() ) {
583 current_loc = un_it->get_location();
595 int min_dist = INT_MAX;
597 for ( unit_itor = units.
begin(); unit_itor != units.
end(); ++unit_itor ) {
600 int dist =
distance_between(unit_itor->get_location(),recruit_loc) - unit_itor->level();
601 if (dist < min_dist) {
603 min_loc = unit_itor->get_location();
607 if (min_dist < INT_MAX) {
626 LOG_NG <<
"placing new unit on location " << recruit_location;
628 u->set_movement(u->total_movement(),
true);
630 u->set_movement(0,
true);
640 find_recruit_leader(u->side(), recruit_location, recruited_from);
641 u->set_location(recruit_location);
650 set_recruit_facing(new_unit_itor, *u, recruit_location, leader_loc);
652 new_unit_itor->set_facing(facing);
657 recruit_checksums(*u, wml_triggered);
661 if(!new_unit_itor.valid()) {
666 const std::string event_name = is_recall ?
"prerecall" :
"prerecruit";
667 LOG_NG <<
"firing " << event_name <<
" event";
671 if ( !validate_recruit_iterator(new_unit_itor, current_loc) )
672 return std::tuple(
true, 0,
false);
673 new_unit_itor->set_hidden(
true);
682 new_unit_itor->set_hidden(
false);
691 std::get<0>(res) |= std::get<0>(
actions::get_village(current_loc, new_unit_itor->side(), &std::get<2>(res)));
692 if ( !validate_recruit_iterator(new_unit_itor, current_loc) )
693 return std::tuple(
true, 0,
false);
699 std::get<0>(res) |= clearer.
clear_unit(current_loc, *new_unit_itor);
702 const std::string event_name = is_recall ?
"recall" :
"recruit";
703 LOG_NG <<
"firing " << event_name <<
" event";
710 std::get<0>(res) |= std::get<0>(clearer.
fire_events());
711 if ( new_unit_itor.valid() )
762 if (recall->recall_cost() < 0) {
767 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
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.
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.
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.
Included some of the flavortext from weapon specials.
const std::string & id() const
Gets this unit's id.
int w() const
Effective map width.
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...
std::string get_checksum(const unit &u, backwards_compatibility::unit_checksum_version version)
Gets a checksum for a unit.
void spend_gold(const int amount)
No vacant castle tiles around a leader on a keep.
game_events::manager * game_events
void pump()
Process all events currently in the queue.
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)...
pointer get_shared_ptr() const
This is exactly the same as operator-> but it's slightly more readable, and can replace &*iter syntax...
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.
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.
int h() const
Effective map height.
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.