The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
candidates.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2016 by Bartosz Waresiak <[email protected]>
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  * Defines formula ai candidate actions
18  * */
19 
20 #include "ai/formula/ai.hpp"
22 #include "log.hpp"
23 #include "resources.hpp"
24 
25 static lg::log_domain log_formula_ai("ai/engine/fai");
26 #define ERR_AI LOG_STREAM(err, log_formula_ai)
27 
28 
29 namespace game_logic {
30 
32  const std::string& type, const config& cfg,
33  function_symbol_table* function_table) :
34  name_(name),
35  type_(type),
36  eval_(new game_logic::formula(cfg["evaluation"], function_table)),
37  action_(new game_logic::formula(cfg["action"], function_table)),
38  score_(0)
39 {}
40 
42  const game_logic::formula_callable& callable, const ai::formula_ai* ai)
43 {
44  int res = 0;
45  try {
46  res = (formula::evaluate(formula, callable)).as_int();
47  } catch(formula_error& e) {
48  ai->handle_exception(e);
49  res = 0;
50  } catch(type_error& e) {
51  res = 0;
52  ERR_AI << "formula type error while evaluating candidate action: " << e.message << std::endl;
53  }
54 
55  return res;
56 }
57 
59  const std::string& name, const std::string& type,
60  const config& cfg, function_symbol_table* function_table)
61  : base_candidate_action(name, type, cfg, function_table)
62  , filter_map_()
63 {
64  const config & filter_params = cfg.child("filter");
65 
66  if( filter_params ) {
67  for(const config::attribute filter_param : filter_params.attribute_range())
68  {
69  game_logic::const_formula_ptr filter_formula(
70  new game_logic::formula(filter_param.second, function_table));
71 
72  filter_map_[filter_param.first]=filter_formula;
73  }
74  }
75 }
76 
78 {
79  game_logic::map_formula_callable callable(static_cast<const formula_callable*>(ai));
80  callable.add_ref();
81  callable.add("input", input);
82 
83  return formula::evaluate(formula, callable);
84 
85 }
86 
88  const std::string& type, const config& cfg,
89  function_symbol_table* function_table)
90  : candidate_action_with_filters(name, type, cfg, function_table)
91  , my_unit_()
92 {}
93 
95 {
96  score_ = 0;
97 
98  candidate_action_filters::const_iterator me_filter = filter_map_.find("me");
99 
100  std::vector<variant> res;
101 
102  for(unit_map::unit_iterator i = units.begin() ; i != units.end() ; ++i)
103  {
104  if (i->side() == ai->get_side() && i->movement_left() > 0) {
105  res.push_back(variant(new unit_callable(*i)));
106  }
107  }
108 
109  variant my_units(&res);
110 
111  variant filtered_units;
112  try {
113  if(me_filter != filter_map_.end() )
114  filtered_units = do_filtering(ai, my_units, me_filter->second);
115  else
116  filtered_units=my_units;
117  }
118  catch(formula_error& e) {
119  ai->handle_exception(e, "Error while executing filter formula for '" + get_name() + "' Candidate Action");
120  return;
121  }
122 
123  for(variant_iterator i = filtered_units.begin() ; i != filtered_units.end() ; ++i)
124  {
125  game_logic::map_formula_callable callable(static_cast<const formula_callable*>(ai));
126  callable.add_ref();
127  callable.add("me", *i);
128 
129  int res = execute_formula(eval_, callable, ai);
130 
131  if(res > score_) {
132  score_ = res;
133  my_unit_ = *i;
134  }
135  }
136 }
137 
139 {
140  callable.add("me", my_unit_);
141 }
142 
144  const std::string& type, const config& cfg,
145  function_symbol_table* function_table)
146  : candidate_action_with_filters(name, type, cfg, function_table)
147  , my_unit_()
148  , enemy_unit_()
149 {}
150 
152 {
153  score_ = 0;
154 
155  candidate_action_filters::const_iterator me_filter = filter_map_.find("me");
156  candidate_action_filters::const_iterator target_filter = filter_map_.find("target");
157 
158  std::vector<variant> my_res, enemy_res;
159 
160  for(unit_map::unit_iterator i = units.begin() ; i != units.end() ; ++i)
161  {
162  if (i->side() == ai->get_side())
163  {
164  if (i->attacks_left()) {
165  my_res.push_back(variant(new unit_callable(*i)));
166  }
167  } else
168  {
169  if (ai->current_team().is_enemy(i->side()) && !i->incapacitated() && !i->invisible(i->get_location())) {
170  enemy_res.push_back(variant(new unit_callable(*i)));
171  }
172  }
173  }
174  variant my_units(&my_res);
175  variant enemy_units(&enemy_res);
176 
177  variant filtered_my_units, filtered_enemy_units;
178  try {
179  if(me_filter != filter_map_.end() )
180  filtered_my_units = do_filtering(ai, my_units, me_filter->second);
181  else
182  filtered_my_units = my_units;
183 
184  if(target_filter != filter_map_.end() )
185  filtered_enemy_units = do_filtering(ai, enemy_units, target_filter->second);
186  else
187  filtered_enemy_units = enemy_units;
188  }
189  catch(formula_error& e) {
190  ai->handle_exception(e, "Error while executing filter formula for '" + get_name() + "' Candidate Action");
191  return;
192  }
193 
194  try{
195  if( !(filtered_enemy_units.num_elements() && filtered_my_units.num_elements() ) )
196  return;
197  }
198  catch(type_error& e) {
199  ERR_AI << "Error while executing filter formulas for '" + get_name() + "' Candidate Action: " << e.message << std::endl;
200  return;
201  }
202 
203  std::vector< const unit_callable* > my_units_flt;
204  std::vector< const unit_callable* > enemy_units_flt;
205 
206  for(variant_iterator i = filtered_my_units.begin() ; i != filtered_my_units.end() ; ++i) {
207  const unit_callable* u_callable = dynamic_cast<const unit_callable*>( (*i).as_callable() );
208  if(u_callable == nullptr) {
209  ERR_AI << "ERROR in "<< get_name() << "Candidate Action: Filter formula returned table that does not contain units" << std::endl;
210  return;
211  }
212  my_units_flt.push_back(u_callable);
213  }
214 
215  for(variant_iterator i = filtered_enemy_units.begin() ; i != filtered_enemy_units.end() ; ++i) {
216  const unit_callable* u_callable = dynamic_cast<const unit_callable*>( (*i).as_callable() );
217  if(u_callable == nullptr) {
218  ERR_AI << "ERROR in "<< get_name() << "Candidate Action: Filter formula returned table that does not contain units" << std::endl;
219  return;
220  }
221  enemy_units_flt.push_back(u_callable);
222  }
223 
224  for( size_t my_unit = 0 ; my_unit < my_units_flt.size() ; ++my_unit){
225  const unit_callable* my_unit_callalbe = my_units_flt[my_unit];
226  for( size_t enemy_unit = 0 ; enemy_unit < enemy_units_flt.size() ; ++enemy_unit){
227  if( ai->can_reach_unit( my_unit_callalbe->get_location(), enemy_units_flt[enemy_unit]->get_location() )) {
228 
229  game_logic::map_formula_callable callable(static_cast<const formula_callable*>(ai));
230  callable.add_ref();
231  callable.add("me", filtered_my_units[my_unit]);
232  callable.add("target", filtered_enemy_units[enemy_unit]);
233 
234  int res = execute_formula(eval_, callable, ai);
235 
236  if(res > score_) {
237  score_ = res;
238  my_unit_ = filtered_my_units[my_unit];
239  enemy_unit_ = filtered_enemy_units[enemy_unit];
240  }
241  }
242  }
243  }
244 }
245 
247 {
248  callable.add("me", my_unit_);
249  callable.add("target", enemy_unit_);
250 }
251 
252 }
Defines formula ai.
virtual side_number get_side() const
Get the side number.
Definition: contexts.hpp:480
size_t num_elements() const
Definition: variant.cpp:526
unit_iterator end()
Definition: map.hpp:311
Defines formula ai candidate actions - headers.
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1221
GLenum GLenum GLenum input
Definition: glew.h:10668
bool is_enemy(int n) const
Definition: team.hpp:247
attribute_map::value_type attribute
Definition: config.hpp:393
unit_iterator begin()
Definition: map.hpp:308
variant_iterator end() const
Definition: variant.cpp:500
variant do_filtering(ai::formula_ai *ai, variant &input, game_logic::const_formula_ptr formula)
Definition: candidates.cpp:77
move_candidate_action(const std::string &name, const std::string &type, const config &cfg, function_symbol_table *function_table)
Definition: candidates.cpp:87
virtual void update_callable_map(game_logic::map_formula_callable &callable)
Definition: candidates.cpp:138
static lg::log_domain log_formula_ai("ai/engine/fai")
game_logic::candidate_action_filters filter_map_
Definition: candidates.hpp:80
A small explanation about what's going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:57
int execute_formula(const const_formula_ptr &formula, const game_logic::formula_callable &callable, const ai::formula_ai *ai)
Definition: candidates.cpp:41
base_candidate_action(const std::string &name, const std::string &type, const config &cfg, function_symbol_table *function_table)
Definition: candidates.cpp:31
Iterator class for the variant.
Definition: variant.hpp:188
virtual void evaluate(ai::formula_ai *ai, unit_map &units)
Definition: candidates.cpp:94
candidate_action_with_filters(const std::string &name, const std::string &type, const config &cfg, function_symbol_table *function_table)
Definition: candidates.cpp:58
GLuint res
Definition: glew.h:9258
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:31
variant_iterator begin() const
Definition: variant.cpp:490
const location & get_location() const
const_attr_itors attribute_range() const
Definition: config.cpp:984
bool can_reach_unit(map_location unit_A, map_location unit_B) const
Definition: ai.cpp:920
size_t i
Definition: function.cpp:1057
map_formula_callable & add(const std::string &key, const variant &value)
Definition: formula.cpp:41
const std::string & get_name() const
Definition: candidates.hpp:59
GLuint const GLchar * name
Definition: glew.h:1782
virtual const team & current_team() const
Definition: contexts.hpp:539
#define ERR_AI
Definition: candidates.cpp:26
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...
Definition: config.cpp:658
Standard logging facilities (interface).
std::string message
Definition: exceptions.hpp:29
Container associating units to locations.
Definition: map.hpp:90
#define e
attack_candidate_action(const std::string &name, const std::string &type, const config &cfg, function_symbol_table *function_table)
Definition: candidates.cpp:143
virtual void evaluate(ai::formula_ai *ai, unit_map &units)
Definition: candidates.cpp:151
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
virtual void update_callable_map(game_logic::map_formula_callable &callable)
Definition: candidates.cpp:246
GLsizei const GLcharARB ** string
Definition: glew.h:4503
unit_map * units
Definition: resources.cpp:35
void handle_exception(game_logic::formula_error &e) const
Definition: ai.cpp:122