37 #define DBG_AI_CONFIGURATION LOG_STREAM(debug, log_ai_configuration)
38 #define LOG_AI_CONFIGURATION LOG_STREAM(info, log_ai_configuration)
39 #define WRN_AI_CONFIGURATION LOG_STREAM(warn, log_ai_configuration)
40 #define ERR_AI_CONFIGURATION LOG_STREAM(err, log_ai_configuration)
43 #define ERR_WML LOG_STREAM(err, log_wml)
60 ERR_AI_CONFIGURATION <<
"Missing default_ai_algorithm. This will result in no AI being loaded by default.";
65 const std::string &
id = ai_configuration[
"id"];
68 ERR_AI_CONFIGURATION <<
"skipped AI config due to missing id" <<
". Config contains:"<< std::endl << ai_configuration;
72 ERR_AI_CONFIGURATION <<
"skipped AI config due to duplicate id [" <<
id <<
"]. Config contains:"<< std::endl << ai_configuration;
78 desc.
mp_rank=ai_configuration[
"mp_rank"].to_int(std::numeric_limits<int>::max());
79 desc.
text = ai_configuration[
"description"].t_str();
80 desc.
cfg=ai_configuration;
88 void extract_ai_configurations(std::map<std::string, description> &storage,
const config &input)
91 const std::string &
id = ai_configuration[
"id"];
94 ERR_AI_CONFIGURATION <<
"skipped AI config due to missing id" <<
". Config contains:"<< std::endl << ai_configuration;
97 if (storage.count(
id)>0){
98 ERR_AI_CONFIGURATION <<
"skipped AI config due to duplicate id [" <<
id <<
"]. Config contains:"<< std::endl << ai_configuration;
104 desc.text = ai_configuration[
"description"].t_str();
105 desc.mp_rank = ai_configuration[
"mp_rank"].to_int(std::numeric_limits<int>::max());
106 desc.cfg=ai_configuration;
108 storage.emplace(
id, desc);
123 for (
const config &mod : mods) {
130 std::vector<description*> ais_list;
132 const auto add_if_not_hidden = [&ais_list](
description*
d) {
135 if(!cfg[
"hidden"].to_bool(
false)) {
136 ais_list.push_back(
d);
143 add_if_not_hidden(&a_config.second);
147 add_if_not_hidden(&e_config.second);
151 add_if_not_hidden(&m_config.second);
155 std::stable_sort(ais_list.begin(), ais_list.end(),
157 return a->mp_rank < b->mp_rank;
174 return mod_cfg_it->second.cfg;
177 return era_cfg_it->second.cfg;
180 return cfg_it->second.cfg;
215 ai_a[
"ai_algorithm"] = *v;
225 ERR_AI_CONFIGURATION <<
"side "<< side <<
": default configuration is not available, not applying it";
237 parsed_cfg.
append(aiparam);
246 if (aspect_cfg[
"name"] !=
"composite_aspect") {
250 if (!aspect_cfg.has_child(
"default")) {
251 WRN_AI_CONFIGURATION <<
"side "<< side <<
": aspect with id=["<<aspect_cfg[
"id"]<<
"] lacks default config facet!";
254 aspect_cfg.merge_children(
"default");
263 DBG_AI_CONFIGURATION <<
"side "<< side <<
": done parsing side config, it contains:"<< std::endl << parsed_cfg;
271 static const std::set<std::string>
non_aspect_attributes {
"turns",
"time_of_day",
"engine",
"ai_algorithm",
"id",
"description",
"hidden",
"mp_rank"};
272 static const std::set<std::string>
just_copy_tags {
"engine",
"stage",
"aspect",
"goal",
"modify_ai",
"micro_ai"};
273 static const std::set<std::string>
old_goal_tags {
"target",
"target_location",
"protect_unit",
"protect_location"};
276 std::string algorithm;
277 config base_config, parsed_config;
280 if (aiparam.has_attribute(
"turns")) {
281 turns = aiparam[
"turns"].str();
283 if (aiparam.has_attribute(
"time_of_day")) {
286 if (aiparam.has_attribute(
"engine")) {
287 engine = aiparam[
"engine"].str();
292 if (aiparam.has_attribute(
"ai_algorithm")) {
293 if (algorithm.empty()) {
294 algorithm = aiparam[
"ai_algorithm"].str();
296 }
else if(algorithm != aiparam[
"ai_algorithm"]) {
297 lg::log_to_chat() <<
"side " << side <<
" has two [ai] tags with contradictory ai_algorithm - the first one will take precedence.\n";
298 ERR_WML <<
"side " << side <<
" has two [ai] tags with contradictory ai_algorithm - the first one will take precedence.";
301 std::deque<std::pair<std::string, config>> facet_configs;
302 for(
const auto& [key, value] : aiparam.attribute_range()) {
307 facet_config[
"engine"] =
engine;
308 facet_config[
"name"] =
"standard_aspect";
309 facet_config[
"turns"] = turns;
311 facet_config[
"value"] = value;
312 facet_configs.emplace_back(key, facet_config);
314 for(
const auto [child_key, child_cfg] : aiparam.all_children_view()) {
317 parsed_config.
add_child(child_key, child_cfg);
319 (child_key !=
"modify_ai" && child_cfg[
"engine"] ==
"fai") ||
320 (child_key ==
"modify_ai" && child_cfg.all_children_count() > 0 && child_cfg.all_children_range().front().cfg[
"engine"] ==
"fai")
327 config goal_config, criteria_config = child_cfg;
328 goal_config[
"name"] = child_key;
329 goal_config[
"turns"] = turns;
331 if(child_key.substr(0,7) ==
"protect" && criteria_config.
has_attribute(
"protect_radius")) {
332 goal_config[
"protect_radius"] = criteria_config[
"protect_radius"];
336 goal_config[
"value"] = criteria_config[
"value"];
339 goal_config.
add_child(
"criteria", criteria_config);
340 parsed_config.
add_child(
"goal", std::move(goal_config));
346 if (child_key ==
"attacks" || child_cfg.has_attribute(
"value") || child_cfg.has_child(
"value")) {
347 facet_configs.emplace_back(child_key, child_cfg);
350 facet_config[
"engine"] =
engine;
351 facet_config[
"name"] =
"standard_aspect";
352 facet_config[
"turns"] = turns;
354 facet_config.
add_child(
"value", child_cfg);
355 if (child_key ==
"leader_goal" && !child_cfg[
"id"].empty()) {
357 const std::string&
id = child_cfg[
"id"];
358 if(
id !=
"*" &&
id.find_first_not_of(
"0123456789") != std::string::npos) {
359 facet_config[
"id"] = child_cfg[
"id"];
362 facet_configs.emplace_back(child_key, facet_config);
365 std::map<std::string, config> aspect_configs;
366 while (!facet_configs.empty()) {
367 const std::string &
aspect = facet_configs.front().first;
368 const config &facet_config = facet_configs.front().second;
370 aspect_configs[
aspect][
"name"] =
"composite_aspect";
372 facet_configs.pop_front();
374 typedef std::map<std::string, config>::value_type aspect_pair;
375 for (
const aspect_pair&
p : aspect_configs) {
380 for(
auto& child : parsed_config.
child_range(
"aspect")) {
381 if(child[
"id"] ==
"recruitment") {
383 child[
"id"] =
"recruitment_instructions";
386 if (algorithm.empty() && !parsed_config.
has_child(
"stage")) {
390 base_config.
add_child(child_key, child_cfg);
393 cfg.
add_child(
"ai", std::move(base_config));
virtual bool add_child(const path_element &child, const config &cfg)
static void add_mod_ai_from_config(config::const_child_itors configs)
static description_map ai_configurations_
static config default_config_
static std::vector< description * > get_available_ais()
Returns a list of available AIs.
static description_map era_ai_configurations_
static bool get_side_config_from_file(const std::string &file, config &cfg)
get side config from file
static std::string default_ai_algorithm_
static void init(const game_config_view &game_config)
Init the parameters of ai configuration parser.
static const config & get_ai_config_for(const std::string &id)
Return the config for a specified ai.
static bool parse_side_config(side_number side, const config &original_cfg, config &cfg)
static void add_era_ai_from_config(const config &game_config)
static void expand_simplified_aspects(side_number side, config &cfg)
Expand simplified aspects, similar to the change from 1.7.2 to 1.7.3 but with some additional syntax ...
static const config & get_default_ai_parameters()
get default AI parameters
static description_map mod_ai_configurations_
Variant for storing WML attributes.
A config object defines a single node in a WML file, with access to child nodes.
void merge_children_by_attribute(config_key_type key, config_key_type attribute)
All children with the given key and with equal values of the specified attribute will be merged into ...
void append(const config &cfg)
Append data from another config object to this one.
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
void remove_child(config_key_type key, std::size_t index)
std::size_t child_count(config_key_type key) const
auto all_children_view() const
In-order iteration over all children.
config & add_child_at(config_key_type key, const config &val, std::size_t index)
void clear_children(T... keys)
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
bool has_attribute(config_key_type key) const
child_itors child_range(config_key_type key)
void remove_attribute(config_key_type key)
boost::iterator_range< const_child_iterator > const_child_itors
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.
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
A class grating read only view to a vector of config objects, viewed as one config with all children ...
#define DBG_AI_CONFIGURATION
#define ERR_AI_CONFIGURATION
#define LOG_AI_CONFIGURATION
#define WRN_AI_CONFIGURATION
Managing the AIs configuration - headers.
std::string deprecated_message(const std::string &elem_name, DEP_LEVEL level, const version_info &version, const std::string &detail)
Declarations for File-IO.
std::string id
Text to match against addon_info.tags()
Standard logging facilities (interface).
A small explanation about what's going on here: Each action has access to two game_info objects First...
static const std::set< std::string > non_aspect_attributes
static const std::set< std::string > old_goal_tags
static lg::log_domain log_wml("wml")
static const std::set< std::string > just_copy_tags
static lg::log_domain log_ai_configuration("ai/config")
utils::optional< std::string > get_wml_location(const std::string &path, const utils::optional< std::string > ¤t_dir)
Returns a translated path to the actual file or directory, if it exists.
std::unique_ptr< std::istream > scoped_istream
Game configuration data as global variables.
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
std::string::const_iterator iterator
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.
void read(config &cfg, std::istream &in, abstract_validator *validator)
Object which defines a time of day with associated bonuses, image, sounds etc.