# ai_instance.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_instance.cpp 17260 2009-08-22 15:38:42Z rubidium $ */
    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_config.hpp"
    00023 #include "ai_storage.hpp"
    00024 #include "ai_instance.hpp"
    00025 #include "ai_gui.hpp"
    00026
    00027 /* Convert all AI related classes to Squirrel data.
    00028  * Note: this line a marker in squirrel_export.sh. Do not change! */
    00029 #include "api/ai_abstractlist.hpp.sq"
    00030 #include "api/ai_accounting.hpp.sq"
    00031 #include "api/ai_airport.hpp.sq"
    00032 #include "api/ai_base.hpp.sq"
    00033 #include "api/ai_bridge.hpp.sq"
    00034 #include "api/ai_bridgelist.hpp.sq"
    00035 #include "api/ai_cargo.hpp.sq"
    00036 #include "api/ai_cargolist.hpp.sq"
    00037 #include "api/ai_company.hpp.sq"
    00038 #include "api/ai_controller.hpp.sq"
    00039 #include "api/ai_date.hpp.sq"
    00040 #include "api/ai_depotlist.hpp.sq"
    00041 #include "api/ai_engine.hpp.sq"
    00042 #include "api/ai_enginelist.hpp.sq"
    00043 #include "api/ai_error.hpp.sq"
    00044 #include "api/ai_event.hpp.sq"
    00045 #include "api/ai_event_types.hpp.sq"
    00046 #include "api/ai_execmode.hpp.sq"
    00047 #include "api/ai_gamesettings.hpp.sq"
    00048 #include "api/ai_group.hpp.sq"
    00049 #include "api/ai_grouplist.hpp.sq"
    00050 #include "api/ai_industry.hpp.sq"
    00051 #include "api/ai_industrylist.hpp.sq"
    00052 #include "api/ai_industrytype.hpp.sq"
    00053 #include "api/ai_industrytypelist.hpp.sq"
    00054 #include "api/ai_list.hpp.sq"
    00055 #include "api/ai_log.hpp.sq"
    00056 #include "api/ai_map.hpp.sq"
    00057 #include "api/ai_marine.hpp.sq"
    00058 #include "api/ai_order.hpp.sq"
    00059 #include "api/ai_rail.hpp.sq"
    00060 #include "api/ai_railtypelist.hpp.sq"
    00061 #include "api/ai_road.hpp.sq"
    00062 #include "api/ai_sign.hpp.sq"
    00063 #include "api/ai_signlist.hpp.sq"
    00064 #include "api/ai_station.hpp.sq"
    00065 #include "api/ai_stationlist.hpp.sq"
    00066 #include "api/ai_subsidy.hpp.sq"
    00067 #include "api/ai_subsidylist.hpp.sq"
    00068 #include "api/ai_testmode.hpp.sq"
    00069 #include "api/ai_tile.hpp.sq"
    00070 #include "api/ai_tilelist.hpp.sq"
    00071 #include "api/ai_town.hpp.sq"
    00072 #include "api/ai_townlist.hpp.sq"
    00073 #include "api/ai_tunnel.hpp.sq"
    00074 #include "api/ai_vehicle.hpp.sq"
    00075 #include "api/ai_vehiclelist.hpp.sq"
    00076 #include "api/ai_waypoint.hpp.sq"
    00077 #include "api/ai_waypointlist.hpp.sq"
    00078
    00079 #undef DEFINE_SCRIPT_FILES
    00080
    00081 /* static */ AIInstance *AIInstance::current_instance = NULL;
    00082
    00083 AIStorage::~AIStorage()
    00084 {
    00085   /* Free our pointers */
    00086   if (event_data != NULL) AIEventController::FreeEventPointer();
    00087   if (log_data != NULL) AILog::FreeLogPointer();
    00088 }
    00089
    00090 static void PrintFunc(bool error_msg, const SQChar *message)
    00091 {
    00092   /* Convert to OpenTTD internal capable string */
    00093   AIController::Print(error_msg, FS2OTTD(message));
    00094 }
    00095
    00096 AIInstance::AIInstance(AIInfo *info) :
    00097   controller(NULL),
    00098   storage(NULL),
    00099   engine(NULL),
    00100   instance(NULL),
    00101   is_started(false),
    00102   is_dead(false),
    00103   is_save_data_on_stack(false),
    00104   suspend(0),
    00105   callback(NULL)
    00106 {
    00107   /* Set the instance already, so we can use AIObject::Set commands */
    00108   GetCompany(_current_company)->ai_instance = this;
    00109   AIInstance::current_instance = this;
    00110
    00111   this->controller = new AIController();
    00112   this->storage    = new AIStorage();
    00113   this->engine     = new Squirrel();
    00114   this->engine->SetPrintFunction(&PrintFunc);
    00115
    00116   /* The import method is available at a very early stage */
    00117   this->engine->AddMethod("import", &AILibrary::Import, 4, ".ssi");
    00118
    00119   /* Register the AIController */
    00120   SQAIController_Register(this->engine);
    00121
    00122   /* Register the API functions and classes */
    00123   this->RegisterAPI();
    00124
    00125   /* Load and execute the script for this AI */
    00126   const char *main_script = info->GetMainScript();
    00127   if (strcmp(main_script, "%_dummy") == 0) {
    00128     extern void AI_CreateAIDummy(HSQUIRRELVM vm);
    00129     AI_CreateAIDummy(this->engine->GetVM());
    00130   } else if (!this->engine->LoadScript(main_script)) {
    00131     this->Died();
    00132     return;
    00133   }
    00134
    00135   /* Create the main-class */
    00136   this->instance = MallocT<SQObject>(1);
    00137   if (!this->engine->CreateClassInstance(info->GetInstanceName(), this->controller, this->instance)) {
    00138     this->Died();
    00139     return;
    00140   }
    00141 }
    00142
    00143 AIInstance::~AIInstance()
    00144 {
    00145   if (instance != NULL) this->engine->ReleaseObject(this->instance);
    00146   if (engine != NULL) delete this->engine;
    00147   delete this->storage;
    00148   delete this->controller;
    00149   free(this->instance);
    00150 }
    00151
    00152 void AIInstance::RegisterAPI()
    00153 {
    00154 /* Register all classes */
    00155   squirrel_register_std(this->engine);
    00156   SQAIAbstractList_Register(this->engine);
    00157   SQAIAccounting_Register(this->engine);
    00158   SQAIAirport_Register(this->engine);
    00159   SQAIBase_Register(this->engine);
    00160   SQAIBridge_Register(this->engine);
    00161   SQAIBridgeList_Register(this->engine);
    00162   SQAIBridgeList_Length_Register(this->engine);
    00163   SQAICargo_Register(this->engine);
    00164   SQAICargoList_Register(this->engine);
    00165   SQAICargoList_IndustryAccepting_Register(this->engine);
    00166   SQAICargoList_IndustryProducing_Register(this->engine);
    00167   SQAICompany_Register(this->engine);
    00168   SQAIDate_Register(this->engine);
    00169   SQAIDepotList_Register(this->engine);
    00170   SQAIEngine_Register(this->engine);
    00171   SQAIEngineList_Register(this->engine);
    00172   SQAIError_Register(this->engine);
    00173   SQAIEvent_Register(this->engine);
    00174   SQAIEventCompanyBankrupt_Register(this->engine);
    00175   SQAIEventCompanyInTrouble_Register(this->engine);
    00176   SQAIEventCompanyMerger_Register(this->engine);
    00177   SQAIEventCompanyNew_Register(this->engine);
    00178   SQAIEventController_Register(this->engine);
    00179   SQAIEventDisasterZeppelinerCleared_Register(this->engine);
    00180   SQAIEventDisasterZeppelinerCrashed_Register(this->engine);
    00181   SQAIEventEngineAvailable_Register(this->engine);
    00182   SQAIEventEnginePreview_Register(this->engine);
    00183   SQAIEventIndustryClose_Register(this->engine);
    00184   SQAIEventIndustryOpen_Register(this->engine);
    00185   SQAIEventStationFirstVehicle_Register(this->engine);
    00186   SQAIEventSubsidyAwarded_Register(this->engine);
    00187   SQAIEventSubsidyExpired_Register(this->engine);
    00188   SQAIEventSubsidyOffer_Register(this->engine);
    00189   SQAIEventSubsidyOfferExpired_Register(this->engine);
    00190   SQAIEventVehicleCrashed_Register(this->engine);
    00191   SQAIEventVehicleLost_Register(this->engine);
    00192   SQAIEventVehicleUnprofitable_Register(this->engine);
    00193   SQAIEventVehicleWaitingInDepot_Register(this->engine);
    00194   SQAIExecMode_Register(this->engine);
    00195   SQAIGameSettings_Register(this->engine);
    00196   SQAIGroup_Register(this->engine);
    00197   SQAIGroupList_Register(this->engine);
    00198   SQAIIndustry_Register(this->engine);
    00199   SQAIIndustryList_Register(this->engine);
    00200   SQAIIndustryList_CargoAccepting_Register(this->engine);
    00201   SQAIIndustryList_CargoProducing_Register(this->engine);
    00202   SQAIIndustryType_Register(this->engine);
    00203   SQAIIndustryTypeList_Register(this->engine);
    00204   SQAIList_Register(this->engine);
    00205   SQAILog_Register(this->engine);
    00206   SQAIMap_Register(this->engine);
    00207   SQAIMarine_Register(this->engine);
    00208   SQAIOrder_Register(this->engine);
    00209   SQAIRail_Register(this->engine);
    00210   SQAIRailTypeList_Register(this->engine);
    00211   SQAIRoad_Register(this->engine);
    00212   SQAISign_Register(this->engine);
    00213   SQAISignList_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
    00259   const AIInfo *info = AIConfig::GetConfig(_current_company)->GetInfo();
    00260   if (info != NULL) {
    00261     ShowErrorMessage(INVALID_STRING_ID, STR_AI_PLEASE_REPORT_CRASH, 0, 0);
    00262
    00263     if (info->GetURL() != NULL) {
    00264       AILog::Info("Please report the error to the following URL:");
    00265       AILog::Info(info->GetURL());
    00266     }
    00267   }
    00268 }
    00269
    00270 void AIInstance::GameLoop()
    00271 {
    00272   if (this->IsDead()) return;
    00273   if (this->engine->HasScriptCrashed()) {
    00274     /* The script crashed during saving, kill it here. */
    00275     this->Died();
    00276     return;
    00277   }
    00278   this->controller->ticks++;
    00279
    00280   if (this->suspend   < -1) this->suspend++; // Multiplayer suspend, increase up to -1.
    00281   if (this->suspend   < 0)  return;          // Multiplayer suspend, wait for Continue().
    00282   if (--this->suspend > 0)  return;          // Singleplayer suspend, decrease to 0.
    00283
    00284   /* If there is a callback to call, call that first */
    00285   if (this->callback != NULL) {
    00286     if (this->is_save_data_on_stack) {
    00287       sq_poptop(this->engine->GetVM());
    00288       this->is_save_data_on_stack = false;
    00289     }
    00290     try {
    00291       this->callback(this);
    00292     } catch (AI_VMSuspend e) {
    00293       this->suspend  = e.GetSuspendTime();
    00294       this->callback = e.GetSuspendCallback();
    00295
    00296       return;
    00297     }
    00298   }
    00299
    00300   this->suspend  = 0;
    00301   this->callback = NULL;
    00302
    00303   if (!this->is_started) {
    00304     try {
    00305       AIObject::SetAllowDoCommand(false);
    00306       /* Run the constructor if it exists. Don't allow any DoCommands in it. */
    00307       if (this->engine->MethodExists(*this->instance, "constructor")) {
    00308         if (!this->engine->CallMethod(*this->instance, "constructor", 100000) || this->engine->IsSuspended()) {
    00309           if (this->engine->IsSuspended()) AILog::Error("This AI took too long to initialize. AI is not started.");
    00310           this->Died();
    00311           return;
    00312         }
    00313       }
    00314       if (!this->CallLoad() || this->engine->IsSuspended()) {
    00315         if (this->engine->IsSuspended()) AILog::Error("This AI took too long in the Load function. AI is not started.");
    00316         this->Died();
    00317         return;
    00318       }
    00319       AIObject::SetAllowDoCommand(true);
    00320       /* Start the AI by calling Start() */
    00321       if (!this->engine->CallMethod(*this->instance, "Start",  _settings_game.ai.ai_max_opcode_till_suspend) || !this->engine->IsSuspended()) this->Died();
    00322     } catch (AI_VMSuspend e) {
    00323       this->suspend  = e.GetSuspendTime();
    00324       this->callback = e.GetSuspendCallback();
    00325     } catch (AI_FatalError e) {
    00326       this->is_dead = true;
    00327       this->engine->ThrowError(e.GetErrorMessage());
    00328       this->engine->ResumeError();
    00329       this->Died();
    00330     }
    00331
    00332     this->is_started = true;
    00333     return;
    00334   }
    00335   if (this->is_save_data_on_stack) {
    00336     sq_poptop(this->engine->GetVM());
    00337     this->is_save_data_on_stack = false;
    00338   }
    00339
    00340   /* Continue the VM */
    00341   try {
    00342     if (!this->engine->Resume(_settings_game.ai.ai_max_opcode_till_suspend)) this->Died();
    00343   } catch (AI_VMSuspend e) {
    00344     this->suspend  = e.GetSuspendTime();
    00345     this->callback = e.GetSuspendCallback();
    00346   } catch (AI_FatalError e) {
    00347     this->is_dead = true;
    00348     this->engine->ThrowError(e.GetErrorMessage());
    00349     this->engine->ResumeError();
    00350     this->Died();
    00351   }
    00352 }
    00353
    00354 void AIInstance::CollectGarbage()
    00355 {
    00356   if (this->is_started && !this->IsDead()) this->engine->CollectGarbage();
    00357 }
    00358
    00359 /* static */ void AIInstance::DoCommandReturn(AIInstance *instance)
    00360 {
    00361   instance->engine->InsertResult(AIObject::GetLastCommandRes());
    00362 }
    00363
    00364 /* static */ void AIInstance::DoCommandReturnVehicleID(AIInstance *instance)
    00365 {
    00366   instance->engine->InsertResult(AIObject::GetNewVehicleID());
    00367 }
    00368
    00369 /* static */ void AIInstance::DoCommandReturnSignID(AIInstance *instance)
    00370 {
    00371   instance->engine->InsertResult(AIObject::GetNewSignID());
    00372 }
    00373
    00374 /* static */ void AIInstance::DoCommandReturnGroupID(AIInstance *instance)
    00375 {
    00376   instance->engine->InsertResult(AIObject::GetNewGroupID());
    00377 }
    00378
    00379 /* static */ AIStorage *AIInstance::GetStorage()
    00380 {
    00381   assert(IsValidCompanyID(_current_company) && !IsHumanCompany(_current_company));
    00382   return GetCompany(_current_company)->ai_instance->storage;
    00383 }
    00384
    00385 /*
    00386  * All data is stored in the following format:
    00387  * First 1 byte indicating if there is a data blob at all.
    00388  * 1 byte indicating the type of data.
    00389  * The data itself, this differs per type:
    00390  *  - integer: a binary representation of the integer (int32).
    00391  *  - string:  First one byte with the string length, then a 0-terminated char
    00392  *             array. The string can't be longer then 255 bytes (including
    00393  *             terminating '\0').
    00394  *  - array:   All data-elements of the array are saved recursive in this
    00395  *             format, and ended with an element of the type
    00396  *             SQSL_ARRAY_TABLE_END.
    00397  *  - table:   All key/value pairs are saved in this format (first key 1, then
    00398  *             value 1, then key 2, etc.). All keys and values can have an
    00399  *             arbitrary type (as long as it is supported by the save function
    00400  *             of course). The table is ended with an element of the type
    00401  *             SQSL_ARRAY_TABLE_END.
    00402  *  - bool:    A single byte with value 1 representing true and 0 false.
    00403  *  - null:    No data.
    00404  */
    00405
    00407 enum SQSaveLoadType {
    00408   SQSL_INT             = 0x00,
    00409   SQSL_STRING          = 0x01,
    00410   SQSL_ARRAY           = 0x02,
    00411   SQSL_TABLE           = 0x03,
    00412   SQSL_BOOL            = 0x04,
    00413   SQSL_NULL            = 0x05,
    00414   SQSL_ARRAY_TABLE_END = 0xFF,
    00415 };
    00416
    00417 static byte _ai_sl_byte;
    00418
    00419 static const SaveLoad _ai_byte[] = {
    00420   SLEG_VAR(_ai_sl_byte, SLE_UINT8),
    00421   SLE_END()
    00422 };
    00423
    00424 enum {
    00425   AISAVE_MAX_DEPTH = 25,
    00426 };
    00427
    00428 /* static */ bool AIInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test)
    00429 {
    00430   if (max_depth == 0) {
    00431     AILog::Error("Savedata can only be nested to 25 deep. No data saved.");
    00432     return false;
    00433   }
    00434
    00435   switch (sq_gettype(vm, index)) {
    00436     case OT_INTEGER: {
    00437       if (!test) {
    00438         _ai_sl_byte = SQSL_INT;
    00439         SlObject(NULL, _ai_byte);
    00440       }
    00441       SQInteger res;
    00442       sq_getinteger(vm, index, &res);
    00443       if (!test) {
    00444         int value = (int)res;
    00445         SlArray(&value, 1, SLE_INT32);
    00446       }
    00447       return true;
    00448     }
    00449
    00450     case OT_STRING: {
    00451       if (!test) {
    00452         _ai_sl_byte = SQSL_STRING;
    00453         SlObject(NULL, _ai_byte);
    00454       }
    00455       const SQChar *res;
    00456       sq_getstring(vm, index, &res);
    00457       /* @bug if a string longer than 512 characters is given to FS2OTTD, the
    00458        *  internal buffer overflows. */
    00459       const char *buf = FS2OTTD(res);
    00460       size_t len = strlen(buf) + 1;
    00461       if (len >= 255) {
    00462         AILog::Error("Maximum string length is 254 chars. No data saved.");
    00463         return false;
    00464       }
    00465       if (!test) {
    00466         _ai_sl_byte = (byte)len;
    00467         SlObject(NULL, _ai_byte);
    00468         SlArray((void*)buf, len, SLE_CHAR);
    00469       }
    00470       return true;
    00471     }
    00472
    00473     case OT_ARRAY: {
    00474       if (!test) {
    00475         _ai_sl_byte = SQSL_ARRAY;
    00476         SlObject(NULL, _ai_byte);
    00477       }
    00478       sq_pushnull(vm);
    00479       while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
    00480         /* Store the value */
    00481         bool res = SaveObject(vm, -1, max_depth - 1, test);
    00482         sq_pop(vm, 2);
    00483         if (!res) {
    00484           sq_pop(vm, 1);
    00485           return false;
    00486         }
    00487       }
    00488       sq_pop(vm, 1);
    00489       if (!test) {
    00490         _ai_sl_byte = SQSL_ARRAY_TABLE_END;
    00491         SlObject(NULL, _ai_byte);
    00492       }
    00493       return true;
    00494     }
    00495
    00496     case OT_TABLE: {
    00497       if (!test) {
    00498         _ai_sl_byte = SQSL_TABLE;
    00499         SlObject(NULL, _ai_byte);
    00500       }
    00501       sq_pushnull(vm);
    00502       while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
    00503         /* Store the key + value */
    00504         bool res = SaveObject(vm, -2, max_depth - 1, test) && SaveObject(vm, -1, max_depth - 1, test);
    00505         sq_pop(vm, 2);
    00506         if (!res) {
    00507           sq_pop(vm, 1);
    00508           return false;
    00509         }
    00510       }
    00511       sq_pop(vm, 1);
    00512       if (!test) {
    00513         _ai_sl_byte = SQSL_ARRAY_TABLE_END;
    00514         SlObject(NULL, _ai_byte);
    00515       }
    00516       return true;
    00517     }
    00518
    00519     case OT_BOOL: {
    00520       if (!test) {
    00521         _ai_sl_byte = SQSL_BOOL;
    00522         SlObject(NULL, _ai_byte);
    00523       }
    00524       SQBool res;
    00525       sq_getbool(vm, index, &res);
    00526       if (!test) {
    00527         _ai_sl_byte = res ? 1 : 0;
    00528         SlObject(NULL, _ai_byte);
    00529       }
    00530       return true;
    00531     }
    00532
    00533     case OT_NULL: {
    00534       if (!test) {
    00535         _ai_sl_byte = SQSL_NULL;
    00536         SlObject(NULL, _ai_byte);
    00537       }
    00538       return true;
    00539     }
    00540
    00541     default:
    00542       AILog::Error("You tried to save an unsupported type. No data saved.");
    00543       return false;
    00544   }
    00545 }
    00546
    00547 /* static */ void AIInstance::SaveEmpty()
    00548 {
    00549   _ai_sl_byte = 0;
    00550   SlObject(NULL, _ai_byte);
    00551 }
    00552
    00553 void AIInstance::Save()
    00554 {
    00555   /* Don't save data if the AI didn't start yet or if it crashed. */
    00556   if (this->engine == NULL || this->engine->HasScriptCrashed()) {
    00557     SaveEmpty();
    00558     return;
    00559   }
    00560
    00561   HSQUIRRELVM vm = this->engine->GetVM();
    00562   if (this->is_save_data_on_stack) {
    00563     _ai_sl_byte = 1;
    00564     SlObject(NULL, _ai_byte);
    00565     /* Save the data that was just loaded. */
    00566     SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
    00567   } else if (!this->is_started) {
    00568     SaveEmpty();
    00569     return;
    00570   } else if (this->engine->MethodExists(*this->instance, "Save")) {
    00571     HSQOBJECT savedata;
    00572     /* We don't want to be interrupted during the save function. */
    00573     bool backup_allow = AIObject::GetAllowDoCommand();
    00574     AIObject::SetAllowDoCommand(false);
    00575     try {
    00576       if (!this->engine->CallMethod(*this->instance, "Save", &savedata)) {
    00577         /* The script crashed in the Save function. We can't kill
    00578          * it here, but do so in the next AI tick. */
    00579         SaveEmpty();
    00580         this->engine->CrashOccurred();
    00581         return;
    00582       }
    00583     } catch (AI_FatalError e) {
    00584       /* If we don't mark the AI as dead here cleaning up the squirrel
    00585        * stack could throw AI_FatalError again. */
    00586       this->is_dead = true;
    00587       this->engine->ThrowError(e.GetErrorMessage());
    00588       this->engine->ResumeError();
    00589       SaveEmpty();
    00590       /* We can't kill the AI here, so mark it as crashed (not dead) and
    00591        * kill it in the next AI tick. */
    00592       this->is_dead = false;
    00593       this->engine->CrashOccurred();
    00594       return;
    00595     }
    00596     AIObject::SetAllowDoCommand(backup_allow);
    00597
    00598     if (!sq_istable(savedata)) {
    00599       AILog::Error("Save function should return a table.");
    00600       SaveEmpty();
    00601       this->engine->CrashOccurred();
    00602       return;
    00603     }
    00604     sq_pushobject(vm, savedata);
    00605     if (SaveObject(vm, -1, AISAVE_MAX_DEPTH, true)) {
    00606       _ai_sl_byte = 1;
    00607       SlObject(NULL, _ai_byte);
    00608       SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
    00609       this->is_save_data_on_stack = true;
    00610     } else {
    00611       SaveEmpty();
    00612       this->engine->CrashOccurred();
    00613     }
    00614   } else {
    00615     AILog::Warning("Save function is not implemented");
    00616     _ai_sl_byte = 0;
    00617     SlObject(NULL, _ai_byte);
    00618   }
    00619
    00620 }
    00621
    00622 /* static */ bool AIInstance::LoadObjects(HSQUIRRELVM vm)
    00623 {
    00624   SlObject(NULL, _ai_byte);
    00625   switch (_ai_sl_byte) {
    00626     case SQSL_INT: {
    00627       int value;
    00628       SlArray(&value, 1, SLE_INT32);
    00629       if (vm != NULL) sq_pushinteger(vm, (SQInteger)value);
    00630       return true;
    00631     }
    00632
    00633     case SQSL_STRING: {
    00634       SlObject(NULL, _ai_byte);
    00635       static char buf[256];
    00636       SlArray(buf, _ai_sl_byte, SLE_CHAR);
    00637       if (vm != NULL) sq_pushstring(vm, OTTD2FS(buf), -1);
    00638       return true;
    00639     }
    00640
    00641     case SQSL_ARRAY: {
    00642       if (vm != NULL) sq_newarray(vm, 0);
    00643       while (LoadObjects(vm)) {
    00644         if (vm != NULL) sq_arrayappend(vm, -2);
    00645         /* The value is popped from the stack by squirrel. */
    00646       }
    00647       return true;
    00648     }
    00649
    00650     case SQSL_TABLE: {
    00651       if (vm != NULL) sq_newtable(vm);
    00652       while (LoadObjects(vm)) {
    00653         LoadObjects(vm);
    00654         if (vm != NULL) sq_rawset(vm, -3);
    00655         /* The key (-2) and value (-1) are popped from the stack by squirrel. */
    00656       }
    00657       return true;
    00658     }
    00659
    00660     case SQSL_BOOL: {
    00661       SlObject(NULL, _ai_byte);
    00662       if (vm != NULL) sq_pushinteger(vm, (SQBool)(_ai_sl_byte != 0));
    00663       return true;
    00664     }
    00665
    00666     case SQSL_NULL: {
    00667       if (vm != NULL) sq_pushnull(vm);
    00668       return true;
    00669     }
    00670
    00671     case SQSL_ARRAY_TABLE_END: {
    00672       return false;
    00673     }
    00674
    00675     default: NOT_REACHED();
    00676   }
    00677 }
    00678
    00679 /* static */ void AIInstance::LoadEmpty()
    00680 {
    00681   SlObject(NULL, _ai_byte);
    00682   /* Check if there was anything saved at all. */
    00683   if (_ai_sl_byte == 0) return;
    00684
    00685   LoadObjects(NULL);
    00686 }
    00687
    00688 void AIInstance::Load(int version)
    00689 {
    00690   if (this->engine == NULL || version == -1) {
    00691     LoadEmpty();
    00692     return;
    00693   }
    00694   HSQUIRRELVM vm = this->engine->GetVM();
    00695
    00696   SlObject(NULL, _ai_byte);
    00697   /* Check if there was anything saved at all. */
    00698   if (_ai_sl_byte == 0) return;
    00699
    00700   sq_pushinteger(vm, version);
    00701   LoadObjects(vm);
    00702   this->is_save_data_on_stack = true;
    00703 }
    00704
    00705 bool AIInstance::CallLoad()
    00706 {
    00707   HSQUIRRELVM vm = this->engine->GetVM();
    00708   /* Is there save data that we should load? */
    00709   if (!this->is_save_data_on_stack) return true;
    00710   /* Whatever happens, after CallLoad the savegame data is removed from the stack. */
    00711   this->is_save_data_on_stack = false;
    00712
    00713   if (!this->engine->MethodExists(*this->instance, "Load")) {
    00714     AILog::Warning("Loading failed: there was data for the AI to load, but the AI does not have a Load() function.");
    00715
    00716     /* Pop the savegame data and version. */
    00717     sq_pop(vm, 2);
    00718     return true;
    00719   }
    00720
    00721   /* Go to the instance-root */
    00722   sq_pushobject(vm, *this->instance);
    00723   /* Find the function-name inside the script */
    00724   sq_pushstring(vm, OTTD2FS("Load"), -1);
    00725   /* Change the "Load" string in a function pointer */
    00726   sq_get(vm, -2);
    00727   /* Push the main instance as "this" object */
    00728   sq_pushobject(vm, *this->instance);
    00729   /* Push the version data and savegame data as arguments */
    00730   sq_push(vm, -5);
    00731   sq_push(vm, -5);
    00732
    00733   /* Call the AI load function. sq_call removes the arguments (but not the
    00734    * function pointer) from the stack. */
    00735   if (SQ_FAILED(sq_call(vm, 3, SQFalse, SQFalse, 100000))) return false;
    00736
    00737   /* Pop 1) The version, 2) the savegame data, 3) the object instance, 4) the function pointer. */
    00738   sq_pop(vm, 4);
    00739   return true;
    00740 }