The Battle for Wesnoth  1.19.12+dev
contexts.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2025
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/game_info.hpp" // for typesafe_aspect_ptr, etc
32 #include "ai/manager.hpp" // for manager
33 
34 #include "chat_events.hpp" // for chat_handler, etc
35 #include "config.hpp" // for config, etc
36 #include "display_chat_manager.hpp"
37 #include "game_board.hpp" // for game_board
38 #include "game_config.hpp" // for debug
39 #include "game_display.hpp" // for game_display
40 #include "log.hpp" // for LOG_STREAM, logger, etc
41 #include "map/map.hpp" // for gamemap
42 #include "pathfind/pathfind.hpp" // for paths::dest_vect, paths, etc
43 #include "resources.hpp" // for units, gameboard, etc
44 #include "serialization/string_utils.hpp" // for split, etc
45 #include "team.hpp" // for team
46 #include "terrain/filter.hpp" // for terrain_filter
47 #include "terrain/translation.hpp" // for terrain_code
48 #include "time_of_day.hpp" // for time_of_day
49 #include "tod_manager.hpp" // for tod_manager
50 #include "units/unit.hpp" // for unit
52 #include "units/map.hpp" // for unit_map::iterator_base, etc
53 #include "formula/variant.hpp" // for variant
54 
55 #include <algorithm> // for find, count, max, fill_n
56 #include <cmath> // for sqrt
57 #include <cstdlib> // for abs
58 #include <ctime> // for time
59 #include <iterator> // for back_inserter
60 #include <ostream> // for operator<<, basic_ostream, etc
61 
62 static lg::log_domain log_ai("ai/general");
63 #define DBG_AI LOG_STREAM(debug, log_ai)
64 #define LOG_AI LOG_STREAM(info, log_ai)
65 #define WRN_AI LOG_STREAM(warn, log_ai)
66 #define ERR_AI LOG_STREAM(err, log_ai)
67 
68 // =======================================================================
69 //
70 // =======================================================================
71 namespace ai {
72 
74 {
76 }
77 
79 {
81 }
82 
84 {
86 }
87 
89 {
91 }
92 
94 {
96 }
97 
99 {
101 }
102 
103 attack_result_ptr readwrite_context_impl::execute_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
105  double m_aggression = i.valid() && i->can_recruit() ? get_leader_aggression() : get_aggression();
106  return actions::execute_attack_action(get_side(),true,attacker_loc,defender_loc,attacker_weapon, m_aggression);
107 }
108 
109 attack_result_ptr readonly_context_impl::check_attack_action(const map_location& attacker_loc, const map_location& defender_loc, int attacker_weapon){
111  double m_aggression = i.valid() && i->can_recruit() ? get_leader_aggression() : get_aggression();
112  return actions::execute_attack_action(get_side(),false,attacker_loc,defender_loc,attacker_weapon, m_aggression);
113 }
114 
115 move_result_ptr readwrite_context_impl::execute_move_action(const map_location& from, const map_location& to, bool remove_movement, bool unreach_is_ok){
116  return actions::execute_move_action(get_side(),true,from,to,remove_movement,unreach_is_ok);
117 }
118 
119 move_result_ptr readonly_context_impl::check_move_action(const map_location& from, const map_location& to, bool remove_movement, bool unreach_is_ok){
120  return actions::execute_move_action(get_side(),false,from,to,remove_movement,unreach_is_ok);
121 }
122 
124  return actions::execute_recall_action(get_side(),true,id,where,from);
125 }
126 
128  return actions::execute_recruit_action(get_side(),true,unit_name,where,from);
129 }
130 
132  return actions::execute_recall_action(get_side(),false,id,where,from);
133 }
134 
136  return actions::execute_recruit_action(get_side(),false,unit_name,where,from);
137 }
138 
139 stopunit_result_ptr readwrite_context_impl::execute_stopunit_action(const map_location& unit_location, bool remove_movement, bool remove_attacks){
140  return actions::execute_stopunit_action(get_side(),true,unit_location,remove_movement,remove_attacks);
141 }
142 
143 stopunit_result_ptr readonly_context_impl::check_stopunit_action(const map_location& unit_location, bool remove_movement, bool remove_attacks){
144  return actions::execute_stopunit_action(get_side(),false,unit_location,remove_movement,remove_attacks);
145 }
146 
148  return actions::execute_synced_command_action(get_side(),true,lua_code,location);
149 }
150 
152  return actions::execute_synced_command_action(get_side(),false,lua_code,location);
153 }
154 
155 template<typename T>
157 {
158  known_aspects_.emplace(name, std::make_shared<typesafe_known_aspect<T>>(name, where, aspects_));
159 }
160 
162  : cfg_(cfg),
163  engines_(),
164  known_aspects_(),
165  advancements_(),
166  aggression_(),
167  allow_ally_villages_(),
168  aspects_(),
169  attacks_(),
170  avoid_(),
171  caution_(),
172  defensive_position_cache_(),
173  dstsrc_(),enemy_dstsrc_(),
174  enemy_possible_moves_(),
175  enemy_srcdst_(),
176  grouping_(),
177  goals_(),
178  keeps_(),
179  leader_aggression_(),
180  leader_goal_(),
181  leader_ignores_keep_(),
182  leader_value_(),
183  move_maps_enemy_valid_(false),
184  move_maps_valid_(false),
185  dst_src_valid_lua_(false),
186  dst_src_enemy_valid_lua_(false),
187  src_dst_valid_lua_(false),
188  src_dst_enemy_valid_lua_(false),
189  passive_leader_(),
190  passive_leader_shares_keep_(),
191  possible_moves_(),
192  recruitment_diversity_(),
193  recruitment_instructions_(),
194  recruitment_more_(),
195  recruitment_pattern_(),
196  recruitment_randomness_(),
197  recruitment_save_gold_(),
198  recursion_counter_(context.get_recursion_count()),
199  retreat_enemy_weight_(),
200  retreat_factor_(),
201  scout_village_targeting_(),
202  simple_targeting_(),
203  srcdst_(),
204  support_villages_(),
205  unit_stats_cache_(),
206  village_value_(),
207  villages_per_scout_()
208 {
209  init_side_context_proxy(context);
211 
212  add_known_aspect("advancements", advancements_);
213  add_known_aspect("aggression",aggression_);
214  add_known_aspect("allow_ally_villages",allow_ally_villages_);
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::chrono::system_clock::now(), "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(const team& t : resources::gameboard->teams()) {
401  if(t.owns_village(dst)) {
402  int side = t.side();
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<<"]";
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<<"]";
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 =
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  auto itors = srcdst.equal_range(loc);
471  for(auto i = itors.first; i != itors.second; ++i) {
472  const int defense = itor->defense_modifier(resources::gameboard->map().get_terrain(i->second));
473  if(defense > pos.chance_to_hit) {
474  continue;
475  }
476 
477  const double vulnerability = power_projection(i->second,enemy_dstsrc);
478  const double support = power_projection(i->second,dstsrc);
479 
480  if(defense < pos.chance_to_hit || support - vulnerability > pos.support - pos.vulnerability) {
481  pos.loc = i->second;
482  pos.chance_to_hit = defense;
483  pos.vulnerability = vulnerability;
484  pos.support = support;
485  }
486  }
487 
488  defensive_position_cache_.emplace(loc, pos);
490 }
491 
492 std::map<map_location,defensive_position>& readonly_context_impl::defensive_position_cache() const
493 {
495 }
496 
498 {
499  if (advancements_) {
500  return advancements_->get();
501  }
502 
504  return uaa;
505 }
506 
508 {
509  if (aggression_) {
510  return aggression_->get();
511  }
512  return 0;
513 }
514 
516 {
517  if (allow_ally_villages_) {
518  return allow_ally_villages_->get();
519  }
520  return false;
521 }
522 
524 {
525  return aspects_;
526 }
527 
529 {
530  return aspects_;
531 }
532 
534 {
535  if (attacks_) {
536  return attacks_->get();
537  }
538  static attacks_vector av;
539  return av;
540 }
541 
543 {
544  if (attacks_) {
545  return attacks_->get_variant();
546  }
547  static wfl::variant v;
548  return v;
549 }
550 
551 const terrain_filter& readonly_context_impl::get_avoid() const
552 {
553  if (avoid_) {
554  return avoid_->get();
555  }
556  config cfg;
557  cfg.add_child("not");
558  static terrain_filter tf(vconfig(cfg, true), resources::filter_con, false);
559  return tf;
560 }
561 
563 {
564  if (caution_) {
565  return caution_->get();
566  }
567  return 0;
568 }
569 
571 {
572  if (!move_maps_valid_) {
574  }
575  return dstsrc_;
576 }
577 
579 {
580  if (!move_maps_enemy_valid_) {
582  }
583  return enemy_dstsrc_;
584 }
585 
587 {
588  if (!move_maps_enemy_valid_) {
590  }
591  return enemy_possible_moves_;
592 }
593 
595 {
596  if (!move_maps_enemy_valid_) {
598  }
599  return enemy_srcdst_;
600 }
601 
603 {
604  std::string engine_name = cfg["engine"];
605  if (engine_name.empty()) {
606  engine_name="cpp";//default engine
607  }
608 
610  while (en!=engines_.end() && ((*en)->get_name()!=engine_name) && ((*en)->get_id()!=engine_name)) {
611  ++en;
612  }
613 
614  if (en != engines_.end()){
615  return *en;
616  }
617 
619  if (eng == engine_factory::get_list().end()){
620  ERR_AI << "side "<<get_side()<<" : UNABLE TO FIND engine["<<
621  engine_name << ']';
622  DBG_AI << "config snippet contains: " << std::endl << cfg;
623  return engine_ptr();
624  }
625 
626  engine_ptr new_engine = eng->second->get_new_instance(*this,engine_name);
627  if (!new_engine) {
628  ERR_AI << "side "<<get_side()<<" : UNABLE TO CREATE engine["<<
629  engine_name << ']';
630  DBG_AI << "config snippet contains: " << std::endl << cfg;
631  return engine_ptr();
632  }
633  engines_.push_back(new_engine);
634  return engines_.back();
635 }
636 
637 const std::vector<engine_ptr>& readonly_context_impl::get_engines() const
638 {
639  return engines_;
640 }
641 
642 std::vector<engine_ptr>& readonly_context_impl::get_engines()
643 {
644  return engines_;
645 }
646 
648 {
649  if (grouping_) {
650  return grouping_->get();
651  }
652  return std::string();
653 }
654 
655 const std::vector<goal_ptr>& readonly_context_impl::get_goals() const
656 {
657  return goals_;
658 }
659 
660 std::vector<goal_ptr>& readonly_context_impl::get_goals()
661 {
662  return goals_;
663 }
664 
666 {
667  if (leader_aggression_) {
668  return leader_aggression_->get();
669  }
670  return 0;
671 }
672 
674 {
675  if (leader_goal_) {
676  return leader_goal_->get();
677  }
678  return config();
679 }
680 
681 utils::variant<bool, std::vector<std::string>> readonly_context_impl::get_leader_ignores_keep() const
682 {
683  if (leader_ignores_keep_) {
684  return leader_ignores_keep_->get();
685  }
686  return {};
687 }
688 
690 {
691  if (leader_value_) {
692  return leader_value_->get();
693  }
694  return 0;
695 }
696 
697 utils::variant<bool, std::vector<std::string>> readonly_context_impl::get_passive_leader() const
698 {
699  if (passive_leader_) {
700  return passive_leader_->get();
701  }
702  return {};
703 }
704 
705 utils::variant<bool, std::vector<std::string>> readonly_context_impl::get_passive_leader_shares_keep() const
706 {
708  return passive_leader_shares_keep_->get();
709  }
710  return {};
711 }
712 
714 {
715  if (!move_maps_valid_) {
717  }
718  return possible_moves_;
719 }
720 
722 {
724  return recruitment_diversity_->get();
725  }
726  return 0.;
727 }
728 
730 {
732  return recruitment_instructions_->get();
733  }
734  return config();
735 }
736 
737 const std::vector<std::string> readonly_context_impl::get_recruitment_more() const
738 {
739  if (recruitment_more_) {
740  return recruitment_more_->get();
741  }
742  return std::vector<std::string>();
743 }
744 
745 const std::vector<std::string> readonly_context_impl::get_recruitment_pattern() const
746 {
747  if (recruitment_pattern_) {
748  return recruitment_pattern_->get();
749  }
750  return std::vector<std::string>();
751 }
752 
754 {
756  return recruitment_randomness_->get();
757  }
758  return 0;
759 }
760 
762 {
764  return recruitment_save_gold_->get();
765  }
766  return config();
767 }
768 
770 {
771  if (retreat_enemy_weight_) {
772  return retreat_enemy_weight_->get();
773  }
774  return 1;
775 }
776 
778 {
779  if (retreat_factor_) {
780  return retreat_factor_->get();
781  }
782  return 1;
783 }
784 
786 {
788  return scout_village_targeting_->get();
789  }
790  return 1;
791 }
792 
794 {
795  if (simple_targeting_) {
796  return simple_targeting_->get();
797  }
798  return false;
799 }
800 
802 {
803  if (!move_maps_valid_) {
805  }
806  return srcdst_;
807 }
808 
810 {
811  if (support_villages_) {
812  return support_villages_->get();
813  }
814  return false;
815 }
816 
818 {
819  if (village_value_) {
820  return village_value_->get();
821  }
822  return 0;
823 }
824 
826 {
827  if (villages_per_scout_) {
828  return villages_per_scout_->get();
829  }
830  return 0;
831 }
832 
834 {
835  return dst_src_valid_lua_;
836 }
837 
839 {
841 }
842 
844 {
845  return src_dst_valid_lua_;
846 }
847 
849 {
851 }
852 
854 {
856 }
857 
859 {
860  keeps_.clear();
861 }
862 
863 void keeps_cache::handle_generic_event(const std::string &/*event_name*/)
864 {
865  clear();
866 }
867 
869 {
870  move_maps_valid_ = false;
871  move_maps_enemy_valid_ = false;
872 
873  dst_src_valid_lua_ = false;
874  dst_src_enemy_valid_lua_ = false;
875 
876  src_dst_valid_lua_ = false;
877  src_dst_enemy_valid_lua_ = false;
878 }
879 
880 const std::set<map_location>& readonly_context_impl::keeps() const
881 {
882  return keeps_.get();
883 }
884 
886  : map_(nullptr)
887  , keeps_()
888 {
891 }
892 
894 {
897 }
898 
900 {
901  keeps_.clear();
902 }
903 
904 void keeps_cache::init(const gamemap &map)
905 {
906  map_ = &map;
907 }
908 
909 const std::set<map_location>& keeps_cache::get()
910 {
911  if(keeps_.empty()) {
912  // Generate the list of keeps:
913  // iterate over the entire map and find all keeps.
914  for(int x = 0; x != map_->w(); ++x) {
915  for(int y = 0; y != map_->h(); ++y) {
916  const map_location loc(x,y);
917  if(map_->is_keep(loc)) {
918  for(const map_location& adj : get_adjacent_tiles(loc)) {
919  if(map_->is_castle(adj)) {
920  keeps_.insert(loc);
921  break;
922  }
923  }
924  }
925  }
926  }
927  }
928 
929  return keeps_;
930 }
931 
933 {
935  if(leader == resources::gameboard->units().end() || leader->incapacitated()) {
936  return false;
937  }
938 
939  const map_location &start_pos = nearest_keep(leader->get_location());
940  if(start_pos.valid() == false) {
941  return false;
942  }
943 
944  if (leader->get_location() == start_pos) {
945  return true;
946  }
947 
948  // Find where the leader can move
949  const pathfind::paths leader_paths(*leader, false, true, current_team());
950 
951  return leader_paths.destinations.contains(start_pos);
952 }
953 
955 {
956  std::set<map_location> avoided_locations;
957  get_avoid().get_locations(avoided_locations);
958  const std::set<map_location>& keeps = this->keeps();
959  if(keeps.empty()) {
960  static const map_location dummy;
961  return dummy;
962  }
963 
964  const map_location* res = nullptr;
965  int closest = -1;
966  for(std::set<map_location>::const_iterator i = keeps.begin(); i != keeps.end(); ++i) {
967  if (avoided_locations.find(*i)!=avoided_locations.end()) {
968  continue;
969  }
970  const int distance = distance_between(*i,loc);
971  if(res == nullptr || distance < closest) {
972  closest = distance;
973  res = &*i;
974  }
975  }
976  if (res) {
977  return *res;
978  } else {
980  }
981 }
982 
984 {
985  map_location used_locs[6];
986  int ratings[6];
987  std::fill_n(ratings, 0, 6);
988  int num_used_locs = 0;
989 
990  const auto locs = get_adjacent_tiles(loc);
991 
992  const gamemap& map_ = resources::gameboard->map();
993  unit_map& units_ = resources::gameboard->units();
994 
995  int res = 0;
996 
997  bool changed = false;
998  for (int i = 0;; ++i) {
999  if (i == 6) {
1000  if (!changed) break;
1001  // Loop once again, in case a unit found a better spot
1002  // and freed the place for another unit.
1003  changed = false;
1004  i = 0;
1005  }
1006 
1007  if (map_.on_board(locs[i]) == false) {
1008  continue;
1009  }
1010 
1011  const t_translation::terrain_code terrain = map_[locs[i]];
1012 
1013  auto its = dstsrc.equal_range(locs[i]);
1014 
1015  map_location* const beg_used = used_locs;
1016  map_location* end_used = used_locs + num_used_locs;
1017 
1018  int best_rating = 0;
1019  map_location best_unit;
1020 
1021  for(auto it = its.first; it != its.second; ++it) {
1022  const unit_map::const_iterator u = units_.find(it->second);
1023 
1024  // Unit might have been killed, and no longer exist
1025  if(u == units_.end()) {
1026  continue;
1027  }
1028 
1029  const unit& un = *u;
1030 
1031  // The unit might play on the next turn
1032  int attack_turn = resources::tod_manager->turn();
1033  if(un.side() < get_side()) {
1034  ++attack_turn;
1035  }
1036  // Considering the unit location would be too slow, we only apply the bonus granted by the global ToD
1037  const int lawful_bonus = resources::tod_manager->get_time_of_day(attack_turn).lawful_bonus;
1038  int tod_modifier = 0;
1039  if(un.alignment() == unit_alignments::type::lawful) {
1040  tod_modifier = lawful_bonus;
1041  } else if(un.alignment() == unit_alignments::type::chaotic) {
1042  tod_modifier = -lawful_bonus;
1043  } else if(un.alignment() == unit_alignments::type::liminal) {
1044  tod_modifier = -(std::abs(lawful_bonus));
1045  }
1046 
1047  // The 0.5 power avoids underestimating too much the damage of a wounded unit.
1048  int64_t hp = static_cast<int>(std::sqrt(static_cast<double>(un.hitpoints()) / un.max_hitpoints()) * 1000);
1049  int64_t most_damage = 0;
1050  for(const attack_type &att : un.attacks())
1051  {
1052  int damage = att.damage() * att.num_attacks() * (100 + tod_modifier);
1053  if (damage > most_damage) {
1054  most_damage = damage;
1055  }
1056  }
1057 
1058  int64_t village_bonus = map_.is_village(terrain) ? 3 : 2;
1059  int64_t defense = 100 - un.defense_modifier(terrain);
1060  int64_t rating_64 = hp * defense * most_damage * village_bonus / 200;
1061  int rating = rating_64;
1062  if(static_cast<int64_t>(rating) != rating_64) {
1063  WRN_AI << "overflow in ai attack calculation";
1064  }
1065  if(rating > best_rating) {
1066  map_location *pos = std::find(beg_used, end_used, it->second);
1067  // Check if the spot is the same or better than an older one.
1068  if (pos == end_used || rating >= ratings[pos - beg_used]) {
1069  best_rating = rating;
1070  best_unit = it->second;
1071  }
1072  }
1073  }
1074 
1075  if (!best_unit.valid()) continue;
1076  map_location *pos = std::find(beg_used, end_used, best_unit);
1077  int index = pos - beg_used;
1078  if (index == num_used_locs)
1079  ++num_used_locs;
1080  else if (best_rating == ratings[index])
1081  continue;
1082  else {
1083  // The unit was in another spot already, so remove its older rating
1084  // from the final result, and require a new run to fill its old spot.
1085  res -= ratings[index];
1086  changed = true;
1087  }
1088  used_locs[index] = best_unit;
1089  ratings[index] = best_rating;
1090  res += best_rating;
1091  }
1092 
1093  return res / 100000.;
1094 }
1095 
1097 {
1098  dstsrc_ = move_map();
1100  srcdst_ = move_map();
1104  if (i.valid()) {
1105  map_location loc = i->get_location();
1106  srcdst_.erase(loc);
1107  for(move_map::iterator it = dstsrc_.begin(); it != dstsrc_.end(); ) {
1108  if(it->second == loc) {
1109  it = dstsrc_.erase(it);
1110  } else {
1111  ++it;
1112  }
1113  }
1114  }
1115  }
1116  move_maps_valid_ = true;
1117 
1118  // invalidate lua cache
1119  dst_src_valid_lua_ = false;
1120  src_dst_valid_lua_ = false;
1121 }
1122 
1124 {
1125  enemy_dstsrc_ = move_map();
1126  enemy_srcdst_ = move_map();
1129  move_maps_enemy_valid_ = true;
1130 
1131  // invalidate lua cache
1132  dst_src_enemy_valid_lua_ = false;
1133  src_dst_enemy_valid_lua_ = false;
1134 }
1135 
1137 {
1138  dst_src_valid_lua_ = true;
1139 }
1140 
1142 {
1143  dst_src_enemy_valid_lua_ = true;
1144 }
1145 
1147 {
1148  src_dst_valid_lua_ = true;
1149 }
1150 
1152 {
1153  src_dst_enemy_valid_lua_ = true;
1154 }
1155 
1156 const map_location& readonly_context_impl::suitable_keep(const map_location& leader_location, const pathfind::paths& leader_paths) const {
1157  if (resources::gameboard->map().is_keep(leader_location)) {
1158  return leader_location; //if leader already on keep, then return leader_location
1159  }
1160 
1161  map_location const* best_free_keep = &map_location::null_location();
1162  double move_left_at_best_free_keep = 0.0;
1163 
1164  map_location const* best_occupied_keep = &map_location::null_location();
1165  double move_left_at_best_occupied_keep = 0.0;
1166 
1167  for(const pathfind::paths::step &dest : leader_paths.destinations)
1168  {
1169  const map_location &loc = dest.curr;
1170  if (keeps().find(loc)!=keeps().end()){
1171 
1172  const int move_left_at_loc = dest.move_left;
1173  if (resources::gameboard->units().count(loc) == 0) {
1174  if ((*best_free_keep==map_location::null_location())||(move_left_at_loc>move_left_at_best_free_keep)){
1175  best_free_keep = &loc;
1176  move_left_at_best_free_keep = move_left_at_loc;
1177  }
1178  } else {
1179  if ((*best_occupied_keep==map_location::null_location())||(move_left_at_loc>move_left_at_best_occupied_keep)){
1180  best_occupied_keep = &loc;
1181  move_left_at_best_occupied_keep = move_left_at_loc;
1182  }
1183  }
1184  }
1185  }
1186 
1187  if (*best_free_keep != map_location::null_location()){
1188  return *best_free_keep; // if there is a free keep reachable during current turn, return it
1189  }
1190 
1191  if (*best_occupied_keep != map_location::null_location()){
1192  return *best_occupied_keep; // if there is an occupied keep reachable during current turn, return it
1193  }
1194 
1195  return nearest_keep(leader_location); // return nearest keep
1196 }
1197 
1198  /** Weapon choice cache, to speed simulations. */
1200 {
1201  return unit_stats_cache_;
1202 }
1203 
1204 bool readonly_context_impl::is_active(const std::string &time_of_day, const std::string &turns) const
1205 {
1206  if(time_of_day.empty() == false) {
1207  const std::vector<std::string>& times = utils::split(time_of_day);
1208  if(std::count(times.begin(),times.end(),resources::tod_manager->get_time_of_day().id) == 0) {
1209  return false;
1210  }
1211  }
1212 
1213  if(turns.empty() == false) {
1214  int turn = resources::tod_manager->turn();
1215  const std::vector<std::string>& turns_list = utils::split(turns);
1216  for(std::vector<std::string>::const_iterator j = turns_list.begin(); j != turns_list.end() ; ++j ) {
1217  const std::pair<int,int> range = utils::parse_range(*j);
1218  if(turn >= range.first && turn <= range.second) {
1219  return true;
1220  }
1221  }
1222  return false;
1223  }
1224  return true;
1225 }
1226 
1228  const utils::variant<bool, std::vector<std::string>>& aspect_value, const std::string& id) const
1229 {
1230  return utils::visit(
1231  [&id](const auto& v) {
1232  if constexpr(utils::decayed_is_same<bool, decltype(v)>) {
1233  return v;
1234  } else {
1235  return utils::contains(v, id);
1236  }
1237  },
1238  aspect_value);
1239 }
1240 
1241 bool readonly_context_impl::is_keep_ignoring_leader(const std::string &id) const
1242 {
1243  return applies_to_leader(leader_ignores_keep_->get(), id);
1244 }
1245 
1246 bool readonly_context_impl::is_passive_leader(const std::string &id) const
1247 {
1248  return applies_to_leader(passive_leader_->get(), id);
1249 }
1250 
1252 {
1254 }
1255 
1256 } //of namespace ai
Various functions that implement attacks and attack calculations.
map_location loc
Definition: move.cpp:172
Managing the AI-Game interaction - AI actions and their results.
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands.
static auto & dummy
double t
Definition: astarsearch.cpp:63
double g
Definition: astarsearch.cpp:63
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:1054
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:1087
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:1030
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:1042
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:1065
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:1076
static factory_map & get_list()
Definition: engine.hpp:110
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:113
void handle_generic_event(const std::string &event_name)
Definition: contexts.cpp:863
const std::set< map_location > & get()
Definition: contexts.cpp:909
void init(const gamemap &map)
Definition: contexts.cpp:904
std::set< map_location > keeps_
Definition: contexts.hpp:114
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:380
void raise_gamestate_changed()
Notifies all observers of 'ai_gamestate_changed' event.
Definition: manager.cpp:448
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:374
void raise_user_interact()
Notifies all observers of 'ai_user_interact' event.
Definition: manager.cpp:424
game_info & get_active_ai_info_for_side(side_number side)
Gets AI info for active AI of the given side.
Definition: manager.cpp:712
void add_map_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_map_changed' event.
Definition: manager.cpp:394
static manager & get_singleton()
Definition: manager.hpp:140
void add_turn_started_observer(events::observer *event_observer)
Adds an observer of 'ai_turn_started' event.
Definition: manager.cpp:404
void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of 'ai_turn_started' event.
Definition: manager.cpp:419
void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_map_changed' event.
Definition: manager.cpp:414
virtual double get_caution() const override
Definition: contexts.cpp:562
virtual ~readonly_context_impl()
Destructor.
Definition: contexts.cpp:285
virtual void recalculate_move_maps_enemy() const override
Definition: contexts.cpp:1123
std::map< map_location, defensive_position > defensive_position_cache_
Definition: contexts.hpp:1292
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:143
typesafe_aspect_ptr< utils::variant< bool, std::vector< std::string > > > passive_leader_
Definition: contexts.hpp:1310
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:135
virtual bool is_keep_ignoring_leader(const std::string &id) const override
Definition: contexts.cpp:1241
virtual const move_map & get_srcdst() const override
Definition: contexts.cpp:801
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
typesafe_aspect_ptr< std::vector< std::string > > recruitment_more_
Definition: contexts.hpp:1315
virtual bool is_active(const std::string &time_of_day, const std::string &turns) const override
Definition: contexts.cpp:1204
virtual const move_map & get_dstsrc() const override
Definition: contexts.cpp:570
virtual const std::vector< std::string > get_recruitment_pattern() const override
Definition: contexts.cpp:745
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
virtual bool get_simple_targeting() const override
Definition: contexts.cpp:793
typesafe_aspect_ptr< bool > support_villages_
Definition: contexts.hpp:1325
virtual bool is_passive_keep_sharing_leader(const std::string &id) const override
Definition: contexts.cpp:1251
unit_stats_cache_t unit_stats_cache_
Definition: contexts.hpp:1326
void add_known_aspect(const std::string &name, typesafe_aspect_ptr< T > &where)
Definition: contexts.cpp:156
virtual void add_facet(const std::string &id, const config &cfg) const override
Definition: contexts.cpp:437
virtual bool get_allow_ally_villages() const override
Definition: contexts.cpp:515
virtual std::map< map_location, defensive_position > & defensive_position_cache() const override
Definition: contexts.cpp:492
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:109
virtual const std::vector< goal_ptr > & get_goals() const override
Definition: contexts.cpp:655
virtual const game_info & get_info() const override
Definition: contexts.cpp:295
virtual void recalculate_move_maps() const override
Definition: contexts.cpp:1096
typesafe_aspect_ptr< terrain_filter > avoid_
Definition: contexts.hpp:1290
virtual bool is_dst_src_valid_lua() const override
Definition: contexts.cpp:833
typesafe_aspect_ptr< bool > simple_targeting_
Definition: contexts.hpp:1323
virtual const move_map & get_enemy_srcdst() const override
Definition: contexts.cpp:594
virtual double get_recruitment_diversity() const override
Definition: contexts.cpp:721
virtual bool is_src_dst_enemy_valid_lua() const override
Definition: contexts.cpp:848
void raise_user_interact() const override
Function which should be called frequently to allow the user to interact with the interface.
Definition: contexts.cpp:88
virtual double get_retreat_enemy_weight() const override
Definition: contexts.cpp:769
virtual const std::vector< engine_ptr > & get_engines() const override
Definition: contexts.cpp:637
virtual const attacks_vector & get_attacks() const override
Definition: contexts.cpp:533
typesafe_aspect_ptr< attacks_vector > attacks_
Definition: contexts.hpp:1289
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:1156
virtual void invalidate_move_maps() const override
Definition: contexts.cpp:868
virtual const terrain_filter & get_avoid() const override
Definition: contexts.cpp:551
virtual int get_recursion_count() const override
Get the value of the recursion counter.
Definition: contexts.cpp:78
bool applies_to_leader(const utils::variant< bool, std::vector< std::string >> &aspect_value, const std::string &id) const
Definition: contexts.cpp:1227
virtual int get_villages_per_scout() const override
Definition: contexts.cpp:825
virtual config get_leader_goal() const override
Definition: contexts.cpp:673
virtual void invalidate_keeps_cache() const override
Definition: contexts.cpp:858
virtual double get_leader_aggression() const override
Definition: contexts.cpp:665
readonly_context_impl(side_context &context, const config &cfg)
Constructor.
Definition: contexts.cpp:161
virtual const aspect_map & get_aspects() const override
Definition: contexts.cpp:523
virtual const move_map & get_enemy_dstsrc() const override
Definition: contexts.cpp:578
virtual double get_village_value() const override
Definition: contexts.cpp:817
typesafe_aspect_ptr< int > recruitment_randomness_
Definition: contexts.hpp:1317
virtual bool is_passive_leader(const std::string &id) const override
Definition: contexts.cpp:1246
const team & current_team() const override
Return a reference to the 'team' object for the AI.
Definition: contexts.cpp:310
typesafe_aspect_ptr< int > villages_per_scout_
Definition: contexts.hpp:1328
virtual unit_stats_cache_t & unit_stats_cache() const override
Weapon choice cache, to speed simulations.
Definition: contexts.cpp:1199
virtual void set_dst_src_valid_lua() override
Definition: contexts.cpp:1136
typesafe_aspect_ptr< double > recruitment_diversity_
Definition: contexts.hpp:1313
typesafe_aspect_ptr< double > village_value_
Definition: contexts.hpp:1327
virtual void set_src_dst_enemy_valid_lua() override
Definition: contexts.cpp:1151
recursion_counter recursion_counter_
Definition: contexts.hpp:1319
virtual const moves_map & get_enemy_possible_moves() const override
Definition: contexts.cpp:586
void log_message(const std::string &msg) override
Display a debug message as a chat message.
Definition: contexts.cpp:315
virtual const map_location & nearest_keep(const map_location &loc) const override
Definition: contexts.cpp:954
typesafe_aspect_ptr< unit_advancements_aspect > advancements_
Definition: contexts.hpp:1285
typesafe_aspect_ptr< double > retreat_factor_
Definition: contexts.hpp:1321
virtual const config get_recruitment_instructions() const override
Definition: contexts.cpp:729
virtual double get_aggression() const override
Definition: contexts.cpp:507
known_aspect_map known_aspects_
Definition: contexts.hpp:1283
typesafe_aspect_ptr< double > retreat_enemy_weight_
Definition: contexts.hpp:1320
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:151
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:983
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
virtual void invalidate_defensive_position_cache() const override
Definition: contexts.cpp:853
virtual utils::variant< bool, std::vector< std::string > > get_passive_leader() const override
Definition: contexts.cpp:697
typesafe_aspect_ptr< double > leader_value_
Definition: contexts.hpp:1303
typesafe_aspect_ptr< config > recruitment_instructions_
Definition: contexts.hpp:1314
std::vector< engine_ptr > engines_
AI Support Engines.
Definition: contexts.hpp:1281
typesafe_aspect_ptr< utils::variant< bool, std::vector< std::string > > > passive_leader_shares_keep_
Definition: contexts.hpp:1311
virtual bool is_src_dst_valid_lua() const override
Definition: contexts.cpp:843
virtual void add_aspects(std::vector< aspect_ptr > &aspects) override
Definition: contexts.cpp:424
virtual bool is_dst_src_enemy_valid_lua() const override
Definition: contexts.cpp:838
virtual utils::variant< bool, std::vector< std::string > > get_passive_leader_shares_keep() const override
Definition: contexts.cpp:705
virtual double get_leader_value() const override
Definition: contexts.cpp:689
typesafe_aspect_ptr< double > scout_village_targeting_
Definition: contexts.hpp:1322
virtual utils::variant< bool, std::vector< std::string > > get_leader_ignores_keep() const override
Definition: contexts.cpp:681
virtual const std::vector< std::string > get_recruitment_more() const override
Definition: contexts.cpp:737
virtual const wfl::variant & get_attacks_as_variant() const override
Definition: contexts.cpp:542
std::vector< goal_ptr > goals_
Definition: contexts.hpp:1298
virtual void set_dst_src_enemy_valid_lua() override
Definition: contexts.cpp:1141
typesafe_aspect_ptr< utils::variant< bool, std::vector< std::string > > > leader_ignores_keep_
Definition: contexts.hpp:1302
typesafe_aspect_ptr< std::vector< std::string > > recruitment_pattern_
Definition: contexts.hpp:1316
virtual const unit_advancements_aspect & get_advancements() const override
Definition: contexts.cpp:497
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:131
virtual const std::set< map_location > & keeps() const override
Definition: contexts.cpp:880
typesafe_aspect_ptr< config > leader_goal_
Definition: contexts.hpp:1301
virtual void handle_generic_event(const std::string &event_name) override
Handle generic event.
Definition: contexts.cpp:290
virtual bool leader_can_reach_keep() const override
Definition: contexts.cpp:932
virtual bool get_support_villages() const override
Definition: contexts.cpp:809
virtual std::string get_grouping() const override
Definition: contexts.cpp:647
virtual double get_retreat_factor() const override
Definition: contexts.cpp:777
typesafe_aspect_ptr< bool > allow_ally_villages_
Definition: contexts.hpp:1287
virtual const config get_recruitment_save_gold() const override
Definition: contexts.cpp:761
void diagnostic(const std::string &msg) override
Show a diagnostic message on the screen.
Definition: contexts.cpp:303
virtual void on_readonly_context_create() override
Definition: contexts.cpp:241
virtual double get_scout_village_targeting() const override
Definition: contexts.cpp:785
typesafe_aspect_ptr< double > caution_
Definition: contexts.hpp:1291
virtual const moves_map & get_possible_moves() const override
Definition: contexts.cpp:713
virtual int get_recruitment_randomness() const override
Definition: contexts.cpp:753
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:119
typesafe_aspect_ptr< std::string > grouping_
Definition: contexts.hpp:1297
virtual config to_readonly_context_config() const override
serialize to config
Definition: contexts.cpp:270
typesafe_aspect_ptr< double > aggression_
Definition: contexts.hpp:1286
typesafe_aspect_ptr< config > recruitment_save_gold_
Definition: contexts.hpp:1318
typesafe_aspect_ptr< double > leader_aggression_
Definition: contexts.hpp:1300
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:602
virtual void set_src_dst_valid_lua() override
Definition: contexts.cpp:1146
virtual double get_aggression() const override
Definition: contexts.hpp:546
virtual double get_leader_aggression() const override
Definition: contexts.hpp:646
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:342
virtual game_info & get_info_w() override
Functions to retrieve the 'info' object.
Definition: contexts.cpp:299
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:147
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:127
virtual config to_readwrite_context_config() const override
serialize this context to config
Definition: contexts.cpp:265
void raise_gamestate_changed() const override
Notifies all interested observers of the event respectively.
Definition: contexts.cpp:93
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:115
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:123
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:139
recursion_counter recursion_counter_
Definition: contexts.hpp:1425
virtual team & current_team_w() override
Return a reference to the 'team' object for the AI.
Definition: contexts.cpp:98
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:103
virtual int get_recursion_count() const override
Get the value of the recursion counter.
Definition: contexts.cpp:83
int get_count() const
Get the current value of the recursion counter.
Definition: contexts.hpp:66
virtual config to_side_context_config() const override
serialize this context to config
Definition: contexts.cpp:260
virtual int get_recursion_count() const override
Get the value of the recursion counter.
Definition: contexts.cpp:73
recursion_counter recursion_counter_
Definition: contexts.hpp:983
void init_side_context_proxy(side_context &target)
Definition: contexts.hpp:391
virtual side_number get_side() const override
Get the side number.
Definition: contexts.hpp:396
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
child_itors child_range(config_key_type key)
Definition: config.cpp:268
config & add_child(config_key_type key)
Definition: config.cpp:436
void add_chat_message(const std::chrono::system_clock::time_point &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:102
void set_diagnostic(const std::string &msg)
Definition: display.cpp:1395
team & get_team(int i)
Definition: game_board.hpp:92
virtual const unit_map & units() const override
Definition: game_board.hpp:107
virtual const gamemap & map() const override
Definition: game_board.hpp:97
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:384
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:75
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:98
unit_iterator end()
Definition: map.hpp:428
unit_iterator find(std::size_t id)
Definition: map.cpp:302
unit_iterator begin()
Definition: map.hpp:418
unit_iterator find_leader(int side)
Definition: map.cpp:320
This class represents a single unit of a specific type.
Definition: unit.hpp:133
A variable-expanding proxy for the config class.
Definition: variable.hpp:45
Definitions for the interface to Wesnoth Markup Language (WML).
#define ERR_AI
Definition: contexts.cpp:66
static lg::log_domain log_ai("ai/general")
#define DBG_AI
Definition: contexts.cpp:63
#define WRN_AI
Definition: contexts.cpp:65
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:1030
Game information for the AI.
int max_hitpoints() const
The max number of hitpoints this unit can have.
Definition: unit.hpp:521
unit_alignments::type alignment() const
The alignment of this unit.
Definition: unit.hpp:491
int hitpoints() const
The current number of hitpoints this unit has.
Definition: unit.hpp:515
int side() const
The side this unit belongs to.
Definition: unit.hpp:343
int defense_modifier(const t_translation::terrain_code &terrain) const
The unit's defense on a given terrain.
Definition: unit.cpp:1766
attack_itors attacks()
Gets an iterator over this unit's attacks.
Definition: unit.hpp:942
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:512
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:583
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:59
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:95
::tod_manager * tod_manager
Definition: resources.cpp:29
game_board * gameboard
Definition: resources.cpp:20
filter_context * filter_con
Definition: resources.cpp:23
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
constexpr bool decayed_is_same
Equivalent to as std::is_same_v except both types are passed through std::decay first.
Definition: general.hpp:30
bool contains(const Container &container, const Value &value)
Returns true iff value is found in container.
Definition: general.hpp:86
std::pair< int, int > parse_range(std::string_view str)
Recognises the following patterns, and returns a {min, max} pair.
std::vector< std::string > split(const config_attribute_value &val)
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
Definition: general.hpp:140
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:109
@ 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:163
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
map_location loc
Definition: contexts.hpp:97
Encapsulates the map of the game.
Definition: location.hpp:45
bool valid() const
Definition: location.hpp:110
static const map_location & null_location()
Definition: location.hpp:102
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:2213
#define e