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

Reply via email to