57 #include <SDL_timer.h>
69 #define DBG_AI_MANAGER LOG_STREAM(debug, log_ai_manager)
70 #define LOG_AI_MANAGER LOG_STREAM(info, log_ai_manager)
71 #define ERR_AI_MANAGER LOG_STREAM(err, log_ai_manager)
74 #define DBG_AI_MOD LOG_STREAM(debug, log_ai_mod)
75 #define LOG_AI_MOD LOG_STREAM(info, log_ai_mod)
76 #define WRN_AI_MOD LOG_STREAM(warn, log_ai_mod)
77 #define ERR_AI_MOD LOG_STREAM(err, log_ai_mod)
80 :
ai_(), side_context_(nullptr), readonly_context_(nullptr), readwrite_context_(nullptr), default_ai_context_(nullptr), side_(side), cfg_(cfg)
110 if (!mod_ai.has_attribute(
"side")) {
111 mod_ai[
"side"] = side;
117 std::vector<engine_ptr> engines =
ai_->get_engines();
120 (*it)->set_ai_context(&(
ai_->get_ai_context()));
161 DBG_AI_MANAGER <<
"after transforming [modify_side][ai] into new syntax, config contains:"<< std::endl << cfg << std::endl;
187 LOG_AI_MOD <<
"side "<<
side_ <<
" [modify_ai] "<<act<<
" \""<<cfg[
"path"]<<
"\""<<std::endl;
193 }
else if (act ==
"change") {
195 }
else if (act ==
"delete") {
197 }
else if (act ==
"try_delete") {
200 LOG_AI_MOD <<
"[modify_ai] "<<act<<
" failed, ignoring because it's a try_delete"<< std::endl;
204 ERR_AI_MOD <<
"modify_ai tag has invalid 'action' attribute " << act << std::endl;
208 LOG_AI_MOD <<
"[modify_ai] "<<act<<
" failed"<< std::endl;
210 LOG_AI_MOD <<
"[modify_ai] "<<act<<
" success"<< std::endl;
221 cfg[
"version"] =
"10703";
245 if (this->
ai_!=
nullptr) {
259 s <<
"advancements: " << this->
ai_->get_advancements().get_value() << std::endl;
260 s <<
"aggression: " << this->
ai_->get_aggression() << std::endl;
261 s <<
"attack_depth: " << this->
ai_->get_attack_depth() << std::endl;
262 s <<
"caution: " << this->
ai_->get_caution() << std::endl;
263 s <<
"grouping: " << this->
ai_->get_grouping() << std::endl;
264 s <<
"leader_aggression: " << this->
ai_->get_leader_aggression() << std::endl;
265 s <<
"leader_ignores_keep: " << this->
ai_->get_leader_ignores_keep() << std::endl;
266 s <<
"leader_value: " << this->
ai_->get_leader_value() << std::endl;
267 s <<
"passive_leader: " << this->
ai_->get_passive_leader() << std::endl;
268 s <<
"passive_leader_shares_keep: " << this->
ai_->get_passive_leader_shares_keep() << std::endl;
269 s <<
"recruitment_diversity: " << this->
ai_->get_recruitment_diversity() << std::endl;
270 s <<
"recruitment_instructions: " << std::endl <<
"----config begin----" << std::endl;
271 s << this->
ai_->get_recruitment_instructions() <<
"-----config end-----" << std::endl;
272 s <<
"recruitment_more: " <<
utils::join(this->
ai_->get_recruitment_more()) << std::endl;
273 s <<
"recruitment_pattern: " <<
utils::join(this->
ai_->get_recruitment_pattern()) << std::endl;
274 s <<
"recruitment_randomness: " << this->
ai_->get_recruitment_randomness() << std::endl;
275 s <<
"recruitment_save_gold: " << std::endl <<
"----config begin----" << std::endl;
276 s << this->
ai_->get_recruitment_save_gold() <<
"-----config end-----" << std::endl;
277 s <<
"scout_village_targeting: " << this->
ai_->get_scout_village_targeting() << std::endl;
278 s <<
"simple_targeting: " << this->
ai_->get_simple_targeting() << std::endl;
279 s <<
"support_villages: " << this->
ai_->get_support_villages() << std::endl;
280 s <<
"village_value: " << this->
ai_->get_village_value() << std::endl;
281 s <<
"villages_per_scout: " << this->
ai_->get_villages_per_scout() << std::endl;
436 const int interact_time = 30;
438 if(time_since_interact < interact_time) {
506 if (str.length()<1) {
527 const int MAX_HISTORY_VISIBLE = 30;
538 return "AI MANAGER: empty history";
551 return "AI MANAGER: History is empty";
554 int n = std::min<int>( MAX_HISTORY_VISIBLE,
history_.size() );
555 std::stringstream strstream;
556 strstream <<
"AI MANAGER: History - last "<< n <<
" commands:\n";
557 std::deque< command_history_item >::reverse_iterator j =
history_.rbegin();
559 for (
int cmd_id=n; cmd_id>0; --cmd_id){
560 strstream << j->get_number() <<
" :" << j->get_command() <<
'\n';
564 return strstream.str();
572 if (cmd.at(0)==
"!add_ai"){
578 return std::string(
"AI MANAGER: failed attempt to add AI for side ")+std::to_string(side)+
std::string(
" from file ")+file;
582 if (cmd.at(0)==
"!replace_ai"){
588 return std::string(
"AI MANAGER: failed attempt to add AI for side ")+std::to_string(side)+
std::string(
" from file ")+file;
592 }
else if (cmd.size()==2){
594 if (cmd.at(0)==
"!remove_ai"){
597 return std::string(
"AI MANAGER: made an attempt to remove AI for side ")+std::to_string(side);
607 std::deque< command_history_item >::reverse_iterator j =
history_.rbegin();
609 while ( (j!=
history_.rend()) && (j->get_number()!=command) ){
615 return "AI MANAGER: no command with requested number found";
617 }
else if (cmd.size()==1){
618 if (cmd.at(0)==
"!help") {
621 "! - repeat last command (? and ! do not count)\n"
622 "! NUMBER - repeat numbered command\n"
623 "? - show a history list\n"
624 "!add_ai TEAM FILE - add a AI to side (0 - command AI, N - AI for side #N) from file\n"
625 "!remove_ai TEAM - remove AI from side (0 - command AI, N - AI for side #N)\n"
626 "!replace_ai TEAM FILE - replace AI of side (0 - command AI, N - AI for side #N) from file\n"
627 "!help - show this help message";
632 return "AI MANAGER: nothing to do";
644 ERR_AI_MANAGER <<
" unable to read [SIDE] config for side "<< side <<
"from file [" << file <<
"]"<< std::endl;
659 holder new_holder(side,parsed_cfg);
661 ai_stack_for_specific_side.push(new_holder);
673 cfg[
"ai_algorithm"] = ai_algorithm_type;
674 holder new_holder(side,cfg);
676 ai_stack_for_specific_side.push(new_holder);
688 if (!ai_stack_for_specific_side.empty()){
689 ai_stack_for_specific_side.pop();
699 while (!ai_stack_for_specific_side.empty()){
700 ai_stack_for_specific_side.pop();
716 for (
const config& cfg : ai_parameters) {
784 const int turn_start_time = SDL_GetTicks();
795 const int turn_end_time= SDL_GetTicks();
797 DBG_AI_MANAGER <<
"side " << side <<
": total turn time: "<<turn_end_time - turn_start_time <<
" ms "<< std::endl;
813 return ai_map_.insert(std::make_pair(side, std::stack<holder>())).first->second;
823 if (!ai_stack_for_specific_side.empty()){
824 return ai_stack_for_specific_side.top();
827 holder new_holder(side, cfg);
828 ai_stack_for_specific_side.push(new_holder);
829 return ai_stack_for_specific_side.top();
virtual std::string evaluate(const std::string &str)
Evaluate command (using fai)
static void add_observer(events::observer *event_observer)
Adds observer of game events.
child_itors child_range(const std::string &key)
::tod_manager * tod_manager
virtual void set_side(side_number side)=0
Set the side number.
virtual void notify_observers()
static void raise_gamestate_changed()
Notifies all observers of 'ai_gamestate_changed' event.
static bool change_component(component *root, const std::string &path, const config &cfg)
virtual config to_readwrite_context_config() const =0
serialize this context to config
static void raise_map_changed()
Notifies all observers of 'ai_map_changed' event.
readonly_context * readonly_context_
static game_info & get_active_ai_info_for_side(side_number side)
Gets AI info for active AI of the given side.
static void add_turn_started_observer(events::observer *event_observer)
Adds an observer of 'ai_turn_started' event.
holder(side_number side, const config &cfg)
const std::string get_ai_identifier() const
static events::generic_event gamestate_changed_
AI Support engine - creating specific ai components from config.
bool fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
virtual config to_side_context_config() const =0
serialize this context to config
static bool parse_side_config(side_number side, const config &cfg, config &parsed_cfg)
void modify_side_ai_config(config cfg)
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
static const std::string internal_evaluate_command(side_number side, const std::string &str)
Evaluates an internal manager command.
void clear_children(const std::string &key)
To lexical_cast(From value)
Lexical cast converts one type to another.
Definitions for the interface to Wesnoth Markup Language (WML).
std::pair< const_child_iterator, const_child_iterator > const_child_itors
static void add_tod_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_tod_changed' event.
static AI_map_of_stacks ai_map_
const std::string get_ai_overview()
virtual config to_readonly_context_config() const =0
serialize to config
void init(side_number side)
static bool should_intercept(const std::string &str)
Determines if the command should be intercepted and evaluated as internal command.
static std::stack< holder > & get_or_create_ai_stack_for_side(side_number side)
Gets the AI stack for the specified side, create it if it doesn't exist.
void merge_with(const config &c)
Merge config 'c' into this config, overwriting this config's values.
static bool add_ai_for_side_from_file(side_number side, const std::string &file, bool replace=true)
Adds active AI for specified side from file.
static void clear_ais()
Clears all the AIs.
static void raise_recruit_list_changed()
Notifies all observers of 'ai_recruit_list_changed' event.
const std::string get_ai_structure()
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...
static component * get_component(component *root, const std::string &path)
GLsizei const char ** path
static std::deque< command_history_item > history_
virtual void new_turn()
On new turn.
component * get_component(component *root, const std::string &path)
virtual void on_readonly_context_create()=0
static void remove_turn_started_observer(events::observer *event_observer)
Deletes an observer of 'ai_turn_started' event.
static std::string get_active_ai_overview_for_side(side_number side)
Gets AI Overview for active AI of the given side.
static void set_ai_info(const game_info &info)
Sets AI information.
static events::generic_event user_interact_
A component of the AI framework.
static bool add_ai_for_side(side_number side, const std::string &ai_algorithm_type, bool replace=true)
Adds active AI for specified side from parameters.
Composite AI with turn sequence which is a vector of stages.
static config to_config(side_number side)
Gets AI config for active AI of the given side.
side_context * side_context_
static lg::log_domain log_ai_manager("ai/manager")
Managing the AIs lifecycle - headers.
static void play_turn(side_number side)
Plays a turn for the specified side using its active AI.
static void modify_active_ai_for_side(ai::side_number side, const config &cfg)
Modifies AI parameters for active AI of the given side.
static void expand_simplified_aspects(side_number side, config &cfg)
Expand simplified aspects, similar to the change from 1.7.2 to 1.7.3 but with some additional syntax ...
Templates and utility-routines for strings and numbers.
void init()
Initializes the gui subsystems.
game_events::manager * game_events
void modify_ai(const config &cfg)
static void remove_all_ais_for_side(side_number side)
Removes all AIs from side.
std::string join(T const &v, const std::string &s=",")
Generates a new string joining container items in a list.
static const std::string AI_TYPE_DEFAULT
static const std::string AI_TYPE_IDLE_AI
static void clear_ai_info()
Clears AI information.
static bool delete_component(component *root, const std::string &path)
static void remove_ai_for_side(side_number side)
Removes top-level AI from side.
virtual bool attach_handler(observer *obs)
static const std::string evaluate_command(side_number side, const std::string &str)
Evaluates a string command using command AI.
static events::generic_event sync_network_
static bool add_component(component *root, const std::string &path, const config &cfg)
static void raise_user_interact()
Notifies all observers of 'ai_user_interact' event.
static const std::string AI_TYPE_COMPOSITE_AI
static std::string print_component_tree(component *root, const std::string &path)
Game information for the AI.
static std::string get_active_ai_identifier_for_side(side_number side)
Gets AI algorithm identifier for active AI of the given side.
virtual void add_facet(const std::string &id, const config &cfg) const =0
std::set< map_location > recent_attacks
hack.
static events::generic_event map_changed_
Define the game's event mechanism.
static void add_recruit_list_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_recruit_list_changed' event.
static void remove_tod_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_tod_changed' event.
static game_info * ai_info_
static events::generic_event turn_started_
static long history_item_counter_
default_ai_context * default_ai_context_
static const size_t MAX_HISTORY_SIZE
static bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace=true)
Adds active AI for specified side from cfg.
Helper functions for the object which operates in the context of AI for specific side this is part of...
static std::string get_active_ai_structure_for_side(side_number side)
Gets AI Structure for active AI of the given side.
game_events::t_pump & pump()
static events::generic_event tod_changed_
readwrite_context * readwrite_context_
std::map< side_number, std::stack< holder > > AI_map_of_stacks
std::string replace(std::string str, const std::string &src, const std::string &dst)
Replace all instances of src in str with dst.
const std::string describe_ai()
static lg::log_domain log_ai_mod("ai/mod")
static void remove_observer(events::observer *event_observer)
Removes an observer of game events.
std::vector< std::string > parenthetical_split(std::string const &val, const char separator, std::string const &left, std::string const &right, const int flags)
Splits a string based either on a separator where text within parenthesis is protected from splitting...
static const std::string AI_TYPE_FORMULA_AI
void play_turn()
Play the turn.
static const config & get_default_ai_parameters()
get default AI parameters
ai_composite & get_ai_ref()
static const std::string AI_TYPE_SAMPLE_AI
static game_info & get_ai_info()
Gets global AI-game info.
Managing the AIs configuration - headers.
static void add_gamestate_observer(events::observer *event_observer)
Adds observer of game events except ai_user_interact event and ai_sync_network event.
Standard logging facilities (interface).
virtual bool detach_handler(observer *obs)
static bool get_side_config_from_file(const std::string &file, config &cfg)
get side config from file
static void raise_sync_network()
Notifies all observers of 'ai_sync_network' event.
static ai_composite & get_active_ai_for_side(side_number side)
Gets active AI for specified side.
static void raise_tod_changed()
Notifies all observers of 'ai_tod_changed' event.
A config object defines a single node in a WML file, with access to child nodes.
static ai::holder & get_active_ai_holder_for_side_dbg(side_number side)
Gets the active AI holder for debug purposes.
virtual config to_default_ai_context_config() const =0
static int last_interact_
GLsizei const GLcharARB ** string
static void remove_recruit_list_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_recruit_list_changed' event.
static events::generic_event recruit_list_changed_
static void raise_turn_started()
Notifies all observers of 'ai_turn_started' event.
Base class that holds the AI and current AI parameters.
static holder & get_active_ai_holder_for_side(side_number side)
Gets active holder for specified side.
static void add_map_changed_observer(events::observer *event_observer)
Adds an observer of 'ai_map_changed' event.
static void modify_active_ai_config_old_for_side(side_number side, const config::const_child_itors &ai_parameters)
Modifies AI parameters for active AI of the given side.
void merge_children_by_attribute(const std::string &key, const std::string &attribute)
All children with the given key and with equal values of the specified attribute will be merged into ...
static void remove_map_changed_observer(events::observer *event_observer)
Deletes an observer of 'ai_map_changed' event.