69 #include <boost/assign/list_of.hpp>
70 #include <boost/scoped_ptr.hpp>
71 #include <boost/regex.hpp>
74 #define DBG_NG LOG_STREAM(debug, log_engine)
75 #define LOG_NG LOG_STREAM(info, log_engine)
76 #define WRN_NG LOG_STREAM(warn, log_engine)
77 #define ERR_NG LOG_STREAM(err, log_engine)
80 #define DBG_DP LOG_STREAM(debug, log_display)
81 #define LOG_DP LOG_STREAM(info, log_display)
84 #define LOG_WML LOG_STREAM(info, log_wml)
85 #define WRN_WML LOG_STREAM(warn, log_wml)
86 #define ERR_WML LOG_STREAM(err, log_wml)
89 #define ERR_CF LOG_STREAM(err, log_config)
109 int x = cfg[
"x"].to_int(defaultx) - 1;
110 int y = cfg[
"y"].to_int(defaulty) - 1;
121 size_t side_num = cfg[
"side"].to_int(1);
130 if(!variation.empty()) {
133 effect[
"apply_to"] =
"variation";
134 effect[
"name"] = variation;
135 fake->add_modification(
"variation",mod);
138 if(!img_mods.empty()) {
141 effect[
"apply_to"] =
"image_mod";
142 effect[
"add"] = img_mods;
143 fake->add_modification(
"image_mod",mod);
149 std::vector<map_location> fake_unit_path(
const unit& fake_unit,
const std::vector<std::string>& xvals,
const std::vector<std::string>& yvals)
152 std::vector<map_location>
path;
155 for(
size_t i = 0;
i != std::min(xvals.size(),yvals.size()); ++
i) {
157 src.
x = std::stoi(xvals[
i])-1;
158 src.
y = std::stoi(yvals[i])-1;
160 ERR_CF <<
"invalid move_unit_fake source: " << src <<
'\n';
171 dst.
x = std::stoi(xvals[
i])-1;
172 dst.
y = std::stoi(yvals[i])-1;
174 ERR_CF <<
"invalid move_unit_fake destination: " << dst <<
'\n';
179 game_map->
w(), game_map->
h());
181 if (route.
steps.empty()) {
182 WRN_NG <<
"Could not find move_unit_fake route from " << src <<
" to " << dst <<
": ignoring complexities" << std::endl;
186 game_map->
w(), game_map->
h());
187 if(route.
steps.empty()) {
191 WRN_NG <<
"Could not find move_unit_fake route from " << src <<
" to " << dst <<
": ignoring terrain" << std::endl;
193 route =
a_star_search(src, dst, 10000, &calc, game_map->
w(), game_map->
h());
194 assert(!route.
steps.empty());
200 path.insert(path.end(),
249 #define WML_HANDLER_FUNCTION(pname, pei, pcfg) \
250 static void wml_func_##pname(const queued_event &pei, const vconfig &pcfg); \
251 static wml_action wml_action_##pname(#pname, &wml_func_##pname); \
252 static void wml_func_##pname(const queued_event& pei, const vconfig& pcfg)
265 ERR_NG <<
"Error via [do_command]:" << std::endl;
266 ERR_NG << message << std::endl;
279 ERR_NG <<
"[do_command] called while whiteboard is applied, ignoring" << std::endl;
283 static const std::set<std::string> allowed_tags = {
"attack",
"move",
"recruit",
"recall",
"disband",
"fire_event",
"lua_ai"};
288 ERR_NG <<
"[do_command] called too early, only allowed at START or later" << std::endl;
293 if(allowed_tags.find(
i.get_key()) == allowed_tags.end()) {
294 ERR_NG <<
"unsupported tag [" <<
i.get_key() <<
"] in [do_command]" << std::endl;
296 std::copy(allowed_tags.begin(), allowed_tags.end(), std::ostream_iterator<std::string>(o,
" "));
297 ERR_NG <<
"allowed tags: " << o.str() << std::endl;
304 i.get_child().get_parsed_config(),
327 }
else if(!value.
empty()) {
331 if(!current.
empty()) {
332 const unsigned int current_turn_number = tod_man.
turn();
333 int new_turn_number = current.
to_int(current_turn_number);
334 const unsigned int new_turn_number_u =
static_cast<unsigned int>(new_turn_number);
336 ERR_NG <<
"attempted to change current turn number to one out of range (" << new_turn_number <<
")" << std::endl;
337 }
else if(new_turn_number_u != current_turn_number) {
349 if(!dummy_unit.
get())
352 const bool force_scroll = cfg[
"force_scroll"].to_bool(
true);
360 const std::vector<map_location>&
path = fake_unit_path(*dummy_unit, xvals, yvals);
369 LOG_NG <<
"Processing [move_units_fake]\n";
372 size_t num_units = unit_cfgs.size();
373 std::vector<fake_unit_ptr >
units;
374 units.reserve(num_units);
375 std::vector<std::vector<map_location> > paths;
376 paths.reserve(num_units);
378 LOG_NG <<
"Moving " << num_units <<
" units\n";
380 size_t longest_path = 0;
385 int skip_steps =
config[
"skip_steps"];
388 paths.push_back(fake_unit_path(*u, xvals, yvals));
390 paths.back().insert(paths.back().begin(), skip_steps, paths.back().front());
391 longest_path = std::max(longest_path, paths.back().size());
392 DBG_NG <<
"Path " << paths.size() - 1 <<
" has length " << paths.back().size() <<
'\n';
394 u->set_location(paths.back().front());
398 LOG_NG <<
"Units placed, longest path is " << longest_path <<
" long\n";
400 std::vector<map_location> path_step(2);
402 for(
size_t step = 1; step < longest_path; ++step) {
403 DBG_NG <<
"Doing step " << step <<
"...\n";
404 for(
size_t un = 0; un < num_units; ++un) {
405 if(step >= paths[un].
size() || paths[un][step - 1] == paths[un][step])
407 DBG_NG <<
"Moving unit " << un <<
", doing step " << step <<
'\n';
408 path_step[0] = paths[un][step - 1];
409 path_step[1] = paths[un][step];
411 units[un]->set_location(path_step[1]);
412 units[un]->anim_comp().set_standing();
416 LOG_NG <<
"Units moved\n";
422 LOG_NG <<
"recalling unit...\n";
423 config temp_config(cfg.get_config());
431 temp_config[
"x"] =
"recall";
432 temp_config[
"y"] =
"recall";
433 vconfig unit_filter_cfg(temp_config);
434 const vconfig & leader_filter = cfg.
child(
"secondary_unit");
441 DBG_NG <<
"recall list is empty when trying to recall!\n"
442 <<
"player_id: " << player_id <<
" side: " << index+1 <<
"\n";
452 DBG_NG <<
"checking unit against filter...\n";
455 DBG_NG << (*u)->id() <<
" matched the filter...\n";
457 const unit* pass_check = to_recruit.get();
458 if(!cfg[
"check_passability"].to_bool(
true)) pass_check =
nullptr;
463 DBG_NG <<
"...considering " + leader->id() +
" as the recalling leader...\n";
465 if ( lfilt(*leader) &&
467 DBG_NG <<
"...matched the leader filter and is able to recall the unit.\n";
469 loc = leader->get_location();
473 DBG_NG <<
"...valid location for the recall found. Recalling.\n";
476 cfg[
"show"].to_bool(
true), cfg[
"fire_event"].to_bool(
false),
488 DBG_NG <<
"No usable leader found, but found usable location. Recalling.\n";
492 cfg[
"fire_event"].to_bool(
false),
true,
true);
499 LOG_WML <<
"A [recall] tag with the following content failed:\n" << cfg.get_config().debug();
507 virtual config query_user(
int )
const
511 static const std::string s_simple_terrain =
"[A-Za-z\\\\\\|\\/]{1,4}";
512 static const std::string s_terrain = s_simple_terrain +
"(\\^" + s_simple_terrain +
")?";
515 static const std::string s_all =
"(" + s_prefix + s_terrain + s_sep +
")+";
516 static const boost::regex r_all(s_all);
524 if(boost::regex_match(res, r_all))
526 retv[
"map_data"] =
res;
530 virtual config random_choice(
int )
const
560 if(!cfg[
"map_file"].empty()) {
562 map.
read(file_cfg[
"map_data"].str(),
false);
564 map.
read(cfg[
"map"],
false);
568 lg::wml_error() <<
"replace_map: Unable to load map " << log_map_name << std::endl;
577 if (!cfg[
"expand"].to_bool()) {
578 lg::wml_error() <<
"replace_map: Map dimension(s) increase but expand is not set" << std::endl;
585 if (!cfg[
"shrink"].to_bool()) {
586 lg::wml_error() <<
"replace_map: Map dimension(s) decrease but shrink is not set" << std::endl;
615 ERR_NG <<
"trying to set a variable with an empty name:\n" << cfg.get_config().debug();
619 std::vector<config>
data;
620 if(cfg.has_attribute(
"to_variable"))
632 ERR_NG <<
"Cannot do [set_variables] with invalid to_variable variable: " << cfg[
"to_variable"] <<
" with " << cfg.get_config().debug() << std::endl;
635 typedef std::pair<std::string, vconfig> vchild;
636 for (
const vchild&
p : cfg.all_ordered()) {
637 if(
p.first ==
"value") {
638 data.push_back(
p.second.get_parsed_config());
639 }
else if(
p.first ==
"literal") {
640 data.push_back(
p.second.get_config());
641 }
else if(
p.first ==
"split") {
642 const vconfig & split_element =
p.second;
645 std::string separator_string=split_element[
"separator"];
652 bool remove_empty = split_element[
"remove_empty"].to_bool();
654 char* separator = separator_string.
empty() ?
nullptr : &separator_string[0];
656 std::vector<std::string> split_vector;
659 if(separator ==
nullptr)
686 for (
const config &cfg : data) {
687 merged_children.
append(cfg);
689 data = boost::assign::list_of(merged_children).convert_to_container<std::vector<config> >();
693 else if(mode ==
"insert")
697 else if(mode ==
"append")
708 ERR_NG <<
"Cannot do [set_variables] with invalid destination variable: " << name <<
" with " << cfg.get_config().debug() << std::endl;
717 if (!cfg.child(
"source")) {
718 WRN_NG <<
"No source in [store_relative_direction]" << std::endl;
721 if (!cfg.child(
"destination")) {
722 WRN_NG <<
"No destination in [store_relative_direction]" << std::endl;
725 if (!cfg.has_attribute(
"variable")) {
726 WRN_NG <<
"No variable in [store_relative_direction]" << std::endl;
743 ERR_NG <<
"Cannot do [store_relative_direction] with invalid destination variable: " << variable <<
" with " << cfg.get_config().debug() << std::endl;
753 if (!cfg.child(
"source")) {
754 WRN_NG <<
"No source in [store_rotate_map_location]" << std::endl;
757 if (!cfg.child(
"destination")) {
758 WRN_NG <<
"No destination in [store_rotate_map_location]" << std::endl;
761 if (!cfg.has_attribute(
"variable")) {
762 WRN_NG <<
"No variable in [store_rotate_map_location]" << std::endl;
770 int angle = cfg[
"angle"].to_int(1);
776 dst.rotate_right_around_center(src,angle).write(store.
as_container());
780 ERR_NG <<
"Cannot do [store_rotate_map_location] with invalid destination variable: " << variable <<
" with " << cfg.get_config().debug() << std::endl;
791 int turn = cfg[
"turn"];
796 if(variable.empty()) {
797 variable =
"time_of_day";
806 ERR_NG <<
"Found invalid variablename " << variable <<
" in [store_time_of_day] with " << cfg.get_config().debug() <<
"\n";
817 bool border = cfg[
"border"].to_bool(
true);
820 if(!cfg[
"mask_file"].empty()) {
829 mask_map.
read(cfg[
"mask"],
false, border);
832 ERR_NG <<
"terrain mask is in the incorrect format, and couldn't be applied" << std::endl;
844 const bool remove = cfg[
"remove"].to_bool(
false);
850 }
else if (cfg.get_children(
"source").empty() ||
851 cfg.get_children(
"target").empty() ||
852 cfg.get_children(
"filter").empty()) {
853 ERR_WML <<
"[tunnel] is missing a mandatory tag:\n"
854 << cfg.get_config().debug();
859 if(cfg[
"bidirectional"].to_bool(
true)) {
869 config parsed_cfg = cfg.get_parsed_config();
872 if (!to_variable.
blank())
875 unit new_unit(parsed_cfg,
true);
886 ERR_NG <<
"Cannot do [unit] with invalid to_variable: " << to_variable <<
" with " << cfg.get_config().debug() << std::endl;
892 int side = parsed_cfg[
"side"].to_int(1);
896 ERR_NG <<
"wrong side in [unit] tag - no such side: "<<side<<
" ( number of teams :"<<
resources::teams->size()<<
")"<<std::endl;
926 rel = atof(music.c_str());
927 if (rel >= 0.0
f && rel < 100.0
f) {
928 vol =
static_cast<int>(rel*vol/100.0f);
935 rel = atof(sound.c_str());
936 if (rel >= 0.0
f && rel < 100.0
f) {
937 vol =
static_cast<int>(rel*vol/100.0f);
946 if(cfg[
"delayed_variable_substitution"].to_bool(
false)) {
955 if(cfg[
"delayed_variable_substitution"].to_bool(
false)) {
int total_width() const
Real width of the map, including borders.
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 explicit_index() const
Doesn't throw.
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)
void remove_attribute(const std::string &key)
variable_info_detail::maybe_const< vit, config::attribute_value >::type & as_scalar() const
might throw invalid_variablename_exception NOTE: If vit == vit_const, then the lifime of the returned...
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator *calc, const size_t width, const size_t height, const teleport_map *teleports, bool border)
static void get_global_variable(persist_context &ctx, const vconfig &pcfg)
place_recruit_result place_recruit(unit_ptr u, const map_location &recruit_location, const map_location &recruited_from, int cost, bool is_recall, bool show, bool fire_event, bool full_movement, bool wml_triggered)
static thandler * handler
::tod_manager * tod_manager
std::vector< unit_iterator > find_leaders(int side)
Function which doesn't take anything into account.
variable_info_detail::maybe_const< vit, config::child_itors >::type as_array() const
might throw invalid_variablename_exception
void merge_array(std::vector< config > childs) const
merges might throw invalid_variablename_exception
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).
unit_creator & allow_invalidate(bool b)
static void set_global_variable(persist_context &ctx, const vconfig &pcfg)
unit_creator & allow_show(bool b)
Various functions that implement attacks and attack calculations.
void remove(const std::string &id)
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.
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
GLuint GLuint GLsizei GLenum type
static void raise_map_changed()
Notifies all observers of 'ai_map_changed' event.
void place_on_fake_unit_manager(fake_unit_manager *d)
Place this on manager's fake_units_ dequeue.
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
Extends variable_info with methods that can only be applied if vit != vit_const.
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.
config::child_itors replace_array(std::vector< config > childs) const
void show(CVideo &video)
Shows the error in a dialog.
unit_creator & allow_discover(bool b)
REMOVE_EMPTY : remove empty elements.
static void on_replay_error(const std::string &message, bool)
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.
static void add_redo_commands(const config &commands, const game_events::queued_event &ctx)
void overlay_map(const gamemap &o, const config &cfg, map_location loc, bool border)
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
static lg::log_domain log_config("config")
void verify_and_set_global_variable(const vconfig &pcfg)
void write(config &cfg) const
GLint GLint GLint GLint GLint GLint y
Audio output for sound and music.
std::string debug() const
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
bool empty() const
Tests for an attribute that either was never set or was set to "".
unit_creator & allow_add_to_recall(bool b)
void new_turn()
Update lighting settings.
Variant for storing WML attributes.
int total_height() const
Real height of the map, including borders.
bool blank() const
Tests for an attribute that was never set.
STRIP_SPACES : strips leading and trailing blank spaces.
Object which defines a time of day with associated bonuses, image, sounds etc.
This class stores all the data for a single 'side' (in game nomenclature).
GLsizei const char ** path
std::vector< map_location > steps
void set_number_of_turns_by_wml(int num)
std::vector< team > * teams
Structure which holds a single route between one location and another.
bool matches(const unit &u, const map_location &loc) const
Determine if *this matches filter at a specified location.
filter_context * filter_con
variable_access_create get_variable_access_write(const std::string &varname)
returns a variable_access that can be used to change the game variables
GLsizei const GLfloat * value
int w() const
Effective map width.
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)
config & add_child(const std::string &key)
fake_unit_manager * fake_units
Managing the AIs lifecycle - headers.
Function which only uses terrain, ignoring shroud, enemies, etc.
iterator end()
end iterator
static const map_location & null_location()
void needs_rebuild(bool b)
Sets whether the screen (map visuals) needs to be rebuilt. This is typically after the map has been c...
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
void set_sound_volume(int vol)
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
void read(const std::string &data, const bool allow_invalid=true, const int border_size=1)
GLuint GLuint GLsizei count
void set_music_volume(int vol)
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.
static map registry_
Tracks the known action handlers.
Various functions related to the creation of units (recruits, recalls, and placed units)...
Define conditionals for the game's events mechanism, a.k.a.
unit * get()
Get a raw pointer to the underlying unit.
variable_info_detail::maybe_const< vit, config >::type & as_container() const
might throw invalid_variablename_exception
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
int h() const
Effective map height.
std::string get_wml_location(const std::string &filename, const std::string ¤t_dir=std::string())
Returns a complete path to the actual WML file or directory or an empty string if the file isn't pres...
unit_creator & allow_get_village(bool b)
Define the game's event mechanism.
Information on a WML variable.
GLint GLint GLint GLint GLint x
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 lg::log_domain log_display("display")
Declarations for File-IO.
GLuint const GLchar * name
const attribute_value * get(const std::string &key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
virtual const gamemap & map() const
iterator erase(iterator it)
Erase an iterator to this object.
GLint GLint GLsizei GLsizei GLsizei GLint border
bool on_board(const map_location &loc) const
Tell if a location is on the map.
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) ...
void add(const teleport_group &group)
boost::optional< std::string > replace_map(const gamemap &r)
boost::intrusive_ptr< unit > unit_ptr
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.
A variable-expanding proxy for the config class.
Standard logging facilities (interface).
config::child_itors insert_array(std::vector< config > childs) const
static lg::log_domain log_engine("engine")
GLsizei GLenum GLuint GLuint GLsizei char * message
int to_int(int def=0) const
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.
boost::shared_ptr< wb::manager > whiteboard
config::child_itors append_array(std::vector< config > childs) const
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
static void clear_global_variable(persist_context &ctx, const vconfig &pcfg)
std::vector< vconfig > child_list
static lg::log_domain log_wml("wml")
void write(config &cfg) const
A config object defines a single node in a WML file, with access to child nodes.
Helper class, don't construct this directly.
bool file_exists(const std::string &name)
Returns true if a file or directory with such name already exists.
This module contains various pathfinding functions and utilities.
static std::string write_direction(DIRECTION dir)
pathfind::manager * tunnels
GLsizei const GLcharARB ** string
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.
void verify_and_clear_global_variable(const vconfig &pcfg)
int number_of_turns() const