src/ai/core/ai_factory.hpp
branchnoai
changeset 9390 4042c17c8055
child 9391 2d6da2e48112
equal deleted inserted replaced
9389:cb4e3c4ae84e 9390:4042c17c8055
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file ai_factory.hpp declaration of class for AIFactory class */
       
     4 
       
     5 #ifndef AI_FACTORY_HPP
       
     6 #define AI_FACTORY_HPP
       
     7 
       
     8 #include <string>
       
     9 #include <map>
       
    10 #include <assert.h>
       
    11 
       
    12 #include "ai_base.hpp"
       
    13 
       
    14 class AIController;
       
    15 
       
    16 class AIFactoryBase {
       
    17 private:
       
    18 	const char *name;
       
    19 	typedef std::map<std::string, AIFactoryBase *> Factories;
       
    20 
       
    21 	static Factories &GetFactories()
       
    22 	{
       
    23 		static Factories s_factories;
       
    24 		return s_factories;
       
    25 	}
       
    26 
       
    27 protected:
       
    28 	/**
       
    29 	 * This registers your AI to the main system so we know about you.
       
    30 	 */
       
    31 	void RegisterFactory(AIFactoryBase *instance, const char *name)
       
    32 	{
       
    33 		std::pair<Factories::iterator, bool> P = GetFactories().insert(Factories::value_type(name, this));
       
    34 		assert(P.second);
       
    35 		this->name = name;
       
    36 	}
       
    37 
       
    38 public:
       
    39 	virtual ~AIFactoryBase() { GetFactories().erase(this->name); }
       
    40 
       
    41 	static AIController *SelectRandomAI()
       
    42 	{
       
    43 		if (GetFactories().size() == 0) return NULL;
       
    44 
       
    45 		/* Find a random AI */
       
    46 		uint i;
       
    47 		if (_networking) i = InteractiveRandomRange(GetFactories().size());
       
    48 		else             i =            RandomRange(GetFactories().size());
       
    49 
       
    50 		/* Find the Nth item from the array */
       
    51 		Factories::iterator it = GetFactories().begin();
       
    52 		Factories::iterator first_it;
       
    53 		for (; i > 0; i--) it++;
       
    54 		first_it = it;
       
    55 		AIFactoryBase *f = (*it).second;
       
    56 
       
    57 		if (!f->AllowStartup()) {
       
    58 			/* We can't start this AI, try to find the next best */
       
    59 			do {
       
    60 				if (it == GetFactories().end()) it = GetFactories().begin();
       
    61 				else it++;
       
    62 				/* Back at the beginning? Drop out! */
       
    63 				if (first_it == it) break;
       
    64 				f = (*it).second;
       
    65 			} while (!f->AllowStartup());
       
    66 			/* Unable to start any AI */
       
    67 			if (first_it == it) return NULL;
       
    68 		}
       
    69 		return f->CreateInstance();
       
    70 	}
       
    71 
       
    72 
       
    73 
       
    74 	/**
       
    75 	 * Get the author of the AI.
       
    76 	 */
       
    77 	virtual const char *GetAuthor() = 0;
       
    78 
       
    79 	/**
       
    80 	 * Get a short name for the AI.
       
    81 	 */
       
    82 	virtual const char *GetName() = 0;
       
    83 
       
    84 	/**
       
    85 	 * Get a description of the AI.
       
    86 	 */
       
    87 	virtual const char *GetDescription() = 0;
       
    88 
       
    89 	/**
       
    90 	 * Get the version of this AI.
       
    91 	 */
       
    92 	virtual int GetVersion() = 0;
       
    93 
       
    94 	/**
       
    95 	 * Get the date of the version.
       
    96 	 * @return A string like '2007-08-29'.
       
    97 	 */
       
    98 	virtual const char *GetDate() = 0;
       
    99 
       
   100 	/**
       
   101 	 * Create an instance of your AI.
       
   102 	 */
       
   103 	virtual AIController *CreateInstance() = 0;
       
   104 
       
   105 	/**
       
   106 	 * In this function you can do some very limited querying of the game.
       
   107 	 *  If you for example only supply road-vehicle-based AI, and RVs are
       
   108 	 *  disabled, you return 'false', so you won't boot.
       
   109 	 */
       
   110 	virtual bool AllowStartup() { return true; }
       
   111 };
       
   112 
       
   113 /**
       
   114  * The template to define your AIFactory. This makes sure RegisterFactory
       
   115  *  works correctly on initialization.
       
   116  * Example: class FYourClass: public AIFactory<FYourClass> { }
       
   117  */
       
   118 template <class T>
       
   119 class AIFactory: public AIFactoryBase {
       
   120 public:
       
   121 	AIFactory() { this->RegisterFactory(this, ((T *)this)->GetName()); }
       
   122 };
       
   123 
       
   124 #endif /* AI_FACTORY_HPP */