69 #define DBG_NG LOG_STREAM(debug, log_engine) 70 #define LOG_NG LOG_STREAM(info, log_engine) 71 #define WRN_NG LOG_STREAM(warn, log_engine) 72 #define ERR_NG LOG_STREAM(err, log_engine) 75 #define DBG_DP LOG_STREAM(debug, log_display) 76 #define LOG_DP LOG_STREAM(info, log_display) 79 #define LOG_WML LOG_STREAM(info, log_wml) 80 #define WRN_WML LOG_STREAM(warn, log_wml) 81 #define ERR_WML LOG_STREAM(err, log_wml) 84 #define ERR_CF LOG_STREAM(err, log_config) 109 std::string
type = cfg[
"type"];
110 std::string variation = cfg[
"variation"];
111 std::string img_mods = cfg[
"image_mods"];
113 std::size_t side_num = cfg[
"side"].to_int(1);
123 if(!variation.empty()) {
126 effect[
"apply_to"] =
"variation";
127 effect[
"name"] = variation;
128 fake->add_modification(
"variation",mod);
131 if(!img_mods.empty()) {
134 effect[
"apply_to"] =
"image_mod";
135 effect[
"add"] = img_mods;
136 fake->add_modification(
"image_mod",mod);
142 std::vector<map_location> fake_unit_path(
const unit& fake_unit,
const std::vector<std::string>& xvals,
const std::vector<std::string>& yvals)
145 std::vector<map_location>
path;
148 for(std::size_t
i = 0;
i != std::min(xvals.size(),yvals.size()); ++
i) {
153 }
catch(std::invalid_argument&) {
154 ERR_CF <<
"Invalid move_unit_fake source: " << xvals[
i] <<
", " << yvals[
i];
158 ERR_CF <<
"Invalid move_unit_fake source: " << src;
172 }
catch(std::invalid_argument&) {
173 ERR_CF <<
"Invalid move_unit_fake destination: " << xvals[
i] <<
", " << yvals[
i];
176 ERR_CF <<
"Invalid move_unit_fake destination: " << dst;
181 game_map->
w(), game_map->
h());
183 if (route.
steps.empty()) {
184 WRN_NG <<
"Could not find move_unit_fake route from " << src <<
" to " << dst <<
": ignoring complexities";
188 game_map->
w(), game_map->
h());
189 if(route.
steps.empty()) {
193 WRN_NG <<
"Could not find move_unit_fake route from " << src <<
" to " << dst <<
": ignoring terrain";
195 route =
a_star_search(src, dst, 10000, dummy_calc, game_map->
w(), game_map->
h());
196 assert(!route.
steps.empty());
202 path.insert(path.end(),
251 #define WML_HANDLER_FUNCTION(pname, pei, pcfg) \ 252 static void wml_func_##pname(const queued_event& pei, const vconfig& pcfg); \ 253 static wml_action wml_action_##pname(#pname, &wml_func_##pname); \ 254 static void wml_func_##pname(const queued_event& pei, const vconfig& pcfg) 269 ERR_NG <<
"Error via [do_command]:";
283 ERR_NG <<
"[do_command] called while whiteboard is applied, ignoring";
287 static const std::set<std::string> allowed_tags {
"attack",
"move",
"recruit",
"recall",
"disband",
"fire_event",
"custom_command"};
294 ERR_NG <<
"[do_command] called too early, only allowed at START or later";
299 ERR_NG <<
"[do_command] cannot be used in linger mode";
304 ERR_NG <<
"[do_command] cannot be used before the turn has started";
307 if(is_unsynced && is_unsynced_too_early)
309 ERR_NG <<
"[do_command] called too early";
314 ERR_NG <<
"[do_command] cannot invoke synced commands while commands are blocked";
319 ERR_NG <<
"[do_command] can only be used from clients that control the currently playing side";
322 for(
const auto& [key, child] : cfg.all_ordered())
324 if(allowed_tags.find(key) == allowed_tags.end()) {
325 ERR_NG <<
"unsupported tag [" << key <<
"] in [do_command]";
327 std::copy(allowed_tags.begin(), allowed_tags.end(), std::ostream_iterator<std::string>(o,
" "));
328 ERR_NG <<
"allowed tags: " << o.str();
338 child.get_parsed_config(),
359 std::string add = cfg[
"add"];
364 }
else if(!value.
empty()) {
368 if(!current.
empty()) {
369 const unsigned int current_turn_number = tod_man.
turn();
370 int new_turn_number = current.
to_int(current_turn_number);
371 const unsigned int new_turn_number_u =
static_cast<unsigned int>(new_turn_number);
373 ERR_NG <<
"attempted to change current turn number to one out of range (" << new_turn_number <<
")";
374 }
else if(new_turn_number_u != current_turn_number) {
390 if(!dummy_unit.
get())
393 const bool force_scroll = cfg[
"force_scroll"].to_bool(
true);
395 const std::string x = cfg[
"x"];
396 const std::string y = cfg[
"y"];
401 const std::vector<map_location>&
path = fake_unit_path(*dummy_unit, xvals, yvals);
412 LOG_NG <<
"Processing [move_units_fake]";
414 const bool force_scroll = cfg[
"force_scroll"].to_bool();
416 std::size_t num_units = unit_cfgs.size();
417 std::vector<fake_unit_ptr > units;
418 units.reserve(num_units);
419 std::vector<std::vector<map_location>> paths;
420 paths.reserve(num_units);
422 LOG_NG <<
"Moving " << num_units <<
" units";
424 std::size_t longest_path = 0;
429 int skip_steps =
config[
"skip_steps"];
432 paths.push_back(fake_unit_path(*u, xvals, yvals));
434 paths.back().insert(paths.back().begin(), skip_steps, paths.back().front());
435 longest_path = std::max(longest_path, paths.back().size());
436 DBG_NG <<
"Path " << paths.size() - 1 <<
" has length " << paths.back().size();
438 u->set_location(paths.back().front());
442 LOG_NG <<
"Units placed, longest path is " << longest_path <<
" long";
444 std::vector<map_location> path_step(2);
446 for(std::size_t step = 1; step < longest_path; ++step) {
447 DBG_NG <<
"Doing step " << step <<
"...";
448 for(std::size_t un = 0; un < num_units; ++un) {
449 if(step >= paths[un].
size() || paths[un][step - 1] == paths[un][step])
451 DBG_NG <<
"Moving unit " << un <<
", doing step " << step;
452 path_step[0] = paths[un][step - 1];
453 path_step[1] = paths[un][step];
455 units[un]->set_location(path_step[1]);
456 units[un]->anim_comp().set_standing(
false);
471 LOG_NG <<
"recalling unit...";
472 config temp_config(cfg.get_config());
480 temp_config[
"x"] =
"recall";
481 temp_config[
"y"] =
"recall";
483 vconfig unit_filter_cfg(temp_config);
484 const vconfig & leader_filter = cfg.
child(
"secondary_unit");
491 DBG_NG <<
"recall list is empty when trying to recall!";
492 DBG_NG <<
"player_id: " << player_id <<
" side: " << index+1;
502 DBG_NG <<
"checking unit against filter...";
505 DBG_NG << (*u)->id() <<
" matched the filter...";
507 const unit* pass_check = to_recruit.get();
508 if(!cfg[
"check_passability"].to_bool(
true)) pass_check =
nullptr;
510 if(cfg.has_attribute(
"location_id")) {
512 const auto& iter = special_locs.find(cfg[
"location_id"]);
513 if(iter != special_locs.end()) {
514 cfg_loc = iter->second;
519 DBG_NG <<
"...considering " + leader->id() +
" as the recalling leader...";
521 if ( lfilt(*leader) &&
523 DBG_NG <<
"...matched the leader filter and is able to recall the unit.";
525 loc = leader->get_location();
529 DBG_NG <<
"...valid location for the recall found. Recalling.";
533 cfg[
"show"].to_bool(
true), cfg[
"fire_event"].to_bool(
false),
545 DBG_NG <<
"No usable leader found, but found usable location. Recalling.";
550 cfg[
"show"].to_bool(
true), cfg[
"fire_event"].to_bool(
false),
558 LOG_WML <<
"A [recall] tag with the following content failed:\n" << cfg.get_config().debug();
564 map_choice(
const std::string& filename) :
filename_(filename) {}
566 virtual config query_user(
int )
const override 569 return config {
"map_data", res};
571 virtual config random_choice(
int )
const override 575 virtual std::string description()
const override 579 virtual bool is_visible()
const override 607 if(!cfg[
"map_file"].empty()) {
609 map.
read(file_cfg[
"map_data"].str(),
false);
610 }
else if(!cfg[
"map_data"].empty()) {
611 map.
read(cfg[
"map_data"],
false);
614 map.
read(cfg[
"map"],
false);
617 const std::string log_map_name = cfg[
"map"].empty() ? cfg[
"map_file"] : std::string(
"from inline data");
618 lg::log_to_chat() <<
"replace_map: Unable to load map " << log_map_name <<
'\n';
619 ERR_WML <<
"replace_map: Unable to load map " << log_map_name;
628 if (!cfg[
"expand"].to_bool()) {
629 lg::log_to_chat() <<
"replace_map: Map dimension(s) increase but expand is not set\n";
630 ERR_WML <<
"replace_map: Map dimension(s) increase but expand is not set";
637 if (!cfg[
"shrink"].to_bool()) {
638 lg::log_to_chat() <<
"replace_map: Map dimension(s) decrease but shrink is not set\n";
639 ERR_WML <<
"replace_map: Map dimension(s) decrease but shrink is not set";
671 ERR_NG <<
"trying to set a variable with an empty name:\n" << cfg.get_config().debug();
675 std::vector<config>
data;
676 if(cfg.has_attribute(
"to_variable"))
688 ERR_NG <<
"Cannot do [set_variables] with invalid to_variable variable: " << cfg[
"to_variable"] <<
" with " << cfg.get_config().debug();
691 typedef std::pair<std::string, vconfig> vchild;
692 for (
const vchild&
p : cfg.all_ordered()) {
693 if(
p.first ==
"value") {
694 data.push_back(
p.second.get_parsed_config());
695 }
else if(
p.first ==
"literal") {
696 data.push_back(
p.second.get_config());
697 }
else if(
p.first ==
"split") {
698 const vconfig & split_element =
p.second;
700 std::string split_string=split_element[
"list"];
701 std::string separator_string=split_element[
"separator"];
702 std::string key_name=split_element[
"key"];
708 bool remove_empty = split_element[
"remove_empty"].to_bool();
710 char* separator = separator_string.
empty() ? nullptr : &separator_string[0];
711 if(separator_string.size() > 1){
712 ERR_NG <<
"[set_variables] [split] separator only supports 1 character, multiple passed: " << split_element[
"separator"] <<
" with " << cfg.
get_config().
debug();
715 std::vector<std::string> split_vector;
718 if(separator ==
nullptr)
722 split_vector.push_back(std::string(1, *
i));
731 data.emplace_back(key_name, *
i);
738 const std::string& mode = cfg[
"mode"];
745 for (
const config &ch : data) {
746 merged_children.
append(ch);
748 data = {merged_children};
752 else if(mode ==
"insert")
756 else if(mode ==
"append")
767 ERR_NG <<
"Cannot do [set_variables] with invalid destination variable: " << name <<
" with " << cfg.get_config().debug();
778 if (!cfg.child(
"source")) {
779 WRN_NG <<
"No source in [store_relative_direction]";
782 if (!cfg.child(
"destination")) {
783 WRN_NG <<
"No destination in [store_relative_direction]";
786 if (!cfg.has_attribute(
"variable")) {
787 WRN_NG <<
"No variable in [store_relative_direction]";
794 std::string variable = cfg[
"variable"];
804 ERR_NG <<
"Cannot do [store_relative_direction] with invalid destination variable: " << variable <<
" with " << cfg.get_config().debug();
816 if (!cfg.child(
"source")) {
817 WRN_NG <<
"No source in [store_rotate_map_location]";
820 if (!cfg.child(
"destination")) {
821 WRN_NG <<
"No destination in [store_rotate_map_location]";
824 if (!cfg.has_attribute(
"variable")) {
825 WRN_NG <<
"No variable in [store_rotate_map_location]";
832 std::string variable = cfg[
"variable"];
833 int angle = cfg[
"angle"].to_int(1);
839 dst.rotate_right_around_center(src,angle).write(store.
as_container());
843 ERR_NG <<
"Cannot do [store_rotate_map_location] with invalid destination variable: " << variable <<
" with " << cfg.get_config().debug();
849 const bool remove = cfg[
"remove"].to_bool(
false);
850 const bool delay = cfg[
"delayed_variable_substitution"].to_bool(
true);
852 const std::vector<std::string> ids =
utils::split(cfg[
"id"]);
853 for (
const std::string &
id : ids) {
856 }
else if (cfg.get_children(
"source").empty() ||
857 cfg.get_children(
"target").empty() ||
858 cfg.get_children(
"filter").empty()) {
859 ERR_WML <<
"[tunnel] is missing a mandatory tag:\n" 860 << cfg.get_config().debug();
865 if(cfg[
"bidirectional"].to_bool(
true)) {
876 config parsed_cfg = cfg.get_parsed_config();
879 if (!to_variable.
blank())
887 new_unit->write(var);
893 ERR_NG <<
"Cannot do [unit] with invalid to_variable: " << to_variable <<
" with " << cfg.get_config().debug();
899 int side = parsed_cfg[
"side"].to_int(1);
925 if(cfg[
"delayed_variable_substitution"].to_bool(
false)) {
std::optional< std::string > replace_map(const gamemap &r)
void verify_and_get_global_variable(const vconfig &pcfg)
play_controller * controller
static void add_undo_commands(const config &commands, const game_events::queued_event &ctx)
bool empty() const
Tests for an attribute that either was never set or was set to "".
std::map< std::string, handler > map
unit_creator & allow_rename_side(bool b)
config get_user_choice(const std::string &name, const user_choice &uch, int side=0)
static synced_state get_synced_state()
static void get_global_variable(persist_context &ctx, const vconfig &pcfg)
static DIRECTION parse_direction(const std::string &str)
::tod_manager * tod_manager
std::vector< unit_iterator > find_leaders(int side)
static display * get_singleton()
Returns the display object if a display object exists.
Function which doesn't take anything into account.
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
virtual const std::vector< team > & teams() const override
location_map & special_locations()
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
virtual const unit_map & units() const override
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
This class represents a single unit of a specific type.
wml_action(const std::string &tag, handler function)
Using this constructor for a static object outside action_wml.cpp will likely lead to a static initia...
void append(const config &cfg)
Append data from another config object to this one.
Various functions implementing vision (through fog of war and shroud).
static manager & get_singleton()
void raise_gamestate_changed()
Notifies all observers of 'ai_gamestate_changed' event.
unit_creator & allow_invalidate(bool b)
static void set_global_variable(persist_context &ctx, const vconfig &pcfg)
unit_creator & allow_show(bool b)
bool explicit_index() const
Various functions that implement attacks and attack calculations.
void remove(const std::string &id)
Variant for storing WML attributes.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
internal_ptr get_unit_ptr()
Get a copy of the internal unit pointer.
config & get_variable_cfg(const std::string &varname)
throws invalid_variablename_exception if varname is no valid variable name.
void raise_map_changed()
Notifies all observers of 'ai_map_changed' event.
maybe_const_t< config::attribute_value, V > & as_scalar() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
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.
unit_creator & allow_discover(bool b)
const attribute_value * get(config_key_type key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
virtual const gamemap & map() const override
WML_HANDLER_FUNCTION(clear_global_variable,, pcfg)
Experimental data persistence.
void modify_turns_by_wml(const std::string &mod)
unit_type_data unit_types
Define actions for the game's events mechanism.
config::child_itors insert_array(std::vector< config > children) const
This class encapsulates the recall list of a team.
static lg::log_domain log_config("config")
void verify_and_set_global_variable(const vconfig &pcfg)
bool matches(const unit &u, const map_location &loc) const
Determine if *this matches filter at a specified location.
Additional functionality for a non-const variable_info.
int to_int(int def=0) const
maybe_const_t< config, V > & as_container() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
An object to leave the synced context during draw or unsynced wml items when we don’t know whether w...
void remove_attribute(config_key_type key)
unit_creator & allow_add_to_recall(bool b)
std::shared_ptr< unit > unit_ptr
void new_turn()
Update lighting settings.
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 show() const
Shows the error in a dialog.
This class stores all the data for a single 'side' (in game nomenclature).
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
std::vector< map_location > steps
void set_number_of_turns_by_wml(int num)
std::string deprecated_message(const std::string &elem_name, DEP_LEVEL level, const version_info &version, const std::string &detail)
int w() const
Effective map width.
Structure which holds a single route between one location and another.
void merge_array(std::vector< config > children) const
variable_access_create get_variable_access_write(const std::string &varname)
returns a variable_access that can be used to change the game variables
bool blank() const
Tests for an attribute that was never set.
Interface for querying local choices.
iterator begin()
begin iterator
Encapsulates the map of the game.
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
REMOVE_EMPTY: remove empty elements.
fake_unit_manager * fake_units
config::child_itors append_array(std::vector< config > children) const
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands...
Function which only uses terrain, ignoring shroud, enemies, etc.
void read(const std::string &data, const bool allow_invalid=true)
iterator end()
end iterator
void needs_rebuild(bool b)
Sets whether the screen (map visuals) needs to be rebuilt.
int number_of_turns() const
std::string read_map(const std::string &name)
void set_turn_by_wml(const int num, game_data *vars=nullptr, const bool increase_limit_if_needed=true)
Dynamically change the current turn number.
Encapsulates the map of the game.
Various functions related to moving units.
Helper class, don't construct this directly.
static map registry_
Tracks the known action handlers.
std::shared_ptr< wb::manager > whiteboard
Various functions related to the creation of units (recruits, recalls, and placed units)...
Define conditionals for the game's events mechanism, a.k.a.
int total_width() const
Real width of the map, including borders.
unit * get()
Get a raw pointer to the underlying unit.
unit_creator & allow_get_village(bool b)
fake
For describing the type of faked display, if any.
Define the game's event mechanism.
config::child_itors replace_array(std::vector< config > children) const
bool on_board(const map_location &loc) const
Tell if a location is on the map.
static lg::log_domain log_display("display")
Declarations for File-IO.
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
int total_height() const
Real height of the map, including borders.
config & add_child(config_key_type key)
iterator erase(iterator it)
Erase an iterator to this object.
void add_unit(const config &cfg, const vconfig *vcfg=nullptr)
adds a unit on map without firing any events (so, usable during team construction in gamestatus) ...
static void on_replay_error(const std::string &message)
void add(const teleport_group &group)
Information on a WML variable.
static bool run_in_synced_context_if_not_already(const std::string &commandname, const config &data, bool use_undo=true, bool show=true, synced_command::error_handler_function error_handler=default_error_function)
Checks whether we are currently running in a synced context, and if not we enters it...
void reload_map()
Updates internals that cache map size.
std::vector< std::string > split(const config_attribute_value &val)
A variable-expanding proxy for the config class.
const config & get_config() const
Standard logging facilities (interface).
static const map_location & null_location()
static lg::log_domain log_engine("engine")
A RAII object to temporary leave the synced context like in wesnoth.synchronize_choice.
int side() const
The side this unit belongs to.
static void clear_global_variable(persist_context &ctx, const vconfig &pcfg)
maybe_const_t< config::child_itors, V > as_array() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
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.
std::vector< vconfig > child_list
static lg::log_domain log_wml("wml")
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator &calc, const std::size_t width, const std::size_t height, const teleport_map *teleports, bool border)
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.
static std::string write_direction(DIRECTION dir)
pathfind::manager * tunnels
std::string::const_iterator iterator
Holds a temporary unit that can be drawn on the map without being placed in the unit_map.
Display units performing various actions: moving, attacking, and dying.
void move_unit(const std::vector< map_location > &path, unit_ptr u, bool animate, map_location::DIRECTION dir, bool force_scroll)
Display a unit moving along a given path.
std::string debug() const
void verify_and_clear_global_variable(const vconfig &pcfg)
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
static game_display * get_singleton()
variable_access_const get_variable_access_read(const std::string &varname) const
returns a variable_access that cannot be used to change the game variables