ai_core.cpp
Go to the documentation of this file.00001
00002
00005 #include "../stdafx.h"
00006 #include "../core/bitmath_func.hpp"
00007 #include "../company_base.h"
00008 #include "../company_func.h"
00009 #include "../debug.h"
00010 #include "../network/network.h"
00011 #include "../settings_type.h"
00012 #include "../window_func.h"
00013 #include "../command_func.h"
00014 #include "ai.hpp"
00015 #include "ai_scanner.hpp"
00016 #include "ai_instance.hpp"
00017 #include "ai_config.hpp"
00018
00019 uint AI::frame_counter = 0;
00020 AIScanner *AI::ai_scanner = NULL;
00021
00022 bool AI::CanStartNew()
00023 {
00024
00025 return !_networking || (_network_server && _settings_game.ai.ai_in_multiplayer);
00026 }
00027
00028 void AI::StartNew(CompanyID company)
00029 {
00030 assert(IsValidCompanyID(company));
00031
00032
00033 if (_networking && !_network_server) return;
00034
00035 AIInfo *info = AIConfig::GetConfig(company)->GetInfo();
00036 if (info == NULL) {
00037 info = AI::ai_scanner->SelectRandomAI();
00038 assert(info != NULL);
00039
00040 AIConfig::GetConfig(company)->ChangeAI(info->GetInstanceName());
00041 }
00042
00043 _current_company = company;
00044 Company *c = GetCompany(company);
00045
00046 c->ai_info = info;
00047 assert(c->ai_instance == NULL);
00048 c->ai_instance = new AIInstance(info);
00049
00050 InvalidateWindowData(WC_AI_DEBUG, 0, -1);
00051 return;
00052 }
00053
00054 void AI::GameLoop()
00055 {
00056
00057 if (_networking && (!_network_server || !_settings_game.ai.ai_in_multiplayer)) return;
00058
00059
00060 AI::frame_counter++;
00061 assert(_settings_game.difficulty.competitor_speed <= 4);
00062 if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
00063
00064 const Company *c;
00065 FOR_ALL_COMPANIES(c) {
00066 if (!IsHumanCompany(c->index)) {
00067 _current_company = c->index;
00068 c->ai_instance->GameLoop();
00069 }
00070 }
00071
00072
00073
00074 if ((AI::frame_counter & 255) == 0) {
00075 CompanyID cid = (CompanyID)GB(AI::frame_counter, 8, 4);
00076 if (IsValidCompanyID(cid) && !IsHumanCompany(cid)) GetCompany(cid)->ai_instance->CollectGarbage();
00077 }
00078
00079 _current_company = OWNER_NONE;
00080 }
00081
00082 uint AI::GetTick()
00083 {
00084 return AI::frame_counter;
00085 }
00086
00087 void AI::Stop(CompanyID company)
00088 {
00089 if (_networking && !_network_server) return;
00090
00091 CompanyID old_company = _current_company;
00092 _current_company = company;
00093 Company *c = GetCompany(company);
00094
00095 delete c->ai_instance;
00096 c->ai_instance = NULL;
00097
00098 _current_company = old_company;
00099
00100 InvalidateWindowData(WC_AI_DEBUG, 0, -1);
00101 }
00102
00103 void AI::KillAll()
00104 {
00105
00106 if (GetCompanyPoolSize() == 0) return;
00107
00108 const Company *c;
00109 FOR_ALL_COMPANIES(c) {
00110 if (!IsHumanCompany(c->index)) AI::Stop(c->index);
00111 }
00112 }
00113
00114 void AI::Initialize()
00115 {
00116 if (AI::ai_scanner != NULL) AI::Uninitialize(true);
00117
00118 AI::frame_counter = 0;
00119 if (AI::ai_scanner == NULL) AI::ai_scanner = new AIScanner();
00120 }
00121
00122 void AI::Uninitialize(bool keepConfig)
00123 {
00124 AI::KillAll();
00125
00126 if (keepConfig) {
00127
00128
00129 Rescan();
00130 } else {
00131 delete AI::ai_scanner;
00132 AI::ai_scanner = NULL;
00133
00134 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00135 if (_settings_game.ai_config[c] != NULL) {
00136 delete _settings_game.ai_config[c];
00137 _settings_game.ai_config[c] = NULL;
00138 }
00139 if (_settings_newgame.ai_config[c] != NULL) {
00140 delete _settings_newgame.ai_config[c];
00141 _settings_newgame.ai_config[c] = NULL;
00142 }
00143 }
00144 }
00145 }
00146
00147 void AI::ResetConfig()
00148 {
00149
00150
00151
00152 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00153 if (_settings_game.ai_config[c] != NULL && _settings_game.ai_config[c]->HasAI()) {
00154 if (!_settings_game.ai_config[c]->ResetInfo()) {
00155 DEBUG(ai, 0, "After a reload, the AI by the name '%s' was no longer found, and removed from the list.", _settings_game.ai_config[c]->GetName());
00156 _settings_game.ai_config[c]->ChangeAI(NULL);
00157 }
00158 }
00159 if (_settings_newgame.ai_config[c] != NULL && _settings_newgame.ai_config[c]->HasAI()) {
00160 if (!_settings_newgame.ai_config[c]->ResetInfo()) {
00161 DEBUG(ai, 0, "After a reload, the AI by the name '%s' was no longer found, and removed from the list.", _settings_newgame.ai_config[c]->GetName());
00162 _settings_newgame.ai_config[c]->ChangeAI(NULL);
00163 }
00164 }
00165 }
00166 }
00167
00168 void AI::NewEvent(CompanyID company, AIEvent *event)
00169 {
00170
00171 event->AddRef();
00172
00173
00174 if (_networking && !_network_server) {
00175 event->Release();
00176 return;
00177 }
00178
00179
00180 if (!IsValidCompanyID(company) || IsHumanCompany(company)) {
00181 event->Release();
00182 return;
00183 }
00184
00185
00186 CompanyID old_company = _current_company;
00187 _current_company = company;
00188 AIEventController::InsertEvent(event);
00189 _current_company = old_company;
00190
00191 event->Release();
00192 }
00193
00194 void AI::BroadcastNewEvent(AIEvent *event, CompanyID skip_company)
00195 {
00196
00197 event->AddRef();
00198
00199
00200 if (_networking && !_network_server) {
00201 event->Release();
00202 return;
00203 }
00204
00205
00206 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00207 if (c != skip_company) AI::NewEvent(c, event);
00208 }
00209
00210 event->Release();
00211 }
00212
00213 void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
00214 {
00215 AIObject::SetLastCommandRes(success);
00216
00217 if (!success) {
00218 AIObject::SetLastError(AIError::StringToError(_error_message));
00219 } else {
00220 AIObject::IncreaseDoCommandCosts(AIObject::GetLastCost());
00221 }
00222
00223 GetCompany(_current_company)->ai_instance->Continue();
00224 }
00225
00226 void AI::Save(CompanyID company)
00227 {
00228 if (!_networking || _network_server) {
00229 assert(IsValidCompanyID(company));
00230 assert(GetCompany(company)->ai_instance != NULL);
00231
00232 CompanyID old_company = _current_company;
00233 _current_company = company;
00234 GetCompany(company)->ai_instance->Save();
00235 _current_company = old_company;
00236 } else {
00237 AIInstance::SaveEmpty();
00238 }
00239 }
00240
00241 void AI::Load(CompanyID company, int version)
00242 {
00243 if (!_networking || _network_server) {
00244 assert(IsValidCompanyID(company));
00245 assert(GetCompany(company)->ai_instance != NULL);
00246
00247 CompanyID old_company = _current_company;
00248 _current_company = company;
00249 GetCompany(company)->ai_instance->Load(version);
00250 _current_company = old_company;
00251 } else {
00252
00253 AIInstance::LoadEmpty();
00254 }
00255 }
00256
00257 int AI::GetStartNextTime()
00258 {
00259
00260 for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
00261 if (!IsValidCompanyID(c)) return AIConfig::GetConfig(c)->GetSetting("start_date");
00262 }
00263
00264
00265 return DAYS_IN_YEAR;
00266 }
00267
00268 char *AI::GetConsoleList(char *p, const char *last)
00269 {
00270 return AI::ai_scanner->GetAIConsoleList(p, last);
00271 }
00272
00273 const AIInfoList *AI::GetInfoList()
00274 {
00275 return AI::ai_scanner->GetAIInfoList();
00276 }
00277
00278 const AIInfoList *AI::GetUniqueInfoList()
00279 {
00280 return AI::ai_scanner->GetUniqueAIInfoList();
00281 }
00282
00283 AIInfo *AI::FindInfo(const char *name, int version)
00284 {
00285 return AI::ai_scanner->FindInfo(name, version);
00286 }
00287
00288 bool AI::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm)
00289 {
00290 return AI::ai_scanner->ImportLibrary(library, class_name, version, vm, GetCompany(_current_company)->ai_instance->GetController());
00291 }
00292
00293 void AI::Rescan()
00294 {
00295 AI::ai_scanner->RescanAIDir();
00296 ResetConfig();
00297 }