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)
51 ERR_AI_CONFIGURATION <<
"Missing AI [default_config]. Therefore, default_config_ set to empty." << std::endl;
60 ERR_AI_CONFIGURATION <<
"skipped AI config due to missing id" <<
". Config contains:"<< std::endl << ai_configuration << std::endl;
64 ERR_AI_CONFIGURATION <<
"skipped AI config due to duplicate id [" <<
id <<
"]. Config contains:"<< std::endl << ai_configuration << std::endl;
70 desc.
text = ai_configuration[
"description"].t_str();
71 desc.
cfg=ai_configuration;
79 void extract_ai_configurations(std::map<std::string, description> &storage,
const config &
input)
85 ERR_AI_CONFIGURATION <<
"skipped AI config due to missing id" <<
". Config contains:"<< std::endl << ai_configuration << std::endl;
88 if (storage.count(
id)>0){
89 ERR_AI_CONFIGURATION <<
"skipped AI config due to duplicate id [" <<
id <<
"]. Config contains:"<< std::endl << ai_configuration << std::endl;
95 desc.text = ai_configuration[
"description"].t_str();
96 desc.cfg=ai_configuration;
98 storage.insert(std::make_pair(
id,desc));
113 for (
const config &mod : mods) {
119 std::vector<description*> ais_list;
121 ais_list.push_back(&desc->second);
125 ais_list.push_back(&desc->second);
129 ais_list.push_back(&desc->second);
145 return mod_cfg_it->second.cfg;
148 return era_cfg_it->second.cfg;
151 return cfg_it->second.cfg;
166 ERR_AI_CONFIGURATION <<
"Error while reading AI configuration from file '" << file <<
"'" << std::endl;
169 LOG_AI_CONFIGURATION <<
"Successfully read AI configuration from file '" << file <<
"'" << std::endl;
192 ai_a[
"ai_algorithm"] = *
v;
195 DBG_AI_CONFIGURATION <<
"side " << side <<
": config contains:"<< std::endl << cfg << std::endl;
202 ERR_AI_CONFIGURATION <<
"side "<< side <<
": default configuration is not available, not applying it" << std::endl;
205 LOG_AI_CONFIGURATION <<
"side "<< side <<
": expanding simplified aspects into full facets"<< std::endl;
214 parsed_cfg.
append(aiparam);
221 LOG_AI_CONFIGURATION <<
"side "<< side <<
": removing duplicate [default] tags from aspects"<< std::endl;
223 if (aspect_cfg[
"name"] !=
"composite_aspect") {
227 if (!aspect_cfg.child(
"default")) {
228 WRN_AI_CONFIGURATION <<
"side "<< side <<
": aspect with id=["<<aspect_cfg[
"id"]<<
"] lacks default config facet!" <<std::endl;
231 aspect_cfg.merge_children(
"default");
240 DBG_AI_CONFIGURATION <<
"side "<< side <<
": done parsing side config, it contains:"<< std::endl << parsed_cfg << std::endl;
248 static const std::set<std::string>
non_aspect_attributes = {
"turns",
"time_of_day",
"engine",
"ai_algorithm",
"id",
"description"};
249 static const std::set<std::string>
just_copy_tags = {
"engine",
"stage",
"aspect",
"goal",
"modify_ai"};
250 static const std::set<std::string>
old_goal_tags = {
"target",
"target_location",
"protect_unit",
"protect_location"};
254 config base_config, parsed_config;
257 if (aiparam.has_attribute(
"turns")) {
258 turns = aiparam[
"turns"].str();
260 if (aiparam.has_attribute(
"time_of_day")) {
261 time_of_day = aiparam[
"time_of_day"].str();
263 if (aiparam.has_attribute(
"engine")) {
264 engine = aiparam[
"engine"].str();
266 if (aiparam.has_attribute(
"ai_algorithm")) {
267 if (algorithm.empty()) {
268 algorithm = aiparam[
"ai_algorithm"].str();
270 }
else if(algorithm != aiparam[
"ai_algorithm"]) {
271 lg::wml_error() <<
"side " << side <<
" has two [ai] tags with contradictory ai_algorithm - the first one will take precedence.\n";
274 std::deque<std::pair<std::string, config> > facet_configs;
276 if (non_aspect_attributes.count(attr.first)) {
280 facet_config[
"engine"] = engine;
281 facet_config[
"name"] =
"standard_aspect";
282 facet_config[
"turns"] =
turns;
283 facet_config[
"time_of_day"] = time_of_day;
284 facet_config[
"value"] = attr.second;
285 facet_configs.push_back(std::make_pair(attr.first, facet_config));
288 if (just_copy_tags.count(child.key)) {
290 parsed_config.
add_child(child.key, child.cfg);
292 }
else if(old_goal_tags.count(child.key)) {
294 config goal_config, criteria_config = child.cfg;
295 goal_config[
"name"] = child.key;
296 goal_config[
"turns"] =
turns;
297 goal_config[
"time_of_day"] = time_of_day;
298 if(child.key.substr(0,7) ==
"protect" && criteria_config.
has_attribute(
"protect_radius")) {
299 goal_config[
"protect_radius"] = criteria_config[
"protect_radius"];
303 goal_config[
"value"] = criteria_config[
"value"];
306 parsed_config.
add_child(
"goal", goal_config);
312 if (child.key ==
"attacks" || child.cfg.has_attribute(
"value") || child.cfg.has_child(
"value")) {
313 facet_configs.push_back(std::make_pair(child.key, child.cfg));
316 facet_config[
"engine"] = engine;
317 facet_config[
"name"] =
"standard_aspect";
318 facet_config[
"turns"] =
turns;
319 facet_config[
"time_of_day"] = time_of_day;
320 facet_config.
add_child(
"value", child.cfg);
321 if (child.key ==
"leader_goal" && !child.cfg[
"id"].empty()) {
324 if(
id !=
"*" &&
id.find_first_not_of(
"0123456789") != std::string::npos) {
325 facet_config[
"id"] = child.cfg[
"id"];
328 facet_configs.push_back(std::make_pair(child.key, facet_config));
331 std::map<std::string, config> aspect_configs;
332 while (!facet_configs.empty()) {
334 const config &facet_config = facet_configs.front().second;
335 aspect_configs[aspect][
"id"] = aspect;
336 aspect_configs[aspect][
"name"] =
"composite_aspect";
337 aspect_configs[aspect].add_child(
"facet", facet_config);
338 facet_configs.pop_front();
340 typedef std::map<std::string, config>::value_type aspect_pair;
341 for (
const aspect_pair&
p : aspect_configs) {
345 if (algorithm.empty() && !parsed_config.
has_child(
"stage")) {
349 base_config.
add_child(child.key, child.cfg);
static const std::set< std::string > non_aspect_attributes
child_itors child_range(const std::string &key)
void remove_attribute(const std::string &key)
void append(const config &cfg)
Append data from another config object to this one.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
static config default_config_
GLenum GLenum GLenum input
attribute_map::value_type attribute
static void add_mod_ai_from_config(config::const_child_itors configs)
static bool parse_side_config(side_number side, const config &cfg, config &parsed_cfg)
#define WRN_AI_CONFIGURATION
void clear_children(const std::string &key)
std::pair< const_child_iterator, const_child_iterator > const_child_itors
Variant for storing WML attributes.
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.
bool has_child(const std::string &key) const
Determine whether a config has a child or not.
A small explanation about what's going on here: Each action has access to two game_info objects First...
static description_map era_ai_configurations_
static std::vector< description * > get_available_ais()
Returns a list of available AIs.
#define LOG_AI_CONFIGURATION
all_children_itors all_children_range() const
In-order iteration over all children.
static description_map ai_configurations_
void remove_child(const std::string &key, unsigned index)
config & add_child(const std::string &key)
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
#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=std::string())
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.
void read(config &cfg, std::istream &in, abstract_validator *validator)
static description_map mod_ai_configurations_
unsigned child_count(const std::string &key) const
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.
std::istream * preprocess_file(std::string const &fname, preproc_map *defines)
bool has_attribute(const std::string &key) const
static const config & get_default_ai_parameters()
get default AI parameters
#define ERR_AI_CONFIGURATION
Managing the AIs configuration - headers.
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Standard logging facilities (interface).
static bool get_side_config_from_file(const std::string &file, config &cfg)
get side config from file
static void init(const config &game_config)
Init the parameters of ai configuration parser.
A config object defines a single node in a WML file, with access to child nodes.
static const config & get_ai_config_for(const std::string &id)
Return the config for a specified ai.
GLsizei const GLcharARB ** string
config & add_child_at(const std::string &key, const config &val, unsigned index)
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 ...