52 #define DBG_NG LOG_STREAM(debug, log_engine)
53 #define LOG_NG LOG_STREAM(info, log_engine)
54 #define WRN_NG LOG_STREAM(warn, log_engine)
55 #define ERR_NG LOG_STREAM(err, log_engine)
58 #define DBG_DP LOG_STREAM(debug, log_display)
59 #define LOG_DP LOG_STREAM(info, log_display)
62 #define LOG_WML LOG_STREAM(info, log_wml)
63 #define WRN_WML LOG_STREAM(warn, log_wml)
64 #define ERR_WML LOG_STREAM(err, log_wml)
67 #define ERR_CF LOG_STREAM(err, log_config)
92 std::string
type = cfg[
"type"];
93 std::string variation = cfg[
"variation"];
94 std::string img_mods = cfg[
"image_mods"];
96 std::size_t side_num = cfg[
"side"].to_int(1);
106 if(!variation.empty()) {
109 effect[
"apply_to"] =
"variation";
110 effect[
"name"] = variation;
111 fake->add_modification(
"variation",mod);
114 if(!img_mods.empty()) {
117 effect[
"apply_to"] =
"image_mod";
118 effect[
"add"] = img_mods;
119 fake->add_modification(
"image_mod",mod);
125 std::vector<map_location> fake_unit_path(
const unit& fake_unit,
const std::vector<std::string>& xvals,
const std::vector<std::string>& yvals)
128 std::vector<map_location>
path;
131 for(std::size_t
i = 0;
i != std::min(xvals.size(),yvals.size()); ++
i) {
134 src.set_wml_x(std::stoi(xvals[
i]));
135 src.set_wml_y(std::stoi(yvals[
i]));
136 }
catch(std::invalid_argument&) {
137 ERR_CF <<
"Invalid move_unit_fake source: " << xvals[
i] <<
", " << yvals[
i];
141 ERR_CF <<
"Invalid move_unit_fake source: " <<
src;
153 dst.set_wml_x(std::stoi(xvals[
i]));
154 dst.set_wml_y(std::stoi(yvals[
i]));
155 }
catch(std::invalid_argument&) {
156 ERR_CF <<
"Invalid move_unit_fake destination: " << xvals[
i] <<
", " << yvals[
i];
159 ERR_CF <<
"Invalid move_unit_fake destination: " <<
dst;
164 game_map->
w(), game_map->
h());
166 if (route.
steps.empty()) {
167 WRN_NG <<
"Could not find move_unit_fake route from " <<
src <<
" to " <<
dst <<
": ignoring complexities";
171 game_map->
w(), game_map->
h());
172 if(route.
steps.empty()) {
176 WRN_NG <<
"Could not find move_unit_fake route from " <<
src <<
" to " <<
dst <<
": ignoring terrain";
179 assert(!route.
steps.empty());
234 #define WML_HANDLER_FUNCTION(pname, pei, pcfg) \
235 static void wml_func_##pname(const queued_event& pei, const vconfig& pcfg); \
236 static wml_action wml_action_##pname(#pname, &wml_func_##pname); \
237 static void wml_func_##pname(const queued_event& pei, const vconfig& pcfg)
252 ERR_NG <<
"Error via [do_command]:";
266 ERR_NG <<
"[do_command] called while whiteboard is applied, ignoring";
270 static const std::set<std::string> allowed_tags {
"attack",
"move",
"recruit",
"recall",
"disband",
"fire_event",
"custom_command"};
277 ERR_NG <<
"[do_command] called too early, only allowed at START or later";
280 if(is_unsynced && !is_during_turn)
282 ERR_NG <<
"[do_command] can only be used during a turn when a user woudl also be able to invoke commands";
287 ERR_NG <<
"[do_command] cannot invoke synced commands while commands are blocked";
292 ERR_NG <<
"[do_command] can only be used from clients that control the currently playing side";
295 for(
const auto& [key, child] : cfg.all_ordered())
297 if(allowed_tags.find(key) == allowed_tags.end()) {
298 ERR_NG <<
"unsupported tag [" << key <<
"] in [do_command]";
300 std::copy(allowed_tags.begin(), allowed_tags.end(), std::ostream_iterator<std::string>(o,
" "));
301 ERR_NG <<
"allowed tags: " << o.str();
311 child.get_parsed_config(),
332 std::string add = cfg[
"add"];
337 }
else if(!value.
empty()) {
341 if(!current.empty()) {
342 const unsigned int current_turn_number = tod_man.
turn();
343 int new_turn_number = current.to_int(current_turn_number);
344 const unsigned int new_turn_number_u =
static_cast<unsigned int>(new_turn_number);
346 ERR_NG <<
"attempted to change current turn number to one out of range (" << new_turn_number <<
")";
347 }
else if(new_turn_number_u != current_turn_number) {
363 if(!dummy_unit.
get())
366 const bool force_scroll = cfg[
"force_scroll"].to_bool(
true);
368 const std::string x = cfg[
"x"];
369 const std::string y = cfg[
"y"];
374 const std::vector<map_location>&
path = fake_unit_path(*dummy_unit, xvals, yvals);
385 LOG_NG <<
"Processing [move_units_fake]";
387 const bool force_scroll = cfg[
"force_scroll"].to_bool();
389 std::size_t num_units = unit_cfgs.size();
390 std::vector<fake_unit_ptr > units;
391 units.reserve(num_units);
392 std::vector<std::vector<map_location>> paths;
393 paths.reserve(num_units);
395 LOG_NG <<
"Moving " << num_units <<
" units";
397 std::size_t longest_path = 0;
402 int skip_steps =
config[
"skip_steps"];
405 paths.push_back(fake_unit_path(*u, xvals, yvals));
407 paths.back().insert(paths.back().begin(), skip_steps, paths.back().front());
408 longest_path = std::max(longest_path, paths.back().size());
409 DBG_NG <<
"Path " << paths.size() - 1 <<
" has length " << paths.back().size();
411 u->set_location(paths.back().front());
415 LOG_NG <<
"Units placed, longest path is " << longest_path <<
" long";
417 std::vector<map_location> path_step(2);
419 for(std::size_t step = 1; step < longest_path; ++step) {
420 DBG_NG <<
"Doing step " << step <<
"...";
421 for(std::size_t un = 0; un < num_units; ++un) {
422 if(step >= paths[un].
size() || paths[un][step - 1] == paths[un][step])
424 DBG_NG <<
"Moving unit " << un <<
", doing step " << step;
425 path_step[0] = paths[un][step - 1];
426 path_step[1] = paths[un][step];
428 units[un]->set_location(path_step[1]);
429 units[un]->anim_comp().set_standing(
false);
444 LOG_NG <<
"recalling unit...";
445 config temp_config(cfg.get_config());
453 temp_config[
"x"] =
"recall";
454 temp_config[
"y"] =
"recall";
456 vconfig unit_filter_cfg(temp_config);
457 const vconfig & leader_filter = cfg.
child(
"secondary_unit");
460 LOG_NG <<
"for side " <<
t.side() <<
"...";
461 const std::string player_id =
t.save_id_or_number();
463 if(
t.recall_list().size() < 1) {
464 DBG_NG <<
"recall list is empty when trying to recall!";
465 DBG_NG <<
"player_id: " << player_id <<
" side: " <<
t.side();
475 DBG_NG <<
"checking unit against filter...";
478 DBG_NG << (*u)->id() <<
" matched the filter...";
480 const unit* pass_check = to_recruit.get();
481 if(!cfg[
"check_passability"].to_bool(
true)) pass_check =
nullptr;
483 if(cfg.has_attribute(
"location_id")) {
485 const auto& iter = special_locs.find(cfg[
"location_id"]);
486 if(iter != special_locs.end()) {
487 cfg_loc = iter->second;
492 DBG_NG <<
"...considering " + leader->id() +
" as the recalling leader...";
494 if ( lfilt(*leader) &&
496 DBG_NG <<
"...matched the leader filter and is able to recall the unit.";
498 loc = leader->get_location();
502 DBG_NG <<
"...valid location for the recall found. Recalling.";
506 cfg[
"show"].to_bool(
true), cfg[
"fire_event"].to_bool(
false),
518 DBG_NG <<
"No usable leader found, but found usable location. Recalling.";
523 cfg[
"show"].to_bool(
true), cfg[
"fire_event"].to_bool(
false),
531 LOG_WML <<
"A [recall] tag with the following content failed:\n" << cfg.get_config().debug();
539 virtual config query_user(
int )
const override
542 return config {
"map_data", res};
544 virtual config random_choice(
int )
const override
548 virtual std::string description()
const override
552 virtual bool is_visible()
const override
580 if(!cfg[
"map_file"].empty()) {
582 map.
read(file_cfg[
"map_data"].str(),
false);
583 }
else if(!cfg[
"map_data"].empty()) {
584 map.
read(cfg[
"map_data"],
false);
587 map.
read(cfg[
"map"],
false);
590 const std::string log_map_name = cfg[
"map"].empty() ? cfg[
"map_file"] : std::string(
"from inline data");
591 lg::log_to_chat() <<
"replace_map: Unable to load map " << log_map_name <<
'\n';
592 ERR_WML <<
"replace_map: Unable to load map " << log_map_name;
601 if (!cfg[
"expand"].to_bool()) {
602 lg::log_to_chat() <<
"replace_map: Map dimension(s) increase but expand is not set\n";
603 ERR_WML <<
"replace_map: Map dimension(s) increase but expand is not set";
610 if (!cfg[
"shrink"].to_bool()) {
611 lg::log_to_chat() <<
"replace_map: Map dimension(s) decrease but shrink is not set\n";
612 ERR_WML <<
"replace_map: Map dimension(s) decrease but shrink is not set";
644 ERR_NG <<
"trying to set a variable with an empty name:\n" << cfg.get_config().debug();
648 std::vector<config>
data;
649 if(cfg.has_attribute(
"to_variable"))
661 ERR_NG <<
"Cannot do [set_variables] with invalid to_variable variable: " << cfg[
"to_variable"] <<
" with " << cfg.get_config().debug();
664 typedef std::pair<std::string, vconfig> vchild;
665 for (
const vchild&
p : cfg.all_ordered()) {
666 if(
p.first ==
"value") {
667 data.push_back(
p.second.get_parsed_config());
668 }
else if(
p.first ==
"literal") {
669 data.push_back(
p.second.get_config());
670 }
else if(
p.first ==
"split") {
671 const vconfig & split_element =
p.second;
673 std::string split_string=split_element[
"list"];
674 std::string separator_string=split_element[
"separator"];
675 std::string key_name=split_element[
"key"];
681 bool remove_empty = split_element[
"remove_empty"].to_bool();
683 char* separator = separator_string.
empty() ? nullptr : &separator_string[0];
684 if(separator_string.size() > 1){
685 ERR_NG <<
"[set_variables] [split] separator only supports 1 character, multiple passed: " << split_element[
"separator"] <<
" with " << cfg.
get_config().
debug();
688 std::vector<std::string> split_vector;
691 if(separator ==
nullptr)
695 split_vector.push_back(std::string(1, *
i));
704 data.emplace_back(key_name, *
i);
711 const std::string& mode = cfg[
"mode"];
719 merged_children.
append(ch);
721 data = {merged_children};
725 else if(mode ==
"insert")
729 else if(mode ==
"append")
740 ERR_NG <<
"Cannot do [set_variables] with invalid destination variable: " << name <<
" with " << cfg.get_config().debug();
751 if (!cfg.child(
"source")) {
752 WRN_NG <<
"No source in [store_relative_direction]";
755 if (!cfg.child(
"destination")) {
756 WRN_NG <<
"No destination in [store_relative_direction]";
759 if (!cfg.has_attribute(
"variable")) {
760 WRN_NG <<
"No variable in [store_relative_direction]";
767 std::string variable = cfg[
"variable"];
777 ERR_NG <<
"Cannot do [store_relative_direction] with invalid destination variable: " << variable <<
" with " << cfg.get_config().debug();
789 if (!cfg.child(
"source")) {
790 WRN_NG <<
"No source in [store_rotate_map_location]";
793 if (!cfg.child(
"destination")) {
794 WRN_NG <<
"No destination in [store_rotate_map_location]";
797 if (!cfg.has_attribute(
"variable")) {
798 WRN_NG <<
"No variable in [store_rotate_map_location]";
805 std::string variable = cfg[
"variable"];
806 int angle = cfg[
"angle"].to_int(1);
816 ERR_NG <<
"Cannot do [store_rotate_map_location] with invalid destination variable: " << variable <<
" with " << cfg.get_config().debug();
822 const bool remove = cfg[
"remove"].to_bool(
false);
823 const bool delay = cfg[
"delayed_variable_substitution"].to_bool(
true);
825 const std::vector<std::string> ids =
utils::split(cfg[
"id"]);
826 for (
const std::string &
id : ids) {
829 }
else if (cfg.get_children(
"source").empty() ||
830 cfg.get_children(
"target").empty() ||
831 cfg.get_children(
"filter").empty()) {
832 ERR_WML <<
"[tunnel] is missing a mandatory tag:\n"
833 << cfg.get_config().debug();
834 }
else if (cfg.get_children(
"source").size() > 1 ||
835 cfg.get_children(
"target").size() > 1 ||
836 cfg.get_children(
"filter").size() > 1) {
837 ERR_WML <<
"[tunnel] should have exactly one of each mandatory tag:\n"
838 << cfg.get_config().debug();
843 if(cfg[
"bidirectional"].to_bool(
true)) {
854 config parsed_cfg = cfg.get_parsed_config();
857 if (!to_variable.
blank())
865 new_unit->write(var);
871 ERR_NG <<
"Cannot do [unit] with invalid to_variable: " << to_variable <<
" with " << cfg.get_config().debug();
877 int side = parsed_cfg[
"side"].to_int(1);
903 ERR_WML <<
"Error occured inside [unit]: " <<
e.what();
static lg::log_domain log_engine("engine")
static lg::log_domain log_display("display")
static lg::log_domain log_wml("wml")
static lg::log_domain log_config("config")
Define actions for the game's events mechanism.
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands.
static manager & get_singleton()
Variant for storing WML attributes.
int to_int(int def=0) const
bool blank() const
Tests for an attribute that was never set.
bool empty() const
Tests for an attribute that either was never set or was set to "".
A config object defines a single node in a WML file, with access to child nodes.
void append(const config &cfg)
Append data from another config object to this one.
void remove_attribute(config_key_type key)
std::string debug() const
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.
config & add_child(config_key_type key)
void reload_map()
Updates internals that cache map size.
static display * get_singleton()
Returns the display object if a display object exists.
Holds a temporary unit that can be drawn on the map without being placed in the unit_map.
internal_ptr get_unit_ptr()
Get a copy of the internal unit pointer.
unit * get()
Get a raw pointer to the underlying unit.
void place_on_fake_unit_manager(fake_unit_manager *d)
Place this on manager's fake_units_ dequeue.
virtual const std::vector< team > & teams() const override
utils::optional< std::string > replace_map(const gamemap &r)
virtual const unit_map & units() const override
virtual const gamemap & map() const override
@ PRELOAD
the preload [event] is fired next phase: PRESTART (normal game), TURN_STARTING_WAITING (reloaded game...
@ INITIAL
creating intitial [unit]s, executing toplevel [lua] etc.
@ TURN_PLAYING
The User is controlling the game and invoking actions The game can be saved here.
variable_access_create get_variable_access_write(const std::string &varname)
returns a variable_access that can be used to change the game variables
config & get_variable_cfg(const std::string &varname)
throws invalid_variablename_exception if varname is no valid variable name.
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
static game_display * get_singleton()
void new_turn()
Update lighting settings.
void needs_rebuild(bool b)
Sets whether the screen (map visuals) needs to be rebuilt.
static map registry_
Tracks the known action handlers.
std::map< std::string, handler > map
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...
int w() const
Effective map width.
int h() const
Effective map height.
int total_width() const
Real width of the map, including borders.
int total_height() const
Real height of the map, including borders.
bool on_board(const map_location &loc) const
Tell if a location is on the map.
location_map & special_locations()
Encapsulates the map of the game.
void read(const std::string &data, const bool allow_invalid=true)
A RAII object to temporary leave the synced context like in wesnoth.synchronize_choice.
void add(const teleport_group &group)
void remove(const std::string &id)
This class encapsulates the recall list of a team.
iterator erase(iterator it)
Erase an iterator to this object.
iterator end()
end iterator
iterator begin()
begin iterator
An object to leave the synced context during draw or unsynced wml items when we don’t know whether we...
static synced_state get_synced_state()
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.
This class stores all the data for a single 'side' (in game nomenclature).
int number_of_turns() const
void modify_turns_by_wml(const std::string &mod)
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.
void set_number_of_turns_by_wml(int num)
unit_creator & allow_invalidate(bool b)
unit_creator & allow_get_village(bool b)
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)
unit_creator & allow_discover(bool b)
unit_creator & allow_show(bool b)
unit_creator & allow_rename_side(bool b)
unit_creator & allow_add_to_recall(bool b)
bool matches(const unit &u, const map_location &loc) const
Determine if *this matches filter at a specified location.
std::vector< unit_iterator > find_leaders(int side)
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.
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.
Additional functionality for a non-const variable_info.
config::child_itors insert_array(std::vector< config > children) const
void merge_array(std::vector< config > children) const
config::child_itors replace_array(std::vector< config > children) const
config::child_itors append_array(std::vector< config > children) const
Information on a WML variable.
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...
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...
maybe_const_t< config, V > & as_container() const
If instantiated with vi_policy_const, the lifetime of the returned const attribute_value reference mi...
bool explicit_index() const
A variable-expanding proxy for the config class.
std::vector< vconfig > child_list
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
const config & get_config() const
Various functions related to the creation of units (recruits, recalls, and placed units).
std::string deprecated_message(const std::string &elem_name, DEP_LEVEL level, const version_info &version, const std::string &detail)
Declarations for File-IO.
int side() const
The side this unit belongs to.
Standard logging facilities (interface).
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::string read_map(const std::string &name)
WML_HANDLER_FUNCTION(clear_global_variable,, pcfg)
Experimental data persistence.
static void on_replay_error(const std::string &message)
void remove()
Removes a tip.
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
config get_user_choice(const std::string &name, const user_choice &uch, int side=0)
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)
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,...
::tod_manager * tod_manager
fake_unit_manager * fake_units
pathfind::manager * tunnels
play_controller * controller
std::shared_ptr< wb::manager > whiteboard
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::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
@ STRIP_SPACES
REMOVE_EMPTY: remove empty elements.
std::vector< std::string > split(const config_attribute_value &val)
fake
For describing the type of faked display, if any.
std::string::const_iterator iterator
This module contains various pathfinding functions and utilities.
static void clear_global_variable(persist_context &ctx, const vconfig &pcfg)
static void set_global_variable(persist_context &ctx, const vconfig &pcfg)
void verify_and_set_global_variable(const vconfig &pcfg)
void verify_and_clear_global_variable(const vconfig &pcfg)
static void get_global_variable(persist_context &ctx, const vconfig &pcfg)
void verify_and_get_global_variable(const vconfig &pcfg)
std::shared_ptr< unit > unit_ptr
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
std::string filename
Filename.
Encapsulates the map of the game.
static DIRECTION parse_direction(const std::string &str)
static const map_location & null_location()
static std::string write_direction(DIRECTION dir)
Interface for querying local choices.
Function which doesn't take anything into account.
Function which only uses terrain, ignoring shroud, enemies, etc.
Structure which holds a single route between one location and another.
std::vector< map_location > steps
Helper class, don't construct this directly.
unit_type_data unit_types
Display units performing various actions: moving, attacking, and dying.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...