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