# ai_scanner.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "../stdafx.h"
    00013 #include "../debug.h"
    00014 #include "../network/network.h"
    00015 #include "../core/random_func.hpp"
    00016
    00017 #include "../script/squirrel_class.hpp"
    00018 #include "ai_info.hpp"
    00019 #include "ai_scanner.hpp"
    00020
    00021
    00022 AIScannerInfo::AIScannerInfo() :
    00023   ScriptScanner(),
    00024   info_dummy(NULL)
    00025 {
    00026 }
    00027
    00028 void AIScannerInfo::Initialize()
    00029 {
    00030   ScriptScanner::Initialize("AIScanner");
    00031
    00032   /* Create the dummy AI */
    00033   free(this->main_script);
    00034   this->main_script = strdup("%_dummy");
    00035   extern void Script_CreateDummyInfo(HSQUIRRELVM vm, const char *type, const char *dir);
    00036   Script_CreateDummyInfo(this->engine->GetVM(), "AI", "ai");
    00037 }
    00038
    00039 void AIScannerInfo::SetDummyAI(class AIInfo *info)
    00040 {
    00041   this->info_dummy = info;
    00042 }
    00043
    00044 AIScannerInfo::~AIScannerInfo()
    00045 {
    00046   delete this->info_dummy;
    00047 }
    00048
    00049 void AIScannerInfo::GetScriptName(ScriptInfo *info, char *name, int len)
    00050 {
    00051   snprintf(name, len, "%s", info->GetName());
    00052 }
    00053
    00054 void AIScannerInfo::RegisterAPI(class Squirrel *engine)
    00055 {
    00056   AIInfo::RegisterAPI(engine);
    00057 }
    00058
    00059 AIInfo *AIScannerInfo::SelectRandomAI() const
    00060 {
    00061   uint num_random_ais = 0;
    00062   for (ScriptInfoList::const_iterator it = this->info_single_list.begin(); it != this->info_single_list.end(); it++) {
    00063     AIInfo *i = static_cast<AIInfo *>((*it).second);
    00064     if (i->UseAsRandomAI()) num_random_ais++;
    00065   }
    00066
    00067   if (num_random_ais == 0) {
    00068     DEBUG(script, 0, "No suitable AI found, loading 'dummy' AI.");
    00069     return this->info_dummy;
    00070   }
    00071
    00072   /* Find a random AI */
    00073   uint pos;
    00074   if (_networking) {
    00075     pos = InteractiveRandomRange(num_random_ais);
    00076   } else {
    00077     pos = RandomRange(num_random_ais);
    00078   }
    00079
    00080   /* Find the Nth item from the array */
    00081   ScriptInfoList::const_iterator it = this->info_single_list.begin();
    00082
    00083 #define GetAIInfo(it) static_cast<AIInfo *>((*it).second)
    00084   while (!GetAIInfo(it)->UseAsRandomAI()) it++;
    00085   for (; pos > 0; pos--) {
    00086     it++;
    00087     while (!GetAIInfo(it)->UseAsRandomAI()) it++;
    00088   }
    00089   return GetAIInfo(it);
    00090 #undef GetAIInfo
    00091 }
    00092
    00093 AIInfo *AIScannerInfo::FindInfo(const char *nameParam, int versionParam, bool force_exact_match)
    00094 {
    00095   if (this->info_list.size() == 0) return NULL;
    00096   if (nameParam == NULL) return NULL;
    00097
    00098   char ai_name[1024];
    00099   ttd_strlcpy(ai_name, nameParam, sizeof(ai_name));
    00100   strtolower(ai_name);
    00101
    00102   AIInfo *info = NULL;
    00103   int version = -1;
    00104
    00105   if (versionParam == -1) {
    00106     /* We want to load the latest version of this AI; so find it */
    00107     if (this->info_single_list.find(ai_name) != this->info_single_list.end()) return static_cast<AIInfo *>(this->info_single_list[ai_name]);
    00108
    00109     /* If we didn't find a match AI, maybe the user included a version */
    00110     char *e = strrchr(ai_name, '.');
    00111     if (e == NULL) return NULL;
    00112     *e = '\0';
    00113     e++;
    00114     versionParam = atoi(e);
    00115     /* FALL THROUGH, like we were calling this function with a version. */
    00116   }
    00117
    00118   if (force_exact_match) {
    00119     /* Try to find a direct 'name.version' match */
    00120     char ai_name_tmp[1024];
    00121     snprintf(ai_name_tmp, sizeof(ai_name_tmp), "%s.%d", ai_name, versionParam);
    00122     strtolower(ai_name_tmp);
    00123     if (this->info_list.find(ai_name_tmp) != this->info_list.end()) return static_cast<AIInfo *>(this->info_list[ai_name_tmp]);
    00124   }
    00125
    00126   /* See if there is a compatible AI which goes by that name, with the highest
    00127    *  version which allows loading the requested version */
    00128   ScriptInfoList::iterator it = this->info_list.begin();
    00129   for (; it != this->info_list.end(); it++) {
    00130     AIInfo *i = static_cast<AIInfo *>((*it).second);
    00131     if (strcasecmp(ai_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) {
    00132       version = (*it).second->GetVersion();
    00133       info = i;
    00134     }
    00135   }
    00136
    00137   return info;
    00138 }
    00139
    00140
    00141 void AIScannerLibrary::Initialize()
    00142 {
    00143   ScriptScanner::Initialize("AIScanner");
    00144 }
    00145
    00146 void AIScannerLibrary::GetScriptName(ScriptInfo *info, char *name, int len)
    00147 {
    00148   AILibrary *library = static_cast<AILibrary *>(info);
    00149   snprintf(name, len, "%s.%s", library->GetCategory(), library->GetInstanceName());
    00150 }
    00151
    00152 void AIScannerLibrary::RegisterAPI(class Squirrel *engine)
    00153 {
    00154   AILibrary::RegisterAPI(engine);
    00155 }
    00156
    00157 AILibrary *AIScannerLibrary::FindLibrary(const char *library, int version)
    00158 {
    00159   /* Internally we store libraries as 'library.version' */
    00160   char library_name[1024];
    00161   snprintf(library_name, sizeof(library_name), "%s.%d", library, version);
    00162   strtolower(library_name);
    00163
    00164   /* Check if the library + version exists */
    00165   ScriptInfoList::iterator iter = this->info_list.find(library_name);
    00166   if (iter == this->info_list.end()) return NULL;
    00167
    00168   return static_cast<AILibrary *>((*iter).second);
    00169 }