truelight@9441: /* $Id$ */ truelight@9441: truebrain@9833: /** @file ai_controller.cpp Implementation of AIControler. */ truelight@9441: truelight@9441: #include "../../stdafx.h" truelight@9441: #include "../../openttd.h" rubidium@9724: #include "../../player_func.h" truebrain@10643: #include "../../core/alloc_func.hpp" truebrain@10958: #include "../../string_func.h" truebrain@11098: #include "../../settings_type.h" truebrain@10643: #include "table/strings.h" truebrain@10643: truebrain@10643: #include truebrain@10643: #include "../../squirrel.hpp" truebrain@10643: #include "../../squirrel_helper.hpp" truebrain@10643: #include "../../squirrel_class.hpp" truebrain@10643: #include "../../squirrel_std.hpp" truebrain@10643: #include "ai_controller.hpp" rubidium@9444: #include "../ai_threads.h" truebrain@10889: #include "../ai_info.hpp" truebrain@11098: #include "../ai.h" truelight@9441: truebrain@10643: /* Convert all AI related classes to Squirrel data. truebrain@10643: * Note: this line a marker in squirrel_export.sh. Do not change! */ truebrain@10643: #include "ai_abstractlist.hpp.sq" truebrain@10643: #include "ai_accounting.hpp.sq" truebrain@10643: #include "ai_airport.hpp.sq" truebrain@10643: #include "ai_base.hpp.sq" truebrain@10643: #include "ai_bridge.hpp.sq" truebrain@10643: #include "ai_bridgelist.hpp.sq" truebrain@10643: #include "ai_cargo.hpp.sq" truebrain@10643: #include "ai_cargolist.hpp.sq" truebrain@10643: #include "ai_company.hpp.sq" truebrain@10643: #include "ai_controller.hpp.sq" truebrain@10643: #include "ai_date.hpp.sq" rubidium@11053: #include "ai_depotlist.hpp.sq" truebrain@10643: #include "ai_engine.hpp.sq" truebrain@10643: #include "ai_enginelist.hpp.sq" truebrain@10643: #include "ai_error.hpp.sq" truebrain@10643: #include "ai_event.hpp.sq" truebrain@10643: #include "ai_event_types.hpp.sq" truebrain@10643: #include "ai_execmode.hpp.sq" rubidium@10852: #include "ai_gamesettings.hpp.sq" rubidium@11057: #include "ai_group.hpp.sq" truebrain@11079: #include "ai_grouplist.hpp.sq" truebrain@10643: #include "ai_industry.hpp.sq" truebrain@10643: #include "ai_industrylist.hpp.sq" truebrain@10643: #include "ai_list.hpp.sq" truebrain@10643: #include "ai_log.hpp.sq" truebrain@10643: #include "ai_map.hpp.sq" truebrain@10643: #include "ai_marine.hpp.sq" truebrain@10643: #include "ai_order.hpp.sq" truebrain@10643: #include "ai_road.hpp.sq" truebrain@10643: #include "ai_sign.hpp.sq" truebrain@10643: #include "ai_station.hpp.sq" truebrain@10643: #include "ai_stationlist.hpp.sq" truebrain@10643: #include "ai_subsidy.hpp.sq" truebrain@10643: #include "ai_subsidylist.hpp.sq" truebrain@10643: #include "ai_testmode.hpp.sq" truebrain@10643: #include "ai_tile.hpp.sq" truebrain@10643: #include "ai_tilelist.hpp.sq" truebrain@10643: #include "ai_town.hpp.sq" truebrain@10643: #include "ai_townlist.hpp.sq" truebrain@10643: #include "ai_transactionmode.hpp.sq" truebrain@10643: #include "ai_tunnel.hpp.sq" truebrain@10643: #include "ai_vehicle.hpp.sq" truebrain@10643: #include "ai_vehiclelist.hpp.sq" truebrain@10643: truebrain@11097: /* static */ void AIController::SetCommandDelay(int ticks) truebrain@11097: { truebrain@11097: if (ticks <= 0) return; truebrain@11097: AIObject::SetDoCommandDelay(ticks); truebrain@11097: } truebrain@11097: truebrain@11043: /* static */ void AIController::Sleep(int ticks) truelight@9441: { truebrain@11043: if (ticks <= 0) { truebrain@11043: AILog::Warning("Sleep() value should be > 0. Assuming value 1."); truebrain@11043: ticks = 1; truebrain@11043: } truebrain@11098: AIController *controller = AI_GetPlayerController(_current_player); truebrain@11098: controller->engine->ResetOpcodeCounter(); truelight@9441: AI_SuspendPlayer(_current_player, ticks); truelight@9441: } truebrain@9782: truebrain@9782: /* static */ void AIController::Print(bool error_msg, const char *message) truebrain@9782: { truebrain@9851: AILog::Log(error_msg ? AILog::LOG_SQ_ERROR : AILog::LOG_SQ_INFO, message); truebrain@9782: } truebrain@10643: truebrain@10643: void AIController::RegisterClasses() truebrain@10643: { truebrain@10902: this->engine->AddMethod("import", &AILibrary::Import, 4, "?ssi"); truebrain@10889: truebrain@10643: /* Register all classes */ truebrain@10643: squirrel_register_std(this->engine); truebrain@10643: SQAIAbstractList_Register(this->engine); truebrain@10643: SQAIAccounting_Register(this->engine); truebrain@10643: SQAIAirport_Register(this->engine); truebrain@10643: SQAIBase_Register(this->engine); truebrain@10643: SQAIBridge_Register(this->engine); truebrain@10643: SQAIBridgeList_Register(this->engine); truebrain@10643: SQAIBridgeList_Length_Register(this->engine); truebrain@10643: SQAICargo_Register(this->engine); truebrain@10643: SQAICargoList_Register(this->engine); truebrain@11164: SQAICargoList_IndustryAccepting_Register(this->engine); truebrain@11164: SQAICargoList_IndustryProducing_Register(this->engine); truebrain@10643: SQAICompany_Register(this->engine); truebrain@10643: SQAIController_Register(this->engine); truebrain@10643: SQAIDate_Register(this->engine); rubidium@11053: SQAIDepotList_Register(this->engine); truebrain@10643: SQAIEngine_Register(this->engine); truebrain@10643: SQAIEngineList_Register(this->engine); truebrain@10643: SQAIError_Register(this->engine); truebrain@10643: SQAIEvent_Register(this->engine); truebrain@10643: SQAIEventCompanyBankrupt_Register(this->engine); truebrain@10643: SQAIEventCompanyInTrouble_Register(this->engine); truebrain@10643: SQAIEventCompanyMerger_Register(this->engine); truebrain@10643: SQAIEventCompanyNew_Register(this->engine); truebrain@10643: SQAIEventController_Register(this->engine); glx@10971: SQAIEventEngineAvailable_Register(this->engine); truebrain@10643: SQAIEventEnginePreview_Register(this->engine); glx@10879: SQAIEventIndustryClose_Register(this->engine); glx@10879: SQAIEventIndustryOpen_Register(this->engine); glx@10973: SQAIEventStationFirstVehicle_Register(this->engine); truebrain@10643: SQAIEventSubsidyAwarded_Register(this->engine); truebrain@10643: SQAIEventSubsidyExpired_Register(this->engine); truebrain@10643: SQAIEventSubsidyOffer_Register(this->engine); truebrain@10643: SQAIEventSubsidyOfferExpired_Register(this->engine); truebrain@10643: SQAIEventTest_Register(this->engine); truebrain@11051: SQAIEventVehicleCrashed_Register(this->engine); truebrain@10643: SQAIEventVehicleLost_Register(this->engine); truebrain@10643: SQAIEventVehicleUnprofitable_Register(this->engine); truebrain@10643: SQAIEventVehicleWaitingInDepot_Register(this->engine); truebrain@10643: SQAIExecMode_Register(this->engine); rubidium@10852: SQAIGameSettings_Register(this->engine); rubidium@11057: SQAIGroup_Register(this->engine); truebrain@11079: SQAIGroupList_Register(this->engine); truebrain@10643: SQAIIndustry_Register(this->engine); truebrain@10643: SQAIIndustryList_Register(this->engine); truebrain@10643: SQAIIndustryList_CargoAccepting_Register(this->engine); truebrain@10643: SQAIIndustryList_CargoProducing_Register(this->engine); truebrain@10643: SQAIList_Register(this->engine); truebrain@10643: SQAILog_Register(this->engine); truebrain@10643: SQAIMap_Register(this->engine); truebrain@10643: SQAIMarine_Register(this->engine); truebrain@10643: SQAIOrder_Register(this->engine); truebrain@10643: SQAIRoad_Register(this->engine); truebrain@10643: SQAISign_Register(this->engine); truebrain@10643: SQAIStation_Register(this->engine); truebrain@10643: SQAIStationList_Register(this->engine); truebrain@10643: SQAIStationList_Vehicle_Register(this->engine); truebrain@10643: SQAISubsidy_Register(this->engine); truebrain@10643: SQAISubsidyList_Register(this->engine); truebrain@10643: SQAITestMode_Register(this->engine); truebrain@10643: SQAITile_Register(this->engine); truebrain@10643: SQAITileList_Register(this->engine); truebrain@10643: SQAITileList_IndustryAccepting_Register(this->engine); truebrain@10643: SQAITileList_IndustryProducing_Register(this->engine); truebrain@10864: SQAITileList_StationType_Register(this->engine); truebrain@10643: SQAITown_Register(this->engine); truebrain@10643: SQAITownList_Register(this->engine); truebrain@10643: SQAITransactionMode_Register(this->engine); truebrain@10643: SQAITunnel_Register(this->engine); truebrain@10643: SQAIVehicle_Register(this->engine); truebrain@10643: SQAIVehicleList_Register(this->engine); truebrain@10643: SQAIVehicleList_Station_Register(this->engine); truebrain@10643: truebrain@10643: this->engine->SetGlobalPointer(this->engine); truebrain@10643: } truebrain@10643: truebrain@10643: static void PrintFunc(bool error_msg, const SQChar *message) truebrain@10643: { truebrain@10643: /* Convert to OpenTTD internal capable string */ truebrain@10643: AIController::Print(error_msg, FS2OTTD(message)); truebrain@10643: } truebrain@10643: truebrain@11098: static void SquirrelSuspendControl() truebrain@11098: { truebrain@11098: AIController::Sleep(1); truebrain@11098: } truebrain@11098: truebrain@10958: AIController::AIController(const char *script, const char *class_name) : truebrain@10958: tick(0), truebrain@10958: engine(NULL), truebrain@10958: SQ_instance(NULL), truebrain@10958: loaded_library_count(0) truebrain@10643: { truebrain@10958: this->script = strdup(script); truebrain@10958: this->class_name = strdup(class_name); truebrain@10958: } truebrain@10958: truebrain@10958: void AIController::Start() truebrain@10958: { truebrain@10958: assert(this->engine == NULL); truebrain@10643: truebrain@10643: /* Create the Squirrel Engine and assign all required classes and settings */ truebrain@10643: this->engine = new Squirrel(); truebrain@10643: this->engine->SetPrintFunction(&PrintFunc); truebrain@10643: this->RegisterClasses(); truebrain@10958: if (!this->engine->LoadScript(this->script)) { truebrain@10643: delete this->engine; truebrain@10643: this->engine = NULL; truebrain@10643: return; truebrain@10643: } truebrain@10643: /* Create the main-class */ truebrain@10643: this->SQ_instance = MallocT(sizeof(SQObject)); truebrain@10958: if (!this->engine->CreateClassInstance(this->class_name, this, this->SQ_instance)) { truebrain@10650: delete this->engine; truebrain@10650: this->engine = NULL; truebrain@10650: return; truebrain@10650: } truebrain@10885: truebrain@10885: /* Run the constructor first */ truebrain@10885: if (this->engine->MethodExists(*this->SQ_instance, "constructor")) { truebrain@10885: this->engine->CallMethod(*this->SQ_instance, "constructor"); truebrain@10885: } truebrain@11097: truebrain@11098: /* Set the maximum opcodes before suspend and suspend control */ truebrain@11098: this->engine->SetMaxOpcodes(_settings_game.ai.ai_max_opcode_till_suspend); truebrain@11098: this->engine->SetSuspendControl(&SquirrelSuspendControl); truebrain@11098: truebrain@10885: /* When that is done, start the Start() function */ truebrain@10885: this->engine->CallMethod(*this->SQ_instance, "Start"); truebrain@10643: } truebrain@10643: truebrain@10643: AIController::~AIController() truebrain@10643: { truebrain@10650: if (this->engine != NULL) delete this->engine; truebrain@10643: free(this->SQ_instance); truebrain@10958: free((void *)this->script); truebrain@10958: free((void *)this->class_name); truebrain@10958: truebrain@10958: for (LoadedLibraryList::iterator iter = this->loaded_library.begin(); iter != this->loaded_library.end(); iter++) { truebrain@10958: free((void *)(*iter).second); truebrain@10958: free((void *)(*iter).first); truebrain@10958: } truebrain@10958: truebrain@10958: this->loaded_library.clear(); truebrain@10643: } truebrain@10643: truebrain@10643: void AIController::IncreaseTick() truebrain@10643: { truebrain@10643: this->tick++; truebrain@10643: } truebrain@10643: truebrain@10643: uint AIController::GetTick() truebrain@10643: { truebrain@10643: return this->tick; truebrain@10643: } truebrain@10958: truebrain@10958: bool AIController::LoadedLibrary(const char *library_name, int *next_number, char *fake_class_name, int fake_class_name_len) truebrain@10958: { truebrain@10958: LoadedLibraryList::iterator iter = this->loaded_library.find(library_name); truebrain@10958: if (iter == this->loaded_library.end()) { truebrain@10958: *next_number = ++this->loaded_library_count; truebrain@10958: return false; truebrain@10958: } truebrain@10958: truebrain@10958: ttd_strlcpy(fake_class_name, (*iter).second, fake_class_name_len); truebrain@10958: return true; truebrain@10958: } truebrain@10958: truebrain@10958: void AIController::AddLoadedLibrary(const char *library_name, const char *fake_class_name) truebrain@10958: { truebrain@10958: this->loaded_library[strdup(library_name)] = strdup(fake_class_name); truebrain@10958: }