/* static */ void AI::StartNew(CompanyID company, bool rerandomise_ai) { assert(Company::IsValidID(company)); /* Clients shouldn't start AIs */ if (_networking && !_network_server) return; AIConfig *config = AIConfig::GetConfig(company, AIConfig::SSS_FORCE_GAME); AIInfo *info = config->GetInfo(); if (info == NULL || (rerandomise_ai && config->IsRandom())) { info = AI::scanner_info->SelectRandomAI(); assert(info != NULL); /* Load default data and store the name in the settings */ config->Change(info->GetName(), -1, false, true); } Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE); Company *c = Company::Get(company); c->ai_info = info; assert(c->ai_instance == NULL); c->ai_instance = new AIInstance(); c->ai_instance->Initialize(info); cur_company.Restore(); InvalidateWindowData(WC_AI_DEBUG, 0, -1); return; }
AIInfo *AIScannerInfo::SelectRandomAI() const { uint num_random_ais = 0; for (ScriptInfoList::const_iterator it = this->info_single_list.begin(); it != this->info_single_list.end(); it++) { AIInfo *i = static_cast<AIInfo *>((*it).second); if (i->UseAsRandomAI()) num_random_ais++; } if (num_random_ais == 0) { DEBUG(script, 0, "No suitable AI found, loading 'dummy' AI."); return this->info_dummy; } /* Find a random AI */ uint pos; if (_networking) { pos = InteractiveRandomRange(num_random_ais); } else { pos = RandomRange(num_random_ais); } /* Find the Nth item from the array */ ScriptInfoList::const_iterator it = this->info_single_list.begin(); #define GetAIInfo(it) static_cast<AIInfo *>((*it).second) while (!GetAIInfo(it)->UseAsRandomAI()) it++; for (; pos > 0; pos--) { it++; while (!GetAIInfo(it)->UseAsRandomAI()) it++; } return GetAIInfo(it); #undef GetAIInfo }
char *AIScanner::GetAIConsoleList(char *p, const char *last, bool newest_only) const { p += seprintf(p, last, "List of AIs:\n"); const AIInfoList &list = newest_only ? this->info_single_list : this->info_list; AIInfoList::const_iterator it = list.begin(); for (; it != list.end(); it++) { AIInfo *i = (*it).second; p += seprintf(p, last, "%10s (v%d): %s\n", i->GetName(), i->GetVersion(), i->GetDescription()); } p += seprintf(p, last, "\n"); return p; }
/* static */ SQInteger AIInfo::Constructor(HSQUIRRELVM vm) { /* Get the AIInfo */ SQUserPointer instance = NULL; if (SQ_FAILED(sq_getinstanceup(vm, 2, &instance, 0)) || instance == NULL) return sq_throwerror(vm, _SC("Pass an instance of a child class of AIInfo to RegisterAI")); AIInfo *info = (AIInfo *)instance; SQInteger res = AIFileInfo::Constructor(vm, info); if (res != 0) return res; AIConfigItem config = _start_date_config; config.name = strdup(config.name); config.description = strdup(config.description); info->config_list.push_back(config); /* Check if we have settings */ if (info->engine->MethodExists(*info->SQ_instance, "GetSettings")) { if (!info->GetSettings()) return SQ_ERROR; } if (info->engine->MethodExists(*info->SQ_instance, "MinVersionToLoad")) { if (!info->engine->CallIntegerMethod(*info->SQ_instance, "MinVersionToLoad", &info->min_loadable_version, MAX_GET_SETTING_OPS)) return SQ_ERROR; } else { info->min_loadable_version = info->GetVersion(); } /* When there is an UseAsRandomAI function, call it. */ if (info->engine->MethodExists(*info->SQ_instance, "UseAsRandomAI")) { if (!info->engine->CallBoolMethod(*info->SQ_instance, "UseAsRandomAI", &info->use_as_random, MAX_GET_SETTING_OPS)) return SQ_ERROR; } else { info->use_as_random = true; } /* Try to get the API version the AI is written for. */ if (info->engine->MethodExists(*info->SQ_instance, "GetAPIVersion")) { if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetAPIVersion", &info->api_version, MAX_GET_SETTING_OPS)) return SQ_ERROR; if (!CheckAPIVersion(info->api_version)) { DEBUG(ai, 1, "Loading info.nut from (%s.%d): GetAPIVersion returned invalid version", info->GetName(), info->GetVersion()); return SQ_ERROR; } } else { info->api_version = strdup("0.7"); } /* Remove the link to the real instance, else it might get deleted by RegisterAI() */ sq_setinstanceup(vm, 2, NULL); /* Register the AI to the base system */ info->base->RegisterAI(info); return 0; }
AIInfo *AIScannerInfo::FindInfo(const char *nameParam, int versionParam, bool force_exact_match) { if (this->info_list.size() == 0) return NULL; if (nameParam == NULL) return NULL; char ai_name[1024]; strecpy(ai_name, nameParam, lastof(ai_name)); strtolower(ai_name); AIInfo *info = NULL; int version = -1; if (versionParam == -1) { /* We want to load the latest version of this AI; so find it */ if (this->info_single_list.find(ai_name) != this->info_single_list.end()) return static_cast<AIInfo *>(this->info_single_list[ai_name]); /* If we didn't find a match AI, maybe the user included a version */ char *e = strrchr(ai_name, '.'); if (e == NULL) return NULL; *e = '\0'; e++; versionParam = atoi(e); /* FALL THROUGH, like we were calling this function with a version. */ } if (force_exact_match) { /* Try to find a direct 'name.version' match */ char ai_name_tmp[1024]; seprintf(ai_name_tmp, lastof(ai_name_tmp), "%s.%d", ai_name, versionParam); strtolower(ai_name_tmp); if (this->info_list.find(ai_name_tmp) != this->info_list.end()) return static_cast<AIInfo *>(this->info_list[ai_name_tmp]); } /* See if there is a compatible AI which goes by that name, with the highest * version which allows loading the requested version */ ScriptInfoList::iterator it = this->info_list.begin(); for (; it != this->info_list.end(); it++) { AIInfo *i = static_cast<AIInfo *>((*it).second); if (strcasecmp(ai_name, i->GetName()) == 0 && i->CanLoadFromVersion(versionParam) && (version == -1 || i->GetVersion() > version)) { version = (*it).second->GetVersion(); info = i; } } return info; }
/* static */ SQInteger AIInfo::DummyConstructor(HSQUIRRELVM vm) { /* Get the AIInfo */ SQUserPointer instance; sq_getinstanceup(vm, 2, &instance, 0); AIInfo *info = (AIInfo *)instance; info->api_version = NULL; SQInteger res = ScriptInfo::Constructor(vm, info); if (res != 0) return res; char buf[8]; seprintf(buf, lastof(buf), "%d.%d", GB(_openttd_newgrf_version, 28, 4), GB(_openttd_newgrf_version, 24, 4)); info->api_version = strdup(buf); /* Remove the link to the real instance, else it might get deleted by RegisterAI() */ sq_setinstanceup(vm, 2, NULL); /* Register the AI to the base system */ static_cast<AIScannerInfo *>(info->GetScanner())->SetDummyAI(info); return 0; }