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