47 #include <boost/scoped_ptr.hpp>
51 #define LOG_AI_RECRUITMENT LOG_STREAM(info, log_ai_recruitment)
52 #define ERR_AI_RECRUITMENT LOG_STREAM(err, log_ai_recruitment)
57 #pragma warning(disable:4250)
62 namespace default_recruitment {
71 const static int SAVE_GOLD_FORECAST_TURNS = 5;
74 const static unsigned int UNIT_THRESHOLD = 5;
78 const static double MAP_BORDER_THICKNESS = 2.0;
79 const static double MAP_BORDER_WIDTH = 0.2;
85 const static int MAP_OFFENSIVE_SHIFT = 0;
88 const static int MAP_VILLAGE_NEARNESS_THRESHOLD = 3;
91 const static int MAP_VILLAGE_SURROUNDING = 1;
96 const static double COMBAT_SCORE_POWER = 1.;
101 const static double COMBAT_CACHE_TOLERANCY = 0.5;
105 const static double VILLAGE_PER_SCOUT_MULTIPLICATOR = 2.;
111 important_terrain_(),
112 own_units_in_combat_counter_(0),
113 average_local_cost_(),
114 cheapest_unit_costs_(),
116 recruit_situation_change_observer_(),
117 average_lawful_bonus_(0.0),
118 recruitment_instructions_(),
119 recruitment_instructions_turn_(-1),
124 if (cfg[
"state"] ==
"save_gold") {
126 }
else if (cfg[
"state"] ==
"spend_all_gold") {
136 cfg[
"state"] =
"save_gold";
138 cfg[
"state"] =
"spend_all_gold";
140 cfg[
"state"] =
"normal";
178 if (
current_team().gold() < cheapest_unit_cost && cheapest_unit_cost > 0) {
206 std::vector<data> leader_data;
208 std::set<std::string> global_recruits;
221 if (
current_team().gold() < cheapest_unit_cost && cheapest_unit_cost > 0) {
222 LOG_AI_RECRUITMENT <<
"Leader " << leader->name() <<
" recruits are too expensive. \n";
233 lg::wml_error() <<
"Unit-type \"" << recruit <<
"\" doesn't exist.\n";
236 data.
scores[recruit] = 0.0;
237 global_recruits.insert(recruit);
241 for (
const std::string& recruit : leader->recruits()) {
243 lg::wml_error() <<
"Unit-type \"" << recruit <<
"\" doesn't exist.\n";
246 data.
scores[recruit] = 0.0;
247 global_recruits.insert(recruit);
259 data.
recruits.insert(recall->type_id());
260 data.
scores[recall->type_id()] = 0.0;
261 global_recruits.insert(recall->type_id());
274 leader_data.push_back(data);
277 if (leader_data.empty()) {
282 if (global_recruits.empty()) {
313 for (
const data&
data : leader_data) {
322 for (
const data&
data : leader_data) {
341 bool save_gold_active = save_gold_turn > 0 && save_gold_turn <= current_turn;
354 if (!best_leader_data) {
365 if (best_recruit.empty()) {
383 if (action_result->is_ok()) {
391 if (!job->operator[](
"total").to_bool(
false)) {
392 job->operator[](
"number") = job->operator[](
"number").to_int(99999) - 1;
414 }
while((action_result && action_result->is_ok()) || !action_result);
424 int status = (action_result) ? action_result->get_status() : -1;
429 if (job && no_gold) {
440 leader_data.
leader->get_location());
441 if (recall_result->is_ok()) {
442 recall_result->execute();
445 return recall_result;
454 leader_data.
leader->get_location());
456 if (recruit_result->is_ok()) {
457 recruit_result->execute();
461 return recruit_result;
472 const data& leader_data)
const {
474 double best_recall_value = -1;
485 double average_cost_of_advanced_unit = 0;
489 if (!advancement_type) {
492 average_cost_of_advanced_unit += advancement_type->
cost();
496 average_cost_of_advanced_unit /=
counter;
499 average_cost_of_advanced_unit =
recall_unit->cost();
501 double xp_quantity =
static_cast<double>(
recall_unit->experience()) /
503 double recall_value =
recall_unit->cost() + xp_quantity * average_cost_of_advanced_unit;
507 if (recall_value > best_recall_value) {
509 best_recall_value = recall_value;
512 return best_recall_id;
520 const config* job)
const {
523 int total_recruit_count = 0;
524 double ratio_score_sum = 0.0;
525 for (
const data&
data : leader_data) {
529 assert(ratio_score_sum > 0.0);
532 std::random_shuffle(leader_data.begin(), leader_data.end());
535 data* best_leader_data =
nullptr;
536 double biggest_difference = -99999.;
541 double desired_ammount =
data.
ratio_score / ratio_score_sum * (total_recruit_count + 1);
543 double difference = desired_ammount - current_ammount;
544 if (difference > biggest_difference) {
545 biggest_difference = difference;
546 best_leader_data = &
data;
549 return best_leader_data;
561 if (!pattern_type.empty()) {
565 double biggest_difference = -99999.;
568 const double score =
i.second;
573 if (!pattern_type.empty()) {
585 double difference = desired_ammount - current_ammount;
589 if (difference > biggest_difference) {
590 biggest_difference = difference;
611 typedef std::map<map_location, double> border_cost_map;
612 border_cost_map important_hexes_candidates;
613 double smallest_border_movecost = 999999;
614 double biggest_border_movecost = 0;
615 for(
int x = 0;
x < map.
w(); ++
x) {
616 for (
int y = 0;
y < map.
h(); ++
y) {
619 if (my_cost_average == -1 || enemy_cost_average == -1) {
624 if (std::abs(my_cost_average - MAP_OFFENSIVE_SHIFT - enemy_cost_average) <
626 double border_movecost = (my_cost_average + enemy_cost_average) / 2;
630 if (border_movecost < smallest_border_movecost) {
631 smallest_border_movecost = border_movecost;
633 if (border_movecost > biggest_border_movecost) {
634 biggest_border_movecost = border_movecost;
639 double threshold = (biggest_border_movecost - smallest_border_movecost) *
640 MAP_BORDER_WIDTH + smallest_border_movecost;
641 for (
const border_cost_map::value_type& candidate : important_hexes_candidates) {
642 if (candidate.second < threshold) {
658 long summed_defense = 0;
659 int total_terrains = 0;
662 int count = entry.second;
664 summed_defense += defense *
count;
665 total_terrains +=
count;
667 double average_defense = (total_terrains == 0) ? 0.0 :
668 static_cast<double>(summed_defense) / total_terrains;
669 return average_defense;
681 const team&
team = (*resources::teams)[side - 1];
686 unsigned int unit_count = 0;
697 if (unit_count < UNIT_THRESHOLD) {
698 std::vector<unit_map::const_iterator> leaders = units.find_leaders(side);
706 for (
const std::string& recruit : leader->recruits()) {
737 sum += time.lawful_bonus;
754 for(
int x = 0;
x < map.
w(); ++
x) {
755 for (
int y = 0;
y < map.
h(); ++
y) {
798 std::vector<map_location> surrounding;
801 std::copy(surrounding.begin(), surrounding.end(),
826 std::vector<map_location> important_villages;
828 std::vector<map_location> surrounding;
832 important_villages.push_back(village);
837 for (
const map_location& village : important_villages) {
839 std::vector<map_location> surrounding;
860 if (!type_a || !type_b) {
861 ERR_AI_RECRUITMENT <<
"Couldn't find unit type: " << ((type_a) ? b : a) <<
"." << std::endl;
872 double damage_to_a = 0.0;
873 double damage_to_b = 0.0;
876 simulate_attack(type_a, type_b, defense_a, defense_b, &damage_to_a, &damage_to_b);
878 simulate_attack(type_b, type_a, defense_b, defense_a, &damage_to_b, &damage_to_a);
880 int a_cost = (type_a->
cost() > 0) ? type_a->
cost() : 1;
881 int b_cost = (type_b->
cost() > 0) ? type_b->
cost() : 1;
888 if (damage_to_a <= 0 && damage_to_b <= 0) {
890 }
else if (damage_to_a <= 0) {
892 }
else if (damage_to_b <= 0) {
896 double value_of_a = damage_to_b / (b_max_hp * a_cost);
897 double value_of_b = damage_to_a / (a_max_hp * b_cost);
899 if (value_of_a > value_of_b) {
900 return value_of_a / value_of_b;
901 }
else if (value_of_a < value_of_b) {
902 return -value_of_b / value_of_a;
926 typedef std::vector<std::pair<std::string, int> > unit_hp_vector;
927 unit_hp_vector enemy_units;
934 if (enemy_units.size() < UNIT_THRESHOLD) {
940 std::set<std::string> possible_recruits;
944 const std::vector<unit_map::const_iterator> leaders = units.find_leaders(
team.
side());
946 possible_recruits.insert(leader->recruits().begin(), leader->recruits().end());
949 for (
const std::string& possible_recruit : possible_recruits) {
953 enemy_units.push_back(std::make_pair(possible_recruit, hp));
959 for (
data& leader : *leader_data) {
960 if (leader.recruits.empty()) {
963 typedef std::map<std::string, double> simple_score_map;
964 simple_score_map temp_scores;
966 for (
const unit_hp_vector::value_type& entry : enemy_units) {
968 int enemy_unit_hp = entry.second;
969 for (
const std::string& recruit : leader.recruits) {
971 score *= enemy_unit_hp;
972 score = pow(score, COMBAT_SCORE_POWER);
973 temp_scores[recruit] += score;
977 if (temp_scores.empty()) {
981 double max = -99999.;
983 for (
const simple_score_map::value_type& entry : temp_scores) {
984 double score = entry.second;
990 double average = sum / temp_scores.size();
996 double new_100 = max;
998 if (score_threshold <= 0) {
999 score_threshold = 0.0001;
1001 double new_0 = max - (score_threshold * (max - average));
1002 if (new_100 == new_0) {
1007 for (
const simple_score_map::value_type& entry : temp_scores) {
1009 double score = entry.second;
1014 double normalized_score = 100 * ((score - new_0) / (new_100 - new_0));
1015 if (normalized_score < 0) {
1016 normalized_score = 0;
1018 leader.scores[recruit] += normalized_score;
1029 double a_defense,
double b_defense) {
1030 double best_distance = 999;
1031 const double* best_value =
nullptr;
1034 double distance_a = std::abs(entry.a_defense - a_defense);
1035 double distance_b = std::abs(entry.b_defense - b_defense);
1036 if (distance_a <= COMBAT_CACHE_TOLERANCY && distance_b <= COMBAT_CACHE_TOLERANCY) {
1037 if(distance_a + distance_b <= best_distance) {
1038 best_distance = distance_a + distance_b;
1039 best_value = &entry.value;
1060 double attacker_defense,
double defender_defense,
1062 int average_lawful_bonus) :
1063 attacker_type(attacker),
1064 defender_type(defender),
1065 attacker_stats(attacker, att_weapon, true, defender, def_weapon,
1067 defender_stats(defender, def_weapon, false, attacker, att_weapon,
1069 attacker_combatant(attacker_stats),
1070 defender_combatant(defender_stats)
1072 attacker_combatant.
fight(defender_combatant);
1079 defender_combatant, attacker_combatant,
1083 attacker_combatant, defender_combatant,
1103 avg_hp = std::max(0., avg_hp);
1104 avg_hp = std::min(static_cast<double>(unit_type->
hitpoints()), avg_hp);
1116 double attacker_defense,
double defender_defense,
1117 double* damage_to_attacker,
double* damage_to_defender)
const {
1118 if(!attacker || !defender || !damage_to_attacker || !damage_to_defender) {
1122 const std::vector<attack_type> attacker_weapons = attacker->
attacks();
1123 const std::vector<attack_type> defender_weapons = defender->
attacks();
1128 for (
const attack_type& att_weapon : attacker_weapons) {
1131 for (
const attack_type& def_weapon : defender_weapons) {
1132 if (att_weapon.range() != def_weapon.range()) {
1137 attacker_defense, defender_defense,
1139 if (!best_def_response || simulation->better_result(best_def_response.get(),
true)) {
1140 best_def_response = simulation;
1144 if (!best_def_response) {
1148 attacker_defense, defender_defense,
1151 if (!best_att_attack || best_def_response->better_result(best_att_attack.get(),
false)) {
1152 best_att_attack = best_def_response;
1156 if (!best_att_attack) {
1160 *damage_to_defender += (defender->
hitpoints() - best_att_attack->get_avg_hp_of_defender());
1161 *damage_to_attacker += (attacker->
hitpoints() - best_att_attack->get_avg_hp_of_attacker());
1169 config* most_important_job =
nullptr;
1170 int most_important_importance = -1;
1171 int biggest_number = -1;
1176 int importance = job[
"importance"].to_int(1);
1177 int number = job[
"number"].to_int(99999);
1178 bool total = job[
"total"].to_bool(
false);
1185 const int count = entry.second;
1187 number = number -
count;
1194 if (importance > most_important_importance ||
1195 (importance == most_important_importance && biggest_number > number)) {
1196 most_important_job = &job;
1197 most_important_importance = importance;
1201 return most_important_job;
1210 const config* job)
const {
1212 if (job->operator[](
"pattern").to_bool(
false)) {
1213 std::vector<std::string> job_types =
utils::split(job->operator[](
"type"));
1215 if (job_types.empty()) {
1219 std::back_inserter(job_types));
1228 while (job_types_it != job_types.end()) {
1229 bool type_ok =
false;
1241 job_types_it = job_types.erase(job_types_it);
1245 if (!job_types.empty()) {
1247 choosen_type = job_types[rand() % job_types.size()];
1250 return choosen_type;
1259 if (recruitment_pattern.empty()) {
1264 std::stringstream
s;
1265 for (std::vector<std::string>::const_iterator
type = recruitment_pattern.begin();
1266 type != recruitment_pattern.end(); ++
type) {
1268 if (type != recruitment_pattern.end() - 1) {
1272 job[
"type"] = s.str();
1273 job[
"number"] = 99999;
1274 job[
"pattern"] =
true;
1275 job[
"blocker"] =
true;
1276 job[
"total"] =
false;
1277 job[
"importance"] = 1;
1300 std::vector<std::string>
ids =
utils::split(job->operator[](
"leader_id"));
1305 return (
std::find(ids.begin(), ids.end(), leader_data.
leader->id()) != ids.end());
1325 int number = entry.second;
1331 if (count >=
limit[
"max"].to_int(0)) {
1345 std::vector<std::string> job_types =
utils::split(job->operator[](
"type"));
1355 if (!recruit_type) {
1359 if (recruit_type->
id() ==
type) {
1367 std::stringstream
s;
1368 s << recruit_type->
level();
1369 if (s.str() ==
type) {
1380 const std::vector<std::string>&
types)
const {
1382 if (types.empty()) {
1398 if (!job->operator[](
"blocker").to_bool(
true)) {
1416 const size_t own_villages = team.
villages().size();
1420 double total_income = 0;
1425 double resulting_income = team.
base_income() + income - std::max(0., upkeep);
1426 total_income += resulting_income;
1428 return total_income;
1445 int neutral_villages = 0;
1460 double own_total_value = 0.;
1461 double team_total_value = 0.;
1462 double enemy_total_value = 0.;
1469 enemy_total_value +=
value;
1471 team_total_value +=
value;
1473 own_total_value +=
value;
1477 int allies_count = 0;
1485 if ((own_total_value == 0. || team_total_value == 0) && enemy_total_value == 0.) {
1487 }
else if (enemy_total_value == 0.) {
1495 double own_ratio = (own_total_value / enemy_total_value) * allies_count;
1496 double team_ratio = team_total_value / enemy_total_value;
1497 return std::min<double>(own_ratio, team_ratio);
1510 if (spend_all_gold > 0 &&
current_team().gold() >= spend_all_gold) {
1516 double income_estimation = 1.;
1527 if (
state_ ==
NORMAL && ratio > save_gold_begin && income_estimation > 0) {
1545 for (score_map::value_type& entry :
data.
scores) {
1546 double& score = entry.second;
1571 typedef std::map<std::string, int> similarity_map;
1572 similarity_map similarities;
1573 for (
const score_map::value_type& entry :
data.
scores) {
1576 if (!recruit_type) {
1581 ++similarities[recruit];
1582 ++similarities[advanced_type];
1587 for (score_map::value_type& entry :
data.
scores) {
1589 double& score = entry.second;
1590 score /= (similarities[recruit] + 1);
1604 int cheapest_cost = 999999;
1612 if (info->
cost() < cheapest_cost) {
1613 cheapest_cost = info->
cost();
1617 for (
const std::string& recruit : leader->recruits()) {
1622 if (info->
cost() < cheapest_cost) {
1623 cheapest_cost = info->
cost();
1632 return cheapest_cost;
1645 for (score_map::value_type& entry :
data.
scores) {
1647 double& score = entry.second;
1662 std::vector<map_location> surrounding;
1664 if (surrounding.empty()) {
1669 if(enemy_it == units.
end()) {
1708 int neutral_villages = 0;
1733 const int count = entry.second;
1744 : recruit_list_changed_(false), gamestate_changed_(0) {
1751 if (event ==
"ai_recruit_list_changed") {
1753 set_recruit_list_changed(
true);
1755 ++gamestate_changed_;
1765 return recruit_list_changed_;
1769 recruit_list_changed_ = changed;
1773 return gamestate_changed_;
1777 gamestate_changed_ = 0;
1786 parsed_cfg[
"pattern"] =
true;
1790 parsed_cfg[
"total"] =
true;
1795 if (!parsed_cfg.has_child(
"recruit")) {
1796 parsed_cfg.add_child(
"recruit",
config_of(
"importance", 0));
1805 std::function<void(std::vector<boost::shared_ptr<recruit_job> >&,
const config&)> factory_jobs =
1807 std::function<void(std::vector<boost::shared_ptr<recruit_limit> >&,
const config&)> factory_limits =
1816 cfg.
add_child(
"recruit", job->to_config());
1819 cfg.
add_child(
"limit", lim->to_config());
1828 job[
"leader_id"], job[
"id"],
1829 job[
"number"].to_int(-1), job[
"importance"].to_int(1),
1830 job[
"total"].to_bool(
false),
1831 job[
"blocker"].to_bool(
true),
1832 job[
"pattern"].to_bool(
true)
1834 jobs.push_back(job_ptr);
1841 lim[
"max"].to_int(0)
1843 limits.push_back(lim_ptr);
virtual side_number get_side() const
Get the side number.
std::string to_string() const
child_itors child_range(const std::string &key)
const double * get_cached_combat_value(const std::string &a, const std::string &b, double a_defense, double b_defense)
For Combat Analysis.
int total_movement() const
double get_avg_hp_of_attacker() const
::tod_manager * tod_manager
count_map own_units_count_
std::vector< unit_iterator > find_leaders(int side)
const map_location & get_location() const
std::map< size_t, int > cheapest_unit_costs_
void reset_gamestate_changed()
std::vector< boost::shared_ptr< recruit_job > > jobs_
int max_hitpoints() const
bool recruit_matches_job(const std::string &recruit, const config *job) const
For Configuration / Aspect "recruitment-instructions" Checks if a given recruit-type is specified in ...
void update_average_local_cost()
For Map Analysis.
boost::shared_ptr< config > value_
bool remove_job_if_no_blocker(config *job)
For Configuration / Aspect "recruitment-instructions".
terrain_count_map important_terrain_
map_location find_vacant_castle(const unit &leader)
Wrapper for find_vacant_tile() when looking for a vacant castle tile near a leader.
std::set< std::string > advancement_tree() const
Get the advancement tree Build a set of unit type's id of this unit type's advancement tree...
bool better_result(const attack_simulation *other, bool for_defender)
virtual recruit_result_ptr check_recruit_action(const std::string &unit_name, const map_location &where=map_location::null_location(), const map_location &from=map_location::null_location())
virtual void execute()
Execute the candidate action.
#define ERR_AI_RECRUITMENT
double get_avg_hp_of_combatant(bool attacker) const
Various functions that implement attacks and attack calculations.
const std::set< std::string > & recruits() const
#define LOG_AI_RECRUITMENT
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
static bool better_combat(const combatant &us_a, const combatant &them_a, const combatant &us_b, const combatant &them_b, double harm_weight)
virtual const config get_recruitment_instructions() const
const std::string get_random_pattern_type_if_exists(const data &leader_data, const config *job) const
For Configuration / Aspect "recruitment-instructions" If the flag pattern is set, this method returns...
GLuint GLuint GLsizei GLenum type
bool limit_ok(const std::string &recruit) const
For Configuration / Aspect "recruitment-instructions" Checks if a recruit-type can be recruited accor...
virtual const std::vector< std::string > get_recruitment_more() const
void handle_recruitment_more(std::vector< data > *leader_data) const
For Aspect "recruitment_more".
Managing the AI-Game interaction - AI actions and their results.
void get_tiles_in_radius(const map_location ¢er, const int radius, std::vector< map_location > &result)
Function that will add to result all locations within radius tiles of center (excluding center itself...
const movetype & movement_type() const
property_handler_map & property_handlers()
double get_score() const
Get the usual score of the candidate action without re-evaluation.
bool is_enemy(int n) const
std::map< map_location, double > average_local_cost_
void update_important_hexes()
For Map Analysis.
std::vector< boost::shared_ptr< recruit_limit > > limits_
data * get_best_leader_from_ratio_scores(std::vector< data > &leader_data, const config *job) const
A helper function for execute().
unit_type_data unit_types
void do_randomness(std::vector< data > *leader_data) const
Will add a random value between 0 and "recruitment_randomness" to all recruits.
void update_scouts_wanted()
This function will use the aspect villages_per_scout to decide how many scouts we want to recruit...
void update_own_units_count()
int get_cheapest_unit_cost_for_leader(const unit_map::const_iterator &leader)
Called at the beginning and whenever the recruitment list changes.
GLint GLint GLint GLint GLint GLint y
static void register_vector_property(std::map< std::string, property_handler_ptr > &property_handlers, const std::string &property, std::vector< boost::shared_ptr< X > > &values, std::function< void(std::vector< boost::shared_ptr< X > > &, const config &)> construction_factory)
const std::string number
template to number regex
void add_unit(const unit &u, bool use_max_moves=true)
Adds a units cost map to cost_map (increments the elements in cost_map)
virtual int get_villages_per_scout() const
const std::string get_best_recruit_from_scores(const data &leader_data, const config *job)
A helper function for execute().
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
void clear_children(const std::string &key)
double get_estimated_unit_gain() const
For Aspect "recruitment_save_gold".
recruit_situation_change_observer recruit_situation_change_observer_
int round_double(double d)
GLsizei GLenum GLenum * types
double get_average_cost_at(int x, int y) const
Accessor for the costs.
std::set< map_location > important_hexes_
double compare_unit_types(const std::string &a, const std::string &b)
For Combat Analysis.
const battle_context_unit_stats attacker_stats
double get_avg_hp_of_defender() const
int average_lawful_bonus_
const terrain_label * set_label(const map_location &loc, const t_string &text, const int creator=-1, const std::string &team="", const SDL_Color color=font::NORMAL_COLOR, const bool visible_in_fog=true, const bool visible_in_shroud=false, const bool immutable=false, const std::string &category="", const t_string &tooltip="")
virtual double power_projection(const map_location &loc, const move_map &dstsrc) const
Function which finds how much 'power' a side can attack a certain location with.
GLdouble GLdouble GLdouble b
double get_estimated_village_gain() const
For Aspect "recruitment_save_gold".
void handle_generic_event(const std::string &event)
combatant defender_combatant
int side_upkeep(int side_num) const
bool recruit_matches_type(const std::string &recruit, const std::string &type) const
For Configuration / Aspect "recruitment-instructions" Checks if a given recruit-type matches one atom...
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.
const std::string & type_id() const
The id of the type of the unit.
double get_unit_ratio() const
For Aspect "recruitment_save_gold".
This class stores all the data for a single 'side' (in game nomenclature).
A small explanation about what's going on here: Each action has access to two game_info objects First...
static void remove_gamestate_observer(events::observer *event_observer)
Removes an observer of game events except ai_user_interact event and ai_sync_network event...
bool incapacitated() const
double get_average_defense(const std::string &unit_type) const
For Map Analysis.
std::vector< team > * teams
void update_average_lawful_bonus()
Calculates a average lawful bonus, so Combat Analysis will work better in caves and custom time of da...
cache_table combat_cache_
filter_context * filter_con
void integrate_recruitment_pattern_in_recruitment_instructions()
For Configuration / Aspect "recruitment_pattern" Converts the (old) recruitment_pattern into a recrui...
GLsizei const GLfloat * value
int w() const
Effective map width.
config * get_most_important_job()
For Configuration / Aspect "recruitment-instructions" We call a [recruit] tag a "job".
GLboolean GLboolean GLboolean GLboolean a
virtual config to_config() const
serialize
Encapsulates the map of the game.
config & add_child(const std::string &key)
void fight(combatant &opponent, bool levelup_considered=true)
Simulate a fight! Can be called multiple times for cumulative calculations.
bool is_enemy_in_radius(const map_location &loc, int radius) const
Helper function.
Managing the AIs lifecycle - headers.
void create_limit(std::vector< boost::shared_ptr< recruit_limit > > &limits, const config &lim)
Structure describing the statistics of a unit involved in the battle.
Recruitment Engine by flix See http://wiki.wesnoth.org/AI_Recruitment.
static const map_location & null_location()
void do_combat_analysis(std::vector< data > *leader_data)
Combat Analysis.
const std::set< map_location > & villages() const
static const ::config * terrain
The terrain used to create the cache.
Templates and utility-routines for strings and numbers.
terrain_costs & get_movement()
GLuint GLuint GLsizei count
virtual const move_map & get_enemy_dstsrc() const
bool recruit_matches_types(const std::string &recruit, const std::vector< std::string > &types) const
For Configuration / Aspect "recruitment-instructions" Checks if a given recruit-type matches one of t...
config to_config() const
serialize
const unit_type * attacker_type
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
action_result_ptr execute_recall(const std::string &id, data &leader_data)
A helper function for execute().
virtual double get_recruitment_diversity() const
Encapsulates the map of the game.
virtual const config get_recruitment_save_gold() const
~recruit_situation_change_observer()
const std::string & usage() const
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
int h() const
Effective map height.
virtual recall_result_ptr check_recall_action(const std::string &id, const map_location &where=map_location::null_location(), const map_location &from=map_location::null_location())
combatant attacker_combatant
void compare_cost_maps_and_update_important_hexes(const pathfind::full_cost_map &my_cost_map, const pathfind::full_cost_map &enemy_cost_map)
For Map Analysis Computes from our cost map and the combined cost map of all enemies the important he...
Structure which uses find_routes() to build a cost map This maps each hex to a the movements a unit w...
action_result_ptr execute_recruit(const std::string &type, data &leader_data)
A helper function for execute().
static void add_recruit_list_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_recruit_list_changed' event.
GLint GLint GLint GLint GLint x
bool recruit_list_changed()
void set_recruit_list_changed(bool changed)
double get_estimated_income(int turns) const
For Aspect "recruitment_save_gold".
int cost(const t_translation::t_terrain &terrain, bool slowed=false) const
Returns the cost associated with the given terrain.
virtual const team & current_team() const
virtual const gamemap & map() const
attack_simulation(const unit_type *attacker, const unit_type *defender, double attacker_defense, double defender_defense, const attack_type *att_weapon, const attack_type *def_weapon, int average_lawful_bonus)
bool on_board(const map_location &loc) const
Tell if a location is on the map.
void create_job(std::vector< boost::shared_ptr< recruit_job > > &jobs, const config &job)
const unit_type * defender_type
bool find(E event, F functor)
Tests whether an event handler is available.
config recruitment_instructions_
recruitment(rca_context &context, const config &cfg)
const std::string * get_appropriate_recall(const std::string &type, const data &leader_data) const
A helper function for execute().
static void add_gamestate_observer(events::observer *event_observer)
Adds observer of game events except ai_user_interact event and ai_sync_network event.
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...
std::vector< attack_type > attacks() const
void simulate_attack(const unit_type *const attacker, const unit_type *const defender, double attacker_defense, double defender_defense, double *damage_to_attacker, double *damage_to_defender) const
For Combat Analysis.
virtual int get_recruitment_randomness() const
A variable-expanding proxy for the config class.
static lg::log_domain log_ai_recruitment("ai/recruitment")
Standard logging facilities (interface).
bool recall_unit(const std::string &id, team ¤t_team, const map_location &loc, const map_location &from, bool show, bool use_undo)
Recalls the unit with the indicated ID for the provided team.
recruitment_aspect(readonly_context &context, const config &cfg, const std::string &id)
static const double BAD_SCORE
Container associating units to locations.
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.
double average_hp(unsigned int healing=0) const
What's the average hp (weighted average of hp_dist).
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.
score_map get_normalized_scores() const
unit_iterator find(size_t id)
int get_cost_at(int x, int y) const
Accessor for the costs.
unit_map::const_iterator leader
recruit_situation_change_observer()
Observer Code.
A config object defines a single node in a WML file, with access to child nodes.
virtual const std::vector< std::string > get_recruitment_pattern() const
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
void update_state()
For Aspect "recruitment_save_gold".
const pathfind::full_cost_map get_cost_map_of_side(int side) const
For Map Analysis.
const std::vector< map_location > & villages() const
Return a list of the locations of villages on the map.
int recruitment_instructions_turn_
This module contains various pathfinding functions and utilities.
void show_important_hexes() const
For Map Analysis.
const battle_context_unit_stats defender_stats
GLsizei const GLcharARB ** string
void do_similarity_penalty(std::vector< data > *leader_data) const
Will give a penalty to similar units.
static void remove_recruit_list_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_recruit_list_changed' event.
std::set< std::string > recruits
const std::string & id() const
The id for this unit_type.
int defense_modifier(const t_translation::t_terrain &terrain) const
Returns the defensive value of the indicated terrain.
double poisoned
Resulting chance we are poisoned.
int own_units_in_combat_counter_
candidate action framework
bool leader_matches_job(const data &leader_data, const config *job) const
For Configuration / Aspect "recruitment-instructions" Checks if a given leader is specified in the "l...