The Battle for Wesnoth  1.15.0-dev
ai.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://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 - headers
18  */
19 
20 #include "ai/formula/ai.hpp"
21 
22 #include "ai/formula/callable_objects.hpp" // for unit_callable, etc
23 #include "chat_events.hpp" // for chat_handler, etc
24 #include "display_chat_manager.hpp"
25 #include "formula/function.hpp" // for formula_expression
26 #include "game_board.hpp" // for game_board
27 #include "game_display.hpp" // for game_display
28 #include "log.hpp" // for LOG_STREAM, logger, etc
29 #include "map/map.hpp" // for gamemap
30 #include "pathfind/pathfind.hpp" // for plain_route, etc
31 #include "pathfind/teleport.hpp" // for get_teleport_locations, etc
32 #include "recall_list_manager.hpp" // for recall_list_manager
33 #include "resources.hpp" // for gameboard, teams, units, etc
34 #include "serialization/string_utils.hpp" // for split
35 #include "team.hpp" // for team
36 #include "terrain/filter.hpp" // for terrain_filter
37 #include "time_of_day.hpp" // for time_of_day
38 #include "tod_manager.hpp" // for tod_manager
39 #include "tstring.hpp" // for t_string, operator+
40 #include "units/unit.hpp" // for unit
41 #include "units/formula_manager.hpp" // for unit_formula_manager
42 #include "units/ptr.hpp" // for unit_ptr
43 #include "units/types.hpp"
44 #include "formula/formula.hpp" // for formula_error, formula, etc
45 #include "map/location.hpp" // for map_location, etc
46 #include "ai/actions.hpp" // for recall_result, etc
47 #include "ai/manager.hpp" // for manager
49 #include "ai/composite/stage.hpp" // for stage
50 #include "ai/default/contexts.hpp" // for attack_analysis
51 #include "ai/formula/function_table.hpp" // for ai_function_symbol_table
52 #include "ai/game_info.hpp" // for move_result_ptr, move_map, etc
53 #include "ai/formula/candidates.hpp" // for base_candidate_action, etc
54 
55 #include <cassert> // for assert
56 #include <ctime> // for time
57 #include <map> // for multimap<>::const_iterator, etc
58 #include <sstream> // for operator<<, basic_ostream, etc
59 #include <stack> // for stack
60 #include <vector> // for vector, allocator, etc
61 
62 static lg::log_domain log_formula_ai("ai/engine/fai");
63 #define DBG_AI LOG_STREAM(debug, log_formula_ai)
64 #define LOG_AI LOG_STREAM(info, log_formula_ai)
65 #define WRN_AI LOG_STREAM(warn, log_formula_ai)
66 #define ERR_AI LOG_STREAM(err, log_formula_ai)
67 
68 
69 using namespace wfl;
70 
71 namespace ai {
72 
74 
76 {
77  ca_ptr new_ca;
78  const t_string &name = rc_action["name"];
79  try {
80  const t_string &type = rc_action["type"];
81 
82  if( type == "movement") {
83  new_ca = std::make_shared<move_candidate_action>(name, type, rc_action, &function_table_);
84  } else if( type == "attack") {
85  new_ca = std::make_shared<attack_candidate_action>(name, type, rc_action, &function_table_);
86  } else {
87  ERR_AI << "Unknown candidate action type: " << type << std::endl;
88  }
89  } catch(const formula_error& e) {
90  handle_exception(e, "Error while registering candidate action '" + name + "'");
91  }
92  return new_ca;
93 }
94 
97 }
98 
99 
101  :
104  ai_ptr_(nullptr),
105  cfg_(cfg),
107  keeps_cache_(),
108  attacks_callable(*this, resources::gameboard->units()),
109 // infinite_loop_guardian_(),
110  vars_(),
111  function_table_(*this)
112 {
114  LOG_AI << "creating new formula ai"<< std::endl;
115 }
116 
118 {
119  handle_exception(e, "Error while parsing formula");
120 }
121 
122 void formula_ai::handle_exception(const formula_error& e, const std::string& failed_operation) const
123 {
124  LOG_AI << failed_operation << ": " << e.formula << std::endl;
125  display_message(failed_operation + ": " + e.formula);
126  //if line number = 0, don't display info about filename and line number
127  if (e.line != 0) {
128  LOG_AI << e.type << " in " << e.filename << ":" << e.line << std::endl;
129  display_message(e.type + " in " + e.filename + ":" + std::to_string(e.line));
130  } else {
131  LOG_AI << e.type << std::endl;
133  }
134 }
135 
136 void formula_ai::display_message(const std::string& msg) const
137 {
138  game_display::get_singleton()->get_chat_manager().add_chat_message(std::time(nullptr), "wfl", get_side(), msg,
140 
141 }
142 
143 formula_ptr formula_ai::create_optional_formula(const std::string& formula_string) const {
144  try{
145  return formula::create_optional_formula(formula_string, &function_table_);
146  }
147  catch(const formula_error& e) {
148  handle_exception(e);
149  return wfl::formula_ptr();
150  }
151 }
152 
153 
155 {
156  ai_ptr_ = context;
157 }
158 
159 
160 std::string formula_ai::evaluate(const std::string& formula_str)
161 {
162  try{
163 
164  formula f(formula_str, &function_table_);
165 
166  map_formula_callable callable(fake_ptr());
167 
168  //formula_debugger fdb;
169  const variant v = f.evaluate(callable,nullptr);
170 
171  if (ai_ptr_) {
172  variant var = variant(this->fake_ptr()).execute_variant(v);
173 
174  if ( !var.is_empty() ) {
175  return "Made move: " + var.to_debug_string();
176  }
177  }
178 
179  return v.to_debug_string();
180  }
181  catch(formula_error& e) {
182  e.line = 0;
183  handle_exception(e);
184  throw;
185  }
186 }
187 
189 {
190  if (!formula_) {
191  throw formula_error("null formula passed to make_action","","formula",0);
192  }
193  LOG_AI << "do move...\n";
194  const variant var = formula_->evaluate(variables);///@todo 1.9 add formula_debugger
195  variant res;
196 
197  if (ai_ptr_) {
198  res = variant(this->fake_ptr()).execute_variant(var);
199  } else {
200  ERR_AI << "skipped execution of action because ai context is not set correctly" << std::endl;
201  }
202 
203  return res;
204 }
205 
207  const map_location &dst, unit_map::iterator &unit_it,
208  pathfind::teleport_map& allowed_teleports) const
209 {
210  map_location destination = dst;
211 
212  unit_map &units_ = resources::gameboard->units();
214 
215  unit_map::const_iterator dst_un = units_.find(destination);
216 
217  map_location res;
218 
219  if( dst_un != units_.end() ) {
220  //there is unit standing at dst, let's try to find free hex to move to
221  const map_location::DIRECTION preferred = destination.get_relative_dir(src);
222 
223  int best_rating = 100;//smaller is better
225  get_adjacent_tiles(destination,adj.data());
226 
227  for(std::size_t n = 0; n < adj.size(); ++n) {
228  if(resources::gameboard->map().on_board(adj[n]) == false) {
229  continue;
230  }
231 
232  if(units_.find(adj[n]) != units_.end()) {
233  continue;
234  }
235 
236  static const std::size_t NDIRECTIONS = map_location::NDIRECTIONS;
237  unsigned int difference = std::abs(static_cast<int>(preferred - n));
238  if(difference > NDIRECTIONS/2) {
239  difference = NDIRECTIONS - difference;
240  }
241 
242  const int rating = difference * 2;
243  if(rating < best_rating || res.valid() == false) {
244  best_rating = rating;
245  res = adj[n];
246  }
247  }
248  }
249 
250  if( res != map_location() ) {
251  destination = res;
252  }
253 
254  pathfind::plain_route route = pathfind::a_star_search(src, destination, 1000.0, calc,
255  resources::gameboard->map().w(), resources::gameboard->map().h(), &allowed_teleports);
256 
257  return route;
258 }
259 
261 {
262  return pathfind::get_teleport_locations(*unit_it, current_team(), true);
263 }
264 
265 void formula_ai::add_formula_function(const std::string& name, const_formula_ptr formula, const_formula_ptr precondition, const std::vector<std::string>& args)
266 {
267  formula_function_ptr fcn(new user_formula_function(name,formula,precondition,args));
268  function_table_.add_function(name, std::move(fcn));
269 }
270 
271 namespace {
272 template<typename Container>
273 variant villages_from_set(const Container& villages,
274  const std::set<map_location>* exclude=nullptr) {
275  std::vector<variant> vars;
276  for(const map_location& loc : villages) {
277  if(exclude && exclude->count(loc)) {
278  continue;
279  }
280  vars.emplace_back(std::make_shared<location_callable>(loc));
281  }
282 
283  return variant(vars);
284 }
285 }
286 
287 variant formula_ai::get_value(const std::string& key) const
288 {
289  const unit_map& units = resources::gameboard->units();
290 
291  if(key == "aggression")
292  {
293  return variant(get_aggression()*1000,variant::DECIMAL_VARIANT);
294 
295  } else if(key == "avoid")
296  {
297  std::set<map_location> av_locs;
298  get_avoid().get_locations(av_locs);
299  return villages_from_set(av_locs);
300 
301  } else if(key == "caution")
302  {
303  return variant(get_caution()*1000,variant::DECIMAL_VARIANT);
304 
305  } else if(key == "grouping")
306  {
307  return variant(get_grouping());
308 
309  } else if(key == "leader_aggression")
310  {
311  return variant(get_leader_aggression()*1000,variant::DECIMAL_VARIANT);
312 
313  } else if(key == "leader_ignores_keep")
314  {
316 
317  } else if(key == "leader_value")
318  {
319  return variant(get_leader_value()*1000,variant::DECIMAL_VARIANT);
320 
321  } else if(key == "passive_leader")
322  {
323  return variant(get_passive_leader());
324 
325  } else if(key == "passive_leader_shares_keep")
326  {
328 
329  } else if(key == "recruitment_pattern")
330  {
331  const std::vector<std::string> &rp = get_recruitment_pattern();
332  std::vector<variant> vars;
333  for(const std::string &i : rp) {
334  vars.emplace_back(i);
335  }
336  return variant(vars);
337 
338  } else if(key == "scout_village_targeting")
339  {
340  return variant(get_scout_village_targeting()*1000,variant::DECIMAL_VARIANT);
341 
342  } else if(key == "support_villages")
343  {
344  return variant(get_support_villages());
345 
346  } else if(key == "village_value")
347  {
348  return variant(get_village_value()*1000,variant::DECIMAL_VARIANT);
349 
350  } else if(key == "villages_per_scout")
351  {
353 
354  } else if(key == "attacks")
355  {
356  return get_attacks_as_variant();
357 
358  } else if(key == "turn")
359  {
360  return variant(resources::tod_manager->turn());
361 
362  } else if(key == "time_of_day")
363  {
364  return variant(resources::tod_manager->get_time_of_day().id);
365 
366  } else if(key == "my_side")
367  {
368  return variant(std::make_shared<team_callable>(resources::gameboard->get_team(get_side())));
369 
370  } else if(key == "my_side_number")
371  {
372  return variant(get_side()-1);
373 
374  } else if(key == "teams")
375  {
376  std::vector<variant> vars;
377  for(std::vector<team>::const_iterator i = resources::gameboard->teams().begin(); i != resources::gameboard->teams().end(); ++i) {
378  vars.emplace_back(std::make_shared<team_callable>(*i));
379  }
380  return variant(vars);
381 
382  } else if(key == "allies")
383  {
384  std::vector<variant> vars;
385  for( std::size_t i = 0; i < resources::gameboard->teams().size(); ++i) {
386  if ( !current_team().is_enemy( i+1 ) )
387  vars.emplace_back(i);
388  }
389  return variant(vars);
390 
391  } else if(key == "enemies")
392  {
393  std::vector<variant> vars;
394  for( std::size_t i = 0; i < resources::gameboard->teams().size(); ++i) {
395  if ( current_team().is_enemy( i+1 ) )
396  vars.emplace_back(i);
397  }
398  return variant(vars);
399 
400  } else if(key == "my_recruits")
401  {
402  std::vector<variant> vars;
403 
405 
406  const std::set<std::string>& recruits = current_team().recruits();
407  if(recruits.empty()) {
408  return variant(vars);
409  }
410  for(std::set<std::string>::const_iterator i = recruits.begin(); i != recruits.end(); ++i)
411  {
412  const unit_type *ut = unit_types.find(*i);
413  if (ut)
414  {
415  vars.emplace_back(std::make_shared<unit_type_callable>(*ut));
416  }
417  }
418  return variant(vars);
419 
420  } else if(key == "recruits_of_side")
421  {
422  std::vector<variant> vars;
423  std::vector< std::vector< variant>> tmp;
424 
426 
427  for( std::size_t i = 0; i<resources::gameboard->teams().size(); ++i)
428  {
429  std::vector<variant> v;
430  tmp.push_back( v );
431 
432  const std::set<std::string>& recruits = resources::gameboard->teams()[i].recruits();
433  if(recruits.empty()) {
434  continue;
435  }
436  for(std::set<std::string>::const_iterator str_it = recruits.begin(); str_it != recruits.end(); ++str_it)
437  {
438  const unit_type *ut = unit_types.find(*str_it);
439  if (ut)
440  {
441  tmp[i].emplace_back(std::make_shared<unit_type_callable>(*ut));
442  }
443  }
444  }
445 
446  for( std::size_t i = 0; i<tmp.size(); ++i)
447  vars.emplace_back(tmp[i]);
448  return variant(vars);
449 
450  } else if(key == "units")
451  {
452  std::vector<variant> vars;
453  for(unit_map::const_iterator i = units.begin(); i != units.end(); ++i) {
454  vars.emplace_back(std::make_shared<unit_callable>(*i));
455  }
456  return variant(vars);
457 
458  } else if(key == "units_of_side")
459  {
460  std::vector<variant> vars;
461  std::vector< std::vector< variant>> tmp;
462  for( std::size_t i = 0; i<resources::gameboard->teams().size(); ++i)
463  {
464  std::vector<variant> v;
465  tmp.push_back( v );
466  }
467  for(const unit &u : units) {
468  tmp[u.side() - 1].emplace_back(std::make_shared<unit_callable>(u));
469  }
470  for( std::size_t i = 0; i<tmp.size(); ++i)
471  vars.emplace_back(tmp[i]);
472  return variant(vars);
473 
474  } else if(key == "my_units")
475  {
476  std::vector<variant> vars;
477  for(unit_map::const_iterator i = units.begin(); i != units.end(); ++i) {
478  if (i->side() == get_side()) {
479  vars.emplace_back(std::make_shared<unit_callable>(*i));
480  }
481  }
482  return variant(vars);
483 
484  } else if(key == "enemy_units")
485  {
486  std::vector<variant> vars;
487  for(unit_map::const_iterator i = units.begin(); i != units.end(); ++i) {
488  if (current_team().is_enemy(i->side())) {
489  if (!i->incapacitated()) {
490  vars.emplace_back(std::make_shared<unit_callable>(*i));
491  }
492  }
493  }
494  return variant(vars);
495 
496  } else if(key == "my_moves")
497  {
498  return variant(std::make_shared<move_map_callable>(get_srcdst(), get_dstsrc(), units));
499 
500  } else if(key == "my_attacks")
501  {
503  } else if(key == "enemy_moves")
504  {
505  return variant(std::make_shared<move_map_callable>(get_enemy_srcdst(), get_enemy_dstsrc(), units));
506 
507  } else if(key == "my_leader")
508  {
510  if(i == units.end()) {
511  return variant();
512  }
513  return variant(std::make_shared<unit_callable>(*i));
514 
515  } else if(key == "recall_list")
516  {
517  std::vector<variant> tmp;
518 
519  for(std::vector<unit_ptr >::const_iterator i = current_team().recall_list().begin(); i != current_team().recall_list().end(); ++i) {
520  tmp.emplace_back(std::make_shared<unit_callable>(**i));
521  }
522 
523  return variant(tmp);
524 
525  } else if(key == "vars")
526  {
527  return variant(vars_.fake_ptr());
528  } else if(key == "keeps")
529  {
530  return get_keeps();
531  } else if(key == "map")
532  {
533  return variant(std::make_shared<gamemap_callable>(*resources::gameboard));
534  } else if(key == "villages")
535  {
536  return villages_from_set(resources::gameboard->map().villages());
537  } else if(key == "villages_of_side")
538  {
539  std::vector<variant> vars;
540  for(std::size_t i = 0; i<resources::gameboard->teams().size(); ++i)
541  {
542  vars.emplace_back();
543  }
544  for(std::size_t i = 0; i<vars.size(); ++i)
545  {
546  vars[i] = villages_from_set(resources::gameboard->teams()[i].villages());
547  }
548  return variant(vars);
549 
550  } else if(key == "my_villages")
551  {
552  return villages_from_set(current_team().villages());
553 
554  } else if(key == "enemy_and_unowned_villages")
555  {
556  return villages_from_set(resources::gameboard->map().villages(), &current_team().villages());
557  }
558 
559  return variant();
560 }
561 
563 {
564  add_input(inputs, "aggression");
565  add_input(inputs, "leader_aggression");
566  add_input(inputs, "caution");
567  add_input(inputs, "attacks");
568  add_input(inputs, "my_side");
569  add_input(inputs, "teams");
570  add_input(inputs, "turn");
571  add_input(inputs, "time_of_day");
572  add_input(inputs, "keeps");
573  add_input(inputs, "vars");
574  add_input(inputs, "allies");
575  add_input(inputs, "enemies");
576  add_input(inputs, "map");
577  add_input(inputs, "my_attacks");
578  add_input(inputs, "enemy_moves");
579  add_input(inputs, "my_leader");
580  add_input(inputs, "my_recruits");
581  //add_input(inputs, "recall_list");
582  add_input(inputs, "recruits_of_side");
583  add_input(inputs, "units");
584  add_input(inputs, "units_of_side");
585  add_input(inputs, "my_units");
586  add_input(inputs, "enemy_units");
587  add_input(inputs, "villages");
588  add_input(inputs, "my_villages");
589  add_input(inputs, "villages_of_side");
590  add_input(inputs, "enemy_and_unowned_villages");
591 }
592 
593 void formula_ai::set_value(const std::string& key, const variant& value) {
594  vars_.mutate_value(key, value);
595 }
596 
598 {
599  if(keeps_cache_.is_null()) {
600  std::vector<variant> vars;
601  for(std::size_t x = 0; x != std::size_t(resources::gameboard->map().w()); ++x) {
602  for(std::size_t y = 0; y != std::size_t(resources::gameboard->map().h()); ++y) {
603  const map_location loc(x,y);
604  if(resources::gameboard->map().is_keep(loc)) {
606  get_adjacent_tiles(loc,adj.data());
607  for(std::size_t n = 0; n < adj.size(); ++n) {
608  if(resources::gameboard->map().is_castle(adj[n])) {
609  vars.emplace_back(std::make_shared<location_callable>(loc));
610  break;
611  }
612  }
613  }
614  }
615  }
616  keeps_cache_ = variant(vars);
617  }
618 
619  return keeps_cache_;
620 }
621 
623  if (tiles_adjacent(unit_A,unit_B)) {
624  return true;
625  }
626  move_map::const_iterator i;
627  std::pair<move_map::const_iterator,
628  move_map::const_iterator> unit_moves;
629 
630  unit_moves = get_srcdst().equal_range(unit_A);
631  for(i = unit_moves.first; i != unit_moves.second; ++i) {
632  if (tiles_adjacent((*i).second,unit_B)) {
633  return true;
634  }
635  }
636  return false;
637 }
638 
640  //make sure we don't run out of refcount
641 
642  for(const config &func : cfg_.child_range("function"))
643  {
644  const t_string &name = func["name"];
645  const t_string &inputs = func["inputs"];
646  const t_string &formula_str = func["formula"];
647 
648  std::vector<std::string> args = utils::split(inputs);
649  try {
651  create_optional_formula(formula_str),
652  create_optional_formula(func["precondition"]),
653  args);
654  }
655  catch(const formula_error& e) {
656  handle_exception(e, "Error while registering function '" + name + "'");
657  }
658  }
659 
660 
662  if (const config &ai_vars = cfg_.child("vars"))
663  {
664  variant var;
665  for(const config::attribute &i : ai_vars.attribute_range()) {
666  var.serialize_from_string(i.second);
667  vars_.add(i.first, var);
668  }
669  }
670 
671 
672 }
673 
674 
676 {
677  fai_ca->evaluate(this,resources::gameboard->units());
678 
679 }
680 
682 {
683  map_formula_callable callable(fake_ptr());
684  fai_ca->update_callable_map( callable );
685  const_formula_ptr move_formula(fai_ca->get_action());
686  return !make_action(move_formula, callable).is_empty();
687 }
688 
689 #if 0
690 formula_ai::gamestate_change_observer::gamestate_change_observer() :
691  set_var_counter_(), set_unit_var_counter_(), continue_counter_()
692 {
694 }
695 
696 formula_ai::gamestate_change_observer::~gamestate_change_observer() {
698 }
699 
700 void formula_ai::gamestate_change_observer::handle_generic_event(const std::string& /*event_name*/) {
701  set_var_counter_ = 0;
702  set_unit_var_counter_ = 0;
703  continue_counter_ = 0;
704 }
705 
706 //return false if number of calls exceeded MAX_CALLS
707 bool formula_ai::gamestate_change_observer::set_var_check() {
708  if(set_var_counter_ >= MAX_CALLS)
709  return false;
710 
711  set_var_counter_++;
712  return true;
713 }
714 
715 bool formula_ai::gamestate_change_observer::set_unit_var_check() {
716  if(set_unit_var_counter_ >= MAX_CALLS)
717  return false;
718 
719  set_unit_var_counter_++;
720  return true;
721 }
722 
723 bool formula_ai::gamestate_change_observer::continue_check() {
724  if(continue_counter_ >= MAX_CALLS)
725  return false;
726 
727  continue_counter_++;
728  return true;
729 }
730 #endif
731 
733 {
734  if (!cfg_)
735  {
736  return config();
737  }
738  DBG_AI << "formula_ai::to_config(): "<< cfg_<<std::endl;
739  config cfg = cfg_;
740 
741  //formula AI variables
742  cfg.clear_children("vars");
743  if (vars_.empty() == false) {
744  config &ai_vars = cfg.add_child("vars");
745 
746  std::string str;
748  {
749  try {
750  str = i->second.serialize_to_string();
751  } catch(const type_error&) {
752  WRN_AI << "variable ["<< i->first <<"] is not serializable - it will not be persisted across savegames"<<std::endl;
753  continue;
754  }
755  if (!str.empty())
756  {
757  ai_vars[i->first] = str;
758  str.clear();
759  }
760  }
761  }
762 
763  return cfg;
764 }
765 
766 } // end of namespace ai
Defines formula ai.
variant execute_variant(const variant &to_exec)
Definition: variant.cpp:659
virtual std::string get_grouping() const override
Definition: contexts.hpp:724
config & child(config_key_type 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:424
::tod_manager * tod_manager
Definition: resources.cpp:29
virtual const move_map & get_enemy_srcdst() const override
Definition: contexts.hpp:700
virtual int get_villages_per_scout() const override
Definition: contexts.hpp:857
unit_iterator end()
Definition: map.hpp:415
formula_ai(const formula_ai &)=delete
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.
Definition: types.cpp:1275
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:92
const_iterator begin() const
Definition: callable.hpp:269
void handle_exception(const wfl::formula_error &e) const
Definition: ai.cpp:117
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.cpp:517
virtual const unit_map & units() const override
Definition: game_board.hpp:114
Defines formula ai candidate actions - headers.
DIRECTION get_relative_dir(const map_location &loc, map_location::RELATIVE_DIR_MODE mode) const
Definition: location.cpp:225
void clear_children(T... keys)
Definition: config.hpp:509
This class represents a single unit of a specific type.
Definition: unit.hpp:99
static variant evaluate(const const_formula_ptr &f, const formula_callable &variables, formula_debugger *fdb=nullptr, variant default_res=variant(0))
Definition: formula.hpp:39
std::string formula
Definition: formula.hpp:106
static manager & get_singleton()
Definition: manager.hpp:151
unit_iterator find_leader(int side)
Definition: map.cpp:329
bool execute_candidate_action(wfl::candidate_action_ptr fai_ca)
Execute the fai candidate action.
Definition: ai.cpp:681
const config cfg_
Definition: ai.hpp:153
std::string filename
Definition: formula.hpp:107
virtual double get_leader_value() const override
Definition: contexts.hpp:761
Managing the AI-Game interaction - AI actions and their results.
void display_message(const std::string &msg) const
Definition: ai.cpp:136
static lg::log_domain log_formula_ai("ai/engine/fai")
child_itors child_range(config_key_type key)
Definition: config.cpp:366
wfl::candidate_action_ptr ca_ptr
Definition: ai.cpp:73
attribute_map::value_type attribute
Definition: config.hpp:256
virtual double get_village_value() const override
Definition: contexts.hpp:851
virtual const move_map & get_srcdst() const override
Definition: contexts.hpp:827
virtual config to_config() const
Definition: ai.cpp:732
unit_iterator begin()
Definition: map.hpp:405
std::vector< formula_input > formula_input_vector
void build_all(unit_type::BUILD_STATUS status)
Makes sure the all unit_types are built to the specified level.
Definition: types.cpp:1321
Composite AI stages.
unit_type_data unit_types
Definition: types.cpp:1452
std::string evaluate(const std::string &formula_str)
Definition: ai.cpp:160
#define h
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
std::shared_ptr< formula_function > formula_function_ptr
Definition: function.hpp:224
void clear()
Definition: config.cpp:867
-file sdl_utils.hpp
virtual wfl::variant get_value(const std::string &key) const override
Definition: ai.cpp:287
void get_locations(std::set< map_location > &locs, bool with_border=false) const
gets all locations on the map that match this filter
Definition: filter.hpp:56
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
#define WRN_AI
Definition: ai.cpp:65
A single unit type that the player may recruit.
Definition: types.hpp:42
void add_chat_message(const std::time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
void on_create()
Definition: ai.cpp:639
static const char * name(const std::vector< SDL_Joystick *> &joysticks, const std::size_t index)
Definition: joystick.cpp:48
bool can_reach_unit(map_location unit_A, map_location unit_B) const
Definition: ai.cpp:622
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:58
void remove_gamestate_observer(events::observer *event_observer)
Removes an observer of game events except ai_user_interact event and ai_sync_network event...
Definition: manager.cpp:349
Structure which holds a single route between one location and another.
Definition: pathfind.hpp:131
map_formula_callable & add(const std::string &key, const variant &value)
Definition: callable.hpp:252
bool valid() const
Definition: location.hpp:93
void set_value(const std::string &key, const wfl::variant &value) override
Definition: ai.cpp:593
virtual double get_leader_aggression() const override
Definition: contexts.hpp:742
std::string type
Definition: formula.hpp:105
game_board * gameboard
Definition: resources.cpp:20
virtual bool get_passive_leader() const override
Definition: contexts.hpp:767
virtual bool get_passive_leader_shares_keep() const override
Definition: contexts.hpp:773
void serialize_from_string(const std::string &str)
Definition: variant.cpp:635
void evaluate_candidate_action(wfl::candidate_action_ptr fai_ca)
Evaluate the fai candidate action.
Definition: ai.cpp:675
bool is_enemy(int n) const
Definition: team.hpp:243
virtual void add_formula_function(const std::string &name, wfl::const_formula_ptr formula, wfl::const_formula_ptr precondition, const std::vector< std::string > &args)
Definition: ai.cpp:265
virtual const move_map & get_enemy_dstsrc() const override
Definition: contexts.hpp:688
Managing the AIs lifecycle - headers.
virtual const std::vector< std::string > get_recruitment_pattern() const override
Definition: contexts.hpp:809
iterator end()
end iterator
std::array< map_location, 6 > adjacent_loc_array_t
Definition: location.hpp:170
wfl::attack_map_callable attacks_callable
Definition: ai.hpp:161
Encapsulates the map of the game.
Definition: location.hpp:42
unit_iterator find(std::size_t id)
Definition: map.cpp:311
bool tiles_adjacent(const map_location &a, const map_location &b)
Function which tells if two locations are adjacent.
Definition: location.cpp:557
#define LOG_AI
Definition: ai.cpp:64
static config unit_moves(reports::context &rc, const unit *u)
Definition: reports.cpp:608
std::size_t i
Definition: function.cpp:933
formula_callable_ptr fake_ptr()
Definition: callable.hpp:41
virtual const team & current_team() const override
Definition: contexts.hpp:524
virtual void get_inputs(wfl::formula_input_vector &inputs) const override
Definition: ai.cpp:562
wfl::map_formula_callable vars_
Definition: ai.hpp:164
Game information for the AI.
recursion_counter recursion_counter_
Definition: ai.hpp:154
Default AI contexts.
#define DBG_AI
Definition: ai.cpp:63
virtual double get_scout_village_targeting() const override
Definition: contexts.hpp:833
#define ERR_AI
Definition: ai.cpp:66
virtual side_number get_side() const override
Get the side number.
Definition: contexts.hpp:465
DIRECTION
Valid directions which can be moved in our hexagonal world.
Definition: location.hpp:44
int w
std::shared_ptr< const formula > const_formula_ptr
Definition: formula_fwd.hpp:23
virtual bool get_leader_ignores_keep() const override
Definition: contexts.hpp:755
formula_input_vector inputs() const
Definition: callable.hpp:62
config & add_child(config_key_type key)
Definition: config.cpp:480
wfl::candidate_action_ptr load_candidate_action_from_config(const config &cfg)
Definition: ai.cpp:75
void mutate_value(const std::string &key, const variant &value)
Definition: callable.hpp:57
std::shared_ptr< base_candidate_action > candidate_action_ptr
Definition: candidates.hpp:36
display_chat_manager & get_chat_manager()
virtual const move_map & get_dstsrc() const override
Definition: contexts.hpp:682
bool is_null() const
Functions to test the type of the internal value.
Definition: variant.hpp:58
std::map< std::string, variant >::const_iterator const_iterator
Definition: callable.hpp:267
virtual double get_aggression() const override
Definition: contexts.hpp:626
virtual const wfl::variant & get_attacks_as_variant() const override
Definition: contexts.hpp:664
const_iterator end() const
Definition: callable.hpp:270
#define f
Definition: contexts.hpp:42
wfl::ai_function_symbol_table function_table_
Definition: ai.hpp:167
void add_gamestate_observer(events::observer *event_observer)
Adds observer of game events except ai_user_interact event and ai_sync_network event.
Definition: manager.cpp:342
Composite AI contexts.
Standard logging facilities (interface).
const teleport_map get_teleport_locations(const unit &u, const team &viewing_team, bool see_all, bool ignore_units, bool check_vision)
Definition: teleport.cpp:259
recall_list_manager & recall_list()
Definition: team.hpp:215
void add_function(const std::string &name, formula_function_ptr &&fcn)
Definition: function.cpp:1429
Container associating units to locations.
Definition: map.hpp:99
int get_count() const
Get the current value of the recursion counter.
Definition: contexts.hpp:70
virtual bool get_support_villages() const override
Definition: contexts.hpp:845
#define e
pathfind::plain_route shortest_path_calculator(const map_location &src, const map_location &dst, unit_map::iterator &unit_it, pathfind::teleport_map &allowed_teleports) const
Definition: ai.cpp:206
virtual const terrain_filter & get_avoid() const override
Definition: contexts.hpp:670
wfl::variant keeps_cache_
Definition: ai.hpp:160
static void add_input(formula_input_vector &inputs, const std::string &key, FORMULA_ACCESS_TYPE access_type=FORMULA_READ_ONLY)
Definition: callable.hpp:135
int get_recursion_count() const override
Get the value of the recursion counter.
Definition: ai.cpp:95
wfl::formula_ptr create_optional_formula(const std::string &formula_string) const
Create a new formula from the string, using the symbol table which is stored in the AI...
Definition: ai.cpp:143
plain_route a_star_search(const map_location &src, const map_location &dst, double stop_at, const cost_calculator &calc, const std::size_t width, const std::size_t height, const teleport_map *teleports, bool border)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
pathfind::teleport_map get_allowed_teleports(unit_map::iterator &unit_it) const
Definition: ai.cpp:260
wfl::variant make_action(wfl::const_formula_ptr formula_, const wfl::formula_callable &variables)
Definition: ai.cpp:188
ai_context * ai_ptr_
Definition: ai.hpp:152
virtual double get_caution() const override
Definition: contexts.hpp:676
static map_location::DIRECTION n
This module contains various pathfinding functions and utilities.
void set_ai_context(ai_context *context)
Definition: ai.cpp:154
wfl::variant get_keeps() const
Definition: ai.cpp:597
bool is_empty() const
Definition: variant.cpp:271
void init_readonly_context_proxy(readonly_context &target)
Definition: contexts.hpp:506
const std::set< std::string > & recruits() const
Definition: team.hpp:223
static game_display * get_singleton()
std::string to_debug_string(bool verbose=false, formula_seen_stack *seen=nullptr) const
Definition: variant.cpp:649
std::shared_ptr< formula > formula_ptr
Definition: formula_fwd.hpp:21