diff --git a/ai/ai.c b/ai/ai.c index b7271d2cee..764d06f940 100644 --- a/ai/ai.c +++ b/ai/ai.c @@ -5,6 +5,7 @@ #include "../variables.h" #include "../command.h" #include "../network.h" +#include "../debug.h" #include "ai.h" #include "default/default.h" @@ -120,18 +121,28 @@ int32 AI_DoCommand(uint tile, uint32 p1, uint32 p2, uint32 flags, uint procc) */ static void AI_RunTick(PlayerID player) { - extern void AiNewDoGameLoop(Player *p); - - Player *p = GetPlayer(player); _current_player = player; - if (_patches.ainew_active) { - AiNewDoGameLoop(p); - } else { - /* Enable all kind of cheats the old AI needs in order to operate correctly... */ - _is_old_ai_player = true; - AiDoGameLoop(p); - _is_old_ai_player = false; +#ifdef GPMI + if (_ai.gpmi) { + gpmi_call_RunTick(_ai_player[player].module, _frame_counter); + return; + } +#endif /* GPMI */ + + { + extern void AiNewDoGameLoop(Player *p); + + Player *p = GetPlayer(player); + + if (_patches.ainew_active) { + AiNewDoGameLoop(p); + } else { + /* Enable all kind of cheats the old AI needs in order to operate correctly... */ + _is_old_ai_player = true; + AiDoGameLoop(p); + _is_old_ai_player = false; + } } } @@ -171,10 +182,7 @@ void AI_RunGameLoop(void) Player *p; FOR_ALL_PLAYERS(p) { - if (p->is_active && p->is_ai) { - /* This should always be true, else something went wrong... */ - assert(_ai_player[p->index].active); - + if (p->is_active && p->is_ai && _ai_player[p->index].active) { /* Run the script */ AI_DequeueCommands(p->index); AI_RunTick(p->index); @@ -190,6 +198,21 @@ void AI_RunGameLoop(void) */ void AI_StartNewAI(PlayerID player) { +#ifdef GPMI + char library[80]; + char params[80]; + + /* XXX -- Todo, make a nice assign for library and params from a nice GUI :) */ + snprintf(library, sizeof(library), "php"); + snprintf(params, sizeof(params), "daeb"); + + _ai_player[player].module = gpmi_mod_load(library, params); + if (_ai_player[player].module == NULL) { + DEBUG(ai, 0)("[AI] Failed to load AI, aborting.."); + return; + } +#endif /* GPMI */ + /* Called if a new AI is booted */ _ai_player[player].active = true; } @@ -204,6 +227,10 @@ void AI_PlayerDied(PlayerID player) /* Called if this AI died */ _ai_player[player].active = false; + +#ifdef GPMI + gpmi_mod_unload(_ai_player[player].module); +#endif /* GPMI */ } /** @@ -211,14 +238,20 @@ void AI_PlayerDied(PlayerID player) */ void AI_Initialize(void) { - bool ai_network_client = _ai.network_client; + bool tmp_ai_network_client = _ai.network_client; +#ifdef GPMI + bool tmp_ai_gpmi = _ai.gpmi; +#endif /* GPMI */ memset(&_ai, 0, sizeof(_ai)); memset(&_ai_player, 0, sizeof(_ai_player)); - _ai.network_client = ai_network_client; + _ai.network_client = tmp_ai_network_client; _ai.network_playas = OWNER_SPECTATOR; _ai.enabled = true; +#ifdef GPMI + _ai.gpmi = tmp_ai_gpmi; +#endif /* GPMI */ } /** @@ -229,6 +262,6 @@ void AI_Uninitialize(void) Player* p; FOR_ALL_PLAYERS(p) { - if (p->is_active && p->is_ai) AI_PlayerDied(p->index); + if (p->is_active && p->is_ai && _ai_player[p->index].active) AI_PlayerDied(p->index); } } diff --git a/ai/ai.h b/ai/ai.h index 910e050b16..97747aa7b4 100644 --- a/ai/ai.h +++ b/ai/ai.h @@ -3,6 +3,9 @@ #include "../functions.h" #include "../network.h" +#ifdef GPMI +#include +#endif /* GPMI */ /* How DoCommands look like for an AI */ typedef struct AICommand { @@ -21,6 +24,9 @@ typedef struct AIPlayer { bool active; //! Is this AI active? AICommand *queue; //! The commands that he has in his queue AICommand *queue_tail; //! The tail of this queue +#ifdef GPMI + gpmi_module *module; //! The link to the GPMI module +#endif /* GPMI */ } AIPlayer; /* The struct to keep some data about the AI in general */ @@ -32,6 +38,10 @@ typedef struct AIStruct { /* For network-clients (a OpenTTD client who acts as an AI connected to a server) */ bool network_client; //! Are we a network_client? uint8 network_playas; //! The current network player we are connected as + +#ifdef GPMI + bool gpmi; //! True if we want GPMI AIs +#endif /* GPMI */ } AIStruct; VARDEF AIStruct _ai; diff --git a/lang/english.txt b/lang/english.txt index 34ad779e59..f7eeb5bc68 100644 --- a/lang/english.txt +++ b/lang/english.txt @@ -1012,6 +1012,7 @@ STR_CONFIG_PATCHES_AI_BUILDS_SHIPS :{LTBLUE}Disable STR_CONFIG_PATCHES_AINEW_ACTIVE :{LTBLUE}Enable new AI (alpha): {ORANGE}{STRING1} STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER :{LTBLUE}Allow AIs in multiplayer (experimental): {ORANGE}{STRING1} +STR_CONFIG_PATCHES_AI_GPMI :{LTBLUE}Enable GPMI-driven AIs: {ORANGE}{STRING1} STR_CONFIG_PATCHES_SERVINT_TRAINS :{LTBLUE}Default service interval for trains: {ORANGE}{STRING1} days/% STR_CONFIG_PATCHES_SERVINT_TRAINS_DISABLED :{LTBLUE}Default service interval for trains: {ORANGE}disabled diff --git a/openttd.c b/openttd.c index 98ab0206b7..caff336bdc 100644 --- a/openttd.c +++ b/openttd.c @@ -408,12 +408,15 @@ int ttd_main(int argc, char* argv[]) /* Set the debug proc */ gpmi_debug_proc = &gpmi_debug_openttd; + /* Set the script-path (GPMI doesn't support multiple paths, yet!) */ + gpmi_path_scripts = strdup("ai/scripts"); + /* Initialize GPMI */ gpmi_init(); /* Add our paths so we can find our own packages */ - gpmi_path_append(&gpmi_path_modules, "gpmi/modules"); - gpmi_path_append(&gpmi_path_packages, "gpmi/packages"); + gpmi_path_append(&gpmi_path_modules, "ai/modules"); + gpmi_path_append(&gpmi_path_packages, "ai/packages"); #endif /* GPMI */ #if defined(UNIX) && !defined(__MORPHOS__) diff --git a/settings.c b/settings.c index 7463ad522f..d18b44564e 100644 --- a/settings.c +++ b/settings.c @@ -11,6 +11,9 @@ #include "variables.h" #include "network.h" #include "settings.h" +#ifdef GPMI +#include "ai/ai.h" +#endif /* GPMI */ typedef struct IniFile IniFile; typedef struct IniItem IniItem; @@ -943,6 +946,9 @@ const SettingDesc patch_settings[] = { {"ainew_active", SDT_BOOL, (void*)false, &_patches.ainew_active, NULL}, {"ai_in_multiplayer", SDT_BOOL, (void*)false, &_patches.ai_in_multiplayer, NULL}, +#ifdef GPMI + {"ai_gpmi", SDT_BOOL, (void*)true, &_ai.gpmi, NULL}, +#endif /* GPMI */ {"map_x", SDT_UINT32, (void*)8, &_patches.map_x, NULL}, {"map_y", SDT_UINT32, (void*)8, &_patches.map_y, NULL}, diff --git a/settings_gui.c b/settings_gui.c index 6301ff0e19..9e8365b75c 100644 --- a/settings_gui.c +++ b/settings_gui.c @@ -19,6 +19,9 @@ #include "console.h" #include "town.h" #include "variables.h" +#ifdef GPMI +#include "ai/ai.h" +#endif /* GPMI */ static uint32 _difficulty_click_a; static uint32 _difficulty_click_b; @@ -760,6 +763,9 @@ static const PatchEntry _patches_economy[] = { static const PatchEntry _patches_ai[] = { {PE_BOOL, 0, STR_CONFIG_PATCHES_AINEW_ACTIVE, "ainew_active", &_patches.ainew_active, 0, 1, 1, &AiNew_PatchActive_Warning}, {PE_BOOL, 0, STR_CONFIG_PATCHES_AI_IN_MULTIPLAYER, "ai_in_multiplayer", &_patches.ai_in_multiplayer, 0, 1, 1, &Ai_In_Multiplayer_Warning}, +#ifdef GPMI + {PE_BOOL, 0, STR_CONFIG_PATCHES_AI_GPMI, "ai_gpmi", &_ai.gpmi, 0, 1, 1, NULL}, +#endif /* GPMI */ {PE_BOOL, 0, STR_CONFIG_PATCHES_AI_BUILDS_TRAINS, "ai_disable_veh_train", &_patches.ai_disable_veh_train, 0, 0, 0, NULL}, {PE_BOOL, 0, STR_CONFIG_PATCHES_AI_BUILDS_ROADVEH,"ai_disable_veh_roadveh",&_patches.ai_disable_veh_roadveh, 0, 0, 0, NULL},