Author: crab
Date: Thu Jun 4 23:25:36 2009
New Revision: 36062
URL: http://svn.gna.org/viewcvs/wesnoth?rev=36062&view=rev
Log:
AI refactoring: use a factory lookup pattern to create AIs
Modified:
trunk/src/ai/ai.cpp
trunk/src/ai/ai.hpp
trunk/src/ai/ai_interface.hpp
trunk/src/ai/ai_manager.cpp
trunk/src/ai/ai_manager.hpp
trunk/src/ai/contexts.hpp
trunk/src/ai/formula_ai.cpp
trunk/src/ai/registry.cpp
trunk/src/ai/testing/stage_fallback.cpp
trunk/src/ai/testing/stage_fallback.hpp
Modified: trunk/src/ai/ai.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/ai.cpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/ai.cpp (original)
+++ trunk/src/ai/ai.cpp Thu Jun 4 23:25:36 2009
@@ -247,9 +247,6 @@
}
ai_default::~ai_default(){
- if (formula_ai_!=NULL) {
- delete formula_ai_;
- }
}
void ai_default::switch_side(ai::side_number side){
@@ -1482,11 +1479,12 @@
if (get_recursion_count()<ai::recursion_counter::MAX_COUNTER_VALUE)
{
if (!current_team().ai_parameters()["recruitment"].empty()){
- if (formula_ai_ == NULL){
- formula_ai_ =
static_cast<formula_ai*>(ai::manager::create_transient_ai(ai::manager::AI_TYPE_FORMULA_AI,
this));
- }
-
- assert(formula_ai_ != NULL);
+ if (!formula_ai_){
+ formula_ai_ptr_ =
(ai::manager::create_transient_ai(ai::manager::AI_TYPE_FORMULA_AI, this));
+ formula_ai_ = static_cast<formula_ai*>
(formula_ai_ptr_.get());
+ }
+
+ assert(formula_ai_!=NULL);
if (formula_ai_->do_recruitment()) {
LOG_AI << "Recruitment done by formula_ai\n";
Modified: trunk/src/ai/ai.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/ai.hpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/ai.hpp (original)
+++ trunk/src/ai/ai.hpp Thu Jun 4 23:25:36 2009
@@ -96,6 +96,7 @@
int get_recursion_count() const;
private:
ai::recursion_counter recursion_counter_;
+
protected:
std::map<location,defensive_position> defensive_position_cache_;
@@ -409,7 +410,8 @@
int recruiting_preferred_;
static const int min_recruiting_value_to_force_recruit = 28;
protected:
- formula_ai* formula_ai_;
+ formula_ai *formula_ai_;
+ ai::ai_ptr formula_ai_ptr_;
};
#endif
Modified: trunk/src/ai/ai_interface.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/ai_interface.hpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/ai_interface.hpp (original)
+++ trunk/src/ai/ai_interface.hpp Thu Jun 4 23:25:36 2009
@@ -20,8 +20,13 @@
#ifndef AI_AI_INTERFACE_HPP_INCLUDED
#define AI_AI_INTERFACE_HPP_INCLUDED
+#include "../global.hpp"
+
#include "../formula_callable.hpp"
+
#include "game_info.hpp"
+
+#include "default/contexts.hpp"
namespace ai {
@@ -65,6 +70,50 @@
};
+class ai_factory;
+
+class ai_factory{
+public:
+ typedef boost::shared_ptr< ai_factory > factory_ptr;
+ typedef std::map<std::string, factory_ptr> factory_map;
+ typedef std::pair<const std::string, factory_ptr> factory_map_pair;
+
+ static factory_map& get_list() {
+ static factory_map *ai_factories;
+ if (ai_factories==NULL) {
+ ai_factories = new factory_map;
+ }
+ return *ai_factories;
+ }
+
+ /* cfg is commented out so far, because ai parameter handling is a mess
atm */
+ virtual ai_ptr get_new_instance( default_ai_context &context/*, const
config &cfg*/) = 0;
+
+ ai_factory( const std::string &name )
+ {
+ factory_ptr ptr_to_this(this);
+ get_list().insert(make_pair(name,ptr_to_this));
+ }
+};
+
+
+template<class AI>
+class register_ai_factory : public ai_factory {
+public:
+ register_ai_factory( const std::string &name )
+ : ai_factory( name )
+ {
+ }
+
+ virtual ai_ptr get_new_instance( default_ai_context &context/*, const
config &cfg*/){
+ ai_ptr a(new AI(context));
+ a->on_create();
+ return a;
+ }
+};
+
+
+
} //end of namespace ai
#endif
Modified: trunk/src/ai/ai_manager.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/ai_manager.cpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/ai_manager.cpp (original)
+++ trunk/src/ai/ai_manager.cpp Thu Jun 4 23:25:36 2009
@@ -54,7 +54,7 @@
#define ERR_AI_MANAGER LOG_STREAM(err, log_ai_manager)
holder::holder( int side, const std::string& ai_algorithm_type )
- : ai_(NULL), side_context_(NULL), readonly_context_(NULL),
readwrite_context_(NULL), default_ai_context_(NULL),
ai_algorithm_type_(ai_algorithm_type), ai_effective_parameters_(),
ai_global_parameters_(), ai_memory_(), ai_parameters_(), side_(side)
+ : ai_(), side_context_(NULL), readonly_context_(NULL),
readwrite_context_(NULL), default_ai_context_(NULL),
ai_algorithm_type_(ai_algorithm_type), ai_effective_parameters_(),
ai_global_parameters_(), ai_memory_(), ai_parameters_(), side_(side)
{
DBG_AI_MANAGER << describe_ai() << "Preparing new AI holder" <<
std::endl;
}
@@ -78,7 +78,7 @@
default_ai_context_ = new
default_ai_context_impl(*readwrite_context_);
}
this->ai_ = create_ai(side);
- if (this->ai_ == NULL) {
+ if (!this->ai_) {
ERR_AI_MANAGER << describe_ai()<<"AI lazy initialization
error!" << std::endl;
}
@@ -87,10 +87,9 @@
holder::~holder()
{
- if (this->ai_ != NULL) {
+ if (this->ai_) {
LOG_AI_MANAGER << describe_ai() << "Managed AI will be deleted"
<< std::endl;
}
- delete this->ai_;
delete this->default_ai_context_;
delete this->readwrite_context_;
delete this->readonly_context_;
@@ -100,10 +99,10 @@
interface& holder::get_ai_ref( int side )
{
- if (this->ai_ == NULL) {
+ if (!this->ai_) {
this->init(side);
}
- assert(this->ai_ != NULL);
+ assert(this->ai_);
return *this->ai_;
}
@@ -202,7 +201,7 @@
return true;
}
-interface* holder::create_ai( int side )
+ai_ptr holder::create_ai( int side )
{
assert (side > 0);
assert (default_ai_context_!=NULL);
@@ -549,76 +548,21 @@
}
-interface* manager::create_transient_ai( const std::string &ai_algorithm_type,
default_ai_context *ai_context )
+ai_ptr manager::create_transient_ai( const std::string &ai_algorithm_type,
default_ai_context *ai_context )
{
assert(ai_context!=NULL);
- //@todo 1.7 modify this code to use a 'factory lookup' pattern -
- //a singleton which holds a map<string,ai_factory_ptr> of all functors
which can create AIs.
- //this will allow individual AI implementations to 'register'
themselves.
-
-
-
- //: To add an AI of your own, put
- // if(ai_algorithm_type == "my_ai") {
- // LOG_AI_MANAGER << "Creating new AI of type [" <<
"my_ai" << "]"<< std::endl;
- // interface *a = new my_ai(*ai_context);
- // a->on_create();
- // return a;
- // }
- // at the top of this function
-
- //if(ai_algorithm_type == manager::AI_TYPE_SAMPLE_AI) {
- // LOG_AI_MANAGER << "Creating new AI of type [" <<
manager::AI_TYPE_IDLE_AI << "]"<< std::endl;
- // interface *a = new sample_ai(*ai_context);
- // a->on_create();
- // return a;
- //}
-
- if(ai_algorithm_type == manager::AI_TYPE_IDLE_AI) {
- LOG_AI_MANAGER << "Creating new AI of type [" <<
manager::AI_TYPE_IDLE_AI << "]"<< std::endl;
- interface *a = new idle_ai(*ai_context);
- a->on_create();
- return a;
- }
-
- if(ai_algorithm_type == manager::AI_TYPE_FORMULA_AI) {
- LOG_AI_MANAGER << "Creating new AI of type [" <<
manager::AI_TYPE_FORMULA_AI << "]"<< std::endl;
- interface *a = new formula_ai(*ai_context);
- a->on_create();
- return a;
- }
-
- if(ai_algorithm_type == manager::AI_TYPE_DFOOL_AI) {
- LOG_AI_MANAGER << "Creating new AI of type [" <<
manager::AI_TYPE_DFOOL_AI << "]"<< std::endl;
- interface *a = new dfool::dfool_ai(*ai_context);
- a->on_create();
- return a;
- }
-
- if(ai_algorithm_type == manager::AI_TYPE_AI2) {
- LOG_AI_MANAGER << "Creating new AI of type [" <<
manager::AI_TYPE_AI2 << "]"<< std::endl;
- interface *a = new ai2(*ai_context);
- a->on_create();
- return a;
- }
-
-
- if(ai_algorithm_type == manager::AI_TYPE_COMPOSITE_AI) {
- LOG_AI_MANAGER << "Creating new AI of type [" <<
manager::AI_TYPE_COMPOSITE_AI << "]"<< std::endl;
- interface *a = new composite_ai::ai_composite(*ai_context);
- a->on_create();
- return a;
- }
-
-
- if (!ai_algorithm_type.empty() && ai_algorithm_type !=
manager::AI_TYPE_DEFAULT) {
- ERR_AI_MANAGER << "AI not found: [" << ai_algorithm_type << "].
Using default instead.\n";
- }
-
- LOG_AI_MANAGER << "Creating new AI of type [" <<
manager::AI_TYPE_DEFAULT << "]"<< std::endl;
- interface *a = new ai_default(*ai_context);
- a->on_create();
- return a;
+
+ //to add your own ai, register it in registry,cpp
+ ai_factory::factory_map::iterator aii =
ai_factory::get_list().find(ai_algorithm_type);
+ if (aii == ai_factory::get_list().end()){
+ aii = ai_factory::get_list().find("");
+ if (aii == ai_factory::get_list().end()){
+ throw game::game_error("no default ai set!");
+ }
+ }
+ LOG_AI_MANAGER << "Creating new AI of type [" << ai_algorithm_type <<
"]"<< std::endl;
+ ai_ptr new_ai = aii->second->get_new_instance(*ai_context);
+ return new_ai;
}
std::vector<std::string> manager::get_available_ais()
Modified: trunk/src/ai/ai_manager.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/ai_manager.hpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/ai_manager.hpp (original)
+++ trunk/src/ai/ai_manager.hpp Thu Jun 4 23:25:36 2009
@@ -79,7 +79,7 @@
bool is_mandate_ok();
private:
- interface *ai_;
+ ai_ptr ai_;
side_context *side_context_;
readonly_context *readonly_context_;
readwrite_context *readwrite_context_;
@@ -91,7 +91,7 @@
std::vector<config> ai_parameters_;
int side_;
- interface* create_ai( int side );
+ ai_ptr create_ai( int side );
};
/**
@@ -270,13 +270,12 @@
/**
- * Returns a pointer to a new AI. It is the sole responsibility of the
caller
- * to manage its lifetime.
+ * Returns a smart pointer to a new AI.
* @param ai_algorithm_type type of AI algorithm to create
* @param context context in which this ai is created
* @return the reference to the created AI
*/
- static interface* create_transient_ai( const std::string&
ai_algorithm_type, default_ai_context *ai_context);
+ static ai_ptr create_transient_ai( const std::string&
ai_algorithm_type, default_ai_context *ai_context);
/**
Modified: trunk/src/ai/contexts.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/contexts.hpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/contexts.hpp (original)
+++ trunk/src/ai/contexts.hpp Thu Jun 4 23:25:36 2009
@@ -33,11 +33,15 @@
namespace ai {
+class interface;
+
+typedef boost::shared_ptr< interface > ai_ptr;
+
// recursion counter
class recursion_counter {
public:
recursion_counter(int counter)
- : counter_(counter++)
+ : counter_(++counter)
{
if (counter > MAX_COUNTER_VALUE ) {
throw game::game_error("maximum recursion depth
reached!");
Modified: trunk/src/ai/formula_ai.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/formula_ai.cpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/formula_ai.cpp (original)
+++ trunk/src/ai/formula_ai.cpp Thu Jun 4 23:25:36 2009
@@ -1857,8 +1857,8 @@
if(!formula_) {
if(get_recursion_count()<ai::recursion_counter::MAX_COUNTER_VALUE) {
LOG_AI << "Falling back to default AI.\n";
- util::scoped_ptr< ai::interface > fallback(
ai::manager::create_transient_ai(ai::manager::AI_TYPE_DEFAULT, this));
- if (fallback != NULL){
+ ai::ai_ptr fallback(
ai::manager::create_transient_ai(ai::manager::AI_TYPE_DEFAULT, this));
+ if (fallback){
fallback->play_turn();
}
}
@@ -2182,8 +2182,8 @@
} else
{
LOG_AI << "Explicit fallback to: " <<
fallback_command->key() << std::endl;
- util::scoped_ptr< ai::interface >
fallback ( ai::manager::create_transient_ai(fallback_command->key(), this));
- if(fallback != NULL) {
+ ai::ai_ptr fallback(
ai::manager::create_transient_ai(fallback_command->key(), this));
+ if(fallback) {
fallback->play_turn();
}
}
Modified: trunk/src/ai/registry.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/registry.cpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/registry.cpp (original)
+++ trunk/src/ai/registry.cpp Thu Jun 4 23:25:36 2009
@@ -32,14 +32,14 @@
// =======================================================================
// AIs
// =======================================================================
-/*
-static ai_factory<ai> ai_factory("");
-static ai_factory<ai> default_ai_ai_factory("default_ai");
-static ai_factory<ai2> ai2_ai_factory("ai2");
-static ai_factory<dfool_ai> dfool_ai_ai_factory("dfool_ai");
-static ai_factory<formula_ai> formula_ai_ai_factory("formula_ai");
-static ai_factory<composite_ai> composite_ai_ai_factory("composite_ai");
-*/
+
+static register_ai_factory<ai_default> ai_factory_default("");
+static register_ai_factory<ai_default> ai_default_ai_factory("default_ai");
+static register_ai_factory<ai2> ai2_ai_factory("ai2");
+static register_ai_factory<dfool::dfool_ai> ai_dfool_ai_factory("dfool_ai");
+static register_ai_factory<formula_ai> ai_formula_ai_factory("formula_ai");
+static register_ai_factory<composite_ai::ai_composite>
ai_composite_ai_factory("composite_ai");
+
// =======================================================================
// Engines
Modified: trunk/src/ai/testing/stage_fallback.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/testing/stage_fallback.cpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/testing/stage_fallback.cpp (original)
+++ trunk/src/ai/testing/stage_fallback.cpp Thu Jun 4 23:25:36 2009
@@ -32,7 +32,7 @@
#define ERR_AI_TESTING_STAGE_FALLBACK LOG_STREAM(err,
log_ai_testing_stage_fallback)
fallback_to_other_ai::fallback_to_other_ai(
ai::composite_ai::composite_ai_context &context, const config &cfg )
- : stage(context,cfg), cfg_(cfg), fallback_ai_(NULL)
+ : stage(context,cfg), cfg_(cfg), fallback_ai_()
{
}
@@ -53,9 +53,6 @@
fallback_to_other_ai::~fallback_to_other_ai()
{
- if (fallback_ai_!=NULL){
- delete fallback_ai_;
- }
}
} // of namespace testing_ai_default
Modified: trunk/src/ai/testing/stage_fallback.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai/testing/stage_fallback.hpp?rev=36062&r1=36061&r2=36062&view=diff
==============================================================================
--- trunk/src/ai/testing/stage_fallback.hpp (original)
+++ trunk/src/ai/testing/stage_fallback.hpp Thu Jun 4 23:25:36 2009
@@ -43,10 +43,9 @@
private:
const config &cfg_;
- ai::interface *fallback_ai_;
+ ai::ai_ptr fallback_ai_;
};
-
-} // of namespace testing_ai_default
+} // end of namespace testing_ai_default
#endif
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits