35 #define DBG_AI_CONFIGURATION LOG_STREAM(debug, log_ai_configuration) 36 #define LOG_AI_CONFIGURATION LOG_STREAM(info, log_ai_configuration) 37 #define WRN_AI_CONFIGURATION LOG_STREAM(warn, log_ai_configuration) 38 #define ERR_AI_CONFIGURATION LOG_STREAM(err, log_ai_configuration) 49 ERR_AI_CONFIGURATION <<
"Missing AI [default_config]. Therefore, default_config_ set to empty." << std::endl;
54 ERR_AI_CONFIGURATION <<
"Missing default_ai_algorithm. This will result in no AI being loaded by default." << std::endl;
59 const std::string &
id = ai_configuration[
"id"];
62 ERR_AI_CONFIGURATION <<
"skipped AI config due to missing id" <<
". Config contains:"<< std::endl << ai_configuration << std::endl;
66 ERR_AI_CONFIGURATION <<
"skipped AI config due to duplicate id [" <<
id <<
"]. Config contains:"<< std::endl << ai_configuration << std::endl;
72 desc.
mp_rank=ai_configuration[
"mp_rank"].to_int(std::numeric_limits<int>::max());
73 desc.
text = ai_configuration[
"description"].t_str();
74 desc.
cfg=ai_configuration;
82 void extract_ai_configurations(std::map<std::string, description> &storage,
const config &input)
85 const std::string &
id = ai_configuration[
"id"];
88 ERR_AI_CONFIGURATION <<
"skipped AI config due to missing id" <<
". Config contains:"<< std::endl << ai_configuration << std::endl;
91 if (storage.count(
id)>0){
92 ERR_AI_CONFIGURATION <<
"skipped AI config due to duplicate id [" <<
id <<
"]. Config contains:"<< std::endl << ai_configuration << std::endl;
98 desc.
text = ai_configuration[
"description"].t_str();
99 desc.
mp_rank = ai_configuration[
"mp_rank"].to_int(std::numeric_limits<int>::max());
100 desc.
cfg=ai_configuration;
102 storage.emplace(
id, desc);
117 for (
const config &mod : mods) {
124 std::vector<description*> ais_list;
126 const auto add_if_not_hidden = [&ais_list](
description*
d) {
129 if(!cfg[
"hidden"].to_bool(
false)) {
130 ais_list.push_back(
d);
137 add_if_not_hidden(&a_config.second);
141 add_if_not_hidden(&e_config.second);
145 add_if_not_hidden(&m_config.second);
149 std::stable_sort(ais_list.begin(), ais_list.end(),
168 return mod_cfg_it->second.cfg;
171 return era_cfg_it->second.cfg;
174 return cfg_it->second.cfg;
190 ERR_AI_CONFIGURATION <<
"Error while reading AI configuration from file '" << file <<
"'" << std::endl;
193 LOG_AI_CONFIGURATION <<
"Successfully read AI configuration from file '" << file <<
"'" << std::endl;
216 ai_a[
"ai_algorithm"] = *v;
219 DBG_AI_CONFIGURATION <<
"side " << side <<
": config contains:"<< std::endl << cfg << std::endl;
226 ERR_AI_CONFIGURATION <<
"side "<< side <<
": default configuration is not available, not applying it" << std::endl;
229 LOG_AI_CONFIGURATION <<
"side "<< side <<
": expanding simplified aspects into full facets"<< std::endl;
238 parsed_cfg.
append(aiparam);
245 LOG_AI_CONFIGURATION <<
"side "<< side <<
": removing duplicate [default] tags from aspects"<< std::endl;
247 if (aspect_cfg[
"name"] !=
"composite_aspect") {
251 if (!aspect_cfg.child(
"default")) {
252 WRN_AI_CONFIGURATION <<
"side "<< side <<
": aspect with id=["<<aspect_cfg[
"id"]<<
"] lacks default config facet!" <<std::endl;
255 aspect_cfg.merge_children(
"default");
264 DBG_AI_CONFIGURATION <<
"side "<< side <<
": done parsing side config, it contains:"<< std::endl << parsed_cfg << std::endl;
272 static const std::set<std::string>
non_aspect_attributes {
"turns",
"time_of_day",
"engine",
"ai_algorithm",
"id",
"description",
"hidden",
"mp_rank"};
273 static const std::set<std::string>
just_copy_tags {
"engine",
"stage",
"aspect",
"goal",
"modify_ai"};
274 static const std::set<std::string>
old_goal_tags {
"target",
"target_location",
"protect_unit",
"protect_location"};
277 std::string algorithm;
278 config base_config, parsed_config;
281 if (aiparam.has_attribute(
"turns")) {
282 turns = aiparam[
"turns"].str();
284 if (aiparam.has_attribute(
"time_of_day")) {
285 time_of_day = aiparam[
"time_of_day"].str();
287 if (aiparam.has_attribute(
"engine")) {
288 engine = aiparam[
"engine"].str();
290 if (aiparam.has_attribute(
"ai_algorithm")) {
291 if (algorithm.empty()) {
292 algorithm = aiparam[
"ai_algorithm"].str();
294 }
else if(algorithm != aiparam[
"ai_algorithm"]) {
295 lg::wml_error() <<
"side " << side <<
" has two [ai] tags with contradictory ai_algorithm - the first one will take precedence.\n";
298 std::deque<std::pair<std::string, config>> facet_configs;
304 facet_config[
"engine"] = engine;
305 facet_config[
"name"] =
"standard_aspect";
306 facet_config[
"turns"] =
turns;
307 facet_config[
"time_of_day"] = time_of_day;
308 facet_config[
"value"] = attr.second;
309 facet_configs.emplace_back(attr.first, facet_config);
314 parsed_config.
add_child(child.key, child.cfg);
318 config goal_config, criteria_config = child.cfg;
319 goal_config[
"name"] = child.key;
320 goal_config[
"turns"] =
turns;
321 goal_config[
"time_of_day"] = time_of_day;
322 if(child.key.substr(0,7) ==
"protect" && criteria_config.
has_attribute(
"protect_radius")) {
323 goal_config[
"protect_radius"] = criteria_config[
"protect_radius"];
327 goal_config[
"value"] = criteria_config[
"value"];
330 parsed_config.
add_child(
"goal", std::move(goal_config));
336 if (child.key ==
"attacks" || child.cfg.has_attribute(
"value") || child.cfg.has_child(
"value")) {
337 facet_configs.emplace_back(child.key, child.cfg);
340 facet_config[
"engine"] = engine;
341 facet_config[
"name"] =
"standard_aspect";
342 facet_config[
"turns"] =
turns;
343 facet_config[
"time_of_day"] = time_of_day;
344 facet_config.
add_child(
"value", child.cfg);
345 if (child.key ==
"leader_goal" && !child.cfg[
"id"].empty()) {
347 const std::string&
id = child.cfg[
"id"];
348 if(
id !=
"*" &&
id.find_first_not_of(
"0123456789") != std::string::npos) {
349 facet_config[
"id"] = child.cfg[
"id"];
352 facet_configs.emplace_back(child.key, facet_config);
355 std::map<std::string, config> aspect_configs;
356 while (!facet_configs.empty()) {
357 const std::string &
aspect = facet_configs.front().first;
358 const config &facet_config = facet_configs.front().second;
359 aspect_configs[aspect][
"id"] = aspect;
360 aspect_configs[aspect][
"name"] =
"composite_aspect";
361 aspect_configs[aspect].add_child(
"facet", facet_config);
362 facet_configs.pop_front();
364 typedef std::map<std::string, config>::value_type aspect_pair;
365 for (
const aspect_pair&
p : aspect_configs) {
370 for(
auto& child : parsed_config.
child_range(
"aspect")) {
371 if(child[
"id"] ==
"recruitment") {
372 child[
"id"] =
"recruitment_instructions";
375 if (algorithm.empty() && !parsed_config.
has_child(
"stage")) {
379 base_config.
add_child(child.key, child.cfg);
382 cfg.
add_child(
"ai", std::move(base_config));
static const std::set< std::string > non_aspect_attributes
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
const_all_children_itors all_children_range() const
In-order iteration over all children.
void clear_children(T... keys)
void append(const config &cfg)
Append data from another config object to this one.
Variant for storing WML attributes.
static config default_config_
bool has_attribute(config_key_type key) const
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
unsigned child_count(config_key_type key) const
static void init(const game_config_view &game_config)
Init the parameters of ai configuration parser.
child_itors child_range(config_key_type key)
attribute_map::value_type attribute
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.
static void add_mod_ai_from_config(config::const_child_itors configs)
#define WRN_AI_CONFIGURATION
void remove_attribute(config_key_type key)
static lg::log_domain log_ai_configuration("ai/config")
static const std::set< std::string > just_copy_tags
Object which defines a time of day with associated bonuses, image, sounds etc.
A small explanation about what's going on here: Each action has access to two game_info objects First...
static bool parse_side_config(side_number side, const config &original_cfg, config &cfg)
static description_map era_ai_configurations_
static std::vector< description * > get_available_ais()
Returns a list of available AIs.
void read(config &cfg, std::istream &in, abstract_validator *validator)
#define LOG_AI_CONFIGURATION
config & add_child_at(config_key_type key, const config &val, unsigned index)
static description_map ai_configurations_
std::unique_ptr< std::istream > scoped_istream
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 std::set< std::string > old_goal_tags
boost::iterator_range< const_child_iterator > const_child_itors
#define DBG_AI_CONFIGURATION
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
std::string get_wml_location(const std::string &filename, const std::string ¤t_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn't pres...
static void add_era_ai_from_config(const config &game_config)
Game configuration data as global variables.
std::map< std::string, description > description_map
Declarations for File-IO.
static description_map mod_ai_configurations_
config & add_child(config_key_type key)
static const config & get_default_ai_parameters()
get default AI parameters
#define ERR_AI_CONFIGURATION
Managing the AIs configuration - headers.
Standard logging facilities (interface).
static bool get_side_config_from_file(const std::string &file, config &cfg)
get side config from file
static std::string default_ai_algorithm_
A config object defines a single node in a WML file, with access to child nodes.
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.
static const config & get_ai_config_for(const std::string &id)
Return the config for a specified ai.
void remove_child(config_key_type key, unsigned index)
std::string::const_iterator iterator
const config & child(config_key_type key) const
void merge_children_by_attribute(const std::string &key, const std::string &attribute)
All children with the given key and with equal values of the specified attribute will be merged into ...