From 62207d89e96e47742d2624065a85bcbb91407c60 Mon Sep 17 00:00:00 2001 From: Pauli Nieminen Date: Mon, 1 Sep 2008 17:33:32 +0000 Subject: [PATCH] Fixed loading ai parameters. MP side defination now overwrites era values (bug #12171) --- changelog | 2 ++ src/ai.cpp | 20 ++++++++----- src/team.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++---------- src/team.hpp | 18 +++++++++--- 4 files changed, 94 insertions(+), 25 deletions(-) diff --git a/changelog b/changelog index 57f601d4354..87fd5a9bd0f 100644 --- a/changelog +++ b/changelog @@ -56,6 +56,8 @@ Version 1.5.3+svn: * Fixed [modify_turns] not updating $turn_number when current= was used. * Fixed crash when ai moves units next to level 0 hiden unit (bug #12252) + * Fixed loading ai parameters. MP side defination now overwrites + era values (bug #12171) * Fixed a few inconsistencies related to scenarios which are not at turn 1 at the beginning (namely start autosave detection and initial triggering of a matching "turn *" event). diff --git a/src/ai.cpp b/src/ai.cpp index f9f63539c05..ccb954c0aef 100644 --- a/src/ai.cpp +++ b/src/ai.cpp @@ -336,12 +336,12 @@ bool ai::recruit_usage(const std::string& usage) // If usage is empty consider any unit. LOG_AI << name << " considered\n"; if (i->second.usage() == usage || usage == "") { - found = true; LOG_AI << name << " considered for " << usage << " recruitment\n"; if (!recruits.count(name)) { LOG_AI << name << " rejected, not in recruitment list\n"; continue; } + found = true; if (current_team().gold() - i->second.cost() < min_gold) { LOG_AI << name << " rejected, cost too high (cost: " << i->second.cost() << ", current gold: " << current_team().gold() <<", min_gold: " << min_gold << ")\n"; @@ -369,6 +369,12 @@ bool ai::recruit_usage(const std::string& usage) } else { WRN_AI << "Trying to recruit a: " << usage << " but no unit of that type (usage=) is available.\n"; + + if (usage != "") + { + return current_team().remove_recruitment_pattern_entry(usage); + // remove this recruitment pattern and try again + } } return false; } @@ -1841,12 +1847,12 @@ void ai::do_recruitment() // If there is no recruitment_pattern use "" which makes us consider // any unit available. - if (options.empty()) { - options.push_back(""); - } - // Buy units as long as we have room and can afford it. - while(recruit_usage(options[rand()%options.size()])) { - } + do { + if (options.empty()) { + options.push_back(""); + } + // Buy units as long as we have room and can afford it. + }while(recruit_usage(options[rand()%options.size()])); } void ai::move_leader_to_goals( const move_map& enemy_dstsrc) diff --git a/src/team.cpp b/src/team.cpp index 7dd2de2d2f6..57c6d6c0468 100644 --- a/src/team.cpp +++ b/src/team.cpp @@ -79,7 +79,7 @@ team::team_info::team_info(const config& cfg) : income(cfg["income"]), income_per_village(), can_recruit(), - global_recruitment_pattern(), + global_recruitment_pattern(utils::split(cfg["global_recruitment_pattern"])), recruitment_pattern(utils::split(cfg["recruitment_pattern"])), enemies(), team_name(cfg["team_name"]), @@ -100,6 +100,8 @@ team::team_info::team_info(const config& cfg) : villages_per_scout(), leader_value(0.0), village_value(0.0), + aggression_(0.5), + caution_(0.25), targets(), share_maps(false), share_view(false), @@ -109,14 +111,16 @@ team::team_info::team_info(const config& cfg) : music(cfg["music"]), colour(cfg["colour"].size() ? cfg["colour"] : cfg["side"]) { + // If are starting new scenario overide settings from [ai] tags if (!user_team_name.translatable()) user_team_name = user_team_name.from_serialized(user_team_name); config global_ai_params; const config::child_list& ai_parameters = cfg.get_children("ai"); - for(config::child_list::const_iterator aiparam = ai_parameters.begin(); aiparam != ai_parameters.end(); ++aiparam) { + for(config::child_list::const_reverse_iterator aiparam = ai_parameters.rbegin(); aiparam != ai_parameters.rend(); ++aiparam) { ai_params.push_back(**aiparam); if((**aiparam)["turns"].empty() && (**aiparam)["time_of_day"].empty()) { +// LOG_NG << "Global ai entry: " << **aiparam << "\n"; global_ai_params.append(**aiparam); } } @@ -189,13 +193,15 @@ team::team_info::team_info(const config& cfg) : else controller = AI; - if(ai_algorithm.empty()) { + if(ai_algorithm.empty() +) { ai_algorithm = global_ai_params["ai_algorithm"]; } std::string scouts_val = cfg["villages_per_scout"]; - if(scouts_val.empty()) { + if(scouts_val.empty() +) { scouts_val = global_ai_params["villages_per_scout"]; } @@ -207,7 +213,8 @@ team::team_info::team_info(const config& cfg) : std::string leader_val = cfg["leader_value"]; - if(leader_val.empty()) { + if(leader_val.empty() +) { leader_val = global_ai_params["leader_value"]; } @@ -219,7 +226,8 @@ team::team_info::team_info(const config& cfg) : std::string village_val = cfg["village_value"]; - if(village_val.empty()) { + if(village_val.empty() +) { village_val = global_ai_params["village_value"]; } @@ -229,16 +237,48 @@ team::team_info::team_info(const config& cfg) : village_value = atof(village_val.c_str()); } + std::string aggression_val = cfg["aggression"]; + + if(aggression_val.empty() +) { + aggression_val = global_ai_params["aggression"]; + } + + if(aggression_val.empty()) { + aggression_ = 0.5; + } else { + aggression_ = atof(aggression_val.c_str()); + } + + std::string caution_val = cfg["caution"]; + + if(caution_val.empty() +) { + caution_val = global_ai_params["caution"]; + } + + if(caution_val.empty()) { + caution_ = 1.0; + } else { + caution_ = atof(caution_val.c_str()); + } + + std::vector recruits = utils::split(cfg["recruit"]); for(std::vector::const_iterator i = recruits.begin(); i != recruits.end(); ++i) { can_recruit.insert(*i); } - if(recruitment_pattern.empty()) { + if(recruitment_pattern.empty() +) { recruitment_pattern = utils::split(global_ai_params["recruitment_pattern"]); + LOG_NG << "Recruitment pattern: " << global_ai_params["recruitment_pattern"] << "\n"; + } else { + LOG_NG << "Recruitment pattern from side: " << cfg["recruitment_pattern"] << "\n"; } + /* // Default recruitment pattern is to buy 2 fighters for every 1 archer if(recruitment_pattern.empty()) { recruitment_pattern.push_back("fighter"); @@ -320,6 +360,8 @@ void team::team_info::write(config& cfg) const cfg["villages_per_scout"] = str_cast(villages_per_scout); cfg["leader_value"] = str_cast(leader_value); cfg["village_value"] = str_cast(village_value); + cfg["aggression"] = str_cast(aggression_); + cfg["caution"] = str_cast(caution_); for(std::vector::const_iterator tg = targets.begin(); tg != targets.end(); ++tg) { tg->write(cfg.add_child("target")); @@ -335,10 +377,21 @@ void team::team_info::write(config& cfg) const cfg["recruit"] = can_recruit_str.str(); + std::stringstream global_recruit_pattern_str; + for(std::vector::const_iterator p = global_recruitment_pattern.begin(); + p != global_recruitment_pattern.end(); ++p) { + if(p != global_recruitment_pattern.begin()) + global_recruit_pattern_str << ","; + + global_recruit_pattern_str << *p; + } + + cfg["global_recruitment_pattern"] = global_recruit_pattern_str.str(); + std::stringstream recruit_pattern_str; - std::vector rp = global_recruitment_pattern; - for(std::vector::const_iterator p = rp.begin(); p != rp.end(); ++p) { - if(p != rp.begin()) + for(std::vector::const_iterator p = recruitment_pattern.begin(); + p != recruitment_pattern.end(); ++p) { + if(p != recruitment_pattern.begin()) recruit_pattern_str << ","; recruit_pattern_str << *p; @@ -370,8 +423,6 @@ team::team(const config& cfg, int gold) : countdown_time_(0), action_bonus_count_(0), aiparams_(), - aggression_(0.0), - caution_(0.0), enemies_(), seen_(), ally_shroud_(), @@ -472,8 +523,8 @@ void team::set_time_of_day(int turn, const time_of_day& tod) info_.recruitment_pattern = utils::split(aiparams_["recruitment_pattern"]); if (info_.recruitment_pattern.empty()) info_.recruitment_pattern = info_.global_recruitment_pattern; - aggression_ = lexical_cast_default(aiparams_["aggression"],0.5); - caution_ = lexical_cast_default(aiparams_["caution"],0.25); + info_.aggression_ = lexical_cast_default(aiparams_["aggression"],0.5); + info_.caution_ = lexical_cast_default(aiparams_["caution"],0.25); } bool team::calculate_enemies(size_t index) const diff --git a/src/team.hpp b/src/team.hpp index 42dbcf71039..449a54c54ec 100644 --- a/src/team.hpp +++ b/src/team.hpp @@ -105,6 +105,8 @@ public: int villages_per_scout; double leader_value, village_value; + //cached values for ai parameters + double aggression_, caution_; std::vector targets; @@ -160,6 +162,16 @@ public: std::set& recruits() { return info_.can_recruit; } const std::vector& recruitment_pattern() const { return info_.recruitment_pattern; } + bool remove_recruitment_pattern_entry(const std::string& key) + { + std::vector::iterator itor = std::find(info_.recruitment_pattern.begin(), + info_.recruitment_pattern.end(), + key); + if (itor == info_.recruitment_pattern.end()) + return false; + info_.recruitment_pattern.erase(itor); + return true; + } const std::string& name() const { return info_.name; } const std::string& save_id() const { return info_.save_id; } @@ -195,8 +207,8 @@ public: seen_[index] = true; } - double aggression() const { return aggression_; } - double caution() const { return caution_; } + double aggression() const { return info_.aggression_; } + double caution() const { return info_.caution_; } team_info::CONTROLLER controller() const { return info_.controller; } bool is_human() const { return info_.controller == team_info::HUMAN; } @@ -304,8 +316,6 @@ private: config aiparams_; - //cached values for ai parameters - double aggression_, caution_; bool calculate_enemies(size_t index) const; bool calculate_is_enemy(size_t index) const;