The Battle for Wesnoth  1.17.0-dev
contexts.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2021
3  by Yurii Chernyi <terraninfo@terraninfo.net>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * Helper functions for the object which operates in the context of AI for specific side
18  * This is part of AI interface
19  * @file
20  */
21 
22 #include "ai/contexts.hpp"
23 
24 #include "actions/attack.hpp"
25 
26 #include "ai/actions.hpp" // for actions
27 #include "ai/composite/aspect.hpp" // for typesafe_aspect, aspect, etc
28 #include "ai/composite/engine.hpp" // for engine, engine_factory, etc
29 #include "ai/composite/goal.hpp" // for goal
30 #include "ai/composite/stage.hpp" // for ministage
31 #include "ai/game_info.hpp" // for typesafe_aspect_ptr, etc
33 #include "ai/manager.hpp" // for manager
34 
35 #include "chat_events.hpp" // for chat_handler, etc
36 #include "config.hpp" // for config, etc
37 #include "display_chat_manager.hpp"
38 #include "game_board.hpp" // for game_board
39 #include "game_config.hpp" // for debug
40 #include "game_display.hpp" // for game_display
41 #include "log.hpp" // for LOG_STREAM, logger, etc
42 #include "map/map.hpp" // for gamemap
43 #include "pathfind/pathfind.hpp" // for paths::dest_vect, paths, etc
44 #include "resources.hpp" // for units, gameboard, etc
45 #include "serialization/string_utils.hpp" // for split, etc
46 #include "team.hpp" // for team
47 #include "terrain/filter.hpp" // for terrain_filter
48 #include "terrain/translation.hpp" // for terrain_code
49 #include "time_of_day.hpp" // for time_of_day
50 #include "tod_manager.hpp" // for tod_manager
51 #include "units/unit.hpp" // for unit
52 #include "units/map.hpp" // for unit_map::iterator_base, etc
53 #include "units/ptr.hpp" // for unit_ptr
54 #include "units/types.hpp" // for attack_type, unit_type, etc
55 #include "formula/variant.hpp" // for variant
56 
57 #include <algorithm> // for find, count, max, fill_n
58 #include <cmath> // for sqrt
59 #include <cstdlib> // for abs
60 #include <ctime> // for time
61 #include <iterator> // for back_inserter
62 #include <ostream> // for operator<<, basic_ostream, etc
63 
64 static lg::log_domain log_ai("ai/general");
65 #define DBG_AI LOG_STREAM(debug, log_ai)
66 #define LOG_AI LOG_STREAM(info, log_ai)
67 #define WRN_AI LOG_STREAM(warn, log_ai)
68 #define ERR_AI LOG_STREAM(err, log_ai)
69 
70 // =======================================================================
71 //
72 // =======================================================================
73 namespace ai {
74 
76 {
78 }
79 
81 {
83 }
84 
86 {
88 }
89 
91 {
93 }
94 
96 {
98 }
99 
101 {
103 }
104 
105 attack_result_ptr readwrite_context_impl::execute_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
107  double m_aggression = i.valid() && i->can_recruit() ? get_leader_aggression() : get_aggression();
108  return actions::execute_attack_action(get_side(),true,attacker_loc,defender_loc,attacker_weapon, m_aggression);
109 }
110 
111 attack_result_ptr readonly_context_impl::check_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
113  double m_aggression = i.valid() && i->can_recruit() ? get_leader_aggression() : get_aggression();
114  return actions::execute_attack_action(get_side(),false,attacker_loc,defender_loc,attacker_weapon, m_aggression);
115 }
116 
117 move_result_ptr readwrite_context_impl::execute_move_action(const map_location& from, const map_location& to, bool remove_movement, bool unreach_is_ok){
118  return actions::execute_move_action(get_side(),true,from,to,remove_movement,unreach_is_ok);
119 }
120 
121 move_result_ptr readonly_context_impl::check_move_action(const map_location& from, const map_location& to, bool remove_movement, bool unreach_is_ok){
122  return actions::execute_move_action(get_side(),false,from,to,remove_movement,unreach_is_ok);
123 }
124 
126  return actions::execute_recall_action(get_side(),true,id,where,from);
127 }
128 
130  return actions::execute_recruit_action(get_side(),true,unit_name,where,from);
131 }
132 
134  return actions::execute_recall_action(get_side(),false,id,where,from);
135 }
136 
138  return actions::execute_recruit_action(get_side(),false,unit_name,where,from);
139 }
140 
141 stopunit_result_ptr readwrite_context_impl::execute_stopunit_action(const map_location& unit_location, bool remove_movement, bool remove_attacks){
142  return actions::execute_stopunit_action(get_side(),true,unit_location,remove_movement,remove_attacks);
143 }
144 
145 stopunit_result_ptr readonly_context_impl::check_stopunit_action(const map_location& unit_location, bool remove_movement, bool remove_attacks){
146  return actions::execute_stopunit_action(get_side(),false,unit_location,remove_movement,remove_attacks);
147 }
148 
150  return actions::execute_synced_command_action(get_side(),true,lua_code,location);
151 }
152 
154  return actions::execute_synced_command_action(get_side(),false,lua_code,location);
155 }
156 
157 template<typename T>
159 {
160  known_aspects_.emplace(name, std::make_shared<typesafe_known_aspect<T>>(name, where, aspects_));
161 }
162 
164  : cfg_(cfg),
165  engines_(),
166  known_aspects_(),
167  advancements_(),
168  aggression_(),
169  aspects_(),
170  attacks_(),
171  avoid_(),
172  caution_(),
173  defensive_position_cache_(),
174  dstsrc_(),enemy_dstsrc_(),
175  enemy_possible_moves_(),
176  enemy_srcdst_(),
177  grouping_(),
178  goals_(),
179  keeps_(),
180  leader_aggression_(),
181  leader_goal_(),
182  leader_ignores_keep_(),
183  leader_value_(),
184  move_maps_enemy_valid_(false),
185  move_maps_valid_(false),
186  dst_src_valid_lua_(false),
187  dst_src_enemy_valid_lua_(false),
188  src_dst_valid_lua_(false),
189  src_dst_enemy_valid_lua_(false),
190  passive_leader_(),
191  passive_leader_shares_keep_(),
192  possible_moves_(),
193  recruitment_diversity_(),
194  recruitment_instructions_(),
195  recruitment_more_(),
196  recruitment_pattern_(),
197  recruitment_randomness_(),
198  recruitment_save_gold_(),
200  retreat_enemy_weight_(),
201  retreat_factor_(),
202  scout_village_targeting_(),
203  simple_targeting_(),
204  srcdst_(),
205  support_villages_(),
206  unit_stats_cache_(),
207  village_value_(),
208  villages_per_scout_()
209 {
210  init_side_context_proxy(context);
212 
213  add_known_aspect("advancements", advancements_);
214  add_known_aspect("aggression",aggression_);
215  add_known_aspect("attacks",attacks_);
216  add_known_aspect("avoid",avoid_);
217  add_known_aspect("caution",caution_);
218  add_known_aspect("grouping",grouping_);
219  add_known_aspect("leader_aggression",leader_aggression_);
220  add_known_aspect("leader_goal",leader_goal_);
221  add_known_aspect("leader_ignores_keep",leader_ignores_keep_);
222  add_known_aspect("leader_value",leader_value_);
223  add_known_aspect("passive_leader",passive_leader_);
224  add_known_aspect("passive_leader_shares_keep",passive_leader_shares_keep_);
225  add_known_aspect("recruitment_diversity",recruitment_diversity_);
226  add_known_aspect("recruitment_instructions",recruitment_instructions_);
227  add_known_aspect("recruitment_more",recruitment_more_);
228  add_known_aspect("recruitment_pattern",recruitment_pattern_);
229  add_known_aspect("recruitment_randomness",recruitment_randomness_);
230  add_known_aspect("recruitment_save_gold",recruitment_save_gold_);
231  add_known_aspect("retreat_enemy_weight",retreat_enemy_weight_);
232  add_known_aspect("retreat_factor",retreat_factor_);
233  add_known_aspect("scout_village_targeting",scout_village_targeting_);
234  add_known_aspect("simple_targeting",simple_targeting_);
235  add_known_aspect("support_villages",support_villages_);
236  add_known_aspect("village_value",village_value_);
237  add_known_aspect("villages_per_scout",villages_per_scout_);
239 }
240 
242  //init the composite ai engines
243  for(const config &cfg_element : cfg_.child_range("engine")) {
244  engine::parse_engine_from_config(*this,cfg_element,std::back_inserter(engines_));
245  }
246 
247  // init the composite ai aspects
248  for(const config &cfg_element : cfg_.child_range("aspect")) {
249  std::vector<aspect_ptr> aspects;
250  engine::parse_aspect_from_config(*this,cfg_element,cfg_element["id"],std::back_inserter(aspects));
251  add_aspects(aspects);
252  }
253 
254  // init the composite ai goals
255  for(const config &cfg_element : cfg_.child_range("goal")) {
256  engine::parse_goal_from_config(*this,cfg_element,std::back_inserter(get_goals()));
257  }
258 }
259 
261 {
262  return config();
263 }
264 
266 {
267  return config();
268 }
269 
271 {
272  config cfg;
273  for(const engine_ptr &e : engines_) {
274  cfg.add_child("engine",e->to_config());
275  }
276  for(const aspect_map::value_type &a : aspects_) {
277  cfg.add_child("aspect",a.second->to_config());
278  }
279  for(const goal_ptr &g : goals_) {
280  cfg.add_child("goal",g->to_config());
281  }
282  return cfg;
283 }
284 
286 {
288 }
289 
290 void readonly_context_impl::handle_generic_event(const std::string& /*event_name*/)
291 {
293 }
294 
297 }
298 
301 }
302 
303 void readonly_context_impl::diagnostic(const std::string& msg)
304 {
305  if(game_config::debug) {
307  }
308 }
309 
311 {
313 }
314 
315 void readonly_context_impl::log_message(const std::string& msg)
316 {
317  if(game_config::debug) {
319  std::time(nullptr), "ai", get_side(), msg, events::chat_handler::MESSAGE_PUBLIC, false);
320  }
321 }
322 
323 void readonly_context_impl::calculate_possible_moves(std::map<map_location,pathfind::paths>& res, move_map& srcdst,
324  move_map& dstsrc, bool enemy, bool assume_full_movement,
325  const terrain_filter* remove_destinations) const
326 {
327  calculate_moves(resources::gameboard->units(),res,srcdst,dstsrc,enemy,assume_full_movement,remove_destinations);
328 }
329 
330 void readonly_context_impl::calculate_moves(const unit_map& units, std::map<map_location,pathfind::paths>& res, move_map& srcdst,
331  move_map& dstsrc, bool enemy, bool assume_full_movement,
332  const terrain_filter* remove_destinations,
333  bool see_all
334  ) const
335 {
336 
337  for(unit_map::const_iterator un_it = units.begin(); un_it != units.end(); ++un_it) {
338  // If we are looking for the movement of enemies, then this unit must be an enemy unit.
339  // If we are looking for movement of our own units, it must be on our side.
340  // If we are assuming full movement, then it may be a unit on our side, or allied.
341  if ((enemy && current_team().is_enemy(un_it->side()) == false) ||
342  (!enemy && !assume_full_movement && un_it->side() != get_side()) ||
343  (!enemy && assume_full_movement && current_team().is_enemy(un_it->side()))) {
344  continue;
345  }
346  // Discount incapacitated units
347  if (un_it->incapacitated() ||
348  (!assume_full_movement && un_it->movement_left() == 0)) {
349  continue;
350  }
351 
352  // We can't see where invisible enemy units might move.
353  if (enemy && un_it->invisible(un_it->get_location()) && !see_all) {
354  continue;
355  }
356  // If it's an enemy unit, reset its moves while we do the calculations.
357  const unit_movement_resetter move_resetter(*un_it,enemy || assume_full_movement);
358 
359  // Insert the trivial moves of staying on the same map location.
360  if (un_it->movement_left() > 0) {
361  std::pair<map_location,map_location> trivial_mv(un_it->get_location(), un_it->get_location());
362  srcdst.insert(trivial_mv);
363  dstsrc.insert(trivial_mv);
364  }
365  /**
366  * TODO: This is where support for a speculative unit map is incomplete.
367  * There are several places (deep) within the paths constructor
368  * where resources::gameboard->units() is assumed to be the unit map. Rather
369  * than introduce a new parameter to numerous functions, a better
370  * solution may be for the creator of the speculative map (if one
371  * is used in the future) to cause resources::gameboard->units() to point to
372  * that map (and restore the "real" pointer when the speculating
373  * is completed). If that approach is adopted, calculate_moves()
374  * and calculate_possible_moves() become redundant, and one of
375  * them should probably be eliminated.
376  */
377  res.emplace(un_it->get_location(), pathfind::paths(*un_it, false, true, current_team(), 0, see_all));
378  }
379 
380  // deactivate terrain filtering if it's just the dummy 'matches nothing'
381  static const config only_not_tag("not");
382  if(remove_destinations && remove_destinations->to_config() == only_not_tag) {
383  remove_destinations = nullptr;
384  }
385 
386  for(std::map<map_location,pathfind::paths>::iterator m = res.begin(); m != res.end(); ++m) {
387  for(const pathfind::paths::step &dest : m->second.destinations)
388  {
389  const map_location& src = m->first;
390  const map_location& dst = dest.curr;
391 
392  if(remove_destinations != nullptr && remove_destinations->match(dst)) {
393  continue;
394  }
395 
396  bool friend_owns = false;
397 
398  // Don't take friendly villages
399  if(!enemy && resources::gameboard->map().is_village(dst)) {
400  for(std::size_t n = 0; n != resources::gameboard->teams().size(); ++n) {
401  if(resources::gameboard->teams()[n].owns_village(dst)) {
402  int side = n + 1;
403  if (get_side() != side && !current_team().is_enemy(side)) {
404  friend_owns = true;
405  }
406 
407  break;
408  }
409  }
410  }
411 
412  if(friend_owns) {
413  continue;
414  }
415 
416  if(src != dst && (resources::gameboard->find_visible_unit(dst, current_team()) == resources::gameboard->units().end()) ) {
417  srcdst.emplace(src, dst);
418  dstsrc.emplace(dst, src);
419  }
420  }
421  }
422 }
423 
424 void readonly_context_impl::add_aspects(std::vector< aspect_ptr > &aspects )
425 {
426  for(aspect_ptr a : aspects) {
427  const std::string id = a->get_id();
429  if (i != known_aspects_.end()) {
430  i->second->set(a);
431  } else {
432  ERR_AI << "when adding aspects, unknown aspect id["<<id<<"]"<<std::endl;
433  }
434  }
435 }
436 
437 void readonly_context_impl::add_facet(const std::string &id, const config &cfg) const
438 {
439  known_aspect_map::const_iterator i = known_aspects_.find(id);
440  if (i != known_aspects_.end()) {
441  i->second->add_facet(cfg);
442  } else {
443  ERR_AI << "when adding aspects, unknown aspect id["<<id<<"]"<<std::endl;
444  }
445 }
446 
448  const move_map& dstsrc, const move_map& srcdst, const move_map& enemy_dstsrc) const
449 {
451  if(itor == resources::gameboard->units().end()) {
452  static defensive_position pos;
453  pos.chance_to_hit = 0;
454  pos.vulnerability = pos.support = 0;
455  return pos;
456  }
457 
458  const std::map<map_location,defensive_position>::const_iterator position =
459  defensive_position_cache_.find(loc);
460 
461  if(position != defensive_position_cache_.end()) {
462  return position->second;
463  }
464 
465  defensive_position pos;
466  pos.chance_to_hit = 100;
467  pos.vulnerability = 10000.0;
468  pos.support = 0.0;
469 
470  typedef move_map::const_iterator Itor;
471  const std::pair<Itor,Itor> itors = srcdst.equal_range(loc);
472  for(Itor i = itors.first; i != itors.second; ++i) {
473  const int defense = itor->defense_modifier(resources::gameboard->map().get_terrain(i->second));
474  if(defense > pos.chance_to_hit) {
475  continue;
476  }
477 
478  const double vulnerability = power_projection(i->second,enemy_dstsrc);
479  const double support = power_projection(i->second,dstsrc);
480 
481  if(defense < pos.chance_to_hit || support - vulnerability > pos.support - pos.vulnerability) {
482  pos.loc = i->second;
483  pos.chance_to_hit = defense;
484  pos.vulnerability = vulnerability;
485  pos.support = support;
486  }
487  }
488 
489  defensive_position_cache_.emplace(loc, pos);
490  return defensive_position_cache_[loc];
491 }
492 
493 std::map<map_location,defensive_position>& readonly_context_impl::defensive_position_cache() const
494 {
496 }
497 
499 {
500  if (advancements_) {
501  return advancements_->get();
502  }
503 
505  return uaa;
506 }
507 
509 {
510  if (aggression_) {
511  return aggression_->get();
512  }
513  return 0;
514 }
515 
517 {
518  return aspects_;
519 }
520 
522 {
523  return aspects_;
524 }
525 
527 {
528  if (attacks_) {
529  return attacks_->get();
530  }
531  static attacks_vector av;
532  return av;
533 }
534 
536 {
537  if (attacks_) {
538  return attacks_->get_variant();
539  }
540  static wfl::variant v;
541  return v;
542 }
543 
544 const terrain_filter& readonly_context_impl::get_avoid() const
545 {
546  if (avoid_) {
547  return avoid_->get();
548  }
549  config cfg;
550  cfg.add_child("not");
551  static terrain_filter tf(vconfig(cfg, true), resources::filter_con, false);
552  return tf;
553 }
554 
556 {
557  if (caution_) {
558  return caution_->get();
559  }
560  return 0;
561 }
562 
564 {
565  if (!move_maps_valid_) {
567  }
568  return dstsrc_;
569 }
570 
572 {
573  if (!move_maps_enemy_valid_) {
575  }
576  return enemy_dstsrc_;
577 }
578 
580 {
581  if (!move_maps_enemy_valid_) {
583  }
584  return enemy_possible_moves_;
585 }
586 
588 {
589  if (!move_maps_enemy_valid_) {
591  }
592  return enemy_srcdst_;
593 }
594 
596 {
597  std::string engine_name = cfg["engine"];
598  if (engine_name.empty()) {
599  engine_name="cpp";//default engine
600  }
601 
603  while (en!=engines_.end() && ((*en)->get_name()!=engine_name) && ((*en)->get_id()!=engine_name)) {
604  ++en;
605  }
606 
607  if (en != engines_.end()){
608  return *en;
609  }
610 
612  if (eng == engine_factory::get_list().end()){
613  ERR_AI << "side "<<get_side()<<" : UNABLE TO FIND engine["<<
614  engine_name <<"]" << std::endl;
615  DBG_AI << "config snippet contains: " << std::endl << cfg << std::endl;
616  return engine_ptr();
617  }
618 
619  engine_ptr new_engine = eng->second->get_new_instance(*this,engine_name);
620  if (!new_engine) {
621  ERR_AI << "side "<<get_side()<<" : UNABLE TO CREATE engine["<<
622  engine_name <<"] " << std::endl;
623  DBG_AI << "config snippet contains: " << std::endl << cfg << std::endl;
624  return engine_ptr();
625  }
626  engines_.push_back(new_engine);
627  return engines_.back();
628 }
629 
630 const std::vector<engine_ptr>& readonly_context_impl::get_engines() const
631 {
632  return engines_;
633 }
634 
635 std::vector<engine_ptr>& readonly_context_impl::get_engines()
636 {
637  return engines_;
638 }
639 
641 {
642  if (grouping_) {
643  return grouping_->get();
644  }
645  return std::string();
646 }
647 
648 const std::vector<goal_ptr>& readonly_context_impl::get_goals() const
649 {
650  return goals_;
651 }
652 
653 std::vector<goal_ptr>& readonly_context_impl::get_goals()
654 {
655  return goals_;
656 }
657 
659 {
660  if (leader_aggression_) {
661  return leader_aggression_->get();
662  }
663  return 0;
664 }
665 
667 {
668  if (leader_goal_) {
669  return leader_goal_->get();
670  }
671  return config();
672 }
673 
674 utils::variant<bool, std::vector<std::string>> readonly_context_impl::get_leader_ignores_keep() const
675 {
676  if (leader_ignores_keep_) {
677  return leader_ignores_keep_->get();
678  }
679  return {};
680 }
681 
683 {
684  if (leader_value_) {
685  return leader_value_->get();
686  }
687  return 0;
688 }
689 
690 utils::variant<bool, std::vector<std::string>> readonly_context_impl::get_passive_leader() const
691 {
692  if (passive_leader_) {
693  return passive_leader_->get();
694  }
695  return {};
696 }
697 
698 utils::variant<bool, std::vector<std::string>> readonly_context_impl::get_passive_leader_shares_keep() const
699 {
701  return passive_leader_shares_keep_->get();
702  }
703  return {};
704 }
705 
707 {
708  if (!move_maps_valid_) {
710  }
711  return possible_moves_;
712 }
713 
715 {
717  return recruitment_diversity_->get();
718  }
719  return 0.;
720 }
721 
723 {
725  return recruitment_instructions_->get();
726  }
727  return config();
728 }
729 
730 const std::vector<std::string> readonly_context_impl::get_recruitment_more() const
731 {
732  if (recruitment_more_) {
733  return recruitment_more_->get();
734  }
735  return std::vector<std::string>();
736 }
737 
738 const std::vector<std::string> readonly_context_impl::get_recruitment_pattern() const
739 {
740  if (recruitment_pattern_) {
741  return recruitment_pattern_->get();
742  }
743  return std::vector<std::string>();
744 }
745 
747 {
749  return recruitment_randomness_->get();
750  }
751  return 0;
752 }
753 
755 {
757  return recruitment_save_gold_->get();
758  }
759  return config();
760 }
761 
763 {
764  if (retreat_enemy_weight_) {
765  return retreat_enemy_weight_->get();
766  }
767  return 1;
768 }
769 
771 {
772  if (retreat_factor_) {
773  return retreat_factor_->get();
774  }
775  return 1;
776 }
777 
779 {
781  return scout_village_targeting_->get();
782  }
783  return 1;
784 }
785 
787 {
788  if (simple_targeting_) {
789  return simple_targeting_->get();
790  }
791  return false;
792 }
793 
795 {
796  if (!move_maps_valid_) {
798  }
799  return srcdst_;
800 }
801 
803 {
804  if (support_villages_) {
805  return support_villages_->get();
806  }
807  return false;
808 }
809 
811 {
812  if (village_value_) {
813  return village_value_->get();
814  }
815  return 0;
816 }
817 
819 {
820  if (villages_per_scout_) {
821  return villages_per_scout_->get();
822  }
823  return 0;
824 }
825 
827 {
828  return dst_src_valid_lua_;
829 }
830 
832 {
834 }
835 
837 {
838  return src_dst_valid_lua_;
839 }
840 
842 {
844 }
845 
847 {
849 }
850 
852 {
853  keeps_.clear();
854 }
855 
856 void keeps_cache::handle_generic_event(const std::string &/*event_name*/)
857 {
858  clear();
859 }
860 
862 {
863  move_maps_valid_ = false;
864  move_maps_enemy_valid_ = false;
865 
866  dst_src_valid_lua_ = false;
867  dst_src_enemy_valid_lua_ = false;
868 
869  src_dst_valid_lua_ = false;
870  src_dst_enemy_valid_lua_ = false;
871 }
872 
873 const std::set<map_location>& readonly_context_impl::keeps() const
874 {
875  return keeps_.get();
876 }
877 
879  : map_(nullptr)
880  , keeps_()
881 {
884 }
885 
887 {
890 }
891 
893 {
894  keeps_.clear();
895 }
896 
897 void keeps_cache::init(const gamemap &map)
898 {
899  map_ = &map;
900 }
901 
902 const std::set<map_location>& keeps_cache::get()
903 {
904  if(keeps_.empty()) {
905  // Generate the list of keeps:
906  // iterate over the entire map and find all keeps.
907  for(int x = 0; x != map_->w(); ++x) {
908  for(int y = 0; y != map_->h(); ++y) {
909  const map_location loc(x,y);
910  if(map_->is_keep(loc)) {
911  for(const map_location& adj : get_adjacent_tiles(loc)) {
912  if(map_->is_castle(adj)) {
913  keeps_.insert(loc);
914  break;
915  }
916  }
917  }
918  }
919  }
920  }
921 
922  return keeps_;
923 }
924 
926 {
927  const unit_map::iterator leader = resources::gameboard->units().find_leader(get_side());
928  if(leader == resources::gameboard->units().end() || leader->incapacitated()) {
929  return false;
930  }
931 
932  const map_location &start_pos = nearest_keep(leader->get_location());
933  if(start_pos.valid() == false) {
934  return false;
935  }
936 
937  if (leader->get_location() == start_pos) {
938  return true;
939  }
940 
941  // Find where the leader can move
942  const pathfind::paths leader_paths(*leader, false, true, current_team());
943 
944  return leader_paths.destinations.contains(start_pos);
945 }
946 
948 {
949  std::set<map_location> avoided_locations;
950  get_avoid().get_locations(avoided_locations);
951  const std::set<map_location>& keeps = this->keeps();
952  if(keeps.empty()) {
953  static const map_location dummy;
954  return dummy;
955  }
956 
957  const map_location* res = nullptr;
958  int closest = -1;
959  for(std::set<map_location>::const_iterator i = keeps.begin(); i != keeps.end(); ++i) {
960  if (avoided_locations.find(*i)!=avoided_locations.end()) {
961  continue;
962  }
963  const int distance = distance_between(*i,loc);
964  if(res == nullptr || distance < closest) {
965  closest = distance;
966  res = &*i;
967  }
968  }
969  if (res) {
970  return *res;
971  } else {
973  }
974 }
975 
976 double readonly_context_impl::power_projection(const map_location& loc, const move_map& dstsrc) const
977 {
978  map_location used_locs[6];
979  int ratings[6];
980  std::fill_n(ratings, 0, 6);
981  int num_used_locs = 0;
982 
983  const auto locs = get_adjacent_tiles(loc);
984 
985  const gamemap& map_ = resources::gameboard->map();
986  unit_map& units_ = resources::gameboard->units();
987 
988  int res = 0;
989 
990  bool changed = false;
991  for (int i = 0;; ++i) {
992  if (i == 6) {
993  if (!changed) break;
994  // Loop once again, in case a unit found a better spot
995  // and freed the place for another unit.
996  changed = false;
997  i = 0;
998  }
999 
1000  if (map_.on_board(locs[i]) == false) {
1001  continue;
1002  }
1003 
1004  const t_translation::terrain_code terrain = map_[locs[i]];
1005 
1006  typedef move_map::const_iterator Itor;
1007  typedef std::pair<Itor,Itor> Range;
1008  Range its = dstsrc.equal_range(locs[i]);
1009 
1010  map_location* const beg_used = used_locs;
1011  map_location* end_used = used_locs + num_used_locs;
1012 
1013  int best_rating = 0;
1014  map_location best_unit;
1015 
1016  for(Itor it = its.first; it != its.second; ++it) {
1017  const unit_map::const_iterator u = units_.find(it->second);
1018 
1019  // Unit might have been killed, and no longer exist
1020  if(u == units_.end()) {
1021  continue;
1022  }
1023 
1024  const unit& un = *u;
1025 
1026  // The unit might play on the next turn
1027  int attack_turn = resources::tod_manager->turn();
1028  if(un.side() < get_side()) {
1029  ++attack_turn;
1030  }
1031  // Considering the unit location would be too slow, we only apply the bonus granted by the global ToD
1032  const int lawful_bonus = resources::tod_manager->get_time_of_day(attack_turn).lawful_bonus;
1033  int tod_modifier = 0;
1034  if(un.alignment() == unit_type::ALIGNMENT::LAWFUL) {
1035  tod_modifier = lawful_bonus;
1036  } else if(un.alignment() == unit_type::ALIGNMENT::CHAOTIC) {
1037  tod_modifier = -lawful_bonus;
1038  } else if(un.alignment() == unit_type::ALIGNMENT::LIMINAL) {
1039  tod_modifier = -(std::abs(lawful_bonus));
1040  }
1041 
1042  // The 0.5 power avoids underestimating too much the damage of a wounded unit.
1043  int64_t hp = static_cast<int>(std::sqrt(static_cast<double>(un.hitpoints()) / un.max_hitpoints()) * 1000);
1044  int64_t most_damage = 0;
1045  for(const attack_type &att : un.attacks())
1046  {
1047  int damage = att.damage() * att.num_attacks() * (100 + tod_modifier);
1048  if (damage > most_damage) {
1049  most_damage = damage;
1050  }
1051  }
1052 
1053  int64_t village_bonus = map_.is_village(terrain) ? 3 : 2;
1054  int64_t defense = 100 - un.defense_modifier(terrain);
1055  int64_t rating_64 = hp * defense * most_damage * village_bonus / 200;
1056  int rating = rating_64;
1057  if(static_cast<int64_t>(rating) != rating_64) {
1058  WRN_AI << "overflow in ai attack calculation\n";
1059  }
1060  if(rating > best_rating) {
1061  map_location *pos = std::find(beg_used, end_used, it->second);
1062  // Check if the spot is the same or better than an older one.
1063  if (pos == end_used || rating >= ratings[pos - beg_used]) {
1064  best_rating = rating;
1065  best_unit = it->second;
1066  }
1067  }
1068  }
1069 
1070  if (!best_unit.valid()) continue;
1071  map_location *pos = std::find(beg_used, end_used, best_unit);
1072  int index = pos - beg_used;
1073  if (index == num_used_locs)
1074  ++num_used_locs;
1075  else if (best_rating == ratings[index])
1076  continue;
1077  else {
1078  // The unit was in another spot already, so remove its older rating
1079  // from the final result, and require a new run to fill its old spot.
1080  res -= ratings[index];
1081  changed = true;
1082  }
1083  used_locs[index] = best_unit;
1084  ratings[index] = best_rating;
1085  res += best_rating;
1086  }
1087 
1088  return res / 100000.;
1089 }
1090 
1092 {
1093  dstsrc_ = move_map();
1094  possible_moves_ = moves_map();
1095  srcdst_ = move_map();
1096  calculate_possible_moves(possible_moves_,srcdst_,dstsrc_,false,false,&get_avoid());
1097  if (is_passive_leader("") && !is_passive_keep_sharing_leader("")) {
1099  if (i.valid()) {
1100  map_location loc = i->get_location();
1101  srcdst_.erase(loc);
1102  for(move_map::iterator it = dstsrc_.begin(); it != dstsrc_.end(); ) {
1103  if(it->second == loc) {
1104  it = dstsrc_.erase(it);
1105  } else {
1106  ++it;
1107  }
1108  }
1109  }
1110  }
1111  move_maps_valid_ = true;
1112 
1113  // invalidate lua cache
1114  dst_src_valid_lua_ = false;
1115  src_dst_valid_lua_ = false;
1116 }
1117 
1119 {
1120  enemy_dstsrc_ = move_map();
1121  enemy_srcdst_ = move_map();
1122  enemy_possible_moves_ = moves_map();
1123  calculate_possible_moves(enemy_possible_moves_,enemy_srcdst_,enemy_dstsrc_,true);
1124  move_maps_enemy_valid_ = true;
1125 
1126  // invalidate lua cache
1127  dst_src_enemy_valid_lua_ = false;
1128  src_dst_enemy_valid_lua_ = false;
1129 }
1130 
1132 {
1133  dst_src_valid_lua_ = true;
1134 }
1135 
1137 {
1138  dst_src_enemy_valid_lua_ = true;
1139 }
1140 
1142 {
1143  src_dst_valid_lua_ = true;
1144 }
1145 
1147 {
1148  src_dst_enemy_valid_lua_ = true;
1149 }
1150 
1151 const map_location& readonly_context_impl::suitable_keep(const map_location& leader_location, const pathfind::paths& leader_paths) const {
1152  if (resources::gameboard->map().is_keep(leader_location)) {
1153  return leader_location; //if leader already on keep, then return leader_location
1154  }
1155 
1156  map_location const* best_free_keep = &map_location::null_location();
1157  double move_left_at_best_free_keep = 0.0;
1158 
1159  map_location const* best_occupied_keep = &map_location::null_location();
1160  double move_left_at_best_occupied_keep = 0.0;
1161 
1162  for(const pathfind::paths::step &dest : leader_paths.destinations)
1163  {
1164  const map_location &loc = dest.curr;
1165  if (keeps().find(loc)!=keeps().end()){
1166 
1167  const int move_left_at_loc = dest.move_left;
1168  if (resources::gameboard->units().count(loc) == 0) {
1169  if ((*best_free_keep==map_location::null_location())||(move_left_at_loc>move_left_at_best_free_keep)){
1170  best_free_keep = &loc;
1171  move_left_at_best_free_keep = move_left_at_loc;
1172  }
1173  } else {
1174  if ((*best_occupied_keep==map_location::null_location())||(move_left_at_loc>move_left_at_best_occupied_keep)){
1175  best_occupied_keep = &loc;
1176  move_left_at_best_occupied_keep = move_left_at_loc;
1177  }
1178  }
1179  }
1180  }
1181 
1182  if (*best_free_keep != map_location::null_location()){
1183  return *best_free_keep; // if there is a free keep reachable during current turn, return it
1184  }
1185 
1186  if (*best_occupied_keep != map_location::null_location()){
1187  return *best_occupied_keep; // if there is an occupied keep reachable during current turn, return it
1188  }
1189 
1190  return nearest_keep(leader_location); // return nearest keep
1191 }
1192 
1193  /** Weapon choice cache, to speed simulations. */
1195 {
1196  return unit_stats_cache_;
1197 }
1198 
1199 bool readonly_context_impl::is_active(const std::string &time_of_day, const std::string &turns) const
1200 {
1201  if(time_of_day.empty() == false) {
1202  const std::vector<std::string>& times = utils::split(time_of_day);
1203  if(std::count(times.begin(),times.end(),resources::tod_manager->get_time_of_day().id) == 0) {
1204  return false;
1205  }
1206  }
1207 
1208  if(turns.empty() == false) {
1209  int turn = resources::tod_manager->turn();
1210  const std::vector<std::string>& turns_list = utils::split(turns);
1211  for(std::vector<std::string>::const_iterator j = turns_list.begin(); j != turns_list.end() ; ++j ) {
1212  const std::pair<int,int> range = utils::parse_range(*j);
1213  if(turn >= range.first && turn <= range.second) {
1214  return true;
1215  }
1216  }
1217  return false;
1218  }
1219  return true;
1220 }
1221 
1223  const utils::variant<bool, std::vector<std::string>>& aspect_value, const std::string& id) const
1224 {
1225  return utils::visit(
1226  [&id](const auto& v) {
1227  if constexpr(utils::decayed_is_same<bool, decltype(v)>) {
1228  return v;
1229  } else {
1230  return utils::contains(v, id);
1231  }
1232  },
1233  aspect_value);
1234 }
1235 
1236 bool readonly_context_impl::is_keep_ignoring_leader(const std::string &id) const
1237 {
1238  return applies_to_leader(leader_ignores_keep_->get(), id);
1239 }
1240 
1241 bool readonly_context_impl::is_passive_leader(const std::string &id) const
1242 {
1243  return applies_to_leader(passive_leader_->get(), id);
1244 }
1245 
1247 {
1248  return applies_to_leader(passive_leader_shares_keep_->get(), id);
1249 }
1250 
1251 } //of namespace ai
static void parse_aspect_from_config(readonly_context &context, const config &cfg, const std::string &id, std::back_insert_iterator< std::vector< aspect_ptr >> b)
Definition: engine.cpp:52
typesafe_aspect_ptr< terrain_filter > avoid_
Definition: contexts.hpp:1287
virtual bool get_support_villages() const override
Definition: contexts.cpp:802
virtual side_number get_side() const override
Get the side number.
Definition: contexts.hpp:962
bool is_keep(const map_location &loc) const
Definition: map.cpp:72
virtual const std::vector< std::string > get_recruitment_pattern() const override
Definition: contexts.cpp:738
virtual int get_villages_per_scout() const override
Definition: contexts.cpp:818
virtual const attacks_vector & get_attacks() const override
Definition: contexts.cpp:526
::tod_manager * tod_manager
Definition: resources.cpp:30
virtual int get_recursion_count() const override
Get the value of the recursion counter.
Definition: contexts.cpp:80
unit_iterator end()
Definition: map.hpp:429
std::pair< int, int > parse_range(const std::string &str)
typesafe_aspect_ptr< bool > simple_targeting_
Definition: contexts.hpp:1320
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:92
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:85
std::shared_ptr< stopunit_result > stopunit_result_ptr
Definition: game_info.hpp:87
virtual const std::vector< std::string > get_recruitment_more() const override
Definition: contexts.cpp:730
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:475
virtual const unit_map & units() const override
Definition: game_board.hpp:112
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()) override
Check if it is possible to recruit a unit for us on specified location.
Definition: contexts.cpp:137
This class represents a single unit of a specific type.
Definition: unit.hpp:121
void init(const gamemap &map)
Definition: contexts.cpp:897
int dummy
Definition: lstrlib.cpp:1347
virtual const move_map & get_enemy_dstsrc() const override
Definition: contexts.cpp:571
bool is_castle(const map_location &loc) const
Definition: map.cpp:70
virtual void handle_generic_event(const std::string &event_name) override
Handle generic event.
Definition: contexts.cpp:290
virtual const config get_recruitment_instructions() const override
Definition: contexts.cpp:722
typesafe_aspect_ptr< config > leader_goal_
Definition: contexts.hpp:1298
static manager & get_singleton()
Definition: manager.hpp:145
void raise_gamestate_changed()
Notifies all observers of &#39;ai_gamestate_changed&#39; event.
Definition: manager.cpp:441
virtual team & current_team_w() override
Return a reference to the &#39;team&#39; object for the AI.
Definition: contexts.cpp:100
void calculate_possible_moves(std::map< map_location, pathfind::paths > &possible_moves, move_map &srcdst, move_map &dstsrc, bool enemy, bool assume_full_movement=false, const terrain_filter *remove_destinations=nullptr) const override
Calculate the moves units may possibly make.
Definition: contexts.cpp:323
Various functions that implement attacks and attack calculations.
unit_iterator find_leader(int side)
Definition: map.cpp:328
virtual stopunit_result_ptr execute_stopunit_action(const map_location &unit_location, bool remove_movement=true, bool remove_attacks=false) override
Ask the game to remove unit movements and/or attack.
Definition: contexts.cpp:141
virtual bool is_active(const std::string &time_of_day, const std::string &turns) const override
Definition: contexts.cpp:1199
typesafe_aspect_ptr< double > caution_
Definition: contexts.hpp:1288
void add_known_aspect(const std::string &name, typesafe_aspect_ptr< T > &where)
Definition: contexts.cpp:158
#define a
Managing the AI-Game interaction - AI actions and their results.
game_info & get_active_ai_info_for_side(side_number side)
Gets AI info for active AI of the given side.
Definition: manager.cpp:705
int hitpoints() const
The current number of hitpoints this unit has.
Definition: unit.hpp:490
virtual const moves_map & get_enemy_possible_moves() const override
Definition: contexts.cpp:579
virtual void set_src_dst_enemy_valid_lua() override
Definition: contexts.cpp:1146
void log_message(const std::string &msg) override
Display a debug message as a chat message.
Definition: contexts.cpp:315
child_itors child_range(config_key_type key)
Definition: config.cpp:344
std::string id
Definition: time_of_day.hpp:90
virtual bool is_passive_keep_sharing_leader(const std::string &id) const override
Definition: contexts.cpp:1246
virtual recruit_result_ptr execute_recruit_action(const std::string &unit_name, const map_location &where=map_location::null_location(), const map_location &from=map_location::null_location()) override
Ask the game to recruit a unit for us on specified location.
Definition: contexts.cpp:129
virtual void invalidate_keeps_cache() const override
Definition: contexts.cpp:851
readonly_context_impl(side_context &context, const config &cfg)
Constructor.
Definition: contexts.cpp:163
void add_turn_started_observer(events::observer *event_observer)
Adds an observer of &#39;ai_turn_started&#39; event.
Definition: manager.cpp:399
std::shared_ptr< move_result > move_result_ptr
Definition: game_info.hpp:85
void clear(const std::string &key)
Definition: general.cpp:186
virtual const gamemap & map() const override
Definition: game_board.hpp:102
int lawful_bonus
The % bonus lawful units receive.
Definition: time_of_day.hpp:83
dest_vect destinations
Definition: pathfind.hpp:101
unit_iterator begin()
Definition: map.hpp:419
move_result_ptr check_move_action(const map_location &from, const map_location &to, bool remove_movement=true, bool unreach_is_ok=false) override
Check if it is possible to move our unit from location &#39;from&#39; to location &#39;to&#39;.
Definition: contexts.cpp:121
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
Definition: translation.hpp:50
static void parse_engine_from_config(readonly_context &context, const config &cfg, std::back_insert_iterator< std::vector< engine_ptr >> b)
Definition: engine.cpp:70
stopunit_result_ptr check_stopunit_action(const map_location &unit_location, bool remove_movement=true, bool remove_attacks=false) override
Check if it is possible to remove unit movements and/or attack.
Definition: contexts.cpp:145
Composite AI stages.
typesafe_aspect_ptr< double > retreat_factor_
Definition: contexts.hpp:1318
AI Support engine - creating specific ai components from config.
std::vector< goal_ptr > goals_
Definition: contexts.hpp:1295
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
const defensive_position & best_defensive_position(const map_location &unit, const move_map &dstsrc, const move_map &srcdst, const move_map &enemy_dstsrc) const override
Definition: contexts.cpp:447
std::shared_ptr< recruit_result > recruit_result_ptr
Definition: game_info.hpp:84
virtual config get_leader_goal() const override
Definition: contexts.cpp:666
virtual const std::set< map_location > & keeps() const override
Definition: contexts.cpp:873
void init_side_context_proxy(side_context &target)
Definition: contexts.hpp:396
static config unit_name(const unit *u)
Definition: reports.cpp:160
static void parse_goal_from_config(readonly_context &context, const config &cfg, std::back_insert_iterator< std::vector< goal_ptr >> b)
Definition: engine.cpp:79
virtual double get_scout_village_targeting() const override
Definition: contexts.cpp:778
virtual bool is_keep_ignoring_leader(const std::string &id) const override
Definition: contexts.cpp:1236
std::shared_ptr< attack_result > attack_result_ptr
Definition: game_info.hpp:82
virtual utils::variant< bool, std::vector< std::string > > get_passive_leader_shares_keep() const override
Definition: contexts.cpp:698
virtual const aspect_map & get_aspects() const override
Definition: contexts.cpp:516
typesafe_aspect_ptr< double > leader_value_
Definition: contexts.hpp:1300
bool applies_to_leader(const utils::variant< bool, std::vector< std::string >> &aspect_value, const std::string &id) const
Definition: contexts.cpp:1222
Definitions for the interface to Wesnoth Markup Language (WML).
virtual double get_retreat_factor() const override
Definition: contexts.cpp:770
std::map< map_location, defensive_position > defensive_position_cache_
Definition: contexts.hpp:1289
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)
typesafe_aspect_ptr< int > villages_per_scout_
Definition: contexts.hpp:1325
virtual bool leader_can_reach_keep() const override
Definition: contexts.cpp:925
std::shared_ptr< aspect > aspect_ptr
Definition: game_info.hpp:95
virtual double get_retreat_enemy_weight() const override
Definition: contexts.cpp:762
std::multimap< map_location, map_location > move_map
The standard way in which a map of possible moves is recorded.
Definition: game_info.hpp:43
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:76
virtual double power_projection(const map_location &loc, const move_map &dstsrc) const override
Function which finds how much &#39;power&#39; a side can attack a certain location with.
Definition: contexts.cpp:976
typesafe_aspect_ptr< double > retreat_enemy_weight_
Definition: contexts.hpp:1317
std::vector< attack_analysis > attacks_vector
Definition: game_info.hpp:51
std::map< map_location, pathfind::paths > moves_map
The standard way in which a map of possible movement routes to location is recorded.
Definition: game_info.hpp:46
Object which defines a time of day with associated bonuses, image, sounds etc.
Definition: time_of_day.hpp:56
virtual void on_readonly_context_create() override
Definition: contexts.cpp:241
int defense_modifier(const t_translation::terrain_code &terrain) const
The unit&#39;s defense on a given terrain.
Definition: unit.cpp:1605
#define ERR_AI
Definition: contexts.cpp:68
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:72
A small explanation about what&#39;s going on here: Each action has access to two game_info objects First...
Definition: actions.cpp:61
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:375
std::shared_ptr< typesafe_aspect< T > > typesafe_aspect_ptr
Definition: game_info.hpp:58
team & get_team(int i)
Definition: game_board.hpp:97
static recall_result_ptr execute_recall_action(side_number side, bool execute, const std::string &unit_id, const map_location &where, const map_location &from)
Ask the game to recall a unit for us on specified location.
Definition: actions.cpp:1027
std::shared_ptr< recall_result > recall_result_ptr
Definition: game_info.hpp:83
void raise_gamestate_changed() const override
Notifies all interested observers of the event respectively.
Definition: contexts.cpp:95
virtual const move_map & get_enemy_srcdst() const override
Definition: contexts.cpp:587
const std::set< map_location > & get()
Definition: contexts.cpp:902
std::shared_ptr< goal > goal_ptr
Definition: game_info.hpp:100
virtual void add_aspects(std::vector< aspect_ptr > &aspects) override
Definition: contexts.cpp:424
virtual const config get_recruitment_save_gold() const override
Definition: contexts.cpp:754
int w() const
Effective map width.
Definition: map.hpp:50
virtual int get_recruitment_randomness() const override
Definition: contexts.cpp:746
map_location curr
Definition: pathfind.hpp:89
void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of &#39;ai_turn_started&#39; event.
Definition: manager.cpp:414
filter_context * filter_con
Definition: resources.cpp:24
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
Definition: tod_manager.hpp:56
virtual const std::vector< engine_ptr > & get_engines() const override
Definition: contexts.cpp:630
bool valid() const
Definition: location.hpp:89
virtual const std::vector< goal_ptr > & get_goals() const override
Definition: contexts.cpp:648
game_board * gameboard
Definition: resources.cpp:21
virtual const unit_advancements_aspect & get_advancements() const override
Definition: contexts.cpp:498
virtual ~readonly_context_impl()
Destructor.
Definition: contexts.cpp:285
void calculate_moves(const unit_map &units, std::map< map_location, pathfind::paths > &possible_moves, move_map &srcdst, move_map &dstsrc, bool enemy, bool assume_full_movement=false, const terrain_filter *remove_destinations=nullptr, bool see_all=false) const override
A more fundamental version of calculate_possible_moves which allows the use of a speculative unit map...
Definition: contexts.cpp:330
static factory_map & get_list()
Definition: engine.hpp:114
typesafe_aspect_ptr< std::vector< std::string > > recruitment_pattern_
Definition: contexts.hpp:1313
static lg::log_domain log_ai("ai/general")
virtual config to_readwrite_context_config() const override
serialize this context to config
Definition: contexts.cpp:265
virtual synced_command_result_ptr execute_synced_command_action(const std::string &lua_code, const map_location &location=map_location::null_location()) override
Ask the game to run Lua code.
Definition: contexts.cpp:149
virtual bool is_src_dst_enemy_valid_lua() const override
Definition: contexts.cpp:841
Encapsulates the map of the game.
Definition: map.hpp:171
virtual std::map< map_location, defensive_position > & defensive_position_cache() const override
Definition: contexts.cpp:493
virtual const wfl::variant & get_attacks_as_variant() const override
Definition: contexts.cpp:535
virtual const map_location & suitable_keep(const map_location &leader_location, const pathfind::paths &leader_paths) const override
get most suitable keep for leader - nearest free that can be reached in 1 turn, if none - return near...
Definition: contexts.cpp:1151
#define DBG_AI
Definition: contexts.cpp:65
bool is_enemy(int n) const
Definition: team.hpp:255
Object which temporarily resets a unit&#39;s movement.
Definition: unit.hpp:1992
const team & current_team() const override
Return a reference to the &#39;team&#39; object for the AI.
Definition: contexts.cpp:310
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands...
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()) override
Check if it is possible to recall a unit for us on specified location.
Definition: contexts.cpp:133
virtual const move_map & get_srcdst() const override
Definition: contexts.cpp:794
typesafe_aspect_ptr< double > scout_village_targeting_
Definition: contexts.hpp:1319
virtual move_result_ptr execute_move_action(const map_location &from, const map_location &to, bool remove_movement=true, bool unreach_is_ok=false) override
Ask the game to move our unit from location &#39;from&#39; to location &#39;to&#39;, optionally - doing a partial mov...
Definition: contexts.cpp:117
typesafe_aspect_ptr< config > recruitment_instructions_
Definition: contexts.hpp:1311
virtual engine_ptr get_engine_by_cfg(const config &cfg) override
get engine by cfg, creating it if it is not created yet but known
Definition: contexts.cpp:595
constexpr bool decayed_is_same
Equivalent to as std::is_same_v except both types are passed throgh std::decay first.
Definition: general.hpp:33
virtual game_info & get_info_w() override
Functions to retrieve the &#39;info&#39; object.
Definition: contexts.cpp:299
std::set< map_location > keeps_
Definition: contexts.hpp:118
virtual std::string get_grouping() const override
Definition: contexts.cpp:640
recursion_counter recursion_counter_
Definition: contexts.hpp:983
std::shared_ptr< synced_command_result > synced_command_result_ptr
Definition: game_info.hpp:88
virtual const moves_map & get_possible_moves() const override
Definition: contexts.cpp:706
Encapsulates the map of the game.
Definition: location.hpp:38
unit_iterator find(std::size_t id)
Definition: map.cpp:310
virtual void recalculate_move_maps() const override
Definition: contexts.cpp:1091
virtual int get_recursion_count() const override
Get the value of the recursion counter.
Definition: contexts.cpp:75
virtual recall_result_ptr execute_recall_action(const std::string &id, const map_location &where=map_location::null_location(), const map_location &from=map_location::null_location()) override
Ask the game to recall a unit for us on specified location.
Definition: contexts.cpp:125
virtual utils::variant< bool, std::vector< std::string > > get_passive_leader() const override
Definition: contexts.cpp:690
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:215
virtual void set_dst_src_valid_lua() override
Definition: contexts.cpp:1131
virtual bool is_dst_src_enemy_valid_lua() const override
Definition: contexts.cpp:831
virtual void set_dst_src_enemy_valid_lua() override
Definition: contexts.cpp:1136
virtual void set_src_dst_valid_lua() override
Definition: contexts.cpp:1141
void raise_user_interact()
Notifies all observers of &#39;ai_user_interact&#39; event.
Definition: manager.cpp:419
virtual bool get_simple_targeting() const override
Definition: contexts.cpp:786
virtual unit_stats_cache_t & unit_stats_cache() const override
Weapon choice cache, to speed simulations.
Definition: contexts.cpp:1194
virtual double get_recruitment_diversity() const override
Definition: contexts.cpp:714
std::vector< engine_ptr > engines_
AI Support Engines.
Definition: contexts.hpp:1279
std::size_t i
Definition: function.cpp:967
void raise_user_interact() const override
Function which should be called frequently to allow the user to interact with the interface...
Definition: contexts.cpp:90
int max_hitpoints() const
The max number of hitpoints this unit can have.
Definition: unit.hpp:496
typesafe_aspect_ptr< bool > support_villages_
Definition: contexts.hpp:1322
Game information for the AI.
void set_diagnostic(const std::string &msg)
Definition: display.cpp:1635
synced_command_result_ptr check_synced_command_action(const std::string &lua_code, const map_location &location=map_location::null_location()) override
Check if it is possible to run Lua code.
Definition: contexts.cpp:153
virtual double get_leader_value() const override
Definition: contexts.cpp:682
double g
Definition: astarsearch.cpp:65
typesafe_aspect_ptr< double > leader_aggression_
Definition: contexts.hpp:1297
static attack_result_ptr execute_attack_action(side_number side, bool execute, const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon, double aggression)
Ask the game to attack an enemy defender using our unit attacker from attackers current location...
Definition: actions.cpp:1003
attack_itors attacks()
Gets an iterator over this unit&#39;s attacks.
Definition: unit.hpp:916
typesafe_aspect_ptr< utils::variant< bool, std::vector< std::string > > > passive_leader_
Definition: contexts.hpp:1307
static recruit_result_ptr execute_recruit_action(side_number side, bool execute, const std::string &unit_name, const map_location &where, const map_location &from)
Ask the game to recruit a unit for us on specified location.
Definition: actions.cpp:1038
virtual config to_readonly_context_config() const override
serialize to config
Definition: contexts.cpp:270
virtual side_number get_side() const override
Get the side number.
Definition: contexts.hpp:401
static synced_command_result_ptr execute_synced_command_action(side_number side, bool execute, const std::string &lua_code, const map_location &location)
Ask the game to run Lua code.
Definition: actions.cpp:1060
typesafe_aspect_ptr< attacks_vector > attacks_
Definition: contexts.hpp:1286
bool on_board(const map_location &loc) const
Tell if a location is on the map.
Definition: map.cpp:385
const bool & debug
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:72
typesafe_aspect_ptr< unit_advancements_aspect > advancements_
Definition: contexts.hpp:1283
typesafe_aspect_ptr< std::vector< std::string > > recruitment_more_
Definition: contexts.hpp:1312
std::map< std::pair< map_location, const unit_type * >, std::pair< battle_context_unit_stats, battle_context_unit_stats > > unit_stats_cache_t
Definition: contexts.hpp:346
virtual void invalidate_defensive_position_cache() const override
Definition: contexts.cpp:846
Helper functions for the object which operates in the context of AI for specific side this is part of...
typesafe_aspect_ptr< std::string > grouping_
Definition: contexts.hpp:1294
config & add_child(config_key_type key)
Definition: config.cpp:514
virtual double get_aggression() const override
Definition: contexts.cpp:508
static stopunit_result_ptr execute_stopunit_action(side_number side, bool execute, const map_location &unit_location, bool remove_movement, bool remove_attacks)
Ask the game to remove unit movements and/or attack.
Definition: actions.cpp:1049
virtual const terrain_filter & get_avoid() const override
Definition: contexts.cpp:544
virtual bool is_src_dst_valid_lua() const override
Definition: contexts.cpp:836
display_chat_manager & get_chat_manager()
bool is_village(const map_location &loc) const
Definition: map.cpp:66
int turns()
Definition: game.cpp:559
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Definition: location.cpp:546
std::map< std::string, aspect_ptr > aspect_map
Definition: game_info.hpp:104
virtual void invalidate_move_maps() const override
Definition: contexts.cpp:861
virtual double get_caution() const override
Definition: contexts.cpp:555
#define WRN_AI
Definition: contexts.cpp:67
UNIT_ALIGNMENT alignment() const
The alignment of this unit.
Definition: unit.hpp:466
std::vector< std::string > split(const config_attribute_value &val)
virtual attack_result_ptr execute_attack_action(const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon) override
Ask the game to attack an enemy defender using our unit attacker from attackers current location...
Definition: contexts.cpp:105
typesafe_aspect_ptr< utils::variant< bool, std::vector< std::string > > > leader_ignores_keep_
Definition: contexts.hpp:1299
virtual utils::variant< bool, std::vector< std::string > > get_leader_ignores_keep() const override
Definition: contexts.cpp:674
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:369
known_aspect_map known_aspects_
Definition: contexts.hpp:1281
A variable-expanding proxy for the config class.
Definition: variable.hpp:44
bool contains(const map_location &) const
Definition: pathfind.cpp:515
Standard logging facilities (interface).
const gamemap * map_
Definition: contexts.hpp:117
Object which contains all the possible locations a unit can move to, with associated best routes to t...
Definition: pathfind.hpp:72
static const map_location & null_location()
Definition: location.hpp:81
Container associating units to locations.
Definition: map.hpp:98
int get_count() const
Get the current value of the recursion counter.
Definition: contexts.hpp:70
typesafe_aspect_ptr< int > recruitment_randomness_
Definition: contexts.hpp:1314
void handle_generic_event(const std::string &event_name)
Definition: contexts.cpp:856
virtual config to_side_context_config() const override
serialize this context to config
Definition: contexts.cpp:260
typesafe_aspect_ptr< double > recruitment_diversity_
Definition: contexts.hpp:1310
virtual int get_recursion_count() const override
Get the value of the recursion counter.
Definition: contexts.cpp:85
int turn() const
#define e
int side() const
The side this unit belongs to.
Definition: unit.hpp:334
virtual const map_location & nearest_keep(const map_location &loc) const override
Definition: contexts.cpp:947
typesafe_aspect_ptr< double > aggression_
Definition: contexts.hpp:1284
std::shared_ptr< engine > engine_ptr
Definition: game_info.hpp:99
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
virtual const game_info & get_info() const override
Definition: contexts.cpp:295
bool valid() const
Definition: map.hpp:274
virtual double get_village_value() const override
Definition: contexts.cpp:810
typesafe_aspect_ptr< utils::variant< bool, std::vector< std::string > > > passive_leader_shares_keep_
Definition: contexts.hpp:1308
attack_result_ptr check_attack_action(const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon) override
Check if it is possible to attack enemy defender using our unit attacker from attackers current locat...
Definition: contexts.cpp:111
virtual void recalculate_move_maps_enemy() const override
Definition: contexts.cpp:1118
static map_location::DIRECTION n
typesafe_aspect_ptr< config > recruitment_save_gold_
Definition: contexts.hpp:1315
int h() const
Effective map height.
Definition: map.hpp:53
This module contains various pathfinding functions and utilities.
virtual const move_map & get_dstsrc() const override
Definition: contexts.cpp:563
typesafe_aspect_ptr< double > village_value_
Definition: contexts.hpp:1324
std::string::const_iterator iterator
Definition: tokenizer.hpp:25
virtual bool is_passive_leader(const std::string &id) const override
Definition: contexts.cpp:1241
void diagnostic(const std::string &msg) override
Show a diagnostic message on the screen.
Definition: contexts.cpp:303
static move_result_ptr execute_move_action(side_number side, bool execute, const map_location &from, const map_location &to, bool remove_movement, bool unreach_is_ok=false)
Ask the game to move our unit from location &#39;from&#39; to location &#39;to&#39;, optionally - doing a partial mov...
Definition: actions.cpp:1015
virtual bool is_dst_src_valid_lua() const override
Definition: contexts.cpp:826
virtual double get_leader_aggression() const override
Definition: contexts.cpp:658
void add_map_changed_observer(events::observer *event_observer)
Adds an observer of &#39;ai_map_changed&#39; event.
Definition: manager.cpp:389
static game_display * get_singleton()
virtual void add_facet(const std::string &id, const config &cfg) const override
Definition: contexts.cpp:437
void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of &#39;ai_map_changed&#39; event.
Definition: manager.cpp:409