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());
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";
297 if(is_unsynced && !is_during_turn)
299 ERR_NG <<
"[do_command] can only be used during a turn when a user woudl also be able to invoke commands";
304 ERR_NG <<
"[do_command] cannot invoke synced commands while commands are blocked";
309 ERR_NG <<
"[do_command] can only be used from clients that control the currently playing side";
312 for(
const auto& [key, child] : cfg.all_ordered())
314 if(allowed_tags.find(key) == allowed_tags.end()) {
315 ERR_NG <<
"unsupported tag [" << key <<
"] in [do_command]";
317 std::copy(allowed_tags.begin(), allowed_tags.end(), std::ostream_iterator<std::string>(o,
" "));
318 ERR_NG <<
"allowed tags: " << o.str();
328 child.get_parsed_config(),
349 std::string add = cfg[
"add"];
354 }
else if(!value.
empty()) {
358 if(!current.empty()) {
359 const unsigned int current_turn_number = tod_man.
turn();
360 int new_turn_number = current.to_int(current_turn_number);
361 const unsigned int new_turn_number_u =
static_cast<unsigned int>(new_turn_number);
363 ERR_NG <<
"attempted to change current turn number to one out of range (" << new_turn_number <<
")";
364 }
else if(new_turn_number_u != current_turn_number) {
380 if(!dummy_unit.
get())
383 const bool force_scroll = cfg[
"force_scroll"].to_bool(
true);
385 const std::string x = cfg[
"x"];
386 const std::string y = cfg[
"y"];
391 const std::vector<map_location>&
path = fake_unit_path(*dummy_unit, xvals, yvals);
402 LOG_NG <<
"Processing [move_units_fake]";
404 const bool force_scroll = cfg[
"force_scroll"].to_bool();
406 std::size_t num_units = unit_cfgs.size();
407 std::vector<fake_unit_ptr > units;
408 units.reserve(num_units);
409 std::vector<std::vector<map_location>> paths;
410 paths.reserve(num_units);
412 LOG_NG <<
"Moving " << num_units <<
" units";
414 std::size_t longest_path = 0;
419 int skip_steps =
config[
"skip_steps"];
422 paths.push_back(fake_unit_path(*u, xvals, yvals));
424 paths.back().insert(paths.back().begin(), skip_steps, paths.back().front());
425 longest_path = std::max(longest_path, paths.back().size());
426 DBG_NG <<
"Path " << paths.size() - 1 <<
" has length " << paths.back().size();
428 u->set_location(paths.back().front());
432 LOG_NG <<
"Units placed, longest path is " << longest_path <<
" long";
434 std::vector<map_location> path_step(2);
436 for(std::size_t step = 1; step < longest_path; ++step) {
437 DBG_NG <<
"Doing step " << step <<
"...";
438 for(std::size_t un = 0; un < num_units; ++un) {
439 if(step >= paths[un].
size() || paths[un][step - 1] == paths[un][step])
441 DBG_NG <<
"Moving unit " << un <<
", doing step " << step;
442 path_step[0] = paths[un][step - 1];
443 path_step[1] = paths[un][step];
445 units[un]->set_location(path_step[1]);
446 units[un]->anim_comp().set_standing(
false);
461 LOG_NG <<
"recalling unit...";
462 config temp_config(cfg.get_config());
470 temp_config[
"x"] =
"recall";
471 temp_config[
"y"] =
"recall";
473 vconfig unit_filter_cfg(temp_config);
474 const vconfig & leader_filter = cfg.
child(
"secondary_unit");
481 DBG_NG <<
"recall list is empty when trying to recall!";
482 DBG_NG <<
"player_id: " << player_id <<
" side: " <<
index+1;
492 DBG_NG <<
"checking unit against filter...";
495 DBG_NG << (*u)->id() <<
" matched the filter...";
497 const unit* pass_check = to_recruit.get();
498 if(!cfg[
"check_passability"].to_bool(
true)) pass_check =
nullptr;
500 if(cfg.has_attribute(
"location_id")) {
502 const auto& iter = special_locs.find(cfg[
"location_id"]);
503 if(iter != special_locs.end()) {
504 cfg_loc = iter->second;
509 DBG_NG <<
"...considering " + leader->id() +
" as the recalling leader...";
511 if ( lfilt(*leader) &&
513 DBG_NG <<
"...matched the leader filter and is able to recall the unit.";
515 loc = leader->get_location();
519 DBG_NG <<
"...valid location for the recall found. Recalling.";
523 cfg[
"show"].to_bool(
true), cfg[
"fire_event"].to_bool(
false),
535 DBG_NG <<
"No usable leader found, but found usable location. Recalling.";
540 cfg[
"show"].to_bool(
true), cfg[
"fire_event"].to_bool(
false),
548 LOG_WML <<
"A [recall] tag with the following content failed:\n" << cfg.get_config().debug();
554 map_choice(
const std::string& filename) :
filename_(filename) {}
556 virtual config query_user(
int )
const override
559 return config {
"map_data", res};
561 virtual config random_choice(
int )
const override
565 virtual std::string description()
const override
569 virtual bool is_visible()
const override
597 if(!cfg[
"map_file"].empty()) {
599 map.
read(file_cfg[
"map_data"].str(),
false);
600 }
else if(!cfg[
"map_data"].empty()) {
601 map.
read(cfg[
"map_data"],
false);
604 map.
read(cfg[
"map"],
false);
607 const std::string log_map_name = cfg[
"map"].empty() ? cfg[
"map_file"] : std::string(
"from inline data");
608 lg::log_to_chat() <<
"replace_map: Unable to load map " << log_map_name <<
'\n';
609 ERR_WML <<
"replace_map: Unable to load map " << log_map_name;
618 if (!cfg[
"expand"].to_bool()) {
619 lg::log_to_chat() <<
"replace_map: Map dimension(s) increase but expand is not set\n";
620 ERR_WML <<
"replace_map: Map dimension(s) increase but expand is not set";
627 if (!cfg[
"shrink"].to_bool()) {
628 lg::log_to_chat() <<
"replace_map: Map dimension(s) decrease but shrink is not set\n";
629 ERR_WML <<
"replace_map: Map dimension(s) decrease but shrink is not set";
661 ERR_NG <<
"trying to set a variable with an empty name:\n" << cfg.get_config().debug();
665 std::vector<config>
data;
666 if(cfg.has_attribute(
"to_variable"))
678 ERR_NG <<
"Cannot do [set_variables] with invalid to_variable variable: " << cfg[
"to_variable"] <<
" with " << cfg.get_config().debug();
681 typedef std::pair<std::string, vconfig> vchild;
682 for (
const vchild&
p : cfg.all_ordered()) {
683 if(
p.first ==
"value") {
684 data.push_back(
p.second.get_parsed_config());
685 }
else if(
p.first ==
"literal") {
686 data.push_back(
p.second.get_config());
687 }
else if(
p.first ==
"split") {
688 const vconfig & split_element =
p.second;
690 std::string split_string=split_element[
"list"];
691 std::string separator_string=split_element[
"separator"];
692 std::string key_name=split_element[
"key"];
698 bool remove_empty = split_element[
"remove_empty"].to_bool();
700 char* separator = separator_string.
empty() ? nullptr : &separator_string[0];
701 if(separator_string.size() > 1){
702 ERR_NG <<
"[set_variables] [split] separator only supports 1 character, multiple passed: " << split_element[
"separator"] <<
" with " << cfg.
get_config().
debug();
705 std::vector<std::string> split_vector;
708 if(separator ==
nullptr)
712 split_vector.push_back(std::string(1, *
i));
721 data.emplace_back(key_name, *
i);
728 const std::string& mode = cfg[
"mode"];
736 merged_children.
append(ch);
738 data = {merged_children};
742 else if(mode ==
"insert")
746 else if(mode ==
"append")
757 ERR_NG <<
"Cannot do [set_variables] with invalid destination variable: " << name <<
" with " << cfg.get_config().debug();
768 if (!cfg.child(
"source")) {
769 WRN_NG <<
"No source in [store_relative_direction]";
772 if (!cfg.child(
"destination")) {
773 WRN_NG <<
"No destination in [store_relative_direction]";
776 if (!cfg.has_attribute(
"variable")) {
777 WRN_NG <<
"No variable in [store_relative_direction]";
784 std::string variable = cfg[
"variable"];
794 ERR_NG <<
"Cannot do [store_relative_direction] with invalid destination variable: " << variable <<
" with " << cfg.get_config().debug();
806 if (!cfg.child(
"source")) {
807 WRN_NG <<
"No source in [store_rotate_map_location]";
810 if (!cfg.child(
"destination")) {
811 WRN_NG <<
"No destination in [store_rotate_map_location]";
814 if (!cfg.has_attribute(
"variable")) {
815 WRN_NG <<
"No variable in [store_rotate_map_location]";
822 std::string variable = cfg[
"variable"];
823 int angle = cfg[
"angle"].to_int(1);
833 ERR_NG <<
"Cannot do [store_rotate_map_location] with invalid destination variable: " << variable <<
" with " << cfg.get_config().debug();
839 const bool remove = cfg[
"remove"].to_bool(
false);
840 const bool delay = cfg[
"delayed_variable_substitution"].to_bool(
true);
842 const std::vector<std::string> ids =
utils::split(cfg[
"id"]);
843 for (
const std::string &
id : ids) {
846 }
else if (cfg.get_children(
"source").empty() ||
847 cfg.get_children(
"target").empty() ||
848 cfg.get_children(
"filter").empty()) {
849 ERR_WML <<
"[tunnel] is missing a mandatory tag:\n"
850 << cfg.get_config().debug();
855 if(cfg[
"bidirectional"].to_bool(
true)) {
866 config parsed_cfg = cfg.get_parsed_config();
869 if (!to_variable.
blank())
877 new_unit->write(var);
883 ERR_NG <<
"Cannot do [unit] with invalid to_variable: " << to_variable <<
" with " << cfg.get_config().debug();
889 int side = parsed_cfg[
"side"].to_int(1);
915 if(cfg[
"delayed_variable_substitution"].to_bool(
false)) {
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.
Various functions that implement attacks and attack calculations.
Various functions related to moving units.
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
std::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 void add_undo_commands(const config &commands, const game_events::queued_event &ctx)
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
Define conditionals for the game's events mechanism, a.k.a.
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 index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
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
Define the game's event mechanism.
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
Encapsulates the map of the game.
static DIRECTION parse_direction(const std::string &str)
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
map_location rotate_right_around_center(const map_location ¢er, int k) const
static const map_location & null_location()
void write(config &cfg) const
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.
Various functions implementing vision (through fog of war and shroud).
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...