Make AI manager a singleton
Fixes #2372. It turned out that the AI kept dangling references to the old Lua state, and crashed while destroying AI contexts for destroyed sides. The best way to avoid it is to ensure that game_state, which already owns the Lua state, also owns the AI. That way, the AI will be destroyed before the Lua state and a dangling reference can't stay.
This commit is contained in:
parent
671cebe035
commit
c8b0833b1a
23 changed files with 184 additions and 154 deletions
|
@ -161,7 +161,7 @@ bool action_result::is_execution() const
|
|||
|
||||
game_info& action_result::get_info() const
|
||||
{
|
||||
return manager::get_active_ai_info_for_side(get_side());
|
||||
return manager::get_singleton().get_active_ai_info_for_side(get_side());
|
||||
}
|
||||
|
||||
team& action_result::get_my_team() const
|
||||
|
@ -311,7 +311,7 @@ void attack_result::do_execute()
|
|||
get_info().recent_attacks.insert(defender_loc_);
|
||||
//end of ugly hack
|
||||
try {
|
||||
manager::raise_gamestate_changed();
|
||||
manager::get_singleton().raise_gamestate_changed();
|
||||
} catch (...) {
|
||||
if (!is_ok()) { DBG_AI_ACTIONS << "Return value of AI ACTION was not checked." << std::endl; } //Demotes to DBG "unchecked result" warning
|
||||
throw;
|
||||
|
@ -510,7 +510,7 @@ void move_result::do_execute()
|
|||
|
||||
if (is_gamestate_changed()) {
|
||||
try {
|
||||
manager::raise_gamestate_changed();
|
||||
manager::get_singleton().raise_gamestate_changed();
|
||||
} catch (...) {
|
||||
if (!is_ok()) { DBG_AI_ACTIONS << "Return value of AI ACTION was not checked." << std::endl; } //Demotes to DBG "unchecked result" warning
|
||||
throw;
|
||||
|
@ -660,7 +660,7 @@ void recall_result::do_execute()
|
|||
|
||||
set_gamestate_changed();
|
||||
try {
|
||||
manager::raise_gamestate_changed();
|
||||
manager::get_singleton().raise_gamestate_changed();
|
||||
} catch (...) {
|
||||
if (!is_ok()) { DBG_AI_ACTIONS << "Return value of AI ACTION was not checked." << std::endl; } //Demotes to DBG "unchecked result" warning
|
||||
throw;
|
||||
|
@ -807,7 +807,7 @@ void recruit_result::do_execute()
|
|||
|
||||
set_gamestate_changed();
|
||||
try {
|
||||
manager::raise_gamestate_changed();
|
||||
manager::get_singleton().raise_gamestate_changed();
|
||||
} catch (...) {
|
||||
if (!is_ok()) { DBG_AI_ACTIONS << "Return value of AI ACTION was not checked." << std::endl; } //Demotes to DBG "unchecked result" warning
|
||||
throw;
|
||||
|
@ -907,12 +907,12 @@ void stopunit_result::do_execute()
|
|||
if (remove_movement_){
|
||||
un->remove_movement_ai();
|
||||
set_gamestate_changed();
|
||||
manager::raise_gamestate_changed();
|
||||
manager::get_singleton().raise_gamestate_changed();
|
||||
}
|
||||
if (remove_attacks_){
|
||||
un->remove_attacks_ai();
|
||||
set_gamestate_changed();
|
||||
manager::raise_gamestate_changed();//to be on the safe side
|
||||
manager::get_singleton().raise_gamestate_changed();//to be on the safe side
|
||||
}
|
||||
} catch (...) {
|
||||
if (!is_ok()) { DBG_AI_ACTIONS << "Return value of AI ACTION was not checked." << std::endl; } //Demotes to DBG "unchecked result" warning
|
||||
|
@ -972,7 +972,7 @@ void synced_command_result::do_execute()
|
|||
|
||||
try {
|
||||
set_gamestate_changed();
|
||||
manager::raise_gamestate_changed();
|
||||
manager::get_singleton().raise_gamestate_changed();
|
||||
} catch (...) {
|
||||
if (!is_ok()) { DBG_AI_ACTIONS << "Return value of AI ACTION was not checked." << std::endl; } //Demotes to DBG "unchecked result" warning
|
||||
throw;
|
||||
|
@ -1114,7 +1114,7 @@ std::map<int,std::string> actions::error_names_;
|
|||
void sim_gamestate_changed(action_result *result, bool gamestate_changed){
|
||||
if(gamestate_changed){
|
||||
result->set_gamestate_changed();
|
||||
manager::raise_gamestate_changed();
|
||||
manager::get_singleton().raise_gamestate_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,14 +46,15 @@ aspect::aspect(readonly_context &context, const config &cfg, const std::string &
|
|||
|
||||
aspect::~aspect()
|
||||
{
|
||||
manager& manager = manager::get_singleton();
|
||||
if (invalidate_on_turn_start_) {
|
||||
manager::remove_turn_started_observer(this);
|
||||
manager.remove_turn_started_observer(this);
|
||||
}
|
||||
if (invalidate_on_tod_change_) {
|
||||
manager::remove_tod_changed_observer(this);
|
||||
manager.remove_tod_changed_observer(this);
|
||||
}
|
||||
if (invalidate_on_gamestate_change_) {
|
||||
manager::remove_gamestate_observer(this);
|
||||
manager.remove_gamestate_observer(this);
|
||||
}
|
||||
if (invalidate_on_minor_gamestate_change_) {
|
||||
///@todo 1.9 add minor_gamestate_change_observer
|
||||
|
@ -72,14 +73,16 @@ void aspect::on_create()
|
|||
|
||||
bool aspect::redeploy(const config &cfg, const std::string& /*id*/)
|
||||
{
|
||||
manager& manager = manager::get_singleton();
|
||||
|
||||
if (invalidate_on_turn_start_) {
|
||||
manager::remove_turn_started_observer(this);
|
||||
manager.remove_turn_started_observer(this);
|
||||
}
|
||||
if (invalidate_on_tod_change_) {
|
||||
manager::remove_tod_changed_observer(this);
|
||||
manager.remove_tod_changed_observer(this);
|
||||
}
|
||||
if (invalidate_on_gamestate_change_) {
|
||||
manager::remove_gamestate_observer(this);
|
||||
manager.remove_gamestate_observer(this);
|
||||
}
|
||||
if (invalidate_on_minor_gamestate_change_) {
|
||||
///@todo 1.9 add minor_gamestate_change_observer
|
||||
|
@ -99,13 +102,13 @@ bool aspect::redeploy(const config &cfg, const std::string& /*id*/)
|
|||
id_ = cfg["id"].str();
|
||||
DBG_AI_ASPECT << "redeploying aspect: engine=["<<engine_<<"], name=["<<name_<<"], id=["<<id_<<"]"<< std::endl;
|
||||
if (invalidate_on_turn_start_) {
|
||||
manager::add_turn_started_observer(this);
|
||||
manager.add_turn_started_observer(this);
|
||||
}
|
||||
if (invalidate_on_tod_change_) {
|
||||
manager::add_tod_changed_observer(this);
|
||||
manager.add_tod_changed_observer(this);
|
||||
}
|
||||
if (invalidate_on_gamestate_change_) {
|
||||
manager::add_gamestate_observer(this);
|
||||
manager.add_gamestate_observer(this);
|
||||
}
|
||||
if (invalidate_on_minor_gamestate_change_) {
|
||||
///@todo 1.9 add minor_gamestate_change_observer
|
||||
|
|
|
@ -92,13 +92,13 @@ int readwrite_context_impl::get_recursion_count() const
|
|||
|
||||
void readonly_context_impl::raise_user_interact() const
|
||||
{
|
||||
manager::raise_user_interact();
|
||||
manager::get_singleton().raise_user_interact();
|
||||
}
|
||||
|
||||
|
||||
void readwrite_context_impl::raise_gamestate_changed() const
|
||||
{
|
||||
manager::raise_gamestate_changed();
|
||||
manager::get_singleton().raise_gamestate_changed();
|
||||
}
|
||||
|
||||
|
||||
|
@ -227,7 +227,7 @@ readonly_context_impl::readonly_context_impl(side_context &context, const config
|
|||
villages_per_scout_()
|
||||
{
|
||||
init_side_context_proxy(context);
|
||||
manager::add_gamestate_observer(this);
|
||||
manager::get_singleton().add_gamestate_observer(this);
|
||||
|
||||
add_known_aspect("advancements", advancements_);
|
||||
add_known_aspect("aggression",aggression_);
|
||||
|
@ -305,7 +305,7 @@ config readonly_context_impl::to_readonly_context_config() const
|
|||
|
||||
readonly_context_impl::~readonly_context_impl()
|
||||
{
|
||||
manager::remove_gamestate_observer(this);
|
||||
manager::get_singleton().remove_gamestate_observer(this);
|
||||
}
|
||||
|
||||
void readonly_context_impl::handle_generic_event(const std::string& /*event_name*/)
|
||||
|
@ -315,12 +315,12 @@ void readonly_context_impl::handle_generic_event(const std::string& /*event_name
|
|||
|
||||
|
||||
const game_info& readonly_context_impl::get_info() const{
|
||||
return manager::get_active_ai_info_for_side(get_side());
|
||||
return manager::get_singleton().get_active_ai_info_for_side(get_side());
|
||||
}
|
||||
|
||||
|
||||
game_info& readwrite_context_impl::get_info_w(){
|
||||
return manager::get_active_ai_info_for_side(get_side());
|
||||
return manager::get_singleton().get_active_ai_info_for_side(get_side());
|
||||
}
|
||||
|
||||
void readonly_context_impl::diagnostic(const std::string& msg)
|
||||
|
@ -950,15 +950,15 @@ keeps_cache::keeps_cache()
|
|||
: map_(nullptr)
|
||||
, keeps_()
|
||||
{
|
||||
ai::manager::add_turn_started_observer(this);
|
||||
ai::manager::add_map_changed_observer(this);
|
||||
ai::manager::get_singleton().add_turn_started_observer(this);
|
||||
ai::manager::get_singleton().add_map_changed_observer(this);
|
||||
}
|
||||
|
||||
|
||||
keeps_cache::~keeps_cache()
|
||||
{
|
||||
ai::manager::remove_turn_started_observer(this);
|
||||
ai::manager::remove_map_changed_observer(this);
|
||||
ai::manager::get_singleton().remove_turn_started_observer(this);
|
||||
ai::manager::get_singleton().remove_map_changed_observer(this);
|
||||
}
|
||||
|
||||
void keeps_cache::clear()
|
||||
|
|
|
@ -139,7 +139,7 @@ void aspect_attacks_base::do_attack_analysis(
|
|||
{
|
||||
// This function is called fairly frequently, so interact with the user here.
|
||||
|
||||
ai::manager::raise_user_interact();
|
||||
ai::manager::get_singleton().raise_user_interact();
|
||||
const int default_attack_depth = 5;
|
||||
if(cur_analysis.movements.size() >= size_t(default_attack_depth)) {
|
||||
//std::cerr << "ANALYSIS " << cur_analysis.movements.size() << " >= " << get_attack_depth() << "\n";
|
||||
|
|
|
@ -262,7 +262,7 @@ void attack_analysis::analyze(const gamemap& map, unit_map& units,
|
|||
|
||||
bool attack_analysis::attack_close(const map_location& loc) const
|
||||
{
|
||||
std::set<map_location> &attacks = manager::get_ai_info().recent_attacks;
|
||||
std::set<map_location> &attacks = manager::get_singleton().get_ai_info().recent_attacks;
|
||||
for(std::set<map_location>::const_iterator i = attacks.begin(); i != attacks.end(); ++i) {
|
||||
if(distance_between(*i,loc) < 4) {
|
||||
return true;
|
||||
|
|
|
@ -354,7 +354,7 @@ void move_leader_to_goals_phase::remove_goal(const std::string &id)
|
|||
mod_ai["side"] = get_side();
|
||||
mod_ai["path"] = "aspect[leader_goal].facet["+id+"]";
|
||||
mod_ai["action"] = "delete";
|
||||
manager::modify_active_ai_for_side(get_side(),mod_ai);
|
||||
manager::get_singleton().modify_active_ai_for_side(get_side(), mod_ai);
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
|
|
|
@ -1756,8 +1756,8 @@ void recruitment::update_scouts_wanted() {
|
|||
*/
|
||||
recruitment::recruit_situation_change_observer::recruit_situation_change_observer()
|
||||
: recruit_list_changed_(false), gamestate_changed_(0) {
|
||||
manager::add_recruit_list_changed_observer(this);
|
||||
manager::add_gamestate_observer(this);
|
||||
manager::get_singleton().add_recruit_list_changed_observer(this);
|
||||
manager::get_singleton().add_gamestate_observer(this);
|
||||
}
|
||||
|
||||
void recruitment::recruit_situation_change_observer::handle_generic_event(
|
||||
|
@ -1771,8 +1771,8 @@ void recruitment::recruit_situation_change_observer::handle_generic_event(
|
|||
}
|
||||
|
||||
recruitment::recruit_situation_change_observer::~recruit_situation_change_observer() {
|
||||
manager::remove_recruit_list_changed_observer(this);
|
||||
manager::remove_gamestate_observer(this);
|
||||
manager::get_singleton().remove_recruit_list_changed_observer(this);
|
||||
manager::get_singleton().remove_gamestate_observer(this);
|
||||
}
|
||||
|
||||
bool recruitment::recruit_situation_change_observer::recruit_list_changed() {
|
||||
|
|
|
@ -164,7 +164,7 @@ void candidate_action_evaluation_loop::remove_completed_cas()
|
|||
cfg["path"] = path;
|
||||
cfg["action"] = "delete";
|
||||
|
||||
ai::manager::modify_active_ai_for_side(this->get_side(), cfg); // we remove the CA
|
||||
ai::manager::get_singleton().modify_active_ai_for_side(this->get_side(), cfg); // we remove the CA
|
||||
}
|
||||
|
||||
|
||||
|
@ -181,7 +181,7 @@ void candidate_action_evaluation_loop::remove_completed_cas()
|
|||
// cfg["path"] = path;
|
||||
// cfg["action"] = "delete";
|
||||
//
|
||||
// ai::manager::modify_active_ai_for_side(this->get_side(), cfg);
|
||||
// ai::manager::get_singleton().modify_active_ai_for_side(this->get_side(), cfg);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
|
|
|
@ -694,11 +694,11 @@ bool formula_ai::execute_candidate_action(ca_ptr fai_ca)
|
|||
formula_ai::gamestate_change_observer::gamestate_change_observer() :
|
||||
set_var_counter_(), set_unit_var_counter_(), continue_counter_()
|
||||
{
|
||||
ai::manager::add_gamestate_observer(this);
|
||||
ai::manager::get_singleton().add_gamestate_observer(this);
|
||||
}
|
||||
|
||||
formula_ai::gamestate_change_observer::~gamestate_change_observer() {
|
||||
ai::manager::remove_gamestate_observer(this);
|
||||
ai::manager::get_singleton().remove_gamestate_observer(this);
|
||||
}
|
||||
|
||||
void formula_ai::gamestate_change_observer::handle_generic_event(const std::string& /*event_name*/) {
|
||||
|
|
|
@ -27,13 +27,13 @@ namespace ai {
|
|||
gamestate_observer::gamestate_observer()
|
||||
: gamestate_change_counter_(0)
|
||||
{
|
||||
ai::manager::add_gamestate_observer(this);
|
||||
ai::manager::get_singleton().add_gamestate_observer(this);
|
||||
}
|
||||
|
||||
|
||||
gamestate_observer::~gamestate_observer()
|
||||
{
|
||||
ai::manager::remove_gamestate_observer(this);
|
||||
ai::manager::get_singleton().remove_gamestate_observer(this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include "config.hpp" // for config, etc
|
||||
#include "game_events/pump.hpp"
|
||||
#include "generic_event.hpp" // for generic_event, etc
|
||||
#include "log.hpp"
|
||||
#include "map/location.hpp" // for map_location
|
||||
#include "resources.hpp"
|
||||
|
@ -303,17 +302,22 @@ component* holder::get_component(component *root, const std::string &path) {
|
|||
// =======================================================================
|
||||
|
||||
|
||||
manager::AI_map_of_stacks manager::ai_map_;
|
||||
std::unique_ptr<game_info> manager::ai_info_;
|
||||
events::generic_event manager::user_interact_("ai_user_interact");
|
||||
events::generic_event manager::sync_network_("ai_sync_network");
|
||||
events::generic_event manager::tod_changed_("ai_tod_changed");
|
||||
events::generic_event manager::gamestate_changed_("ai_gamestate_changed");
|
||||
events::generic_event manager::turn_started_("ai_turn_started");
|
||||
events::generic_event manager::recruit_list_changed_("ai_recruit_list_changed");
|
||||
events::generic_event manager::map_changed_("ai_map_changed");
|
||||
int manager::last_interact_ = 0;
|
||||
int manager::num_interact_ = 0;
|
||||
manager::manager()
|
||||
: user_interact_("ai_user_interact")
|
||||
, sync_network_("ai_sync_network")
|
||||
, tod_changed_("ai_tod_changed")
|
||||
, gamestate_changed_("ai_gamestate_changed")
|
||||
, turn_started_("ai_turn_started")
|
||||
, recruit_list_changed_("ai_recruit_list_changed")
|
||||
, map_changed_("ai_map_changed")
|
||||
, last_interact_(0)
|
||||
, num_interact_(0)
|
||||
{
|
||||
singleton_ = this;
|
||||
}
|
||||
|
||||
|
||||
manager* manager::singleton_ = nullptr;
|
||||
|
||||
|
||||
void manager::set_ai_info(const game_info& i)
|
||||
|
@ -480,7 +484,7 @@ const std::string manager::evaluate_command( side_number side, const std::string
|
|||
}
|
||||
|
||||
|
||||
bool manager::should_intercept( const std::string& str )
|
||||
bool manager::should_intercept( const std::string& str ) const
|
||||
{
|
||||
if (str.length()<1) {
|
||||
return false;
|
||||
|
@ -495,9 +499,6 @@ bool manager::should_intercept( const std::string& str )
|
|||
|
||||
}
|
||||
|
||||
std::deque< command_history_item > manager::history_;
|
||||
long manager::history_item_counter_ = 1;
|
||||
|
||||
//this is stub code to allow testing of basic 'history', 'repeat-last-command', 'add/remove/replace ai' capabilities.
|
||||
//yes, it doesn't look nice. but it is usable.
|
||||
//to be refactored at earliest opportunity
|
||||
|
@ -703,13 +704,13 @@ void manager::append_active_ai_for_side(side_number side, const config& cfg)
|
|||
get_active_ai_holder_for_side(side).append_ai(cfg);
|
||||
}
|
||||
|
||||
std::string manager::get_active_ai_overview_for_side( side_number side)
|
||||
std::string manager::get_active_ai_overview_for_side( side_number side )
|
||||
{
|
||||
return get_active_ai_holder_for_side(side).get_ai_overview();
|
||||
}
|
||||
|
||||
|
||||
std::string manager::get_active_ai_structure_for_side( side_number side)
|
||||
std::string manager::get_active_ai_structure_for_side( side_number side )
|
||||
{
|
||||
return get_active_ai_holder_for_side(side).get_ai_structure();
|
||||
}
|
||||
|
@ -720,7 +721,7 @@ std::string manager::get_active_ai_identifier_for_side( side_number side )
|
|||
return get_active_ai_holder_for_side(side).get_ai_identifier();
|
||||
}
|
||||
|
||||
ai::holder& manager::get_active_ai_holder_for_side_dbg(side_number side)
|
||||
ai::holder& manager::get_active_ai_holder_for_side_dbg( side_number side )
|
||||
{
|
||||
if (!game_config::debug)
|
||||
{
|
||||
|
@ -737,13 +738,13 @@ config manager::to_config( side_number side )
|
|||
}
|
||||
|
||||
|
||||
game_info& manager::get_active_ai_info_for_side( side_number /*side*/ )
|
||||
game_info& manager::get_active_ai_info_for_side( side_number /*side*/ ) const
|
||||
{
|
||||
return *ai_info_;
|
||||
}
|
||||
|
||||
|
||||
game_info& manager::get_ai_info()
|
||||
game_info& manager::get_ai_info() const
|
||||
{
|
||||
return *ai_info_;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "config.hpp" // for config, etc
|
||||
#include "ai/game_info.hpp" // for side_number, ai_ptr
|
||||
#include "ai/game_info.hpp" // for side_number, ai_ptr
|
||||
#include "config.hpp" // for config, etc
|
||||
#include "generic_event.hpp" // for generic_event, etc
|
||||
|
||||
#include <deque> // for deque
|
||||
#include <map> // for map, map<>::value_compare
|
||||
|
@ -112,8 +113,7 @@ private:
|
|||
|
||||
/**
|
||||
* Class that manages AIs for all sides and manages AI redeployment.
|
||||
* This class is responsible for managing the AI lifecycle
|
||||
* It can be accessed like this: ai::manager::foo(...);
|
||||
* This class is responsible for managing the AI lifecycle.
|
||||
*/
|
||||
class manager
|
||||
{
|
||||
|
@ -134,6 +134,26 @@ public:
|
|||
static const std::string AI_TYPE_DEFAULT;
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// CONSTRUCTORS AND DESTRUCTORS
|
||||
// =======================================================================
|
||||
|
||||
manager();
|
||||
|
||||
/* The singleton can't be set to null in the destructor because member objects
|
||||
(which access the singleton) are destroyed *after* the destructor has been run. */
|
||||
~manager() = default;
|
||||
|
||||
// =======================================================================
|
||||
// ACCESS TO MANAGER
|
||||
// =======================================================================
|
||||
|
||||
static manager& get_singleton()
|
||||
{
|
||||
assert(singleton_ != nullptr);
|
||||
return *singleton_;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// LIFECYCLE
|
||||
// =======================================================================
|
||||
|
@ -142,40 +162,40 @@ public:
|
|||
* Sets AI information.
|
||||
* @param info ai_information to be set.
|
||||
*/
|
||||
static void set_ai_info(const game_info& info);
|
||||
void set_ai_info(const game_info& info);
|
||||
|
||||
|
||||
/**
|
||||
* Clears AI information.
|
||||
* Should be called in playsingle_controller 's destructor.
|
||||
*/
|
||||
static void clear_ai_info();
|
||||
void clear_ai_info();
|
||||
|
||||
|
||||
/**
|
||||
* Adds observer of game events.
|
||||
* Should be called in playsingle_controller 's constructor.
|
||||
*/
|
||||
static void add_observer( events::observer* event_observer);
|
||||
void add_observer( events::observer* event_observer);
|
||||
|
||||
|
||||
/**
|
||||
* Removes an observer of game events.
|
||||
* Should be called in playsingle_controller 's destructor.
|
||||
*/
|
||||
static void remove_observer( events::observer* event_observer );
|
||||
void remove_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Adds observer of game events except ai_user_interact event and ai_sync_network event
|
||||
*/
|
||||
static void add_gamestate_observer( events::observer* event_observer);
|
||||
void add_gamestate_observer( events::observer* event_observer);
|
||||
|
||||
|
||||
/**
|
||||
* Removes an observer of game events except ai_user_interact event and ai_sync_network event
|
||||
*/
|
||||
static void remove_gamestate_observer( events::observer* event_observer );
|
||||
void remove_gamestate_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -185,97 +205,92 @@ public:
|
|||
* doesn't occur too often, so there is no problem with calling it very
|
||||
* regularly.
|
||||
*/
|
||||
static void raise_user_interact();
|
||||
void raise_user_interact();
|
||||
|
||||
/**
|
||||
* Notifies all observers of 'ai_sync_network' event.
|
||||
* Basically a request from the AI to sync the network.
|
||||
*/
|
||||
static void raise_sync_network();
|
||||
void raise_sync_network();
|
||||
|
||||
|
||||
/**
|
||||
* Notifies all observers of 'ai_gamestate_changed' event.
|
||||
*/
|
||||
static void raise_gamestate_changed();
|
||||
void raise_gamestate_changed();
|
||||
|
||||
|
||||
/**
|
||||
* Notifies all observers of 'ai_tod_changed' event.
|
||||
*/
|
||||
static void raise_tod_changed();
|
||||
void raise_tod_changed();
|
||||
|
||||
|
||||
/**
|
||||
* Notifies all observers of 'ai_recruit_list_changed' event.
|
||||
*/
|
||||
static void raise_recruit_list_changed();
|
||||
void raise_recruit_list_changed();
|
||||
|
||||
|
||||
/**
|
||||
* Notifies all observers of 'ai_turn_started' event.
|
||||
*/
|
||||
static void raise_turn_started();
|
||||
void raise_turn_started();
|
||||
|
||||
|
||||
/**
|
||||
* Notifies all observers of 'ai_map_changed' event.
|
||||
*/
|
||||
static void raise_map_changed();
|
||||
void raise_map_changed();
|
||||
|
||||
|
||||
/**
|
||||
* Adds an observer of 'ai_map_changed' event.
|
||||
*/
|
||||
static void add_map_changed_observer( events::observer* event_observer );
|
||||
void add_map_changed_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Adds an observer of 'ai_recruit_list_changed' event.
|
||||
*/
|
||||
static void add_recruit_list_changed_observer( events::observer* event_observer );
|
||||
void add_recruit_list_changed_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Adds an observer of 'ai_turn_started' event.
|
||||
*/
|
||||
static void add_turn_started_observer( events::observer* event_observer );
|
||||
void add_turn_started_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Adds an observer of 'ai_tod_changed' event.
|
||||
*/
|
||||
static void add_tod_changed_observer( events::observer* event_observer );
|
||||
void add_tod_changed_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an observer of 'ai_map_changed' event.
|
||||
*/
|
||||
static void remove_map_changed_observer( events::observer* event_observer );
|
||||
void remove_map_changed_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an observer of 'ai_recruit_list_changed' event.
|
||||
*/
|
||||
static void remove_recruit_list_changed_observer( events::observer* event_observer );
|
||||
void remove_recruit_list_changed_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an observer of 'ai_turn_started' event.
|
||||
*/
|
||||
static void remove_turn_started_observer( events::observer* event_observer );
|
||||
void remove_turn_started_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
/**
|
||||
* Deletes an observer of 'ai_tod_changed' event.
|
||||
*/
|
||||
static void remove_tod_changed_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
manager();
|
||||
void remove_tod_changed_observer( events::observer* event_observer );
|
||||
|
||||
|
||||
public:
|
||||
|
@ -293,7 +308,7 @@ public:
|
|||
* @param str string to evaluate.
|
||||
* @return string result of evaluation.
|
||||
*/
|
||||
static const std::string evaluate_command( side_number side, const std::string& str );
|
||||
const std::string evaluate_command( side_number side, const std::string& str );
|
||||
|
||||
|
||||
// =======================================================================
|
||||
|
@ -309,7 +324,7 @@ public:
|
|||
* @param replace should new ai replace the current ai or 'be placed on top of it'.
|
||||
* @return true if successful.
|
||||
*/
|
||||
static bool add_ai_for_side_from_file( side_number side, const std::string& file, bool replace = true );
|
||||
bool add_ai_for_side_from_file( side_number side, const std::string& file, bool replace = true );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -321,7 +336,7 @@ public:
|
|||
* @param replace should new ai replace the current ai or 'be placed on top of it'.
|
||||
* @return true if successful.
|
||||
*/
|
||||
static bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace = true);
|
||||
bool add_ai_for_side_from_config(side_number side, const config &cfg, bool replace = true);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -333,7 +348,7 @@ public:
|
|||
* @param replace should new ai replace the current ai or 'be placed on top of it'.
|
||||
* @return true if successful.
|
||||
*/
|
||||
static bool add_ai_for_side( side_number side, const std::string& ai_algorithm_type, bool replace = true);
|
||||
bool add_ai_for_side( side_number side, const std::string& ai_algorithm_type, bool replace = true);
|
||||
|
||||
|
||||
// =======================================================================
|
||||
|
@ -346,7 +361,7 @@ public:
|
|||
* by manager.
|
||||
* @param side side number (1-based, as in game_info).
|
||||
*/
|
||||
static void remove_ai_for_side( side_number side );
|
||||
void remove_ai_for_side( side_number side );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -355,7 +370,7 @@ public:
|
|||
* by manager.
|
||||
* @param side side number (1-based, as in game_info).
|
||||
*/
|
||||
static void remove_all_ais_for_side( side_number side );
|
||||
void remove_all_ais_for_side( side_number side );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -365,7 +380,7 @@ public:
|
|||
* playsingle_controller. It is necessary to do this if any of the
|
||||
* info structures used by the AI goes out of scope.
|
||||
*/
|
||||
static void clear_ais();
|
||||
void clear_ais();
|
||||
|
||||
// =======================================================================
|
||||
// GET active AI parameters
|
||||
|
@ -377,7 +392,7 @@ public:
|
|||
* @param side side number (1-based).
|
||||
* @return a reference to active AI info.
|
||||
*/
|
||||
static game_info& get_active_ai_info_for_side( side_number side );
|
||||
game_info& get_active_ai_info_for_side( side_number side ) const;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -385,7 +400,7 @@ public:
|
|||
* @param side side number (1-based)
|
||||
* @return an ai overview
|
||||
*/
|
||||
static std::string get_active_ai_overview_for_side( side_number side);
|
||||
std::string get_active_ai_overview_for_side( side_number side );
|
||||
|
||||
|
||||
/**
|
||||
|
@ -393,14 +408,14 @@ public:
|
|||
* @param side side number (1-based)
|
||||
* @return an ai structure
|
||||
*/
|
||||
static std::string get_active_ai_structure_for_side( side_number side);
|
||||
std::string get_active_ai_structure_for_side( side_number side );
|
||||
|
||||
/**
|
||||
* Gets AI algorithm identifier for active AI of the given @a side.
|
||||
* @param side side number (1-based).
|
||||
* @return ai identifier for the active AI
|
||||
*/
|
||||
static std::string get_active_ai_identifier_for_side( side_number side );
|
||||
std::string get_active_ai_identifier_for_side( side_number side );
|
||||
|
||||
/**
|
||||
* Gets the active AI holder for debug purposes.
|
||||
|
@ -408,21 +423,21 @@ public:
|
|||
* @param side side number(1-based)
|
||||
* @return debug ? active holder : empty holder
|
||||
*/
|
||||
static ai::holder& get_active_ai_holder_for_side_dbg(side_number side);
|
||||
ai::holder& get_active_ai_holder_for_side_dbg(side_number side);
|
||||
|
||||
/**
|
||||
* Gets AI config for active AI of the given @a side.
|
||||
* @param side side number (1-based).
|
||||
* @return a config object for the active AI
|
||||
*/
|
||||
static config to_config( side_number side );
|
||||
config to_config( side_number side );
|
||||
|
||||
|
||||
/**
|
||||
* Gets global AI-game info
|
||||
* @return a reference to the AI-game info.
|
||||
*/
|
||||
static game_info& get_ai_info();
|
||||
game_info& get_ai_info() const;
|
||||
|
||||
|
||||
// =======================================================================
|
||||
|
@ -436,7 +451,7 @@ public:
|
|||
* @param cfg - content of [modify_ai] tag
|
||||
*/
|
||||
|
||||
static void modify_active_ai_for_side( ai::side_number side, const config &cfg );
|
||||
void modify_active_ai_for_side( ai::side_number side, const config &cfg );
|
||||
|
||||
/**
|
||||
* Appends AI parameters to active AI of the given @a side.
|
||||
|
@ -445,7 +460,7 @@ public:
|
|||
* @param cfg - content of [modify_side][ai] tag
|
||||
*/
|
||||
|
||||
static void append_active_ai_for_side( ai::side_number side, const config &cfg );
|
||||
void append_active_ai_for_side( ai::side_number side, const config &cfg );
|
||||
|
||||
// =======================================================================
|
||||
// PROXY
|
||||
|
@ -455,27 +470,30 @@ public:
|
|||
* Plays a turn for the specified side using its active AI.
|
||||
* @param side side number (1-based, as in game_info).
|
||||
*/
|
||||
static void play_turn(side_number side);
|
||||
void play_turn(side_number side);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
typedef std::map< side_number, std::stack< holder > > AI_map_of_stacks;
|
||||
static AI_map_of_stacks ai_map_;
|
||||
static std::deque< command_history_item > history_;
|
||||
static long history_item_counter_;
|
||||
static std::unique_ptr<game_info> ai_info_;
|
||||
|
||||
static events::generic_event map_changed_;
|
||||
static events::generic_event recruit_list_changed_;
|
||||
static events::generic_event user_interact_;
|
||||
static events::generic_event sync_network_;
|
||||
static events::generic_event tod_changed_;
|
||||
static events::generic_event gamestate_changed_;
|
||||
static events::generic_event turn_started_;
|
||||
static int last_interact_;
|
||||
static int num_interact_;
|
||||
std::deque< command_history_item > history_;
|
||||
long history_item_counter_;
|
||||
std::unique_ptr<game_info> ai_info_;
|
||||
|
||||
events::generic_event map_changed_;
|
||||
events::generic_event recruit_list_changed_;
|
||||
events::generic_event user_interact_;
|
||||
events::generic_event sync_network_;
|
||||
events::generic_event tod_changed_;
|
||||
events::generic_event gamestate_changed_;
|
||||
events::generic_event turn_started_;
|
||||
int last_interact_;
|
||||
int num_interact_;
|
||||
|
||||
AI_map_of_stacks ai_map_;
|
||||
|
||||
static manager* singleton_;
|
||||
|
||||
|
||||
// =======================================================================
|
||||
|
@ -489,14 +507,14 @@ private:
|
|||
* @return string result of evaluation.
|
||||
* @todo 1.9 rewrite this function to use a fai or lua parser.
|
||||
*/
|
||||
static const std::string internal_evaluate_command( side_number side, const std::string& str );
|
||||
const std::string internal_evaluate_command( side_number side, const std::string& str );
|
||||
|
||||
/**
|
||||
* Determines if the command should be intercepted and evaluated as internal command.
|
||||
* @param str command string to check.
|
||||
* @return true if the command should be intercepted and evaluated.
|
||||
*/
|
||||
static bool should_intercept( const std::string& str );
|
||||
bool should_intercept( const std::string& str ) const;
|
||||
|
||||
// =======================================================================
|
||||
// AI STACKS
|
||||
|
@ -506,7 +524,7 @@ private:
|
|||
/**
|
||||
* Gets the AI stack for the specified side, create it if it doesn't exist.
|
||||
*/
|
||||
static std::stack< holder >& get_or_create_ai_stack_for_side(side_number side);
|
||||
std::stack< holder >& get_or_create_ai_stack_for_side(side_number side);
|
||||
|
||||
// =======================================================================
|
||||
// AI HOLDERS
|
||||
|
@ -516,7 +534,7 @@ private:
|
|||
/**
|
||||
* Gets active holder for specified @a side.
|
||||
*/
|
||||
static holder& get_active_ai_holder_for_side( side_number side );
|
||||
holder& get_active_ai_holder_for_side( side_number side );
|
||||
|
||||
// =======================================================================
|
||||
// AI POINTERS
|
||||
|
@ -530,7 +548,7 @@ private:
|
|||
* @return a reference to the active AI.
|
||||
* @note This reference may become invalid after specific manager operations.
|
||||
*/
|
||||
static ai_composite& get_active_ai_for_side( side_number side );
|
||||
ai_composite& get_active_ai_for_side( side_number side );
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -90,9 +90,9 @@ void ai_testing::log_game_start()
|
|||
{
|
||||
for (std::vector<team>::const_iterator tm = resources::gameboard->teams().begin(); tm != resources::gameboard->teams().end(); ++tm) {
|
||||
int side = tm-resources::gameboard->teams().begin()+1;
|
||||
LOG_AI_TESTING << "AI_IDENTIFIER " <<side << ": " << ai::manager::get_active_ai_identifier_for_side(side) << std::endl;
|
||||
LOG_AI_TESTING << "AI_IDENTIFIER " << side << ": " << ai::manager::get_singleton().get_active_ai_identifier_for_side(side) << std::endl;
|
||||
LOG_AI_TESTING << "TEAM " << side << ": " << tm->side() << std::endl;
|
||||
resources::recorder->add_log_data("ai_log","ai_id"+std::to_string(side),ai::manager::get_active_ai_identifier_for_side(side));
|
||||
resources::recorder->add_log_data("ai_log", "ai_id" + std::to_string(side), ai::manager::get_singleton().get_active_ai_identifier_for_side(side));
|
||||
///@todo 1.9: add information about ai_config
|
||||
}
|
||||
LOG_AI_TESTING << "VERSION: " << game_config::revision << std::endl;
|
||||
|
|
|
@ -636,7 +636,7 @@ WML_HANDLER_FUNCTION(replace_map,, cfg)
|
|||
|
||||
resources::screen->reload_map();
|
||||
resources::screen->needs_rebuild(true);
|
||||
ai::manager::raise_map_changed();
|
||||
ai::manager::get_singleton().raise_map_changed();
|
||||
}
|
||||
|
||||
/// Experimental data persistence
|
||||
|
|
|
@ -49,6 +49,7 @@ game_state::game_state(const config & level, play_controller & pc, const ter_dat
|
|||
pathfind_manager_(new pathfind::manager(level)),
|
||||
reports_(new reports()),
|
||||
lua_kernel_(new game_lua_kernel(*this, pc, *reports_)),
|
||||
ai_manager_(),
|
||||
events_manager_(new game_events::manager()),
|
||||
//TODO: this construct units (in dimiss undo action) but resrouces:: are not available yet,
|
||||
// so we might want to move the innitialisation of undo_stack_ to game_state::init
|
||||
|
@ -75,6 +76,7 @@ game_state::game_state(const config & level, play_controller & pc, game_board& b
|
|||
pathfind_manager_(new pathfind::manager(level)),
|
||||
reports_(new reports()),
|
||||
lua_kernel_(new game_lua_kernel(*this, pc, *reports_)),
|
||||
ai_manager_(),
|
||||
events_manager_(new game_events::manager()),
|
||||
player_number_(level["playing_team"].to_int() + 1),
|
||||
end_level_data_(),
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
class config;
|
||||
|
||||
#include "ai/manager.hpp"
|
||||
#include "filter_context.hpp"
|
||||
#include "game_board.hpp"
|
||||
#include "game_data.hpp"
|
||||
|
@ -47,6 +48,7 @@ public:
|
|||
std::unique_ptr<pathfind::manager> pathfind_manager_;
|
||||
const std::unique_ptr<reports> reports_;
|
||||
std::unique_ptr<game_lua_kernel> lua_kernel_;
|
||||
ai::manager ai_manager_;
|
||||
const std::unique_ptr<game_events::manager> events_manager_;
|
||||
/// undo_stack_ is never nullptr. It is implemented as a pointer so that
|
||||
/// undo_list can be an incomplete type at this point (which reduces the
|
||||
|
|
|
@ -699,7 +699,7 @@ void team_mode_controller::show_list(tree_view_node& node, int side)
|
|||
|
||||
void team_mode_controller::show_ai(tree_view_node& node, int side)
|
||||
{
|
||||
model().set_data(ai::manager::get_active_ai_overview_for_side(side));
|
||||
model().set_data(ai::manager::get_singleton().get_active_ai_overview_for_side(side));
|
||||
|
||||
if(node.count_children() > 0) {
|
||||
return;
|
||||
|
@ -743,7 +743,7 @@ void team_mode_controller::show_ai_components(tree_view_node& node, int side)
|
|||
if(label* lbl = dynamic_cast<label*>(w)) {
|
||||
std::string tag = lbl->get_label();
|
||||
tag.pop_back();
|
||||
model().set_data(config_to_string(ai::manager::to_config(side), tag));
|
||||
model().set_data(config_to_string(ai::manager::get_singleton().to_config(side), tag));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -774,7 +774,7 @@ void team_mode_controller::show_recall_unit(tree_view_node& node, int side)
|
|||
|
||||
void team_mode_controller::show_ai_tree(tree_view_node&, int side)
|
||||
{
|
||||
model().set_data(ai::manager::get_active_ai_structure_for_side(side));
|
||||
model().set_data(ai::manager::get_singleton().get_active_ai_structure_for_side(side));
|
||||
}
|
||||
|
||||
void team_mode_controller::show_units(tree_view_node&, int side)
|
||||
|
|
|
@ -1948,7 +1948,7 @@ void console_handler::do_whiteboard_options()
|
|||
void menu_handler::do_ai_formula(const std::string& str, int side_num, mouse_handler& /*mousehandler*/)
|
||||
{
|
||||
try {
|
||||
add_chat_message(time(nullptr), "wfl", 0, ai::manager::evaluate_command(side_num, str));
|
||||
add_chat_message(time(nullptr), "wfl", 0, ai::manager::get_singleton().evaluate_command(side_num, str));
|
||||
} catch(wfl::formula_error&) {
|
||||
} catch(...) {
|
||||
add_chat_message(time(nullptr), "wfl", 0, "UNKNOWN ERROR IN FORMULA");
|
||||
|
|
|
@ -306,6 +306,10 @@ void play_controller::reset_gamestate(const config& level, int replay_pos)
|
|||
|
||||
gui_->labels().set_team(nullptr);
|
||||
|
||||
/* First destroy the old game state, then create the new one.
|
||||
This is necessary to ensure that while the old AI manager is being destroyed,
|
||||
all its member objects access the old manager instead of the new. */
|
||||
gamestate_.reset();
|
||||
gamestate_.reset(new game_state(level, *this, tdata_));
|
||||
resources::gameboard = &gamestate().board_;
|
||||
resources::gamedata = &gamestate().gamedata_;
|
||||
|
@ -956,7 +960,7 @@ void play_controller::check_victory()
|
|||
if (gui_->video().non_interactive()) {
|
||||
LOG_AIT << "winner: ";
|
||||
for (unsigned l : not_defeated) {
|
||||
std::string ai = ai::manager::get_active_ai_identifier_for_side(l);
|
||||
std::string ai = ai::manager::get_singleton().get_active_ai_identifier_for_side(l);
|
||||
if (ai.empty()) ai = "default ai";
|
||||
LOG_AIT << l << " (using " << ai << ") ";
|
||||
}
|
||||
|
|
|
@ -86,8 +86,8 @@ playsingle_controller::playsingle_controller(const config& level,
|
|||
linger_ = this->is_regular_game_end();
|
||||
|
||||
ai::game_info ai_info;
|
||||
ai::manager::set_ai_info(ai_info);
|
||||
ai::manager::add_observer(this) ;
|
||||
ai::manager::get_singleton().set_ai_info(ai_info);
|
||||
ai::manager::get_singleton().add_observer(this);
|
||||
|
||||
plugins_context_->set_accessor_string("level_result", std::bind(&playsingle_controller::describe_result, this));
|
||||
plugins_context_->set_accessor_int("turn", std::bind(&play_controller::turn, this));
|
||||
|
@ -108,8 +108,8 @@ std::string playsingle_controller::describe_result() const
|
|||
|
||||
playsingle_controller::~playsingle_controller()
|
||||
{
|
||||
ai::manager::remove_observer(this) ;
|
||||
ai::manager::clear_ais() ;
|
||||
ai::manager::get_singleton().remove_observer(this);
|
||||
ai::manager::get_singleton().clear_ais();
|
||||
}
|
||||
|
||||
void playsingle_controller::init_gui()
|
||||
|
@ -552,7 +552,7 @@ void playsingle_controller::play_ai_turn()
|
|||
try {
|
||||
try {
|
||||
if (!should_return_to_play_side()) {
|
||||
ai::manager::play_turn(current_side());
|
||||
ai::manager::get_singleton().play_turn(current_side());
|
||||
}
|
||||
}
|
||||
catch (return_to_play_side_exception&) {
|
||||
|
|
|
@ -2970,7 +2970,7 @@ static int intf_modify_ai(lua_State *L, const char* action)
|
|||
"path", path
|
||||
};
|
||||
if(strcmp(action, "delete") == 0) {
|
||||
ai::manager::modify_active_ai_for_side(side_num, cfg);
|
||||
ai::manager::get_singleton().modify_active_ai_for_side(side_num, cfg);
|
||||
return 0;
|
||||
}
|
||||
config component = luaW_checkconfig(L, 3);
|
||||
|
@ -2980,7 +2980,7 @@ static int intf_modify_ai(lua_State *L, const char* action)
|
|||
len = open_brak - dot - 1;
|
||||
}
|
||||
cfg.add_child(path.substr(dot + 1, len), component);
|
||||
ai::manager::modify_active_ai_for_side(side_num, cfg);
|
||||
ai::manager::get_singleton().modify_active_ai_for_side(side_num, cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2989,13 +2989,13 @@ static int intf_switch_ai(lua_State *L)
|
|||
int side_num = luaL_checkinteger(L, 1);
|
||||
if(lua_isstring(L, 2)) {
|
||||
std::string file = luaL_checkstring(L, 2);
|
||||
if(!ai::manager::add_ai_for_side_from_file(side_num, file)) {
|
||||
if(!ai::manager::get_singleton().add_ai_for_side_from_file(side_num, file)) {
|
||||
std::string err = formatter() << "Could not load AI for side " << side_num << " from file " << file;
|
||||
lua_pushlstring(L, err.c_str(), err.length());
|
||||
return lua_error(L);
|
||||
}
|
||||
} else {
|
||||
ai::manager::add_ai_for_side_from_config(side_num, luaW_checkconfig(L, 2));
|
||||
ai::manager::get_singleton().add_ai_for_side_from_config(side_num, luaW_checkconfig(L, 2));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -3020,7 +3020,7 @@ static int intf_append_ai(lua_State *L)
|
|||
}
|
||||
}
|
||||
}
|
||||
ai::manager::append_active_ai_for_side(side_num, cfg.child("ai"));
|
||||
ai::manager::get_singleton().append_active_ai_for_side(side_num, cfg.child("ai"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3348,7 +3348,7 @@ static int intf_modify_ai_old(lua_State *L)
|
|||
luaW_toconfig(L, 1, cfg);
|
||||
int side = cfg["side"];
|
||||
WRN_LUA << "wesnoth.modify_ai is deprecated\n";
|
||||
ai::manager::modify_active_ai_for_side(side, cfg);
|
||||
ai::manager::get_singleton().modify_active_ai_for_side(side, cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3461,7 +3461,7 @@ static int intf_debug_ai(lua_State *L)
|
|||
int side = lua_tointeger(L, 1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
ai::component* c = ai::manager::get_active_ai_holder_for_side_dbg(side).get_component(nullptr, "");
|
||||
ai::component* c = ai::manager::get_singleton().get_active_ai_holder_for_side_dbg(side).get_component(nullptr, "");
|
||||
|
||||
// Bad, but works
|
||||
std::vector<ai::component*> engines = c->get_children("engine");
|
||||
|
@ -3475,7 +3475,7 @@ static int intf_debug_ai(lua_State *L)
|
|||
}
|
||||
|
||||
// Better way, but doesn't work
|
||||
//ai::component* e = ai::manager::get_active_ai_holder_for_side_dbg(side).get_component(c, "engine[lua]");
|
||||
//ai::component* e = ai::manager::get_singleton().get_active_ai_holder_for_side_dbg(side).get_component(c, "engine[lua]");
|
||||
//ai::engine_lua* lua_engine = dynamic_cast<ai::engine_lua *>(e);
|
||||
|
||||
if (lua_engine == nullptr)
|
||||
|
|
10
src/team.cpp
10
src/team.cpp
|
@ -204,9 +204,9 @@ void team::team_info::read(const config& cfg)
|
|||
user_team_name = t_string::from_serialized(user_team_name);
|
||||
|
||||
if(cfg.has_attribute("ai_config")) {
|
||||
ai::manager::add_ai_for_side_from_file(side, cfg["ai_config"], true);
|
||||
ai::manager::get_singleton().add_ai_for_side_from_file(side, cfg["ai_config"], true);
|
||||
} else {
|
||||
ai::manager::add_ai_for_side_from_config(side, cfg, true);
|
||||
ai::manager::get_singleton().add_ai_for_side_from_config(side, cfg, true);
|
||||
}
|
||||
|
||||
std::vector<std::string> recruits = utils::split(cfg["recruit"]);
|
||||
|
@ -322,7 +322,7 @@ void team::team_info::write(config& cfg) const
|
|||
cfg.add_child("variables", variables);
|
||||
}
|
||||
|
||||
cfg.add_child("ai", ai::manager::to_config(side));
|
||||
cfg.add_child("ai", ai::manager::get_singleton().to_config(side));
|
||||
}
|
||||
|
||||
team::team()
|
||||
|
@ -458,14 +458,14 @@ void team::set_recruits(const std::set<std::string>& recruits)
|
|||
{
|
||||
info_.can_recruit = recruits;
|
||||
info_.minimum_recruit_price = 0;
|
||||
ai::manager::raise_recruit_list_changed();
|
||||
ai::manager::get_singleton().raise_recruit_list_changed();
|
||||
}
|
||||
|
||||
void team::add_recruit(const std::string& recruit)
|
||||
{
|
||||
info_.can_recruit.insert(recruit);
|
||||
info_.minimum_recruit_price = 0;
|
||||
ai::manager::raise_recruit_list_changed();
|
||||
ai::manager::get_singleton().raise_recruit_list_changed();
|
||||
}
|
||||
|
||||
int team::minimum_recruit_price() const
|
||||
|
|
|
@ -1129,7 +1129,7 @@ void unit::set_recruits(const std::vector<std::string>& recruits)
|
|||
recruit_list_ = recruits;
|
||||
//TODO crab
|
||||
//info_.minimum_recruit_price = 0;
|
||||
//ai::manager::raise_recruit_list_changed();
|
||||
//ai::manager::get_singleton().raise_recruit_list_changed();
|
||||
}
|
||||
|
||||
const std::vector<std::string> unit::advances_to_translated() const
|
||||
|
|
Loading…
Add table
Reference in a new issue