# ai_instance.cpp

Go to the documentation of this file.

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