61 #include <boost/smart_ptr/intrusive_ptr.hpp>
62 #include <boost/smart_ptr/shared_ptr.hpp>
70 #define DBG_AI LOG_STREAM(debug, log_ai)
71 #define LOG_AI LOG_STREAM(info, log_ai)
72 #define WRN_AI LOG_STREAM(warn, log_ai)
73 #define ERR_AI LOG_STREAM(err, log_ai)
199 defensive_position_cache_(),
200 dstsrc_(),enemy_dstsrc_(),
201 enemy_possible_moves_(),
206 leader_aggression_(),
208 leader_ignores_keep_(),
210 move_maps_enemy_valid_(false),
211 move_maps_valid_(false),
212 dst_src_valid_lua_(false),
213 dst_src_enemy_valid_lua_(false),
214 src_dst_valid_lua_(false),
215 src_dst_enemy_valid_lua_(false),
217 passive_leader_shares_keep_(),
219 recruitment_diversity_(),
220 recruitment_instructions_(),
222 recruitment_pattern_(),
223 recruitment_randomness_(),
224 recruitment_save_gold_(),
225 recursion_counter_(context.get_recursion_count()),
226 scout_village_targeting_(),
232 villages_per_scout_()
273 std::vector<aspect_ptr> aspects;
302 for(
const aspect_map::value_type
a :
aspects_) {
303 cfg.
add_child(
"aspect",
a.second->to_config());
355 move_map& dstsrc,
bool enemy,
bool assume_full_movement,
362 move_map& dstsrc,
bool enemy,
bool assume_full_movement,
372 if ((enemy &&
current_team().is_enemy(un_it->side()) ==
false) ||
373 (!enemy && !assume_full_movement && un_it->side() !=
get_side()) ||
378 if (un_it->incapacitated() ||
379 (!assume_full_movement && un_it->movement_left() == 0)) {
384 if (enemy && un_it->invisible(un_it->get_location()) && !see_all) {
388 unit* held_unit =
const_cast<unit *
>(&*un_it);
392 if (un_it->movement_left() > 0) {
393 std::pair<map_location,map_location> trivial_mv(un_it->get_location(), un_it->get_location());
394 srcdst.insert(trivial_mv);
395 dstsrc.insert(trivial_mv);
409 res.insert(std::pair<map_location,pathfind::paths>(
415 static const config only_not_tag(
"not");
416 if(remove_destinations && remove_destinations->
to_config() == only_not_tag) {
417 remove_destinations =
nullptr;
426 if(remove_destinations !=
nullptr && remove_destinations->
match(dst)) {
430 bool friend_owns =
false;
451 srcdst.insert(std::pair<map_location,map_location>(src,dst));
452 dstsrc.insert(std::pair<map_location,map_location>(dst,src));
467 ERR_AI <<
"when adding aspects, unknown aspect id["<<
id<<
"]"<<std::endl;
476 i->second->add_facet(cfg);
478 ERR_AI <<
"when adding aspects, unknown aspect id["<<
id<<
"]"<<std::endl;
493 const std::map<map_location,defensive_position>::const_iterator position =
497 return position->second;
505 typedef move_map::const_iterator Itor;
506 const std::pair<Itor,Itor> itors = srcdst.equal_range(loc);
507 for(Itor
i = itors.first;
i != itors.second; ++
i) {
654 if (engine_name.empty()) {
659 while (en!=
engines_.end() && ((*en)->get_name()!=engine_name) && ((*en)->get_id()!=engine_name)) {
671 engine_name <<
"]" << std::endl;
672 DBG_AI <<
"config snippet contains: " << std::endl << cfg << std::endl;
676 engine_ptr new_engine = eng->second->get_new_instance(*
this,engine_name);
679 engine_name <<
"] " << std::endl;
680 DBG_AI <<
"config snippet contains: " << std::endl << cfg << std::endl;
815 return std::vector<std::string>();
824 return std::vector<std::string>();
988 for(
size_t x = 0;
x != size_t(
map_->
w()); ++
x) {
989 for(
size_t y = 0;
y != size_t(
map_->
h()); ++
y) {
994 for(
size_t n = 0;
n != 6; ++
n) {
1017 if(start_pos.
valid() ==
false) {
1021 if (leader->get_location() == start_pos) {
1034 std::set<map_location> avoided_locations;
1036 const std::set<map_location>&
keeps = this->
keeps();
1044 for(std::set<map_location>::const_iterator
i = keeps.begin();
i != keeps.end(); ++
i) {
1045 if (avoided_locations.find(*
i)!=avoided_locations.end()) {
1049 if(res ==
nullptr || distance < closest) {
1066 std::fill_n(ratings, 0, 6);
1067 int num_used_locs = 0;
1077 bool changed =
false;
1078 for (
int i = 0;; ++
i) {
1080 if (!changed)
break;
1093 typedef move_map::const_iterator Itor;
1094 typedef std::pair<Itor,Itor> Range;
1095 Range its = dstsrc.equal_range(locs[i]);
1100 int best_rating = 0;
1103 for(Itor it = its.first; it != its.second; ++it) {
1107 if(u == units_.
end()) {
1111 const unit& un = *u;
1120 int tod_modifier = 0;
1121 if(un.
alignment() == unit_type::ALIGNMENT::LAWFUL) {
1122 tod_modifier = lawful_bonus;
1123 }
else if(un.
alignment() == unit_type::ALIGNMENT::CHAOTIC) {
1124 tod_modifier = -lawful_bonus;
1125 }
else if(un.
alignment() == unit_type::ALIGNMENT::LIMINAL) {
1126 tod_modifier = -(abs(lawful_bonus));
1131 int most_damage = 0;
1134 int damage = att.damage() * att.num_attacks() * (100 + tod_modifier);
1135 if (damage > most_damage) {
1136 most_damage = damage;
1140 int village_bonus = map_.
is_village(terrain) ? 3 : 2;
1142 int rating = hp * defense * most_damage * village_bonus / 200;
1143 if(rating > best_rating) {
1146 if (pos == end_used || rating >= ratings[pos - beg_used]) {
1147 best_rating = rating;
1148 best_unit = it->second;
1153 if (!best_unit.
valid())
continue;
1155 int index = pos - beg_used;
1156 if (index == num_used_locs)
1158 else if (best_rating == ratings[index])
1163 res -= ratings[
index];
1166 used_locs[
index] = best_unit;
1167 ratings[
index] = best_rating;
1171 return res / 100000.;
1186 if(i->second == loc) {
1238 return leader_location;
1242 double move_left_at_best_free_keep = 0.0;
1245 double move_left_at_best_occupied_keep = 0.0;
1252 const int move_left_at_loc = dest.
move_left;
1255 best_free_keep = &loc;
1256 move_left_at_best_free_keep = move_left_at_loc;
1260 best_occupied_keep = &loc;
1261 move_left_at_best_occupied_keep = move_left_at_loc;
1268 return *best_free_keep;
1272 return *best_occupied_keep;
1288 if(time_of_day.empty() ==
false) {
1289 const std::vector<std::string>& times =
utils::split(time_of_day);
1295 if(turns.empty() ==
false) {
1297 const std::vector<std::string>& turns_list =
utils::split(turns);
1298 for(std::vector<std::string>::const_iterator j = turns_list.begin(); j != turns_list.end() ; ++j ) {
1300 if(turn >= range.first && turn <= range.second) {
aspect_type< std::string >::typesafe_ptr grouping_
virtual side_number get_side() const
Get the side number.
boost::shared_ptr< engine > engine_ptr
virtual int get_attack_depth() const
child_itors child_range(const std::string &key)
virtual void set_dst_src_valid_lua()
moves_map possible_moves_
virtual config get_leader_goal() const
virtual void invalidate_keeps_cache() const
::tod_manager * tod_manager
stopunit_result_ptr check_stopunit_action(const map_location &unit_location, bool remove_movement=true, bool remove_attacks=false)
Check if it is possible to remove unit movements and/or attack.
virtual void add_aspects(std::vector< aspect_ptr > &aspects)
int max_hitpoints() const
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...
attack_result_ptr check_attack_action(const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon)
Check if it is possible to attack enemy defender using our unit attacker from attackers current locat...
void init(const gamemap &map)
virtual move_result_ptr execute_move_action(const map_location &from, const map_location &to, bool remove_movement=true, bool unreach_is_ok=false)
Ask the game to move our unit from location 'from' to location 'to', optionally - doing a partial mov...
static void raise_gamestate_changed()
Notifies all observers of 'ai_gamestate_changed' event.
Various functions that implement attacks and attack calculations.
virtual void set_src_dst_enemy_valid_lua()
unit_iterator find_leader(int side)
virtual const std::set< map_location > & keeps() const
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
Calculate the moves units may possibly make.
virtual bool get_passive_leader_shares_keep() const
Managing the AI-Game interaction - AI actions and their results.
static game_info & get_active_ai_info_for_side(side_number side)
Gets AI info for active AI of the given side.
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
bool is_village(const map_location &loc) const
std::map< map_location, pathfind::paths > moves_map
The standard way in which a map of possible movement routes to location is recorded.
virtual attack_result_ptr execute_attack_action(const map_location &attacker_loc, const map_location &defender_loc, int attacker_weapon)
Ask the game to attack an enemy defender using our unit attacker from attackers current location...
aspect_type< double >::typesafe_ptr recruitment_diversity_
static void parse_engine_from_config(readonly_context &context, const config &cfg, std::back_insert_iterator< std::vector< engine_ptr > > b)
bool is_enemy(int n) const
virtual double get_aggression() const
aspect_type< terrain_filter >::typesafe_ptr avoid_
unit_stats_cache_t unit_stats_cache_
readonly_context_impl(side_context &context, const config &cfg)
Constructor.
static void add_turn_started_observer(events::observer *event_observer)
Adds an observer of 'ai_turn_started' event.
aspect_type< config >::typesafe_ptr recruitment_save_gold_
int lawful_bonus
The % bonus lawful units receive.
aspect_type< double >::typesafe_ptr village_value_
synced_command_result_ptr check_synced_command_action(const std::string &lua_code, const map_location &location=map_location::null_location())
Check if it is possible to run Lua code.
virtual void recalculate_move_maps() const
bool move_maps_enemy_valid_
AI Support engine - creating specific ai components from config.
virtual void invalidate_move_maps() const
virtual config to_side_context_config() const
serialize this context to config
std::vector< goal_ptr > goals_
void init_side_context_proxy(side_context &target)
virtual unit_stats_cache_t & unit_stats_cache() const
Weapon choice cache, to speed simulations.
GLint GLint GLint GLint GLint GLint y
virtual const move_map & get_enemy_srcdst() const
static config unit_name(const unit *u)
virtual bool leader_can_reach_keep() const
aspect_type< double >::typesafe_ptr scout_village_targeting_
Definitions for the interface to Wesnoth Markup Language (WML).
virtual void invalidate_defensive_position_cache() const
virtual const map_location & nearest_keep(const map_location &loc) const
std::map< map_location, defensive_position > defensive_position_cache_
aspect_type< bool >::typesafe_ptr simple_targeting_
int defense_modifier(const t_translation::t_terrain &terrain) const
bool match(const map_location &loc) const
virtual double get_leader_aggression() const
virtual bool get_passive_leader() const
virtual const moves_map & get_enemy_possible_moves() const
std::vector< attack_analysis > attacks_vector
Object which defines a time of day with associated bonuses, image, sounds etc.
std::multimap< map_location, map_location > move_map
The standard way in which a map of possible moves is recorded.
virtual const unit_advancements_aspect & get_advancements() const
virtual int get_recursion_count() const
Get the value of the recursion counter.
bool contains(const map_location &) const
This class stores all the data for a single 'side' (in game nomenclature).
A small explanation about what's going on here: Each action has access to two game_info objects First...
static void remove_gamestate_observer(events::observer *event_observer)
Removes an observer of game events except ai_user_interact event and ai_sync_network event...
virtual double get_aggression() const
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.
virtual const std::vector< unit_ptr > & get_recall_list() const
void raise_user_interact() const
Function which should be called frequently to allow the user to interact with the interface...
const std::set< map_location > & get()
virtual bool is_src_dst_enemy_valid_lua() const
std::vector< team > * teams
virtual std::map< map_location, defensive_position > & defensive_position_cache() const
aspect_type< bool >::typesafe_ptr passive_leader_
virtual bool is_dst_src_valid_lua() const
virtual double get_leader_aggression() const
unit_type::ALIGNMENT alignment() const
aspect_type< double >::typesafe_ptr aggression_
size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
static void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of 'ai_turn_started' event.
filter_context * filter_con
virtual engine_ptr get_engine_by_cfg(const config &cfg)
get engine by cfg, creating it if it is not created yet but known
int w() const
Effective map width.
virtual ~readonly_context_impl()
Destructor.
virtual const variant & get_attacks_as_variant() const
static factory_map & get_list()
GLboolean GLboolean GLboolean GLboolean a
static lg::log_domain log_ai("ai/general")
aspect_type< int >::typesafe_ptr attack_depth_
virtual const move_map & get_enemy_dstsrc() const
Encapsulates the map of the game.
virtual config to_readwrite_context_config() const
serialize this context to config
moves_map enemy_possible_moves_
virtual bool get_leader_ignores_keep() const
config & add_child(const std::string &key)
bool dst_src_enemy_valid_lua_
aspect_type< bool >::typesafe_ptr passive_leader_shares_keep_
virtual const move_map & get_dstsrc() const
defensive_position const & best_defensive_position(const map_location &unit, const move_map &dstsrc, const move_map &srcdst, const move_map &enemy_dstsrc) const
Object which temporarily resets a unit's movement.
void log_message(const std::string &msg)
Display a debug message as a chat message.
virtual const std::vector< engine_ptr > & get_engines() const
virtual bool is_dst_src_enemy_valid_lua() const
Managing the AIs lifecycle - headers.
virtual game_info & get_info_w()
Functions to retrieve the 'info' object.
void add_known_aspect(const std::string &name, boost::shared_ptr< typesafe_aspect< T > > &where)
static const map_location & null_location()
virtual bool get_support_villages() const
static const ::config * terrain
The terrain used to create the cache.
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
virtual int get_recruitment_randomness() const
virtual const terrain_filter & get_avoid() const
std::set< map_location > keeps_
GLuint GLuint GLsizei count
recursion_counter recursion_counter_
const std::vector< attack_type > & attacks() const
virtual const moves_map & get_possible_moves() const
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
aspect_type< config >::typesafe_ptr leader_goal_
Encapsulates the map of the game.
virtual bool is_active(const std::string &time_of_day, const std::string &turns) const
virtual const config get_recruitment_instructions() const
std::pair< int, int > parse_range(std::string const &str)
virtual double get_recruitment_diversity() const
static void raise_user_interact()
Notifies all observers of 'ai_user_interact' event.
aspect_type< bool >::typesafe_ptr support_villages_
void get_locations(std::set< map_location > &locs, bool with_border=false) const
virtual int get_recursion_count() const
Get the value of the recursion counter.
virtual const map_location & suitable_keep(const map_location &leader_location, const pathfind::paths &leader_paths)
get most suitable keep for leader - nearest free that can be reached in 1 turn, if none - return near...
std::vector< engine_ptr > engines_
AI Support Engines.
aspect_type< int >::typesafe_ptr recruitment_randomness_
std::map< std::string, tfilter >::iterator itor
int h() const
Effective map height.
int get_count() const
Get the current value of the recursion counter.
void diagnostic(const std::string &msg)
Show a diagnostic message on the screen.
Game information for the AI.
void set_diagnostic(const std::string &msg)
virtual const std::vector< std::string > get_recruitment_pattern() const
virtual const move_map & get_srcdst() const
virtual double get_caution() const
std::map< std::string, aspect_ptr > aspect_map
recursion_counter recursion_counter_
virtual const config get_recruitment_save_gold() const
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)
virtual const std::vector< goal_ptr > & get_goals() const
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.
virtual const std::vector< std::string > get_recruitment_more() const
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.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
GLint GLint GLint GLint GLint x
virtual void add_facet(const std::string &id, const config &cfg) const
const team & current_team() const
Return a reference to the 'team' object for the AI.
aspect_type< bool >::typesafe_ptr leader_ignores_keep_
bool is_castle(const map_location &loc) const
virtual int get_recursion_count() const
Get the value of the recursion counter.
aspect_type< int >::typesafe_ptr villages_per_scout_
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())
Ask the game to recall a unit for us on specified location.
virtual const unit_advancements_aspect & get_advancements() const
aspect_type< config >::typesafe_ptr recruitment_instructions_
boost::shared_ptr< std::vector< unit_const_ptr > > units_
std::map< std::pair< map_location, const unit_type * >, std::pair< battle_context_unit_stats, battle_context_unit_stats > > unit_stats_cache_t
virtual double power_projection(const map_location &loc, const move_map &dstsrc) const
Function which finds how much 'power' a side can attack a certain location with.
aspect_type< double >::typesafe_ptr leader_aggression_
virtual const game_info & get_info() const
Helper functions for the object which operates in the context of AI for specific side this is part of...
aspect_type< double >::typesafe_ptr leader_value_
virtual void on_readonly_context_create()
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.
GLuint const GLchar * name
virtual const gamemap & map() const
virtual config to_readonly_context_config() const
serialize to config
bool on_board(const map_location &loc) const
Tell if a location is on the map.
display_chat_manager & get_chat_manager()
virtual const aspect_map & get_aspects() const
virtual const attacks_vector & get_attacks() const
virtual double get_village_value() const
virtual void set_dst_src_enemy_valid_lua()
aspect_type< double >::typesafe_ptr caution_
aspect_type< std::vector< std::string > >::typesafe_ptr recruitment_pattern_
recursion_counter recursion_counter_
virtual void recalculate_move_maps_enemy() const
bool find(E event, F functor)
Tests whether an event handler is available.
virtual std::string get_grouping() const
static void add_gamestate_observer(events::observer *event_observer)
Adds observer of game events except ai_user_interact event and ai_sync_network event.
virtual team & current_team_w()
Return a reference to the 'team' object for the AI.
known_aspect_map known_aspects_
A variable-expanding proxy for the config class.
Standard logging facilities (interface).
virtual double get_leader_value() const
Object which contains all the possible locations a unit can move to, with associated best routes to t...
recall_list_manager & recall_list()
Container associating units to locations.
move_result_ptr check_move_action(const map_location &from, const map_location &to, bool remove_movement=true, bool unreach_is_ok=false)
Check if it is possible to move our unit from location 'from' to location 'to'.
aspect_type< std::vector< std::string > >::typesafe_ptr recruitment_more_
void handle_generic_event(const std::string &event_name)
void raise_gamestate_changed() const
Notifies all interested observers of the event respectively.
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
unit_iterator find(size_t id)
virtual void handle_generic_event(const std::string &event_name)
Handle generic event.
aspect_type< unit_advancements_aspect >::typesafe_ptr advancements_
virtual void set_src_dst_valid_lua()
A config object defines a single node in a WML file, with access to child nodes.
void add_chat_message(const time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
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())
Check if it is possible to recruit a unit for us on specified location.
virtual int get_villages_per_scout() const
This module contains various pathfinding functions and utilities.
virtual bool get_simple_targeting() const
static void parse_goal_from_config(readonly_context &context, const config &cfg, std::back_insert_iterator< std::vector< goal_ptr > > b)
GLsizei const GLcharARB ** string
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())
Ask the game to recruit a unit for us on specified location.
std::vector< unit_ptr > recall_list_
The underlying data struture. TODO: Should this be a map based on underlying id instead?
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
A more fundamental version of calculate_possible_moves which allows the use of a speculative unit map...
virtual stopunit_result_ptr execute_stopunit_action(const map_location &unit_location, bool remove_movement=true, bool remove_attacks=false)
Ask the game to remove unit movements and/or attack.
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...
virtual bool is_src_dst_valid_lua() const
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())
Check if it is possible to recall a unit for us on specified location.
aspect_type< attacks_vector >::typesafe_ptr attacks_
static void add_map_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_map_changed' event.
bool is_keep(const map_location &loc) const
virtual synced_command_result_ptr execute_synced_command_action(const std::string &lua_code, const map_location &location=map_location::null_location())
Ask the game to run Lua code.
bool src_dst_enemy_valid_lua_
static void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_map_changed' event.
virtual double get_scout_village_targeting() const