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 ShowErrorMessage(INVALID_STRING_ID, STR_AI_PLEASE_REPORT_CRASH, 0, 0);
00259 }
00260
00261 void AIInstance::GameLoop()
00262 {
00263 if (this->is_dead) return;
00264 if (this->engine->HasScriptCrashed()) {
00265
00266 this->Died();
00267 return;
00268 }
00269 this->controller->ticks++;
00270
00271 if (this->suspend < -1) this->suspend++;
00272 if (this->suspend < 0) return;
00273 if (--this->suspend > 0) return;
00274
00275
00276 if (this->callback != NULL) {
00277 try {
00278 this->callback(this);
00279 } catch (AI_VMSuspend e) {
00280 this->suspend = e.GetSuspendTime();
00281 this->callback = e.GetSuspendCallback();
00282
00283 return;
00284 }
00285 }
00286
00287 this->suspend = 0;
00288 this->callback = NULL;
00289
00290 if (!this->is_started) {
00291 try {
00292 AIObject::SetAllowDoCommand(false);
00293
00294 if (this->engine->MethodExists(*this->instance, "constructor")) {
00295 if (!this->engine->CallMethod(*this->instance, "constructor")) { this->Died(); return; }
00296 }
00297 if (!this->CallLoad()) { this->Died(); return; }
00298 AIObject::SetAllowDoCommand(true);
00299
00300 if (!this->engine->CallMethod(*this->instance, "Start", _settings_game.ai.ai_max_opcode_till_suspend) || !this->engine->IsSuspended()) this->Died();
00301 } catch (AI_VMSuspend e) {
00302 this->suspend = e.GetSuspendTime();
00303 this->callback = e.GetSuspendCallback();
00304 }
00305
00306 this->is_started = true;
00307 return;
00308 }
00309
00310
00311 try {
00312 if (!this->engine->Resume(_settings_game.ai.ai_max_opcode_till_suspend)) this->Died();
00313 } catch (AI_VMSuspend e) {
00314 this->suspend = e.GetSuspendTime();
00315 this->callback = e.GetSuspendCallback();
00316 }
00317 }
00318
00319 void AIInstance::CollectGarbage()
00320 {
00321 if (this->is_started && !this->is_dead) this->engine->CollectGarbage();
00322 }
00323
00324 void AIInstance::DoCommandReturn(AIInstance *instance)
00325 {
00326 instance->engine->InsertResult(AIObject::GetLastCommandRes());
00327 }
00328
00329 void AIInstance::DoCommandReturnVehicleID(AIInstance *instance)
00330 {
00331 instance->engine->InsertResult(AIObject::GetNewVehicleID());
00332 }
00333
00334 void AIInstance::DoCommandReturnSignID(AIInstance *instance)
00335 {
00336 instance->engine->InsertResult(AIObject::GetNewSignID());
00337 }
00338
00339 void AIInstance::DoCommandReturnGroupID(AIInstance *instance)
00340 {
00341 instance->engine->InsertResult(AIObject::GetNewGroupID());
00342 }
00343
00344 AIStorage *AIInstance::GetStorage()
00345 {
00346 assert(IsValidCompanyID(_current_company) && !IsHumanCompany(_current_company));
00347 return GetCompany(_current_company)->ai_instance->storage;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00372 enum SQSaveLoadType {
00373 SQSL_INT = 0x00,
00374 SQSL_STRING = 0x01,
00375 SQSL_ARRAY = 0x02,
00376 SQSL_TABLE = 0x03,
00377 SQSL_BOOL = 0x04,
00378 SQSL_NULL = 0x05,
00379 SQSL_ARRAY_TABLE_END = 0xFF,
00380 };
00381
00382 static byte _ai_sl_byte;
00383
00384 static const SaveLoad _ai_byte[] = {
00385 SLEG_VAR(_ai_sl_byte, SLE_UINT8),
00386 SLE_END()
00387 };
00388
00389 enum {
00390 AISAVE_MAX_DEPTH = 25,
00391 };
00392
00393 bool AIInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test)
00394 {
00395 if (max_depth == 0) {
00396 AILog::Error("Savedata can only be nested to 25 deep. No data saved.");
00397 return false;
00398 }
00399
00400 switch (sq_gettype(vm, index)) {
00401 case OT_INTEGER: {
00402 if (!test) {
00403 _ai_sl_byte = SQSL_INT;
00404 SlObject(NULL, _ai_byte);
00405 }
00406 SQInteger res;
00407 sq_getinteger(vm, index, &res);
00408 if (!test) {
00409 int value = (int)res;
00410 SlArray(&value, 1, SLE_INT32);
00411 }
00412 return true;
00413 }
00414
00415 case OT_STRING: {
00416 if (!test) {
00417 _ai_sl_byte = SQSL_STRING;
00418 SlObject(NULL, _ai_byte);
00419 }
00420 const SQChar *res;
00421 sq_getstring(vm, index, &res);
00422
00423
00424 const char *buf = FS2OTTD(res);
00425 size_t len = strlen(buf) + 1;
00426 if (len >= 255) {
00427 AILog::Error("Maximum string length is 254 chars. No data saved.");
00428 return false;
00429 }
00430 if (!test) {
00431 _ai_sl_byte = (byte)len;
00432 SlObject(NULL, _ai_byte);
00433 SlArray((void*)buf, len, SLE_CHAR);
00434 }
00435 return true;
00436 }
00437
00438 case OT_ARRAY: {
00439 if (!test) {
00440 _ai_sl_byte = SQSL_ARRAY;
00441 SlObject(NULL, _ai_byte);
00442 }
00443 sq_pushnull(vm);
00444 while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
00445
00446 bool res = SaveObject(vm, -1, max_depth - 1, test);
00447 sq_pop(vm, 2);
00448 if (!res) {
00449 sq_pop(vm, 1);
00450 return false;
00451 }
00452 }
00453 sq_pop(vm, 1);
00454 if (!test) {
00455 _ai_sl_byte = SQSL_ARRAY_TABLE_END;
00456 SlObject(NULL, _ai_byte);
00457 }
00458 return true;
00459 }
00460
00461 case OT_TABLE: {
00462 if (!test) {
00463 _ai_sl_byte = SQSL_TABLE;
00464 SlObject(NULL, _ai_byte);
00465 }
00466 sq_pushnull(vm);
00467 while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
00468
00469 bool res = SaveObject(vm, -2, max_depth - 1, test) && SaveObject(vm, -1, max_depth - 1, test);
00470 sq_pop(vm, 2);
00471 if (!res) {
00472 sq_pop(vm, 1);
00473 return false;
00474 }
00475 }
00476 sq_pop(vm, 1);
00477 if (!test) {
00478 _ai_sl_byte = SQSL_ARRAY_TABLE_END;
00479 SlObject(NULL, _ai_byte);
00480 }
00481 return true;
00482 }
00483
00484 case OT_BOOL: {
00485 if (!test) {
00486 _ai_sl_byte = SQSL_BOOL;
00487 SlObject(NULL, _ai_byte);
00488 }
00489 SQBool res;
00490 sq_getbool(vm, index, &res);
00491 if (!test) {
00492 _ai_sl_byte = res ? 1 : 0;
00493 SlObject(NULL, _ai_byte);
00494 }
00495 return true;
00496 }
00497
00498 case OT_NULL: {
00499 if (!test) {
00500 _ai_sl_byte = SQSL_NULL;
00501 SlObject(NULL, _ai_byte);
00502 }
00503 return true;
00504 }
00505
00506 default:
00507 AILog::Error("You tried to save an unsupported type. No data saved.");
00508 return false;
00509 }
00510 }
00511
00512 void AIInstance::SaveEmpty()
00513 {
00514 _ai_sl_byte = 0;
00515 SlObject(NULL, _ai_byte);
00516 }
00517
00518 void AIInstance::Save()
00519 {
00520
00521 if (this->engine == NULL || this->engine->HasScriptCrashed()) {
00522 SaveEmpty();
00523 return;
00524 }
00525
00526 HSQUIRRELVM vm = this->engine->GetVM();
00527 if (!this->is_started) {
00528 SQBool res;
00529 sq_getbool(vm, -1, &res);
00530 if (!res) {
00531 SaveEmpty();
00532 return;
00533 }
00534
00535 sq_push(vm, -2);
00536 _ai_sl_byte = 1;
00537 SlObject(NULL, _ai_byte);
00538
00539 SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
00540 sq_poptop(vm);
00541 } else if (this->engine->MethodExists(*this->instance, "Save")) {
00542 HSQOBJECT savedata;
00543
00544 bool backup_allow = AIObject::GetAllowDoCommand();
00545 AIObject::SetAllowDoCommand(false);
00546 if (!this->engine->CallMethod(*this->instance, "Save", &savedata)) {
00547
00548
00549 SaveEmpty();
00550 return;
00551 }
00552 AIObject::SetAllowDoCommand(backup_allow);
00553
00554 if (!sq_istable(savedata)) {
00555 AILog::Error("Save function should return a table.");
00556 SaveEmpty();
00557 return;
00558 }
00559 sq_pushobject(vm, savedata);
00560 if (SaveObject(vm, -1, AISAVE_MAX_DEPTH, true)) {
00561 _ai_sl_byte = 1;
00562 SlObject(NULL, _ai_byte);
00563 SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
00564 } else {
00565 _ai_sl_byte = 0;
00566 SlObject(NULL, _ai_byte);
00567 }
00568 sq_pop(vm, 1);
00569 } else {
00570 AILog::Warning("Save function is not implemented");
00571 _ai_sl_byte = 0;
00572 SlObject(NULL, _ai_byte);
00573 }
00574
00575 }
00576
00577 bool AIInstance::LoadObjects(HSQUIRRELVM vm)
00578 {
00579 SlObject(NULL, _ai_byte);
00580 switch (_ai_sl_byte) {
00581 case SQSL_INT: {
00582 int value;
00583 SlArray(&value, 1, SLE_INT32);
00584 if (vm != NULL) sq_pushinteger(vm, (SQInteger)value);
00585 return true;
00586 }
00587
00588 case SQSL_STRING: {
00589 SlObject(NULL, _ai_byte);
00590 static char buf[256];
00591 SlArray(buf, _ai_sl_byte, SLE_CHAR);
00592 if (vm != NULL) sq_pushstring(vm, OTTD2FS(buf), -1);
00593 return true;
00594 }
00595
00596 case SQSL_ARRAY: {
00597 if (vm != NULL) sq_newarray(vm, 0);
00598 while (LoadObjects(vm)) {
00599 if (vm != NULL) sq_arrayappend(vm, -2);
00600
00601 }
00602 return true;
00603 }
00604
00605 case SQSL_TABLE: {
00606 if (vm != NULL) sq_newtable(vm);
00607 while (LoadObjects(vm)) {
00608 LoadObjects(vm);
00609 if (vm != NULL) sq_rawset(vm, -3);
00610
00611 }
00612 return true;
00613 }
00614
00615 case SQSL_BOOL: {
00616 SlObject(NULL, _ai_byte);
00617 if (vm != NULL) sq_pushinteger(vm, (SQBool)(_ai_sl_byte != 0));
00618 return true;
00619 }
00620
00621 case SQSL_NULL: {
00622 if (vm != NULL) sq_pushnull(vm);
00623 return true;
00624 }
00625
00626 case SQSL_ARRAY_TABLE_END: {
00627 return false;
00628 }
00629
00630 default: NOT_REACHED();
00631 }
00632 }
00633
00634 void AIInstance::LoadEmpty()
00635 {
00636 SlObject(NULL, _ai_byte);
00637
00638 if (_ai_sl_byte == 0) return;
00639
00640 LoadObjects(NULL);
00641 }
00642
00643 void AIInstance::Load(int version)
00644 {
00645 if (this->engine == NULL || version == -1) {
00646 LoadEmpty();
00647 return;
00648 }
00649 HSQUIRRELVM vm = this->engine->GetVM();
00650
00651 SlObject(NULL, _ai_byte);
00652
00653 if (_ai_sl_byte == 0) return;
00654
00655
00656 sq_poptop(vm);
00657 sq_pushinteger(vm, version);
00658 LoadObjects(vm);
00659 sq_pushbool(vm, true);
00660 }
00661
00662 bool AIInstance::CallLoad()
00663 {
00664 HSQUIRRELVM vm = this->engine->GetVM();
00665
00666 SQBool res;
00667 sq_getbool(vm, -1, &res);
00668 sq_poptop(vm);
00669 if (!res) return true;
00670
00671 if (!this->engine->MethodExists(*this->instance, "Load")) {
00672 AILog::Warning("Loading failed: there was data for the AI to load, but the AI does not have a Load() function.");
00673
00674
00675 sq_pop(vm, 2);
00676 return true;
00677 }
00678
00679
00680 sq_pushobject(vm, *this->instance);
00681
00682 sq_pushstring(vm, OTTD2FS("Load"), -1);
00683
00684 sq_get(vm, -2);
00685
00686 sq_pushobject(vm, *this->instance);
00687
00688 sq_push(vm, -5);
00689 sq_push(vm, -5);
00690
00691
00692
00693 if (SQ_FAILED(sq_call(vm, 3, SQFalse, SQFalse))) return false;
00694
00695
00696 sq_pop(vm, 4);
00697 return true;
00698 }