00001
00002
00005 #include "../stdafx.h"
00006 #include "../debug.h"
00007 #include "../settings_type.h"
00008 #include "../vehicle_base.h"
00009 #include "../saveload/saveload.h"
00010 #include "../gui.h"
00011 #include "table/strings.h"
00012
00013 #include <squirrel.h>
00014 #include "../script/squirrel.hpp"
00015 #include "../script/squirrel_helper.hpp"
00016 #include "../script/squirrel_class.hpp"
00017 #include "../script/squirrel_std.hpp"
00018
00019 #define DEFINE_SCRIPT_FILES
00020
00021 #include "ai_info.hpp"
00022 #include "ai_storage.hpp"
00023 #include "ai_instance.hpp"
00024 #include "ai_gui.hpp"
00025
00026
00027
00028 #include "api/ai_abstractlist.hpp.sq"
00029 #include "api/ai_accounting.hpp.sq"
00030 #include "api/ai_airport.hpp.sq"
00031 #include "api/ai_base.hpp.sq"
00032 #include "api/ai_bridge.hpp.sq"
00033 #include "api/ai_bridgelist.hpp.sq"
00034 #include "api/ai_cargo.hpp.sq"
00035 #include "api/ai_cargolist.hpp.sq"
00036 #include "api/ai_company.hpp.sq"
00037 #include "api/ai_controller.hpp.sq"
00038 #include "api/ai_date.hpp.sq"
00039 #include "api/ai_depotlist.hpp.sq"
00040 #include "api/ai_engine.hpp.sq"
00041 #include "api/ai_enginelist.hpp.sq"
00042 #include "api/ai_error.hpp.sq"
00043 #include "api/ai_event.hpp.sq"
00044 #include "api/ai_event_types.hpp.sq"
00045 #include "api/ai_execmode.hpp.sq"
00046 #include "api/ai_gamesettings.hpp.sq"
00047 #include "api/ai_group.hpp.sq"
00048 #include "api/ai_grouplist.hpp.sq"
00049 #include "api/ai_industry.hpp.sq"
00050 #include "api/ai_industrylist.hpp.sq"
00051 #include "api/ai_industrytype.hpp.sq"
00052 #include "api/ai_industrytypelist.hpp.sq"
00053 #include "api/ai_list.hpp.sq"
00054 #include "api/ai_log.hpp.sq"
00055 #include "api/ai_map.hpp.sq"
00056 #include "api/ai_marine.hpp.sq"
00057 #include "api/ai_order.hpp.sq"
00058 #include "api/ai_rail.hpp.sq"
00059 #include "api/ai_railtypelist.hpp.sq"
00060 #include "api/ai_road.hpp.sq"
00061 #include "api/ai_sign.hpp.sq"
00062 #include "api/ai_station.hpp.sq"
00063 #include "api/ai_stationlist.hpp.sq"
00064 #include "api/ai_subsidy.hpp.sq"
00065 #include "api/ai_subsidylist.hpp.sq"
00066 #include "api/ai_testmode.hpp.sq"
00067 #include "api/ai_tile.hpp.sq"
00068 #include "api/ai_tilelist.hpp.sq"
00069 #include "api/ai_town.hpp.sq"
00070 #include "api/ai_townlist.hpp.sq"
00071 #include "api/ai_tunnel.hpp.sq"
00072 #include "api/ai_vehicle.hpp.sq"
00073 #include "api/ai_vehiclelist.hpp.sq"
00074 #include "api/ai_waypoint.hpp.sq"
00075 #include "api/ai_waypointlist.hpp.sq"
00076
00077 #undef DEFINE_SCRIPT_FILES
00078
00079 AIInstance *AIInstance::current_instance = NULL;
00080
00081 AIStorage::~AIStorage()
00082 {
00083
00084 if (event_data != NULL) AIEventController::FreeEventPointer();
00085 if (log_data != NULL) AILog::FreeLogPointer();
00086 }
00087
00088 static void PrintFunc(bool error_msg, const SQChar *message)
00089 {
00090
00091 AIController::Print(error_msg, FS2OTTD(message));
00092 }
00093
00094 AIInstance::AIInstance(AIInfo *info) :
00095 controller(NULL),
00096 storage(NULL),
00097 engine(NULL),
00098 instance(NULL),
00099 is_started(false),
00100 is_dead(false),
00101 suspend(0),
00102 callback(NULL)
00103 {
00104
00105 GetCompany(_current_company)->ai_instance = this;
00106 AIInstance::current_instance = this;
00107
00108 this->controller = new AIController();
00109 this->storage = new AIStorage();
00110 this->engine = new Squirrel();
00111 this->engine->SetPrintFunction(&PrintFunc);
00112
00113
00114 this->engine->AddMethod("import", &AILibrary::Import, 4, ".ssi");
00115
00116
00117 SQAIController_Register(this->engine);
00118
00119
00120 const char *main_script = info->GetMainScript();
00121 if (strcmp(main_script, "%_dummy") == 0) {
00122 extern void AI_CreateAIDummy(HSQUIRRELVM vm);
00123 AI_CreateAIDummy(this->engine->GetVM());
00124 } else if (!this->engine->LoadScript(main_script)) {
00125 this->Died();
00126 return;
00127 }
00128
00129
00130 this->instance = MallocT<SQObject>(1);
00131 if (!this->engine->CreateClassInstance(info->GetInstanceName(), this->controller, this->instance)) {
00132 this->Died();
00133 return;
00134 }
00135
00136
00137 this->RegisterAPI();
00138
00139
00140
00141 sq_pushbool(this->engine->vm, false);
00142 }
00143
00144 AIInstance::~AIInstance()
00145 {
00146 if (instance != NULL) this->engine->ReleaseObject(this->instance);
00147 if (engine != NULL) delete this->engine;
00148 delete this->storage;
00149 delete this->controller;
00150 free(this->instance);
00151 }
00152
00153 void AIInstance::RegisterAPI()
00154 {
00155
00156 squirrel_register_std(this->engine);
00157 SQAIAbstractList_Register(this->engine);
00158 SQAIAccounting_Register(this->engine);
00159 SQAIAirport_Register(this->engine);
00160 SQAIBase_Register(this->engine);
00161 SQAIBridge_Register(this->engine);
00162 SQAIBridgeList_Register(this->engine);
00163 SQAIBridgeList_Length_Register(this->engine);
00164 SQAICargo_Register(this->engine);
00165 SQAICargoList_Register(this->engine);
00166 SQAICargoList_IndustryAccepting_Register(this->engine);
00167 SQAICargoList_IndustryProducing_Register(this->engine);
00168 SQAICompany_Register(this->engine);
00169 SQAIDate_Register(this->engine);
00170 SQAIDepotList_Register(this->engine);
00171 SQAIEngine_Register(this->engine);
00172 SQAIEngineList_Register(this->engine);
00173 SQAIError_Register(this->engine);
00174 SQAIEvent_Register(this->engine);
00175 SQAIEventCompanyBankrupt_Register(this->engine);
00176 SQAIEventCompanyInTrouble_Register(this->engine);
00177 SQAIEventCompanyMerger_Register(this->engine);
00178 SQAIEventCompanyNew_Register(this->engine);
00179 SQAIEventController_Register(this->engine);
00180 SQAIEventDisasterZeppelinerCleared_Register(this->engine);
00181 SQAIEventDisasterZeppelinerCrashed_Register(this->engine);
00182 SQAIEventEngineAvailable_Register(this->engine);
00183 SQAIEventEnginePreview_Register(this->engine);
00184 SQAIEventIndustryClose_Register(this->engine);
00185 SQAIEventIndustryOpen_Register(this->engine);
00186 SQAIEventStationFirstVehicle_Register(this->engine);
00187 SQAIEventSubsidyAwarded_Register(this->engine);
00188 SQAIEventSubsidyExpired_Register(this->engine);
00189 SQAIEventSubsidyOffer_Register(this->engine);
00190 SQAIEventSubsidyOfferExpired_Register(this->engine);
00191 SQAIEventVehicleCrashed_Register(this->engine);
00192 SQAIEventVehicleLost_Register(this->engine);
00193 SQAIEventVehicleUnprofitable_Register(this->engine);
00194 SQAIEventVehicleWaitingInDepot_Register(this->engine);
00195 SQAIExecMode_Register(this->engine);
00196 SQAIGameSettings_Register(this->engine);
00197 SQAIGroup_Register(this->engine);
00198 SQAIGroupList_Register(this->engine);
00199 SQAIIndustry_Register(this->engine);
00200 SQAIIndustryList_Register(this->engine);
00201 SQAIIndustryList_CargoAccepting_Register(this->engine);
00202 SQAIIndustryList_CargoProducing_Register(this->engine);
00203 SQAIIndustryType_Register(this->engine);
00204 SQAIIndustryTypeList_Register(this->engine);
00205 SQAIList_Register(this->engine);
00206 SQAILog_Register(this->engine);
00207 SQAIMap_Register(this->engine);
00208 SQAIMarine_Register(this->engine);
00209 SQAIOrder_Register(this->engine);
00210 SQAIRail_Register(this->engine);
00211 SQAIRailTypeList_Register(this->engine);
00212 SQAIRoad_Register(this->engine);
00213 SQAISign_Register(this->engine);
00214 SQAIStation_Register(this->engine);
00215 SQAIStationList_Register(this->engine);
00216 SQAIStationList_Vehicle_Register(this->engine);
00217 SQAISubsidy_Register(this->engine);
00218 SQAISubsidyList_Register(this->engine);
00219 SQAITestMode_Register(this->engine);
00220 SQAITile_Register(this->engine);
00221 SQAITileList_Register(this->engine);
00222 SQAITileList_IndustryAccepting_Register(this->engine);
00223 SQAITileList_IndustryProducing_Register(this->engine);
00224 SQAITileList_StationType_Register(this->engine);
00225 SQAITown_Register(this->engine);
00226 SQAITownList_Register(this->engine);
00227 SQAITunnel_Register(this->engine);
00228 SQAIVehicle_Register(this->engine);
00229 SQAIVehicleList_Register(this->engine);
00230 SQAIVehicleList_DefaultGroup_Register(this->engine);
00231 SQAIVehicleList_Group_Register(this->engine);
00232 SQAIVehicleList_SharedOrders_Register(this->engine);
00233 SQAIVehicleList_Station_Register(this->engine);
00234 SQAIWaypoint_Register(this->engine);
00235 SQAIWaypointList_Register(this->engine);
00236 SQAIWaypointList_Vehicle_Register(this->engine);
00237
00238 this->engine->SetGlobalPointer(this->engine);
00239 }
00240
00241 void AIInstance::Continue()
00242 {
00243 assert(this->suspend < 0);
00244 this->suspend = -this->suspend - 1;
00245 }
00246
00247 void AIInstance::Died()
00248 {
00249 DEBUG(ai, 0, "The AI died unexpectedly.");
00250 this->is_dead = true;
00251
00252 if (this->instance != NULL) this->engine->ReleaseObject(this->instance);
00253 delete this->engine;
00254 this->instance = NULL;
00255 this->engine = NULL;
00256
00257 ShowAIDebugWindow(_current_company);
00258 if (strcmp(GetCompany(_current_company)->ai_info->GetMainScript(), "%_dummy") != 0) {
00259 ShowErrorMessage(INVALID_STRING_ID, STR_AI_PLEASE_REPORT_CRASH, 0, 0);
00260 }
00261 }
00262
00263 void AIInstance::GameLoop()
00264 {
00265 if (this->is_dead) return;
00266 if (this->engine->HasScriptCrashed()) {
00267
00268 this->Died();
00269 return;
00270 }
00271 this->controller->ticks++;
00272
00273 if (this->suspend < -1) this->suspend++;
00274 if (this->suspend < 0) return;
00275 if (--this->suspend > 0) return;
00276
00277
00278 if (this->callback != NULL) {
00279 try {
00280 this->callback(this);
00281 } catch (AI_VMSuspend e) {
00282 this->suspend = e.GetSuspendTime();
00283 this->callback = e.GetSuspendCallback();
00284
00285 return;
00286 }
00287 }
00288
00289 this->suspend = 0;
00290 this->callback = NULL;
00291
00292 if (!this->is_started) {
00293 try {
00294 AIObject::SetAllowDoCommand(false);
00295
00296 if (this->engine->MethodExists(*this->instance, "constructor")) {
00297 if (!this->engine->CallMethod(*this->instance, "constructor")) { this->Died(); return; }
00298 }
00299 if (!this->CallLoad()) { this->Died(); return; }
00300 AIObject::SetAllowDoCommand(true);
00301
00302 if (!this->engine->CallMethod(*this->instance, "Start", _settings_game.ai.ai_max_opcode_till_suspend) || !this->engine->IsSuspended()) this->Died();
00303 } catch (AI_VMSuspend e) {
00304 this->suspend = e.GetSuspendTime();
00305 this->callback = e.GetSuspendCallback();
00306 }
00307
00308 this->is_started = true;
00309 return;
00310 }
00311
00312
00313 try {
00314 if (!this->engine->Resume(_settings_game.ai.ai_max_opcode_till_suspend)) this->Died();
00315 } catch (AI_VMSuspend e) {
00316 this->suspend = e.GetSuspendTime();
00317 this->callback = e.GetSuspendCallback();
00318 }
00319 }
00320
00321 void AIInstance::CollectGarbage()
00322 {
00323 if (this->is_started && !this->is_dead) this->engine->CollectGarbage();
00324 }
00325
00326 void AIInstance::DoCommandReturn(AIInstance *instance)
00327 {
00328 instance->engine->InsertResult(AIObject::GetLastCommandRes());
00329 }
00330
00331 void AIInstance::DoCommandReturnVehicleID(AIInstance *instance)
00332 {
00333 instance->engine->InsertResult(AIObject::GetNewVehicleID());
00334 }
00335
00336 void AIInstance::DoCommandReturnSignID(AIInstance *instance)
00337 {
00338 instance->engine->InsertResult(AIObject::GetNewSignID());
00339 }
00340
00341 void AIInstance::DoCommandReturnGroupID(AIInstance *instance)
00342 {
00343 instance->engine->InsertResult(AIObject::GetNewGroupID());
00344 }
00345
00346 AIStorage *AIInstance::GetStorage()
00347 {
00348 assert(IsValidCompanyID(_current_company) && !IsHumanCompany(_current_company));
00349 return GetCompany(_current_company)->ai_instance->storage;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00374 enum SQSaveLoadType {
00375 SQSL_INT = 0x00,
00376 SQSL_STRING = 0x01,
00377 SQSL_ARRAY = 0x02,
00378 SQSL_TABLE = 0x03,
00379 SQSL_BOOL = 0x04,
00380 SQSL_NULL = 0x05,
00381 SQSL_ARRAY_TABLE_END = 0xFF,
00382 };
00383
00384 static byte _ai_sl_byte;
00385
00386 static const SaveLoad _ai_byte[] = {
00387 SLEG_VAR(_ai_sl_byte, SLE_UINT8),
00388 SLE_END()
00389 };
00390
00391 enum {
00392 AISAVE_MAX_DEPTH = 25,
00393 };
00394
00395 bool AIInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test)
00396 {
00397 if (max_depth == 0) {
00398 AILog::Error("Savedata can only be nested to 25 deep. No data saved.");
00399 return false;
00400 }
00401
00402 switch (sq_gettype(vm, index)) {
00403 case OT_INTEGER: {
00404 if (!test) {
00405 _ai_sl_byte = SQSL_INT;
00406 SlObject(NULL, _ai_byte);
00407 }
00408 SQInteger res;
00409 sq_getinteger(vm, index, &res);
00410 if (!test) {
00411 int value = (int)res;
00412 SlArray(&value, 1, SLE_INT32);
00413 }
00414 return true;
00415 }
00416
00417 case OT_STRING: {
00418 if (!test) {
00419 _ai_sl_byte = SQSL_STRING;
00420 SlObject(NULL, _ai_byte);
00421 }
00422 const SQChar *res;
00423 sq_getstring(vm, index, &res);
00424
00425
00426 const char *buf = FS2OTTD(res);
00427 size_t len = strlen(buf) + 1;
00428 if (len >= 255) {
00429 AILog::Error("Maximum string length is 254 chars. No data saved.");
00430 return false;
00431 }
00432 if (!test) {
00433 _ai_sl_byte = (byte)len;
00434 SlObject(NULL, _ai_byte);
00435 SlArray((void*)buf, len, SLE_CHAR);
00436 }
00437 return true;
00438 }
00439
00440 case OT_ARRAY: {
00441 if (!test) {
00442 _ai_sl_byte = SQSL_ARRAY;
00443 SlObject(NULL, _ai_byte);
00444 }
00445 sq_pushnull(vm);
00446 while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
00447
00448 bool res = SaveObject(vm, -1, max_depth - 1, test);
00449 sq_pop(vm, 2);
00450 if (!res) {
00451 sq_pop(vm, 1);
00452 return false;
00453 }
00454 }
00455 sq_pop(vm, 1);
00456 if (!test) {
00457 _ai_sl_byte = SQSL_ARRAY_TABLE_END;
00458 SlObject(NULL, _ai_byte);
00459 }
00460 return true;
00461 }
00462
00463 case OT_TABLE: {
00464 if (!test) {
00465 _ai_sl_byte = SQSL_TABLE;
00466 SlObject(NULL, _ai_byte);
00467 }
00468 sq_pushnull(vm);
00469 while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
00470
00471 bool res = SaveObject(vm, -2, max_depth - 1, test) && SaveObject(vm, -1, max_depth - 1, test);
00472 sq_pop(vm, 2);
00473 if (!res) {
00474 sq_pop(vm, 1);
00475 return false;
00476 }
00477 }
00478 sq_pop(vm, 1);
00479 if (!test) {
00480 _ai_sl_byte = SQSL_ARRAY_TABLE_END;
00481 SlObject(NULL, _ai_byte);
00482 }
00483 return true;
00484 }
00485
00486 case OT_BOOL: {
00487 if (!test) {
00488 _ai_sl_byte = SQSL_BOOL;
00489 SlObject(NULL, _ai_byte);
00490 }
00491 SQBool res;
00492 sq_getbool(vm, index, &res);
00493 if (!test) {
00494 _ai_sl_byte = res ? 1 : 0;
00495 SlObject(NULL, _ai_byte);
00496 }
00497 return true;
00498 }
00499
00500 case OT_NULL: {
00501 if (!test) {
00502 _ai_sl_byte = SQSL_NULL;
00503 SlObject(NULL, _ai_byte);
00504 }
00505 return true;
00506 }
00507
00508 default:
00509 AILog::Error("You tried to save an unsupported type. No data saved.");
00510 return false;
00511 }
00512 }
00513
00514 void AIInstance::SaveEmpty()
00515 {
00516 _ai_sl_byte = 0;
00517 SlObject(NULL, _ai_byte);
00518 }
00519
00520 void AIInstance::Save()
00521 {
00522
00523 if (this->engine == NULL || this->engine->HasScriptCrashed()) {
00524 SaveEmpty();
00525 return;
00526 }
00527
00528 HSQUIRRELVM vm = this->engine->GetVM();
00529 if (!this->is_started) {
00530 SQBool res;
00531 sq_getbool(vm, -1, &res);
00532 if (!res) {
00533 SaveEmpty();
00534 return;
00535 }
00536
00537 sq_push(vm, -2);
00538 _ai_sl_byte = 1;
00539 SlObject(NULL, _ai_byte);
00540
00541 SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
00542 sq_poptop(vm);
00543 } else if (this->engine->MethodExists(*this->instance, "Save")) {
00544 HSQOBJECT savedata;
00545
00546 bool backup_allow = AIObject::GetAllowDoCommand();
00547 AIObject::SetAllowDoCommand(false);
00548 if (!this->engine->CallMethod(*this->instance, "Save", &savedata)) {
00549
00550
00551 SaveEmpty();
00552 return;
00553 }
00554 AIObject::SetAllowDoCommand(backup_allow);
00555
00556 if (!sq_istable(savedata)) {
00557 AILog::Error("Save function should return a table.");
00558 SaveEmpty();
00559 return;
00560 }
00561 sq_pushobject(vm, savedata);
00562 if (SaveObject(vm, -1, AISAVE_MAX_DEPTH, true)) {
00563 _ai_sl_byte = 1;
00564 SlObject(NULL, _ai_byte);
00565 SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
00566 } else {
00567 _ai_sl_byte = 0;
00568 SlObject(NULL, _ai_byte);
00569 }
00570 sq_pop(vm, 1);
00571 } else {
00572 AILog::Warning("Save function is not implemented");
00573 _ai_sl_byte = 0;
00574 SlObject(NULL, _ai_byte);
00575 }
00576
00577 }
00578
00579 bool AIInstance::LoadObjects(HSQUIRRELVM vm)
00580 {
00581 SlObject(NULL, _ai_byte);
00582 switch (_ai_sl_byte) {
00583 case SQSL_INT: {
00584 int value;
00585 SlArray(&value, 1, SLE_INT32);
00586 if (vm != NULL) sq_pushinteger(vm, (SQInteger)value);
00587 return true;
00588 }
00589
00590 case SQSL_STRING: {
00591 SlObject(NULL, _ai_byte);
00592 static char buf[256];
00593 SlArray(buf, _ai_sl_byte, SLE_CHAR);
00594 if (vm != NULL) sq_pushstring(vm, OTTD2FS(buf), -1);
00595 return true;
00596 }
00597
00598 case SQSL_ARRAY: {
00599 if (vm != NULL) sq_newarray(vm, 0);
00600 while (LoadObjects(vm)) {
00601 if (vm != NULL) sq_arrayappend(vm, -2);
00602
00603 }
00604 return true;
00605 }
00606
00607 case SQSL_TABLE: {
00608 if (vm != NULL) sq_newtable(vm);
00609 while (LoadObjects(vm)) {
00610 LoadObjects(vm);
00611 if (vm != NULL) sq_rawset(vm, -3);
00612
00613 }
00614 return true;
00615 }
00616
00617 case SQSL_BOOL: {
00618 SlObject(NULL, _ai_byte);
00619 if (vm != NULL) sq_pushinteger(vm, (SQBool)(_ai_sl_byte != 0));
00620 return true;
00621 }
00622
00623 case SQSL_NULL: {
00624 if (vm != NULL) sq_pushnull(vm);
00625 return true;
00626 }
00627
00628 case SQSL_ARRAY_TABLE_END: {
00629 return false;
00630 }
00631
00632 default: NOT_REACHED();
00633 }
00634 }
00635
00636 void AIInstance::LoadEmpty()
00637 {
00638 SlObject(NULL, _ai_byte);
00639
00640 if (_ai_sl_byte == 0) return;
00641
00642 LoadObjects(NULL);
00643 }
00644
00645 void AIInstance::Load(int version)
00646 {
00647 if (this->engine == NULL || version == -1) {
00648 LoadEmpty();
00649 return;
00650 }
00651 HSQUIRRELVM vm = this->engine->GetVM();
00652
00653 SlObject(NULL, _ai_byte);
00654
00655 if (_ai_sl_byte == 0) return;
00656
00657
00658 sq_poptop(vm);
00659 sq_pushinteger(vm, version);
00660 LoadObjects(vm);
00661 sq_pushbool(vm, true);
00662 }
00663
00664 bool AIInstance::CallLoad()
00665 {
00666 HSQUIRRELVM vm = this->engine->GetVM();
00667
00668 SQBool res;
00669 sq_getbool(vm, -1, &res);
00670 sq_poptop(vm);
00671 if (!res) return true;
00672
00673 if (!this->engine->MethodExists(*this->instance, "Load")) {
00674 AILog::Warning("Loading failed: there was data for the AI to load, but the AI does not have a Load() function.");
00675
00676
00677 sq_pop(vm, 2);
00678 return true;
00679 }
00680
00681
00682 sq_pushobject(vm, *this->instance);
00683
00684 sq_pushstring(vm, OTTD2FS("Load"), -1);
00685
00686 sq_get(vm, -2);
00687
00688 sq_pushobject(vm, *this->instance);
00689
00690 sq_push(vm, -5);
00691 sq_push(vm, -5);
00692
00693
00694
00695 if (SQ_FAILED(sq_call(vm, 3, SQFalse, SQFalse))) return false;
00696
00697
00698 sq_pop(vm, 4);
00699 return true;
00700 }