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