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