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