|
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 */ |