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