The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
recruitment.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 - 2016 by Felix Bauer
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Recruitment Engine by flix
18  * See http://wiki.wesnoth.org/AI_Recruitment
19  */
20 
21 #ifndef AI_DEFAULT_RECRUITMENT_HPP_INCLUDED
22 #define AI_DEFAULT_RECRUITMENT_HPP_INCLUDED
23 
24 #include "ai/composite/aspect.hpp"
25 #include "ai/composite/rca.hpp"
26 #include "units/unit.hpp"
27 #include "units/map.hpp"
28 
29 #include <boost/optional.hpp>
30 #include <iomanip>
31 
32 #ifdef _MSC_VER
33 #pragma warning(push)
34 // silence "inherits via dominance" warnings
35 #pragma warning(disable:4250)
36 #endif
37 
38 namespace pathfind {
39 
40 struct full_cost_map;
41 
42 } //of namespace pathfind
43 
44 namespace ai {
45 
46 namespace default_recruitment {
47 
48 // each leader have a score_map
49 // the score map indicates what is the best mix of own units from the leader point of view.
50 // The leader will then recruit according to the map.
51 typedef std::map<std::string, double> score_map;
52 
53 typedef std::map<t_translation::t_terrain, int> terrain_count_map;
54 typedef std::map<std::string, int> count_map;
55 
56 struct data {
58  std::set<std::string> recruits;
59  score_map scores;
60 
61  // We use ratio_score to decide with which ratios the leaders recruit among each other.
62  // For example if leader1 have a ratio_score of 1 and leader2 have a ratio_score of 2
63  // then leader2 will recruit twice as much units than leader1.
64  double ratio_score;
65 
67  bool in_danger;
68 
69  explicit data(const unit_map::const_iterator leader)
70  : leader(leader), ratio_score(1.0), recruit_count(0), in_danger(false) { }
71  double get_score_sum() const {
72  double sum = 0.0;
73  for (const score_map::value_type& entry : scores) {
74  sum += entry.second;
75  }
76  return sum;
77  }
78  score_map get_normalized_scores() const {
79  const double sum = get_score_sum();
80  if (sum == 0.0) {
81  return scores;
82  }
83  score_map normalized;
84  for (const score_map::value_type& entry : scores) {
85  normalized[entry.first] = entry.second / sum;
86  }
87  return normalized;
88  }
90  std::stringstream s;
91  s << "---------------Content of leader data---------------\n";
92  s << "For leader: " << leader->name() << "\n";
93  s << "ratio_score: " << ratio_score << "\n";
94  s << "recruit_count: " << recruit_count << "\n\n";
95  for (const score_map::value_type& entry : scores) {
96  s << std::setw(20) << entry.first <<
97  " score: " << std::setw(7) << entry.second << "\n";
98  }
99  s << "----------------------------------------------------\n";
100  return s.str();
101  }
102 };
103 
105  double a_defense;
106  double b_defense;
107  double value;
108  cached_combat_value(double a_def, double b_def, double v) :
109  a_defense(a_def), b_defense(b_def), value(v) {
110  }
111  bool operator<(const cached_combat_value& o) const {
112  return value < o.value;
113  }
114 };
115 
116 struct recruit_job : public component {
117  std::vector<std::string> types;
121  recruit_job(std::vector<std::string> t, std::string L, std::string id, int n, int i, bool s, bool p, bool b)
122  : types(t), leader(L), id(id)
123  , number(n), importance(i)
124  , total(s), pattern(p), blocker(b)
125  {}
126  config to_config() const {
127  config cfg;
128  if(number > 0 && number < 99999) {
129  cfg["number"] = number;
130  }
131  cfg["importance"] = importance;
132  cfg["total"] = total;
133  cfg["pattern"] = pattern;
134  cfg["blocker"] = blocker;
135  if(!leader.empty()) {
136  cfg["leader_id"] = leader;
137  }
138  if(!id.empty()) {
139  cfg["id"] = id;
140  }
141  if(!types.empty()) {
142  cfg["type"] = utils::join(types);
143  }
144  return cfg;
145  }
146  std::string get_id() const {return id;};
147  std::string get_name() const {return "recruit_job";};
148  std::string get_engine() const {return "cpp";};
149 };
150 
151 struct recruit_limit : public component {
152  std::vector<std::string> types;
154  int limit;
155  recruit_limit(std::vector<std::string> t, std::string id, int lim)
156  : types(t), id(id), limit(lim)
157  {}
158  config to_config() const {
159  config cfg;
160  cfg["max"] = limit;
161  if(!id.empty()) {
162  cfg["id"] = id;
163  }
164  if(!types.empty()) {
165  cfg["type"] = utils::join(types);
166  }
167  return cfg;
168  }
169  std::string get_id() const {return id;};
170  std::string get_name() const {return "recruit_limit";};
171  std::string get_engine() const {return "cpp";};
172 };
173 
174 class recruitment_aspect : public standard_aspect<config> {
175  std::vector<boost::shared_ptr<recruit_job> > jobs_;
176  std::vector<boost::shared_ptr<recruit_limit> > limits_;
177 public:
178  recruitment_aspect(readonly_context &context, const config &cfg, const std::string &id);
179  void recalculate() const;
180  void create_job(std::vector<boost::shared_ptr<recruit_job> > &jobs, const config &job);
181  void create_limit(std::vector<boost::shared_ptr<recruit_limit> > &limits, const config &lim);
182 };
183 
184 typedef std::map<std::string, std::set<cached_combat_value> > table_row;
185 typedef std::map<std::string, table_row> cache_table;
186 
188 public:
189  recruitment(rca_context &context, const config &cfg);
190  virtual ~recruitment() { }
191  virtual double evaluate();
192  virtual void execute();
193  config to_config() const;
194 private:
195 // Helper functions for execute()
196  action_result_ptr execute_recall(const std::string& id, data& leader_data);
197  action_result_ptr execute_recruit(const std::string& type, data& leader_data);
199  const data& leader_data) const;
200  data* get_best_leader_from_ratio_scores(std::vector<data>& leader_data,
201  const config* job) const;
202  const std::string get_best_recruit_from_scores(const data& leader_data,
203  const config* job);
204 
205 // Map Analysis
207  const pathfind::full_cost_map& my_cost_map,
208  const pathfind::full_cost_map& enemy_cost_map);
209  double get_average_defense(const std::string& unit_type) const;
210  const pathfind::full_cost_map get_cost_map_of_side(int side) const;
211  void show_important_hexes() const; //Debug only
214  void update_important_hexes();
215 
216 // Combat Analysis
217  double compare_unit_types(const std::string& a, const std::string& b);
218  void do_combat_analysis(std::vector<data>* leader_data);
219  const double* get_cached_combat_value(const std::string& a, const std::string& b,
220  double a_defense, double b_defense);
221  void simulate_attack(
222  const unit_type* const attacker, const unit_type* const defender,
223  double attacker_defense, double defender_defense,
224  double* damage_to_attacker, double* damage_to_defender) const;
225 
226 // Aspect recruitment_instruction
228  const std::string get_random_pattern_type_if_exists(const data& leader_data,
229  const config* job) const;
231  bool leader_matches_job(const data& leader_data, const config* job) const;
232  bool limit_ok(const std::string& recruit) const;
233  bool recruit_matches_job(const std::string& recruit, const config* job) const;
234  bool recruit_matches_type(const std::string& recruit, const std::string& type) const;
235  bool recruit_matches_types(const std::string& recruit,
236  const std::vector<std::string>& types) const;
237  bool remove_job_if_no_blocker(config* job);
238 
239 // Aspect recruitment_save_gold
240  double get_estimated_income(int turns) const;
241  double get_estimated_unit_gain() const;
242  double get_estimated_village_gain() const;
243  double get_unit_ratio() const;
244  void update_state();
245 
246 // Other
247  void do_randomness(std::vector<data>* leader_data) const;
248  void do_similarity_penalty(std::vector<data>* leader_data) const;
250  void handle_recruitment_more(std::vector<data>* leader_data) const;
251  bool is_enemy_in_radius(const map_location& loc, int radius) const;
252  void update_own_units_count();
253  void update_scouts_wanted();
254 
255 // Observer
257  public:
260 
262 
263  bool recruit_list_changed();
264  void set_recruit_list_changed(bool changed);
265  int gamestate_changed();
267 
268  private:
271 
272  };
273 
274  std::set<map_location> important_hexes_;
275  terrain_count_map important_terrain_;
277  std::map<map_location, double> average_local_cost_;
278  std::map<size_t, int> cheapest_unit_costs_;
279  cache_table combat_cache_;
286  count_map own_units_count_;
289 };
290 
291 } // of namespace default_recruitment
292 
293 } // of namespace ai
294 
295 #ifdef _MSC_VER
296 #pragma warning(pop)
297 #endif
298 
299 #endif
std::string to_string() const
Definition: recruitment.hpp:89
std::vector< std::string > types
const double * get_cached_combat_value(const std::string &a, const std::string &b, double a_defense, double b_defense)
For Combat Analysis.
recruit_limit(std::vector< std::string > t, std::string id, int lim)
GLint GLenum GLboolean normalized
Definition: glew.h:1873
std::map< size_t, int > cheapest_unit_costs_
std::vector< boost::shared_ptr< recruit_job > > jobs_
cached_combat_value(double a_def, double b_def, double v)
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.
bool remove_job_if_no_blocker(config *job)
For Configuration / Aspect "recruitment-instructions".
virtual void execute()
Execute the candidate action.
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
Definition: glew.h:1221
bool limit_ok(const std::string &recruit) const
For Configuration / Aspect "recruitment-instructions" Checks if a recruit-type can be recruited accor...
void handle_recruitment_more(std::vector< data > *leader_data) const
For Aspect "recruitment_more".
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().
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...
int get_cheapest_unit_cost_for_leader(const unit_map::const_iterator &leader)
Called at the beginning and whenever the recruitment list changes.
std::map< std::string, int > count_map
Definition: recruitment.hpp:54
const std::string get_best_recruit_from_scores(const data &leader_data, const config *job)
A helper function for execute().
double get_estimated_unit_gain() const
For Aspect "recruitment_save_gold".
recruit_situation_change_observer recruit_situation_change_observer_
GLdouble GLdouble t
Definition: glew.h:1366
std::map< t_translation::t_terrain, int > terrain_count_map
Definition: recruitment.hpp:53
GLsizei GLenum GLenum * types
Definition: glew.h:3155
std::set< map_location > important_hexes_
double compare_unit_types(const std::string &a, const std::string &b)
For Combat Analysis.
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
double get_estimated_village_gain() const
For Aspect "recruitment_save_gold".
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...
double get_unit_ratio() const
For Aspect "recruitment_save_gold".
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:57
double get_average_defense(const std::string &unit_type) const
For Map Analysis.
void update_average_lawful_bonus()
Calculates a average lawful bonus, so Combat Analysis will work better in caves and custom time of da...
void integrate_recruitment_pattern_in_recruitment_instructions()
For Configuration / Aspect "recruitment_pattern" Converts the (old) recruitment_pattern into a recrui...
const GLdouble * v
Definition: glew.h:1359
config * get_most_important_job()
For Configuration / Aspect "recruitment-instructions" We call a [recruit] tag a "job".
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
bool operator<(const cached_combat_value &o) const
bool is_enemy_in_radius(const map_location &loc, int radius) const
Helper function.
void create_limit(std::vector< boost::shared_ptr< recruit_limit > > &limits, const config &lim)
std::vector< std::string > types
GLfloat GLfloat p
Definition: glew.h:12766
void do_combat_analysis(std::vector< data > *leader_data)
Combat Analysis.
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
action_result_ptr execute_recall(const std::string &id, data &leader_data)
A helper function for execute().
std::string join(T const &v, const std::string &s=",")
Generates a new string joining container items in a list.
Encapsulates the map of the game.
Definition: location.hpp:38
data(const unit_map::const_iterator leader)
Definition: recruitment.hpp:69
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...
Definition: pathfind.hpp:267
size_t i
Definition: function.cpp:1057
action_result_ptr execute_recruit(const std::string &type, data &leader_data)
A helper function for execute().
std::map< std::string, std::set< cached_combat_value > > table_row
double get_estimated_income(int turns) const
For Aspect "recruitment_save_gold".
GLclampd n
Definition: glew.h:5903
void create_job(std::vector< boost::shared_ptr< recruit_job > > &jobs, const config &job)
cl_event event
Definition: glew.h:3070
recruit_job(std::vector< std::string > t, std::string L, std::string id, int n, int i, bool s, bool p, bool b)
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().
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.
recruitment_aspect(readonly_context &context, const config &cfg, const std::string &id)
score_map get_normalized_scores() const
Definition: recruitment.hpp:78
unit_map::const_iterator leader
Definition: recruitment.hpp:57
std::map< std::string, table_row > cache_table
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
virtual double evaluate()
Evaluate the candidate action, resetting the internal state of the action.
GLdouble s
Definition: glew.h:1358
void update_state()
For Aspect "recruitment_save_gold".
const pathfind::full_cost_map get_cost_map_of_side(int side) const
For Map Analysis.
void show_important_hexes() const
For Map Analysis.
std::map< std::string, double > score_map
Definition: recruitment.hpp:51
GLsizei const GLcharARB ** string
Definition: glew.h:4503
void do_similarity_penalty(std::vector< data > *leader_data) const
Will give a penalty to similar units.
std::set< std::string > recruits
Definition: recruitment.hpp:58
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...