(svn r15027) -Merge: tomatos and bananas left to be, here is NoAI for all to see.

NoAI is an API (a framework) to build your own AIs in. See:
   http://wiki.openttd.org/wiki/index.php/AI:Main_Page
 With many thanks to:
  - glx and Rubidium for their syncing, feedback and hard work
  - Yexo for his feedback, patches, and AIs which tested the system very deep
  - Morloth for his feedback and patches
  - TJIP for hosting a challenge which kept NoAI on track
  - All AI authors for testing our AI API, and all other people who helped in one way or another
-Remove: all old AIs and their cheats/hacks
This commit is contained in:
truebrain
2009-01-12 17:11:45 +00:00
parent ec97e1fd0d
commit c2406cd42d
257 changed files with 34620 additions and 7576 deletions

View File

@@ -1,244 +0,0 @@
/* $Id$ */
/** @file ai.cpp Base for all AIs. */
#include "../stdafx.h"
#include "../openttd.h"
#include "../variables.h"
#include "../command_func.h"
#include "../network/network.h"
#include "../core/alloc_func.hpp"
#include "../company_func.h"
#include "../company_base.h"
#include "ai.h"
#include "default/default.h"
#include "trolly/trolly.h"
#include "../signal_func.h"
AIStruct _ai;
AICompany _ai_company[MAX_COMPANIES];
/**
* Dequeues commands put in the queue via AI_PutCommandInQueue.
*/
static void AI_DequeueCommands(CompanyID company)
{
AICommand *com, *entry_com;
entry_com = _ai_company[company].queue;
/* It happens that DoCommandP issues a new DoCommandAI which adds a new command
* to this very same queue (don't argue about this, if it currently doesn't
* happen I can tell you it will happen with AIScript -- TrueLight). If we
* do not make the queue NULL, that commands will be dequeued immediatly.
* Therefor we safe the entry-point to entry_com, and make the queue NULL, so
* the new queue can be safely built up. */
_ai_company[company].queue = NULL;
_ai_company[company].queue_tail = NULL;
/* Dequeue all commands */
while ((com = entry_com) != NULL) {
_current_company = company;
DoCommandP(com->tile, com->p1, com->p2, com->cmd, com->callback, com->text);
/* Free item */
entry_com = com->next;
free(com->text);
free(com);
}
}
/**
* Needed for SP; we need to delay DoCommand with 1 tick, because else events
* will make infinite loops (AIScript).
*/
static void AI_PutCommandInQueue(CompanyID company, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text = NULL)
{
AICommand *com;
if (_ai_company[company].queue_tail == NULL) {
/* There is no item in the queue yet, create the queue */
_ai_company[company].queue = MallocT<AICommand>(1);
_ai_company[company].queue_tail = _ai_company[company].queue;
} else {
/* Add an item at the end */
_ai_company[company].queue_tail->next = MallocT<AICommand>(1);
_ai_company[company].queue_tail = _ai_company[company].queue_tail->next;
}
/* This is our new item */
com = _ai_company[company].queue_tail;
/* Assign the info */
com->tile = tile;
com->p1 = p1;
com->p2 = p2;
com->cmd = cmd;
com->callback = callback;
com->next = NULL;
com->text = text == NULL ? NULL : strdup(text);
}
/**
* Executes a raw DoCommand for the AI.
*/
CommandCost AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint32 cmd, CommandCallback *callback, const char *text)
{
CompanyID old_local_company;
CommandCost res;
/* If you enable DC_EXEC with DC_QUERY_COST you are a really strange
* person.. should we check for those funny jokes?
*/
/* First, do a test-run to see if we can do this */
res = DoCommand(tile, p1, p2, flags & ~DC_EXEC, cmd, text);
/* The command failed, or you didn't want to execute, or you are quering, return */
if (CmdFailed(res) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST)) {
return res;
}
/* NetworkSend_Command needs _local_company to be set correctly, so
* adjust it, and put it back right after the function */
old_local_company = _local_company;
_local_company = _current_company;
#ifdef ENABLE_NETWORK
/* Send the command */
if (_networking) {
/* Network is easy, send it to his handler */
NetworkSend_Command(tile, p1, p2, cmd, callback, text);
} else {
#else
{
#endif
/* If we execute BuildCommands directly in SP, we have a big problem with events
* so we need to delay is for 1 tick */
AI_PutCommandInQueue(_current_company, tile, p1, p2, cmd, callback, text);
}
/* Set _local_company back */
_local_company = old_local_company;
return res;
}
CommandCost AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint32 cmd, const char *text)
{
return AI_DoCommandCc(tile, p1, p2, flags, cmd, NULL, text);
}
/**
* Run 1 tick of the AI. Don't overdo it, keep it realistic.
*/
static void AI_RunTick(CompanyID company)
{
extern void AiNewDoGameLoop(Company *c);
Company *c = GetCompany(company);
_current_company = company;
if (_settings_game.ai.ainew_active) {
AiNewDoGameLoop(c);
} else {
/* Enable all kind of cheats the old AI needs in order to operate correctly... */
_is_old_ai_company = true;
AiDoGameLoop(c);
_is_old_ai_company = false;
}
/* AI could change some track, so update signals */
UpdateSignalsInBuffer();
}
/**
* The gameloop for AIs.
* Handles one tick for all the AIs.
*/
void AI_RunGameLoop()
{
/* Don't do anything if ai is disabled */
if (!_ai.enabled) return;
/* Don't do anything if we are a network-client, or the AI has been disabled */
if (_networking && (!_network_server || !_settings_game.ai.ai_in_multiplayer)) return;
/* New tick */
_ai.tick++;
/* Make sure the AI follows the difficulty rule.. */
assert(_settings_game.difficulty.competitor_speed <= 4);
if ((_ai.tick & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
/* Check for AI-client (so joining a network with an AI) */
if (!_networking || _network_server) {
/* Check if we want to run AIs (server or SP only) */
const Company *c;
FOR_ALL_COMPANIES(c) {
if (c->is_ai) {
/* This should always be true, else something went wrong... */
assert(_ai_company[c->index].active);
/* Run the script */
AI_DequeueCommands(c->index);
AI_RunTick(c->index);
}
}
}
_current_company = OWNER_NONE;
}
/**
* A new AI sees the day of light. You can do here what ever you think is needed.
*/
void AI_StartNewAI(CompanyID company)
{
assert(IsValidCompanyID(company));
/* Called if a new AI is booted */
_ai_company[company].active = true;
}
/**
* This AI company died. Give it some chance to make a final puf.
*/
void AI_CompanyDied(CompanyID company)
{
/* Called if this AI died */
_ai_company[company].active = false;
if (_companies_ainew[company].pathfinder == NULL) return;
AyStarMain_Free(_companies_ainew[company].pathfinder);
delete _companies_ainew[company].pathfinder;
_companies_ainew[company].pathfinder = NULL;
}
/**
* Initialize some AI-related stuff.
*/
void AI_Initialize()
{
/* First, make sure all AIs are DEAD! */
AI_Uninitialize();
memset(&_ai, 0, sizeof(_ai));
memset(&_ai_company, 0, sizeof(_ai_company));
_ai.enabled = true;
}
/**
* Deinitializer for AI-related stuff.
*/
void AI_Uninitialize()
{
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) AI_CompanyDied(c);
}

View File

@@ -1,115 +0,0 @@
/* $Id$ */
/** @file ai.h Base functions for all AIs. */
#ifndef AI_H
#define AI_H
#include "../network/network.h"
#include "../command_type.h"
#include "../core/random_func.hpp"
#include "../settings_type.h"
/* How DoCommands look like for an AI */
struct AICommand {
uint32 tile;
uint32 p1;
uint32 p2;
uint32 cmd;
CommandCallback *callback;
char *text;
uint uid;
AICommand *next;
};
/* The struct for an AIScript Company */
struct AICompany {
bool active; ///< Is this AI active?
AICommand *queue; ///< The commands that he has in his queue
AICommand *queue_tail; ///< The tail of this queue
};
/* The struct to keep some data about the AI in general */
struct AIStruct {
/* General */
bool enabled; ///< Is AI enabled?
uint tick; ///< The current tick (something like _frame_counter, only for AIs)
};
extern AIStruct _ai;
extern AICompany _ai_company[MAX_COMPANIES];
// ai.c
void AI_StartNewAI(CompanyID company);
void AI_CompanyDied(CompanyID company);
void AI_RunGameLoop();
void AI_Initialize();
void AI_Uninitialize();
CommandCost AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, const char *text = NULL);
CommandCost AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback *callback, const char *text = NULL);
/** Is it allowed to start a new AI.
* This function checks some boundries to see if we should launch a new AI.
* @return True if we can start a new AI.
*/
static inline bool AI_AllowNewAI()
{
/* If disabled, no AI */
if (!_ai.enabled)
return false;
/* If in network, but no server, no AI */
if (_networking && !_network_server)
return false;
/* If in network, and server, possible AI */
if (_networking && _network_server) {
/* Do we want AIs in multiplayer? */
if (!_settings_game.ai.ai_in_multiplayer)
return false;
/* Only the NewAI is allowed... sadly enough the old AI just doesn't support this
* system, because all commands are delayed by at least 1 tick, which causes
* a big problem, because it uses variables that are only set AFTER the command
* is really executed... */
if (!_settings_game.ai.ainew_active)
return false;
}
return true;
}
#define AI_CHANCE16(a, b) ((uint16) AI_Random() <= (uint16)((65536 * a) / b))
#define AI_CHANCE16R(a, b, r) ((uint16)(r = AI_Random()) <= (uint16)((65536 * a) / b))
/**
* The random-function that should be used by ALL AIs.
*/
static inline uint AI_RandomRange(uint max)
{
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
* but we pick InteractiveRandomRange if we are a network_server or network-client.
*/
if (_networking)
return InteractiveRandomRange(max);
else
return RandomRange(max);
}
/**
* The random-function that should be used by ALL AIs.
*/
static inline uint32 AI_Random()
{
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
* but we pick InteractiveRandomRange if we are a network_server or network-client.
*/
if (_networking)
return InteractiveRandom();
else
return Random();
}
#endif /* AI_H */

102
src/ai/ai.hpp Normal file
View File

@@ -0,0 +1,102 @@
/* $Id$ */
/** @file ai.hpp Base functions for all AIs. */
#ifndef AI_HPP
#define AI_HPP
#include "api/ai_event_types.hpp"
#ifndef AI_CONFIG_HPP
struct ltstr { bool operator()(const char *s1, const char *s2) const { return strcmp(s1, s2) < 0; } };
#endif /* AI_CONFIG_HPP */
typedef std::map<const char *, class AIInfo *, ltstr> AIInfoList;
void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2);
class AI {
public:
/**
* Is it possible to start a new AI company?
* @return True if a new AI company can be started.
*/
static bool CanStartNew();
/**
* Start a new AI company.
* @param company At which slot the AI company should start.
*/
static void StartNew(CompanyID company);
/**
* Called every game-tick to let AIs do something.
*/
static void GameLoop();
/**
* Get the current AI tick.
*/
static uint GetTick();
/**
* Stop a company to be controlled by an AI.
* @param company The company from which the AI needs to detach.
* @pre !IsHumanCompany(company).
*/
static void Stop(CompanyID company);
/**
* Kill any and all AIs we manage.
*/
static void KillAll();
/**
* Initialize the AI system.
*/
static void Initialize();
/**
* Uninitialize the AI system
* @param keepConfig Should we keep AIConfigs, or can we free that memory?
*/
static void Uninitialize(bool keepConfig);
/**
* Reset all AIConfigs, and make them reload their AIInfo.
* If the AIInfo could no longer be found, an error is reported to the user.
*/
static void ResetConfig();
/**
* Queue a new event for an AI.
*/
static void NewEvent(CompanyID company, AIEvent *event);
/**
* Broadcast a new event to all active AIs.
*/
static void BroadcastNewEvent(AIEvent *event, CompanyID skip_company = MAX_COMPANIES);
/**
* Save data from an AI to a savegame.
*/
static void Save(CompanyID company);
/**
* Load data for an AI from a savegame.
*/
static void Load(CompanyID company);
static char *GetConsoleList(char *p, const char *last);
static const AIInfoList *GetInfoList();
static AIInfo *GetCompanyInfo(const char *name);
static bool ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm);
static void Rescan();
private:
static uint frame_counter;
static class AIScanner *ai_scanner;
};
#endif /* AI_HPP */

143
src/ai/ai_config.cpp Normal file
View File

@@ -0,0 +1,143 @@
/* $Id$ */
/** @file ai_config.cpp Implementation of AIConfig. */
#include "../stdafx.h"
#include "../openttd.h"
#include "../settings_type.h"
#include "ai.hpp"
#include "ai_config.hpp"
#include "ai_info.hpp"
void AIConfig::ChangeAI(const char *name)
{
free((void *)this->name);
this->name = (name == NULL) ? NULL : strdup(name);
this->info = (name == NULL) ? NULL : AI::GetCompanyInfo(this->name);
for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
free((void*)(*it).first);
}
this->settings.clear();
}
AIConfig::AIConfig(const AIConfig *config) :
name(NULL),
info(NULL)
{
this->name = (config->name == NULL) ? NULL : strdup(config->name);
this->info = config->info;
for (SettingValueList::const_iterator it = config->settings.begin(); it != config->settings.end(); it++) {
this->settings[strdup((*it).first)] = (*it).second;
}
}
AIConfig::~AIConfig()
{
this->ChangeAI(NULL);
}
AIInfo *AIConfig::GetInfo()
{
return this->info;
}
bool AIConfig::ResetInfo()
{
this->info = AI::GetCompanyInfo(this->name);
return this->info != NULL;
}
AIConfig *AIConfig::GetConfig(CompanyID company, bool forceNewgameSetting)
{
AIConfig **config;
if (!forceNewgameSetting) {
config = (_game_mode == GM_MENU) ? &_settings_newgame.ai_config[company] : &_settings_game.ai_config[company];
} else {
config = &_settings_newgame.ai_config[company];
}
if (*config == NULL) *config = new AIConfig();
return *config;
}
int AIConfig::GetSetting(const char *name)
{
assert(this->info != NULL);
SettingValueList::iterator it = this->settings.find(name);
/* Return the default value if the setting is not set, or if we are in a not-custom difficult level */
if (it == this->settings.end() || ((_game_mode == GM_MENU) ? _settings_newgame.difficulty.diff_level : _settings_game.difficulty.diff_level) != 3) {
return this->info->GetSettingDefaultValue(name);
}
return (*it).second;
}
void AIConfig::SetSetting(const char *name, int value)
{
/* You can only set ai specific settings if an AI is selected. */
assert(strcmp(name, "start_date") == 0 || this->info != NULL);
SettingValueList::iterator it = this->settings.find(name);
if (it != this->settings.end()) {
(*it).second = value;
} else {
this->settings[strdup(name)] = value;
}
}
bool AIConfig::HasAI()
{
return this->info != NULL;
}
const char *AIConfig::GetName()
{
return this->name;
}
void AIConfig::StringToSettings(const char *value)
{
char *value_copy = strdup(value);
char *s = value_copy;
while (s != NULL) {
/* Analyze the string ('name=value,name=value\0') */
char *item_name = s;
s = strchr(s, '=');
if (s == NULL) break;
if (*s == '\0') break;
*s = '\0';
s++;
char *item_value = s;
s = strchr(s, ',');
if (s != NULL) {
*s = '\0';
s++;
}
this->SetSetting(item_name, atoi(item_value));
}
free(value_copy);
}
void AIConfig::SettingsToString(char *string, int size)
{
string[0] = '\0';
for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
char no[10];
snprintf(no, sizeof(no), "%d", (*it).second);
/* Check if the string would fit in the destination */
size -= strlen((*it).first) - 1 - strlen(no) - 1;
/* If it doesn't fit, skip the next settings */
if (size <= 0) return;
strcat(string, (*it).first);
strcat(string, "=");
strcat(string, no);
strcat(string, ",");
}
string[strlen(string) - 1] = '\0';
}

91
src/ai/ai_config.hpp Normal file
View File

@@ -0,0 +1,91 @@
/* $Id$ */
/** @file ai_config.hpp AIConfig stores the configuration settings of every AI. */
#ifndef AI_CONFIG_HPP
#define AI_CONFIG_HPP
#include <map>
#ifndef AI_HPP
struct ltstr { bool operator()(const char *s1, const char *s2) const { return strcmp(s1, s2) < 0; } };
#endif /* AI_HPP */
class AIConfig {
private:
typedef std::map<const char *, int, ltstr> SettingValueList;
public:
AIConfig() :
name(NULL),
info(NULL)
{}
AIConfig(const AIConfig *config);
~AIConfig();
/**
* Set another AI to be loaded in this slot.
*/
void ChangeAI(const char *name);
/**
* When ever the AI Scanner is reloaded, all infos become invalid. This
* function tells AIConfig about this.
* @return True if the reset was successfull, false if the AI was no longer
* found.
*/
bool ResetInfo();
/**
* Get the AIInfo linked to this AIConfig.
*/
class AIInfo *GetInfo();
/**
* Get the config of a company.
*/
static AIConfig *GetConfig(CompanyID company, bool forceNewgameSetting = false);
/**
* Get the value of a setting for this config. It might fallback to his
* 'info' to find the default value (if not set or if not-custom difficulty
* level).
* @return The (default) value of the setting, or -1 if the setting was not
* found.
*/
int GetSetting(const char *name);
/**
* Set the value of a setting for this config.
*/
void SetSetting(const char *name, int value);
/**
* Is this config attached to an AI?
*/
bool HasAI();
/**
* Get the name of the AI.
*/
const char *GetName();
/**
* Convert a string which is stored in the config file or savegames to
* custom settings of this AI.
*/
void StringToSettings(const char *value);
/**
* Convert the custom settings to a string that can be stored in the config
* file or savegames.
*/
void SettingsToString(char *string, int size);
private:
const char *name;
class AIInfo *info;
SettingValueList settings;
};
#endif /* AI_CONFIG_HPP */

254
src/ai/ai_core.cpp Normal file
View File

@@ -0,0 +1,254 @@
/* $Id$ */
/** @file ai_core.cpp Implementation of AI. */
#include "../stdafx.h"
#include "../openttd.h"
#include "../company_type.h"
#include "../company_base.h"
#include "../company_func.h"
#include "../debug.h"
#include "../network/network.h"
#include "../settings_type.h"
#include "../window_type.h"
#include "../window_func.h"
#include "../command_func.h"
#include "ai.hpp"
#include "ai_info.hpp"
#include "ai_scanner.hpp"
#include "ai_instance.hpp"
#include "ai_config.hpp"
/* static */ uint AI::frame_counter = 0;
/* static */ AIScanner *AI::ai_scanner = NULL;
/* static */ bool AI::CanStartNew()
{
/* Only allow new AIs on the server and only when that is allowed in multiplayer */
return !_networking || (_network_server && _settings_game.ai.ai_in_multiplayer);
}
/* static */ void AI::StartNew(CompanyID company)
{
assert(IsValidCompanyID(company));
/* Clients shouldn't start AIs */
if (_networking && !_network_server) return;
AIInfo *info = AIConfig::GetConfig(company)->GetInfo();
if (info == NULL) {
info = AI::ai_scanner->SelectRandomAI();
assert(info != NULL);
/* Load default data and store the name in the settings */
AIConfig::GetConfig(company)->ChangeAI(info->GetDirName());
}
_current_company = company;
Company *c = GetCompany(company);
c->ai_info = info;
c->ai_instance = new AIInstance(info);
InvalidateWindowData(WC_AI_DEBUG, 0, -1);
return;
}
/* static */ void AI::GameLoop()
{
/* If we are in networking, only servers run this function, and that only if it is allowed */
if (_networking && (!_network_server || !_settings_game.ai.ai_in_multiplayer)) return;
/* The speed with which AIs go, is limited by the 'competitor_speed' */
AI::frame_counter++;
assert(_settings_game.difficulty.competitor_speed <= 4);
if ((AI::frame_counter & ((1 << (4 - _settings_game.difficulty.competitor_speed)) - 1)) != 0) return;
const Company *c;
FOR_ALL_COMPANIES(c) {
if (!IsHumanCompany(c->index)) {
_current_company = c->index;
c->ai_instance->GameLoop();
}
}
_current_company = OWNER_NONE;
}
/* static */ uint AI::GetTick()
{
return AI::frame_counter;
}
/* static */ void AI::Stop(CompanyID company)
{
if (_networking && !_network_server) return;
_current_company = company;
Company *c = GetCompany(company);
delete c->ai_instance;
c->ai_instance = NULL;
InvalidateWindowData(WC_AI_DEBUG, 0, -1);
}
/* static */ void AI::KillAll()
{
/* It might happen there are no companies .. than we have nothing to loop */
if (GetCompanyPoolSize() == 0) return;
const Company *c;
FOR_ALL_COMPANIES(c) {
if (!IsHumanCompany(c->index)) AI::Stop(c->index);
}
}
/* static */ void AI::Initialize()
{
if (AI::ai_scanner != NULL) AI::Uninitialize(true);
AI::frame_counter = 0;
if (AI::ai_scanner == NULL) AI::ai_scanner = new AIScanner();
}
/* static */ void AI::Uninitialize(bool keepConfig)
{
AI::KillAll();
if (keepConfig) {
/* Run a rescan, which indexes all AIInfos again, and check if we can
* still load all the AIS, while keeping the configs in place */
Rescan();
} else {
delete AI::ai_scanner;
AI::ai_scanner = NULL;
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
if (_settings_game.ai_config[c] != NULL) {
delete _settings_game.ai_config[c];
_settings_game.ai_config[c] = NULL;
}
if (_settings_newgame.ai_config[c] != NULL) {
delete _settings_newgame.ai_config[c];
_settings_newgame.ai_config[c] = NULL;
}
}
}
}
/* static */ void AI::ResetConfig()
{
/* Check for both newgame as current game if we can reload the AIInfo insde
* the AIConfig. If not, remove the AI from the list (which will assign
* a random new AI on reload). */
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
if (_settings_game.ai_config[c] != NULL && _settings_game.ai_config[c]->HasAI()) {
if (!_settings_game.ai_config[c]->ResetInfo()) {
DEBUG(ai, 0, "After a reload, the AI by the name '%s' was no longer found, and removed from the list.", _settings_game.ai_config[c]->GetName());
_settings_game.ai_config[c]->ChangeAI(NULL);
}
}
if (_settings_newgame.ai_config[c] != NULL && _settings_newgame.ai_config[c]->HasAI()) {
if (!_settings_newgame.ai_config[c]->ResetInfo()) {
DEBUG(ai, 0, "After a reload, the AI by the name '%s' was no longer found, and removed from the list.", _settings_newgame.ai_config[c]->GetName());
_settings_newgame.ai_config[c]->ChangeAI(NULL);
}
}
}
}
/* static */ void AI::NewEvent(CompanyID company, AIEvent *event)
{
/* Clients should ignore events */
if (_networking && !_network_server) return;
/* Only AIs can have an event-queue */
if (!IsValidCompanyID(company) || IsHumanCompany(company)) return;
/* Queue the event */
CompanyID old_company = _current_company;
_current_company = company;
AIEventController::InsertEvent(event);
_current_company = old_company;
}
/* static */ void AI::BroadcastNewEvent(AIEvent *event, CompanyID skip_company)
{
/* Clients should ignore events */
if (_networking && !_network_server) return;
/* Try to send the event to all AIs */
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
if (c != skip_company) AI::NewEvent(c, event);
}
}
void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
AIObject::SetLastCommandRes(success);
if (!success) {
AIObject::SetLastError(AIError::StringToError(_error_message));
} else {
AIObject::IncreaseDoCommandCosts(AIObject::GetLastCost());
}
GetCompany(_current_company)->ai_instance->Continue();
}
/* static */ void AI::Save(CompanyID company)
{
if (!_networking || _network_server) {
assert(IsValidCompanyID(company));
assert(GetCompany(company)->ai_instance != NULL);
CompanyID old_company = _current_company;
_current_company = company;
GetCompany(company)->ai_instance->Save();
_current_company = old_company;
} else {
AIInstance::SaveEmpty();
}
}
/* static */ void AI::Load(CompanyID company)
{
if (!_networking || _network_server) {
assert(IsValidCompanyID(company));
assert(GetCompany(company)->ai_instance != NULL);
CompanyID old_company = _current_company;
_current_company = company;
GetCompany(company)->ai_instance->Load();
_current_company = old_company;
} else {
/* Read, but ignore, the load data */
AIInstance::LoadEmpty();
}
}
/* static */ char *AI::GetConsoleList(char *p, const char *last)
{
return AI::ai_scanner->GetAIConsoleList(p, last);
}
/* static */ const AIInfoList *AI::GetInfoList()
{
return AI::ai_scanner->GetAIInfoList();
}
/* static */ AIInfo *AI::GetCompanyInfo(const char *name)
{
return AI::ai_scanner->FindAI(name);
}
/* static */ bool AI::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm)
{
return AI::ai_scanner->ImportLibrary(library, class_name, version, vm, GetCompany(_current_company)->ai_instance->GetController());
}
/* static */ void AI::Rescan()
{
AI::ai_scanner->RescanAIDir();
ResetConfig();
}

257
src/ai/ai_gui.cpp Normal file
View File

@@ -0,0 +1,257 @@
/* $Id$ */
/** @file ai_gui.cpp Window for configuring the AIs */
#include "../stdafx.h"
#include "../openttd.h"
#include "../gui.h"
#include "../window_gui.h"
#include "../company_func.h"
#include "../company_base.h"
#include "../company_gui.h"
#include "../economy_func.h"
#include "../variables.h"
#include "../cargotype.h"
#include "../strings_func.h"
#include "../core/alloc_func.hpp"
#include "../window_func.h"
#include "../date_func.h"
#include "../gfx_func.h"
#include "../debug.h"
#include "../command_func.h"
#include "../network/network.h"
#include "ai.hpp"
#include "api/ai_types.hpp"
#include "api/ai_controller.hpp"
#include "api/ai_object.hpp"
#include "api/ai_log.hpp"
#include "ai_info.hpp"
#include "table/strings.h"
#include "../table/sprites.h"
struct AIDebugWindow : public Window {
enum AIDebugWindowWidgets {
AID_WIDGET_CLOSEBOX = 0,
AID_WIDGET_CAPTION,
AID_WIDGET_VIEW,
AID_WIDGET_NAME_TEXT,
AID_WIDGET_RELOAD_TOGGLE,
AID_WIDGET_LOG_PANEL,
AID_WIDGET_SCROLLBAR,
AID_WIDGET_UNUSED_1,
AID_WIDGET_UNUSED_2,
AID_WIDGET_UNUSED_3,
AID_WIDGET_UNUSED_4,
AID_WIDGET_UNUSED_5,
AID_WIDGET_UNUSED_6,
AID_WIDGET_UNUSED_7,
AID_WIDGET_COMPANY_BUTTON_START,
AID_WIDGET_COMPANY_BUTTON_END = AID_WIDGET_COMPANY_BUTTON_START + 14,
};
static CompanyID ai_debug_company;
int redraw_timer;
AIDebugWindow(const WindowDesc *desc, WindowNumber number) : Window(desc, number)
{
/* Disable the companies who are not active or not an AI */
for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
this->SetWidgetDisabledState(i + AID_WIDGET_COMPANY_BUTTON_START, !IsValidCompanyID(i) || !GetCompany(i)->is_ai);
}
this->DisableWidget(AID_WIDGET_RELOAD_TOGGLE);
this->vscroll.cap = 14;
this->vscroll.pos = 0;
this->resize.step_height = 12;
if (ai_debug_company != INVALID_COMPANY) this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
this->FindWindowPlacementAndResize(desc);
}
virtual void OnPaint()
{
/* Check if the currently selected company is still active. */
if (ai_debug_company == INVALID_COMPANY || !IsValidCompanyID(ai_debug_company)) {
if (ai_debug_company != INVALID_COMPANY) {
/* Raise and disable the widget for the previous selection. */
this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
this->DisableWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
ai_debug_company = INVALID_COMPANY;
}
for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
if (IsValidCompanyID(i) && GetCompany(i)->is_ai) {
/* Lower the widget corresponding to this company. */
this->LowerWidget(i + AID_WIDGET_COMPANY_BUTTON_START);
ai_debug_company = i;
break;
}
}
}
/* Update "Reload AI" button */
this->SetWidgetDisabledState(AID_WIDGET_RELOAD_TOGGLE, ai_debug_company == INVALID_COMPANY);
/* Draw standard stuff */
this->DrawWidgets();
/* If there are no active companies, don't display anything else. */
if (ai_debug_company == INVALID_COMPANY) return;
/* Paint the company icons */
for (CompanyID i = COMPANY_FIRST; i < MAX_COMPANIES; i++) {
if (!IsValidCompanyID(i) || !GetCompany(i)->is_ai) {
/* Check if we have the company as an active company */
if (!this->IsWidgetDisabled(i + AID_WIDGET_COMPANY_BUTTON_START)) {
/* Bah, company gone :( */
this->DisableWidget(i + AID_WIDGET_COMPANY_BUTTON_START);
/* We need a repaint */
this->SetDirty();
}
continue;
}
/* Check if we have the company marked as inactive */
if (this->IsWidgetDisabled(i + AID_WIDGET_COMPANY_BUTTON_START)) {
/* New AI! Yippie :p */
this->EnableWidget(i + AID_WIDGET_COMPANY_BUTTON_START);
/* We need a repaint */
this->SetDirty();
}
byte x = (i == ai_debug_company) ? 1 : 0;
DrawCompanyIcon(i, (i % 8) * 37 + 13 + x, (i < 8 ? 0 : 13) + 16 + x);
}
/* Draw the AI name */
AIInfo *info = GetCompany(ai_debug_company)->ai_info;
assert(info != NULL);
DoDrawString(info->GetName(), 7, 47, TC_BLACK);
CompanyID old_company = _current_company;
_current_company = ai_debug_company;
AILog::LogData *log = (AILog::LogData *)AIObject::GetLogPointer();
_current_company = old_company;
SetVScrollCount(this, (log == NULL) ? 0 : log->used);
this->InvalidateWidget(AID_WIDGET_SCROLLBAR);
if (log == NULL) return;
int y = 6;
for (int i = this->vscroll.pos; i < (this->vscroll.cap + this->vscroll.pos); i++) {
uint pos = (log->count + log->pos - i) % log->count;
if (log->lines[pos] == NULL) break;
uint colour;
switch (log->type[pos]) {
case AILog::LOG_SQ_INFO: colour = TC_BLACK; break;
case AILog::LOG_SQ_ERROR: colour = TC_RED; break;
case AILog::LOG_INFO: colour = TC_BLACK; break;
case AILog::LOG_WARNING: colour = TC_YELLOW; break;
case AILog::LOG_ERROR: colour = TC_RED; break;
default: colour = TC_BLACK; break;
}
DoDrawStringTruncated(log->lines[pos], 7, this->widget[AID_WIDGET_LOG_PANEL].top + y, colour, this->widget[AID_WIDGET_LOG_PANEL].right - this->widget[AID_WIDGET_LOG_PANEL].left - 14);
y += 12;
}
}
virtual void OnClick(Point pt, int widget)
{
/* Check which button is clicked */
if (IsInsideMM(widget, AID_WIDGET_COMPANY_BUTTON_START, AID_WIDGET_COMPANY_BUTTON_END + 1)) {
/* Is it no on disable? */
if (!this->IsWidgetDisabled(widget)) {
this->RaiseWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
ai_debug_company = (CompanyID)(widget - AID_WIDGET_COMPANY_BUTTON_START);
this->LowerWidget(ai_debug_company + AID_WIDGET_COMPANY_BUTTON_START);
this->SetDirty();
}
}
if (widget == AID_WIDGET_RELOAD_TOGGLE && !this->IsWidgetDisabled(widget)) {
/* First kill the company of the AI, then start a new one. This should start the current AI again */
DoCommandP(0, 2, ai_debug_company, CMD_COMPANY_CTRL);
DoCommandP(0, 1, 0, CMD_COMPANY_CTRL);
}
}
virtual void OnTimeout()
{
this->RaiseWidget(AID_WIDGET_RELOAD_TOGGLE);
this->SetDirty();
}
virtual void OnInvalidateData(int data = 0)
{
if (data == -1 || ai_debug_company == data) this->SetDirty();
}
virtual void OnResize(Point new_size, Point delta)
{
this->vscroll.cap += delta.y / (int)this->resize.step_height;
}
};
CompanyID AIDebugWindow::ai_debug_company = INVALID_COMPANY;
static const Widget _ai_debug_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, COLOUR_GREY, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // AID_WIDGET_CLOSEBOX
{ WWT_CAPTION, RESIZE_RIGHT, COLOUR_GREY, 11, 298, 0, 13, STR_AI_DEBUG, STR_018C_WINDOW_TITLE_DRAG_THIS}, // AID_WIDGET_CAPTION
{ WWT_PANEL, RESIZE_RIGHT, COLOUR_GREY, 0, 298, 14, 40, 0x0, STR_NULL}, // AID_WIDGET_VIEW
{ WWT_PANEL, RESIZE_RIGHT, COLOUR_GREY, 0, 149, 41, 60, 0x0, STR_AI_DEBUG_NAME_TIP}, // AID_WIDGET_NAME_TEXT
{ WWT_PUSHTXTBTN, RESIZE_LR, COLOUR_GREY, 150, 298, 41, 60, STR_AI_DEBUG_RELOAD, STR_AI_DEBUG_RELOAD_TIP}, // AID_WIDGET_RELOAD_TOGGLE
{ WWT_PANEL, RESIZE_RB, COLOUR_GREY, 0, 286, 61, 240, 0x0, STR_NULL}, // AID_WIDGET_LOG_PANEL
{ WWT_SCROLLBAR, RESIZE_LRB, COLOUR_GREY, 287, 298, 61, 228, STR_NULL, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // AID_WIDGET_SCROLLBAR
/* As this is WIP, leave the next few so we can work a bit with the GUI */
{ WWT_EMPTY, RESIZE_NONE, COLOUR_GREY, 0, 298, 101, 120, 0x0, STR_NULL}, // AID_WIDGET_UNUSED_1
{ WWT_EMPTY, RESIZE_NONE, COLOUR_GREY, 0, 298, 121, 140, 0x0, STR_NULL}, // AID_WIDGET_UNUSED_2
{ WWT_EMPTY, RESIZE_NONE, COLOUR_GREY, 0, 298, 141, 160, 0x0, STR_NULL}, // AID_WIDGET_UNUSED_3
{ WWT_EMPTY, RESIZE_NONE, COLOUR_GREY, 0, 298, 161, 180, 0x0, STR_NULL}, // AID_WIDGET_UNUSED_4
{ WWT_EMPTY, RESIZE_NONE, COLOUR_GREY, 0, 298, 181, 200, 0x0, STR_NULL}, // AID_WIDGET_UNUSED_5
{ WWT_EMPTY, RESIZE_NONE, COLOUR_GREY, 0, 298, 201, 220, 0x0, STR_NULL}, // AID_WIDGET_UNUSED_6
{ WWT_EMPTY, RESIZE_NONE, COLOUR_GREY, 0, 298, 221, 240, 0x0, STR_NULL}, // AID_WIDGET_UNUSED_7
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 2, 38, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, // AID_WIDGET_COMPANY_BUTTON_START
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 39, 75, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 76, 112, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 113, 149, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 150, 186, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 187, 223, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 224, 260, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 261, 297, 14, 26, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 2, 38, 27, 39, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 39, 75, 27, 39, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 76, 112, 27, 39, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 113, 149, 27, 39, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 150, 186, 27, 39, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 187, 223, 27, 39, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY},
{ WWT_PANEL, RESIZE_NONE, COLOUR_GREY, 224, 260, 27, 39, 0x0, STR_704F_CLICK_HERE_TO_TOGGLE_COMPANY}, // AID_WIDGET_COMPANY_BUTTON_END
{ WWT_RESIZEBOX, RESIZE_LRTB, COLOUR_GREY, 287, 298, 229, 240, STR_NULL, STR_RESIZE_BUTTON},
{ WIDGETS_END},
};
static const WindowDesc _ai_debug_desc = {
WDP_AUTO, WDP_AUTO, 299, 241, 299, 241,
WC_AI_DEBUG, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
_ai_debug_widgets
};
void ShowAIDebugWindow()
{
if (!_networking || _network_server) {
AllocateWindowDescFront<AIDebugWindow>(&_ai_debug_desc, 0);
} else {
ShowErrorMessage(INVALID_STRING_ID, STR_AI_DEBUG_SERVER_ONLY, 0, 0);
}
}

10
src/ai/ai_gui.hpp Normal file
View File

@@ -0,0 +1,10 @@
/* $Id$ */
/** @file ai_gui.hpp Window for configuring the AIs */
#ifndef AI_GUI_HPP
#define AI_GUI_HPP
void ShowAIDebugWindow();
#endif /* AI_GUI_HPP */

319
src/ai/ai_info.cpp Normal file
View File

@@ -0,0 +1,319 @@
/* $Id$ */
/** @file ai_info.cpp Implementation of AIFileInfo */
#include "../stdafx.h"
#include "../core/alloc_func.hpp"
#include <squirrel.h>
#include "../script/squirrel.hpp"
#include "../script/squirrel_helper.hpp"
#include "../script/squirrel_class.hpp"
#include "../script/squirrel_std.hpp"
#include "ai.hpp"
#include "ai_info.hpp"
#include "ai_scanner.hpp"
#include "api/ai_controller.hpp"
#include "../settings_type.h"
#include "../openttd.h"
AIFileInfo::~AIFileInfo()
{
this->engine->ReleaseObject(this->SQ_instance);
free((void *)this->author);
free((void *)this->name);
free((void *)this->description);
free((void *)this->date);
free((void *)this->instance_name);
free(this->script_name);
free(this->dir_name);
free(this->SQ_instance);
}
const char *AIFileInfo::GetAuthor()
{
if (this->author == NULL) this->author = this->engine->CallStringMethodStrdup(*this->SQ_instance, "GetAuthor");
return this->author;
}
const char *AIFileInfo::GetName()
{
if (this->name == NULL) this->name = this->engine->CallStringMethodStrdup(*this->SQ_instance, "GetName");
return this->name;
}
const char *AIFileInfo::GetDescription()
{
if (this->description == NULL) this->description = this->engine->CallStringMethodStrdup(*this->SQ_instance, "GetDescription");
return this->description;
}
int AIFileInfo::GetVersion()
{
return this->engine->CallIntegerMethod(*this->SQ_instance, "GetVersion");
}
void AIFileInfo::GetSettings()
{
this->engine->CallMethod(*this->SQ_instance, "GetSettings", NULL, -1);
}
const char *AIFileInfo::GetDate()
{
if (this->date == NULL) this->date = this->engine->CallStringMethodStrdup(*this->SQ_instance, "GetDate");
return this->date;
}
const char *AIFileInfo::GetInstanceName()
{
if (this->instance_name == NULL) this->instance_name = this->engine->CallStringMethodStrdup(*this->SQ_instance, "CreateInstance");
return this->instance_name;
}
bool AIFileInfo::AllowStartup()
{
return true;
}
const char *AIFileInfo::GetDirName()
{
return this->dir_name;
}
const char *AIFileInfo::GetScriptName()
{
return this->script_name;
}
void AIFileInfo::CheckMethods(SQInteger *res, const char *name)
{
if (!this->engine->MethodExists(*this->SQ_instance, name)) {
char error[1024];
snprintf(error, sizeof(error), "your AIFileInfo doesn't have the method '%s'", name);
this->engine->ThrowError(error);
*res = SQ_ERROR;
}
}
/* static */ SQInteger AIFileInfo::Constructor(HSQUIRRELVM vm, AIFileInfo *info)
{
SQInteger res = 0;
/* Set some basic info from the parent */
info->SQ_instance = MallocT<SQObject>(1);
Squirrel::GetInstance(vm, info->SQ_instance, 2);
/* Make sure the instance stays alive over time */
sq_addref(vm, info->SQ_instance);
info->base = ((AIScanner *)Squirrel::GetGlobalPointer(vm));
info->engine = info->base->GetEngine();
/* Check if all needed fields are there */
info->CheckMethods(&res, "GetAuthor");
info->CheckMethods(&res, "GetName");
info->CheckMethods(&res, "GetDescription");
info->CheckMethods(&res, "GetVersion");
info->CheckMethods(&res, "GetDate");
info->CheckMethods(&res, "CreateInstance");
/* Abort if one method was missing */
if (res != 0) return res;
info->script_name = strdup(info->base->GetCurrentScript());
info->dir_name = strdup(info->base->GetCurrentDirName());
return 0;
}
/* static */ SQInteger AIInfo::Constructor(HSQUIRRELVM vm)
{
/* Get the AIInfo */
SQUserPointer instance;
sq_getinstanceup(vm, 2, &instance, 0);
AIInfo *info = (AIInfo *)instance;
SQInteger res = AIFileInfo::Constructor(vm, info);
if (res != 0) return res;
AIConfigItem config;
config.name = strdup("start_date");
config.description = strdup("The amount of months after the start of the last AI, this AI will start (give or take).");
config.min_value = 0;
config.max_value = 120;
config.easy_value = 48;
config.medium_value = 24;
config.hard_value = 12;
config.custom_value = 24;
config.flags = AICONFIG_NONE;
info->config_list.push_back(config);
/* Check if we have settings */
if (info->engine->MethodExists(*info->SQ_instance, "GetSettings")) {
info->GetSettings();
}
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, NULL);
/* Register the AI to the base system */
info->base->RegisterAI(info);
return 0;
}
/* static */ SQInteger AIInfo::DummyConstructor(HSQUIRRELVM vm)
{
/* Get the AIInfo */
SQUserPointer instance;
sq_getinstanceup(vm, 2, &instance, 0);
AIInfo *info = (AIInfo *)instance;
SQInteger res = AIFileInfo::Constructor(vm, info);
if (res != 0) return res;
/* Remove the link to the real instance, else it might get deleted by RegisterAI() */
sq_setinstanceup(vm, 2, NULL);
/* Register the AI to the base system */
info->base->SetDummyAI(info);
return 0;
}
AIInfo::~AIInfo()
{
/* Free all allocated strings */
for (AIConfigItemList::iterator it = this->config_list.begin(); it != this->config_list.end(); it++) {
free((char *)(*it).name);
}
this->config_list.clear();
}
SQInteger AIInfo::AddSetting(HSQUIRRELVM vm)
{
AIConfigItem config;
memset(&config, 0, sizeof(config));
int items = 0;
/* Read the table, and find all properties we care about */
sq_pushnull(vm);
while (SQ_SUCCEEDED(sq_next(vm, -2))) {
const SQChar *sqkey;
sq_getstring(vm, -2, &sqkey);
const char *key = FS2OTTD(sqkey);
if (strcmp(key, "name") == 0) {
const SQChar *sqvalue;
sq_getstring(vm, -1, &sqvalue);
config.name = strdup(FS2OTTD(sqvalue));
char *s;
/* Don't allow '=' and ',' in configure setting names, as we need those
* 2 chars to nicely store the settings as a string. */
while ((s = (char *)strchr(config.name, '=')) != NULL) *s = '_';
while ((s = (char *)strchr(config.name, ',')) != NULL) *s = '_';
items |= 0x001;
} else if (strcmp(key, "description") == 0) {
const SQChar *sqdescription;
sq_getstring(vm, -1, &sqdescription);
config.description = strdup(FS2OTTD(sqdescription));
items |= 0x002;
} else if (strcmp(key, "min_value") == 0) {
SQInteger res;
sq_getinteger(vm, -1, &res);
config.min_value = res;
items |= 0x004;
} else if (strcmp(key, "max_value") == 0) {
SQInteger res;
sq_getinteger(vm, -1, &res);
config.max_value = res;
items |= 0x008;
} else if (strcmp(key, "easy_value") == 0) {
SQInteger res;
sq_getinteger(vm, -1, &res);
config.easy_value = res;
items |= 0x010;
} else if (strcmp(key, "medium_value") == 0) {
SQInteger res;
sq_getinteger(vm, -1, &res);
config.medium_value = res;
items |= 0x020;
} else if (strcmp(key, "hard_value") == 0) {
SQInteger res;
sq_getinteger(vm, -1, &res);
config.hard_value = res;
items |= 0x040;
} else if (strcmp(key, "custom_value") == 0) {
SQInteger res;
sq_getinteger(vm, -1, &res);
config.custom_value = res;
items |= 0x080;
} else if (strcmp(key, "flags") == 0) {
SQInteger res;
sq_getinteger(vm, -1, &res);
config.flags = (AIConfigFlags)res;
items |= 0x100;
} else {
char error[1024];
snprintf(error, sizeof(error), "unknown setting property '%s'", key);
this->engine->ThrowError(error);
return SQ_ERROR;
}
sq_pop(vm, 2);
}
sq_pop(vm, 1);
/* Make sure all properties are defined */
if (items != 0x1FF) {
char error[1024];
snprintf(error, sizeof(error), "please define all properties of a setting");
this->engine->ThrowError(error);
return SQ_ERROR;
}
this->config_list.push_back(config);
return 0;
}
const AIConfigItemList *AIInfo::GetConfigList()
{
return &this->config_list;
}
int AIInfo::GetSettingDefaultValue(const char *name)
{
for (AIConfigItemList::iterator it = this->config_list.begin(); it != this->config_list.end(); it++) {
if (strcmp((*it).name, name) != 0) continue;
/* The default value depends on the difficulty level */
switch ((_game_mode == GM_MENU) ? _settings_newgame.difficulty.diff_level : _settings_game.difficulty.diff_level) {
case 0: return (*it).easy_value;
case 1: return (*it).medium_value;
case 2: return (*it).hard_value;
case 3: return (*it).custom_value;
default: NOT_REACHED();
}
}
/* There is no such setting */
return -1;
}
/* static */ SQInteger AILibrary::Constructor(HSQUIRRELVM vm)
{
/* Create a new AIFileInfo */
AILibrary *library = new AILibrary();
SQInteger res = AIFileInfo::Constructor(vm, library);
if (res != 0) return res;
/* Register the Library to the base system */
library->base->RegisterLibrary(library);
return 0;
}
/* static */ SQInteger AILibrary::Import(HSQUIRRELVM vm)
{
SQConvert::SQAutoFreePointers ptr;
const char *library = GetParam(SQConvert::ForceType<const char *>(), vm, 2, &ptr);
const char *class_name = GetParam(SQConvert::ForceType<const char *>(), vm, 3, &ptr);
int version = GetParam(SQConvert::ForceType<int>(), vm, 4, &ptr);
if (!AI::ImportLibrary(library, class_name, version, vm)) return -1;
return 1;
}

153
src/ai/ai_info.hpp Normal file
View File

@@ -0,0 +1,153 @@
/* $Id$ */
/** @file ai_info.hpp AIInfo keeps track of all information of an AI, like Author, Description, ... */
#ifndef AI_INFO
#define AI_INFO
#include <list>
#include "api/ai_object.hpp"
enum AIConfigFlags {
AICONFIG_NONE = 0x0,
AICONFIG_RANDOM = 0x1, //!< When randomizing the AI, pick any value between min_value and max_value when on custom difficulty setting.
AICONFIG_BOOLEAN = 0x2, //!< This value is a boolean (either 0 (false) or 1 (true) ).
};
struct AIConfigItem {
const char *name; //!< The name of the configuration setting.
const char *description; //!< The description of the configuration setting.
int min_value; //!< The minimal value this configuration setting can have.
int max_value; //!< The maximal value this configuration setting can have.
int custom_value; //!< The default value on custom difficulty setting.
int easy_value; //!< The default value on easy difficulty setting.
int medium_value; //!< The default value on medium difficulty setting.
int hard_value; //!< The default value on hard difficulty setting.
AIConfigFlags flags; //!< Flags for the configuration setting.
};
typedef std::list<AIConfigItem> AIConfigItemList;
class AIFileInfo : public AIObject {
public:
friend class AIInfo;
friend class AILibrary;
AIFileInfo() : author(NULL), name(NULL), description(NULL), date(NULL), instance_name(NULL) {};
~AIFileInfo();
/**
* Get the Author of the AI.
*/
const char *GetAuthor();
/**
* Get the Name of the AI.
*/
const char *GetName();
/**
* Get the description of the AI.
*/
const char *GetDescription();
/**
* Get the version of the AI.
*/
int GetVersion();
/**
* Get the settings of the AI.
*/
void GetSettings();
/**
* Get the date of the AI.
*/
const char *GetDate();
/**
* Get the name of the instance of the AI to create.
*/
const char *GetInstanceName();
/**
* Check if we can start this AI.
*/
bool AllowStartup();
/**
* Get the name of the dir this AI is in.
*/
const char *GetDirName();
/**
* Get the complete script name of this AI.
*/
const char *GetScriptName();
/**
* Check if a given method exists.
*/
void CheckMethods(SQInteger *res, const char *name);
/**
* Process the creation of a FileInfo object.
*/
static SQInteger Constructor(HSQUIRRELVM vm, AIFileInfo *info);
private:
class Squirrel *engine;
HSQOBJECT *SQ_instance;
char *script_name;
char *dir_name;
class AIScanner *base;
const char *author;
const char *name;
const char *description;
const char *date;
const char *instance_name;
};
class AIInfo : public AIFileInfo {
public:
static const char *GetClassName() { return "AIInfo"; }
~AIInfo();
/**
* Create an AI, using this AIInfo as start-template.
*/
static SQInteger Constructor(HSQUIRRELVM vm);
static SQInteger DummyConstructor(HSQUIRRELVM vm);
/**
* Get the config list for this AI.
*/
const AIConfigItemList *GetConfigList();
/**
* Set a setting.
*/
SQInteger AddSetting(HSQUIRRELVM vm);
/**
* Get the default value for a setting.
*/
int GetSettingDefaultValue(const char *name);
private:
AIConfigItemList config_list;
};
class AILibrary : public AIFileInfo {
public:
/**
* Create an AI, using this AIInfo as start-template.
*/
static SQInteger Constructor(HSQUIRRELVM vm);
static SQInteger Import(HSQUIRRELVM vm);
};
#endif /* AI_INFO */

66
src/ai/ai_info_dummy.cpp Normal file
View File

@@ -0,0 +1,66 @@
/* $Id$ */
#include <squirrel.h>
#include "../stdafx.h"
/* The reason this exists in C++, is that a user can trash his ai/ dir,
* leaving no AIs available. The complexity to solve this is insane, and
* therefor the alternative is used, and make sure there is always an AI
* available, no matter what the situation is. By defining it in C++, there
* is simply now way a user can delete it, and therefor safe to use. It has
* to be noted that this AI is complete invisible for the user, and impossible
* to select manual. It is a fail-over in case no AIs are available.
*/
const SQChar dummy_script_info[] = _SC(" \n\
class DummyAI extends AIInfo { \n\
function GetAuthor() { return \"OpenTTD NoAI Developers Team\"; } \n\
function GetName() { return \"DummyAI\"; } \n\
function GetDescription() { return \"A Dummy AI that is loaded when your ai/ dir is empty\"; }\n\
function GetVersion() { return 1; } \n\
function GetDate() { return \"2008-07-26\"; } \n\
function CreateInstance() { return \"DummyAI\"; } \n\
} \n\
\n\
RegisterDummyAI(DummyAI()); \n\
");
const SQChar dummy_script[] = _SC(" \n\
class DummyAI extends AIController { \n\
function Start() { \n\
AILog.Error(\"No suitable AI found to load.\"); \n\
AILog.Error(\"This AI is a dummy AI and won't do anything.\"); \n\
AILog.Error(\"Please add one or several AIs in your ai/ directory.\"); \n\
} \n\
} \n\
");
void AI_CreateAIInfoDummy(HSQUIRRELVM vm)
{
sq_pushroottable(vm);
/* Load and run the script */
if (SQ_SUCCEEDED(sq_compilebuffer(vm, dummy_script_info, scstrlen(dummy_script_info), _SC("dummy"), SQTrue))) {
sq_push(vm, -2);
if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) {
sq_pop(vm, 1);
return;
}
}
NOT_REACHED();
}
void AI_CreateAIDummy(HSQUIRRELVM vm)
{
sq_pushroottable(vm);
/* Load and run the script */
if (SQ_SUCCEEDED(sq_compilebuffer(vm, dummy_script, scstrlen(dummy_script), _SC("dummy"), SQTrue))) {
sq_push(vm, -2);
if (SQ_SUCCEEDED(sq_call(vm, 1, SQFalse, SQTrue))) {
sq_pop(vm, 1);
return;
}
}
NOT_REACHED();
}

628
src/ai/ai_instance.cpp Normal file
View File

@@ -0,0 +1,628 @@
/* $Id$ */
/** @file ai_instance.cpp Implementation of AIInstance. */
#include "../stdafx.h"
#include "../openttd.h"
#include "../debug.h"
#include "../company_func.h"
#include "../core/alloc_func.hpp"
#include "../string_func.h"
#include "../settings_type.h"
#include "../company_base.h"
#include "../saveload/saveload.h"
#include "table/strings.h"
#include <squirrel.h>
#include "../script/squirrel.hpp"
#include "../script/squirrel_helper.hpp"
#include "../script/squirrel_class.hpp"
#include "../script/squirrel_std.hpp"
#include "ai.hpp"
#include "api/ai_controller.hpp"
#include "ai_info.hpp"
#include "ai_storage.hpp"
#include "ai_instance.hpp"
/* Convert all AI related classes to Squirrel data.
* Note: this line a marker in squirrel_export.sh. Do not change! */
#include "api/ai_abstractlist.hpp.sq"
#include "api/ai_accounting.hpp.sq"
#include "api/ai_airport.hpp.sq"
#include "api/ai_base.hpp.sq"
#include "api/ai_bridge.hpp.sq"
#include "api/ai_bridgelist.hpp.sq"
#include "api/ai_cargo.hpp.sq"
#include "api/ai_cargolist.hpp.sq"
#include "api/ai_company.hpp.sq"
#include "api/ai_controller.hpp.sq"
#include "api/ai_date.hpp.sq"
#include "api/ai_depotlist.hpp.sq"
#include "api/ai_engine.hpp.sq"
#include "api/ai_enginelist.hpp.sq"
#include "api/ai_error.hpp.sq"
#include "api/ai_event.hpp.sq"
#include "api/ai_event_types.hpp.sq"
#include "api/ai_execmode.hpp.sq"
#include "api/ai_gamesettings.hpp.sq"
#include "api/ai_group.hpp.sq"
#include "api/ai_grouplist.hpp.sq"
#include "api/ai_industry.hpp.sq"
#include "api/ai_industrylist.hpp.sq"
#include "api/ai_industrytype.hpp.sq"
#include "api/ai_industrytypelist.hpp.sq"
#include "api/ai_list.hpp.sq"
#include "api/ai_log.hpp.sq"
#include "api/ai_map.hpp.sq"
#include "api/ai_marine.hpp.sq"
#include "api/ai_order.hpp.sq"
#include "api/ai_rail.hpp.sq"
#include "api/ai_railtypelist.hpp.sq"
#include "api/ai_road.hpp.sq"
#include "api/ai_sign.hpp.sq"
#include "api/ai_station.hpp.sq"
#include "api/ai_stationlist.hpp.sq"
#include "api/ai_subsidy.hpp.sq"
#include "api/ai_subsidylist.hpp.sq"
#include "api/ai_testmode.hpp.sq"
#include "api/ai_tile.hpp.sq"
#include "api/ai_tilelist.hpp.sq"
#include "api/ai_town.hpp.sq"
#include "api/ai_townlist.hpp.sq"
#include "api/ai_tunnel.hpp.sq"
#include "api/ai_vehicle.hpp.sq"
#include "api/ai_vehiclelist.hpp.sq"
/* static */ AIInstance *AIInstance::current_instance = NULL;
AIStorage::~AIStorage()
{
/* Free our pointers */
if (event_data != NULL) AIEventController::FreeEventPointer();
if (log_data != NULL) AILog::FreeLogPointer();
}
static void PrintFunc(bool error_msg, const SQChar *message)
{
/* Convert to OpenTTD internal capable string */
AIController::Print(error_msg, FS2OTTD(message));
}
AIInstance::AIInstance(AIInfo *info) :
controller(NULL),
storage(NULL),
engine(NULL),
instance(NULL),
is_started(false),
is_dead(false),
suspend(0),
callback(NULL)
{
/* Set the instance already, so we can use AIObject::Set commands */
GetCompany(_current_company)->ai_instance = this;
AIInstance::current_instance = this;
this->controller = new AIController();
this->storage = new AIStorage();
this->engine = new Squirrel();
this->engine->SetPrintFunction(&PrintFunc);
/* The import method is available at a very early stage */
this->engine->AddMethod("import", &AILibrary::Import, 4, "?ssi");
/* Register the AIController */
SQAIController_Register(this->engine);
/* Load and execute the script for this AI */
const char *script_name = info->GetScriptName();
if (strcmp(script_name, "%_dummy") == 0) {
extern void AI_CreateAIDummy(HSQUIRRELVM vm);
AI_CreateAIDummy(this->engine->GetVM());
} else if (!this->engine->LoadScript(script_name)) {
this->Died();
return;
}
/* Create the main-class */
this->instance = MallocT<SQObject>(1);
if (!this->engine->CreateClassInstance(info->GetInstanceName(), this->controller, this->instance)) {
this->Died();
return;
}
/* Register the API functions and classes */
this->RegisterAPI();
/* Run the constructor if it exists. Don't allow any DoCommands in it. */
if (this->engine->MethodExists(*this->instance, "constructor")) {
AIObject::SetAllowDoCommand(false);
this->engine->CallMethod(*this->instance, "constructor");
AIObject::SetAllowDoCommand(true);
}
}
AIInstance::~AIInstance()
{
if (engine != NULL) delete this->engine;
delete this->storage;
delete this->controller;
free(this->instance);
}
void AIInstance::RegisterAPI()
{
/* Register all classes */
squirrel_register_std(this->engine);
SQAIAbstractList_Register(this->engine);
SQAIAccounting_Register(this->engine);
SQAIAirport_Register(this->engine);
SQAIBase_Register(this->engine);
SQAIBridge_Register(this->engine);
SQAIBridgeList_Register(this->engine);
SQAIBridgeList_Length_Register(this->engine);
SQAICargo_Register(this->engine);
SQAICargoList_Register(this->engine);
SQAICargoList_IndustryAccepting_Register(this->engine);
SQAICargoList_IndustryProducing_Register(this->engine);
SQAICompany_Register(this->engine);
SQAIDate_Register(this->engine);
SQAIDepotList_Register(this->engine);
SQAIEngine_Register(this->engine);
SQAIEngineList_Register(this->engine);
SQAIError_Register(this->engine);
SQAIEvent_Register(this->engine);
SQAIEventCompanyBankrupt_Register(this->engine);
SQAIEventCompanyInTrouble_Register(this->engine);
SQAIEventCompanyMerger_Register(this->engine);
SQAIEventCompanyNew_Register(this->engine);
SQAIEventController_Register(this->engine);
SQAIEventEngineAvailable_Register(this->engine);
SQAIEventEnginePreview_Register(this->engine);
SQAIEventIndustryClose_Register(this->engine);
SQAIEventIndustryOpen_Register(this->engine);
SQAIEventStationFirstVehicle_Register(this->engine);
SQAIEventSubsidyAwarded_Register(this->engine);
SQAIEventSubsidyExpired_Register(this->engine);
SQAIEventSubsidyOffer_Register(this->engine);
SQAIEventSubsidyOfferExpired_Register(this->engine);
SQAIEventTest_Register(this->engine);
SQAIEventVehicleCrashed_Register(this->engine);
SQAIEventVehicleLost_Register(this->engine);
SQAIEventVehicleUnprofitable_Register(this->engine);
SQAIEventVehicleWaitingInDepot_Register(this->engine);
SQAIExecMode_Register(this->engine);
SQAIGameSettings_Register(this->engine);
SQAIGroup_Register(this->engine);
SQAIGroupList_Register(this->engine);
SQAIIndustry_Register(this->engine);
SQAIIndustryList_Register(this->engine);
SQAIIndustryList_CargoAccepting_Register(this->engine);
SQAIIndustryList_CargoProducing_Register(this->engine);
SQAIIndustryType_Register(this->engine);
SQAIIndustryTypeList_Register(this->engine);
SQAIList_Register(this->engine);
SQAILog_Register(this->engine);
SQAIMap_Register(this->engine);
SQAIMarine_Register(this->engine);
SQAIOrder_Register(this->engine);
SQAIRail_Register(this->engine);
SQAIRailTypeList_Register(this->engine);
SQAIRoad_Register(this->engine);
SQAISign_Register(this->engine);
SQAIStation_Register(this->engine);
SQAIStationList_Register(this->engine);
SQAIStationList_Vehicle_Register(this->engine);
SQAISubsidy_Register(this->engine);
SQAISubsidyList_Register(this->engine);
SQAITestMode_Register(this->engine);
SQAITile_Register(this->engine);
SQAITileList_Register(this->engine);
SQAITileList_IndustryAccepting_Register(this->engine);
SQAITileList_IndustryProducing_Register(this->engine);
SQAITileList_StationType_Register(this->engine);
SQAITown_Register(this->engine);
SQAITownList_Register(this->engine);
SQAITunnel_Register(this->engine);
SQAIVehicle_Register(this->engine);
SQAIVehicleList_Register(this->engine);
SQAIVehicleList_Station_Register(this->engine);
this->engine->SetGlobalPointer(this->engine);
}
void AIInstance::Continue()
{
assert(this->suspend < 0);
this->suspend = -this->suspend - 1;
}
void AIInstance::Died()
{
DEBUG(ai, 0, "The AI died unexpectedly.");
this->is_dead = true;
delete this->engine;
this->engine = NULL;
}
void AIInstance::GameLoop()
{
if (this->is_dead) return;
this->controller->ticks++;
if (this->suspend < -1) this->suspend++; // Multiplayer suspend, increase up to -1.
if (this->suspend < 0) return; // Multiplayer suspend, wait for Continue().
if (--this->suspend > 0) return; // Singleplayer suspend, decrease to 0.
/* If there is a callback to call, call that first */
if (this->callback != NULL) {
try {
this->callback(this);
} catch (AI_VMSuspend e) {
this->suspend = e.GetSuspendTime();
this->callback = e.GetSuspendCallback();
return;
}
}
this->suspend = 0;
this->callback = NULL;
if (!this->is_started) {
/* Start the AI by calling Start() */
try {
if (!this->engine->CallMethod(*this->instance, "Start", _settings_game.ai.ai_max_opcode_till_suspend)) this->Died();
} catch (AI_VMSuspend e) {
this->suspend = e.GetSuspendTime();
this->callback = e.GetSuspendCallback();
}
this->is_started = true;
return;
}
/* Continue the VM */
try {
if (!this->engine->Resume(_settings_game.ai.ai_max_opcode_till_suspend)) this->Died();
} catch (AI_VMSuspend e) {
this->suspend = e.GetSuspendTime();
this->callback = e.GetSuspendCallback();
}
}
/* static */ void AIInstance::DoCommandReturn(AIInstance *instance)
{
instance->engine->InsertResult(AIObject::GetLastCommandRes());
}
/* static */ void AIInstance::DoCommandReturnVehicleID(AIInstance *instance)
{
instance->engine->InsertResult(AIObject::GetNewVehicleID());
}
/* static */ void AIInstance::DoCommandReturnSignID(AIInstance *instance)
{
instance->engine->InsertResult(AIObject::GetNewSignID());
}
/* static */ void AIInstance::DoCommandReturnGroupID(AIInstance *instance)
{
instance->engine->InsertResult(AIObject::GetNewGroupID());
}
/* static */ AIStorage *AIInstance::GetStorage()
{
assert(IsValidCompanyID(_current_company) && !IsHumanCompany(_current_company));
return GetCompany(_current_company)->ai_instance->storage;
}
/*
* All data is stored in the following format:
* First 1 byte indicating if there is a data blob at all.
* 1 byte indicating the type of data.
* The data itself, this differs per type:
* - integer: a binary representation of the integer (int32).
* - string: First one byte with the string length, then a 0-terminated char
* array. The string can't be longer then 255 bytes (including
* terminating '\0').
* - array: All data-elements of the array are saved recursive in this
* format, and ended with an element of the type
* SQSL_ARRAY_TABLE_END.
* - table: All key/value pairs are saved in this format (first key 1, then
* value 1, then key 2, etc.). All keys and values can have an
* arbitrary type (as long as it is supported by the save function
* of course). The table is ended with an element of the type
* SQSL_ARRAY_TABLE_END.
* - bool: A single byte with value 1 representing true and 0 false.
* - null: No data.
*/
/** The type of the data that follows in the savegame. */
enum SQSaveLoadType {
SQSL_INT = 0x00, ///< The following data is an integer.
SQSL_STRING = 0x01, ///< The following data is an string.
SQSL_ARRAY = 0x02, ///< The following data is an array.
SQSL_TABLE = 0x03, ///< The following data is an table.
SQSL_BOOL = 0x04, ///< The following data is a boolean.
SQSL_NULL = 0x05, ///< A null variable.
SQSL_ARRAY_TABLE_END = 0xFF, ///< Marks the end of an array or table, no data follows.
};
static byte _ai_sl_byte;
static const SaveLoad _ai_byte[] = {
SLEG_VAR(_ai_sl_byte, SLE_UINT8),
SLE_END()
};
enum {
AISAVE_MAX_DEPTH = 25, ///< The maximum recursive depth for items stored in the savegame.
};
/* static */ bool AIInstance::SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test)
{
if (max_depth == 0) {
AILog::Error("Savedata can only be nested to 5 deep. No data saved.");
return false;
}
switch (sq_gettype(vm, index)) {
case OT_INTEGER: {
if (!test) {
_ai_sl_byte = SQSL_INT;
SlObject(NULL, _ai_byte);
}
SQInteger res;
sq_getinteger(vm, index, &res);
if (!test) {
int value = (int)res;
SlArray(&value, 1, SLE_INT32);
}
return true;
}
case OT_STRING: {
if (!test) {
_ai_sl_byte = SQSL_STRING;
SlObject(NULL, _ai_byte);
}
const SQChar *res;
sq_getstring(vm, index, &res);
/* @bug if a string longer than 512 characters is given to FS2OTTD, the
* internal buffer overflows. */
const char *buf = FS2OTTD(res);
size_t len = strlen(buf) + 1;
if (len >= 255) {
AILog::Error("Maximum string length is 254 chars. No data saved.");
return false;
}
if (!test) {
_ai_sl_byte = (byte)len;
SlObject(NULL, _ai_byte);
SlArray((void*)buf, len, SLE_CHAR);
}
return true;
}
case OT_ARRAY: {
if (!test) {
_ai_sl_byte = SQSL_ARRAY;
SlObject(NULL, _ai_byte);
}
sq_pushnull(vm);
while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
/* Store the value */
bool res = SaveObject(vm, -1, max_depth - 1, test);
sq_pop(vm, 2);
if (!res) {
sq_pop(vm, 1);
return false;
}
}
sq_pop(vm, 1);
if (!test) {
_ai_sl_byte = SQSL_ARRAY_TABLE_END;
SlObject(NULL, _ai_byte);
}
return true;
}
case OT_TABLE: {
if (!test) {
_ai_sl_byte = SQSL_TABLE;
SlObject(NULL, _ai_byte);
}
sq_pushnull(vm);
while (SQ_SUCCEEDED(sq_next(vm, index - 1))) {
/* Store the key + value */
bool res = SaveObject(vm, -2, max_depth - 1, test) && SaveObject(vm, -1, max_depth - 1, test);
sq_pop(vm, 2);
if (!res) {
sq_pop(vm, 1);
return false;
}
}
sq_pop(vm, 1);
if (!test) {
_ai_sl_byte = SQSL_ARRAY_TABLE_END;
SlObject(NULL, _ai_byte);
}
return true;
}
case OT_BOOL: {
if (!test) {
_ai_sl_byte = SQSL_BOOL;
SlObject(NULL, _ai_byte);
}
SQBool res;
sq_getbool(vm, index, &res);
if (!test) {
_ai_sl_byte = res ? 1 : 0;
SlObject(NULL, _ai_byte);
}
return true;
}
case OT_NULL: {
if (!test) {
_ai_sl_byte = SQSL_NULL;
SlObject(NULL, _ai_byte);
}
return true;
}
default:
AILog::Error("You tried to save unsupported type. No data saved.");
return false;
}
}
/* static */ void AIInstance::SaveEmpty()
{
_ai_sl_byte = 0;
SlObject(NULL, _ai_byte);
}
void AIInstance::Save()
{
/* Don't save data if the AI didn't start yet. */
if (this->engine == NULL) {
SaveEmpty();
return;
}
/* We don't want to be interrupted during the save function. */
AIObject::SetAllowDoCommand(false);
HSQOBJECT savedata;
if (this->engine->MethodExists(*this->instance, "Save")) {
this->engine->CallMethod(*this->instance, "Save", &savedata);
if (!sq_istable(savedata)) {
AILog::Error("Save function should return a table.");
_ai_sl_byte = 0;
SlObject(NULL, _ai_byte);
AIObject::SetAllowDoCommand(true);
return;
}
HSQUIRRELVM vm = this->engine->GetVM();
sq_pushobject(vm, savedata);
if (SaveObject(vm, -1, AISAVE_MAX_DEPTH, true)) {
_ai_sl_byte = 1;
SlObject(NULL, _ai_byte);
SaveObject(vm, -1, AISAVE_MAX_DEPTH, false);
} else {
_ai_sl_byte = 0;
SlObject(NULL, _ai_byte);
}
sq_pop(vm, 1);
} else {
AILog::Warning("Save function is not implemented");
_ai_sl_byte = 0;
SlObject(NULL, _ai_byte);
}
AIObject::SetAllowDoCommand(true);
}
/* static */ bool AIInstance::LoadObjects(HSQUIRRELVM vm)
{
SlObject(NULL, _ai_byte);
switch (_ai_sl_byte) {
case SQSL_INT: {
int value;
SlArray(&value, 1, SLE_INT32);
if (vm != NULL) sq_pushinteger(vm, (SQInteger)value);
return true;
}
case SQSL_STRING: {
SlObject(NULL, _ai_byte);
static char buf[256];
SlArray(buf, _ai_sl_byte, SLE_CHAR);
if (vm != NULL) sq_pushstring(vm, OTTD2FS(buf), -1);
return true;
}
case SQSL_ARRAY: {
if (vm != NULL) sq_newarray(vm, 0);
while (LoadObjects(vm)) {
if (vm != NULL) sq_arrayappend(vm, -2);
/* The value is popped from the stack by squirrel. */
}
return true;
}
case SQSL_TABLE: {
if (vm != NULL) sq_newtable(vm);
while (LoadObjects(vm)) {
LoadObjects(vm);
if (vm != NULL) sq_rawset(vm, -3);
/* The key (-2) and value (-1) are popped from the stack by squirrel. */
}
return true;
}
case SQSL_BOOL: {
SlObject(NULL, _ai_byte);
if (vm != NULL) sq_pushinteger(vm, (SQBool)(_ai_sl_byte != 0));
return true;
}
case SQSL_NULL: {
if (vm != NULL) sq_pushnull(vm);
return true;
}
case SQSL_ARRAY_TABLE_END: {
return false;
}
default: NOT_REACHED();
}
}
/* static */ void AIInstance::LoadEmpty()
{
SlObject(NULL, _ai_byte);
/* Check if there was anything saved at all. */
if (_ai_sl_byte == 0) return;
LoadObjects(NULL);
}
bool AIInstance::Load()
{
HSQUIRRELVM vm = (this->engine == NULL) ? NULL : this->engine->GetVM();
SlObject(NULL, _ai_byte);
/* Check if there was anything saved at all. */
if (_ai_sl_byte == 0) return true;
AIObject::SetAllowDoCommand(false);
if (vm != NULL) {
/* Go to the instance-root */
sq_pushobject(vm, *this->instance);
/* Find the function-name inside the script */
sq_pushstring(vm, OTTD2FS("Load"), -1);
if (SQ_FAILED(sq_get(vm, -2))) sq_pushnull(vm);
sq_pushobject(vm, *this->instance);
}
LoadObjects(vm);
if (this->engine != NULL) {
if (this->engine->MethodExists(*this->instance, "Load")) {
sq_call(vm, 2, SQFalse, SQFalse);
} else {
AILog::Warning("Loading failed: there was data for the AI to load, but the AI does not have a Load() function.");
}
}
/* Pop 1) the object instance, 2) the function name, 3) the instance again, 4) the table. */
if (vm != NULL) sq_pop(vm, 4);
AIObject::SetAllowDoCommand(true);
return true;
}

140
src/ai/ai_instance.hpp Normal file
View File

@@ -0,0 +1,140 @@
/* $Id$ */
/** @file ai_instance.hpp The AIInstance tracks an AI. */
#ifndef AI_INSTANCE_HPP
#define AI_INSTANCE_HPP
/**
* The callback function when an AI suspends.
*/
typedef void (AISuspendCallbackProc)(class AIInstance *instance);
/**
* A throw-class that is given when the VM wants to suspend.
*/
class AI_VMSuspend {
public:
AI_VMSuspend(int time, AISuspendCallbackProc *callback) :
time(time),
callback(callback)
{}
int GetSuspendTime() { return time; }
AISuspendCallbackProc *GetSuspendCallback() { return callback; }
private:
int time;
AISuspendCallbackProc *callback;
};
class AIInstance {
public:
AIInstance(class AIInfo *info);
~AIInstance();
/**
* An AI in multiplayer waits for the server to handle his DoCommand.
* It keeps waiting for this until this function is called.
*/
void Continue();
/**
* Run the GameLoop of an AI.
*/
void GameLoop();
/**
* Get the storage of this AI.
*/
static class AIStorage *GetStorage();
/**
* Return a true/false reply for a DoCommand.
*/
static void DoCommandReturn(AIInstance *instance);
/**
* Return a VehicleID reply for a DoCommand.
*/
static void DoCommandReturnVehicleID(AIInstance *instance);
/**
* Return a SignID reply for a DoCommand.
*/
static void DoCommandReturnSignID(AIInstance *instance);
/**
* Return a GroupID reply for a DoCommand.
*/
static void DoCommandReturnGroupID(AIInstance *instance);
/**
* Get the controller attached to the instance.
*/
class AIController *GetController() { return controller; }
/**
* Call the AI Save function and save all data in the savegame.
*/
void Save();
/**
* Don't save any data in the savegame.
*/
static void SaveEmpty();
/**
* Load data from a savegame and call the AI Load function if it
* exists.
* @return True if the loading was successfull.
*/
bool Load();
/**
* Load and discard data from a savegame.
*/
static void LoadEmpty();
private:
static class AIInstance *current_instance; //!< Static current AIInstance, so we can register AIs.
class AIController *controller;
class AIStorage *storage;
class Squirrel *engine;
SQObject *instance;
bool is_started;
bool is_dead;
int suspend;
AISuspendCallbackProc *callback;
/**
* Register all API functions to the VM.
*/
void RegisterAPI();
/**
* Tell the AI it died.
*/
void Died();
/**
* Save one object (int / string / arrray / table) to the savegame.
* @param index The index on the squirrel stack of the element to save.
* @param max_depth The maximum depth recursive arrays / tables will be stored
* with before an error is returned.
* @param test If true, don't really store the data but only check if it is
* valid.
* @return True if the saving was successfull.
*/
static bool SaveObject(HSQUIRRELVM vm, SQInteger index, int max_depth, bool test);
/**
* Load all objects from a savegame.
* @return True if the loading was successfull.
*/
static bool LoadObjects(HSQUIRRELVM vm);
};
#endif /* AI_INSTANCE_HPP */

395
src/ai/ai_scanner.cpp Normal file
View File

@@ -0,0 +1,395 @@
/* $Id$ */
/** @file ai_scanner.cpp allows scanning AI scripts */
#include "../stdafx.h"
#include "../debug.h"
#include "../openttd.h"
#include "../string_func.h"
#include "../fileio_func.h"
#include "../fios.h"
#include "../network/network.h"
#include "../core/random_func.hpp"
#include <sys/types.h>
#include <sys/stat.h>
#include <squirrel.h>
#include "../script/squirrel.hpp"
#include "../script/squirrel_helper.hpp"
#include "../script/squirrel_class.hpp"
#include "ai.hpp"
#include "ai_info.hpp"
#include "ai_scanner.hpp"
#include "api/ai_controller.hpp"
void AIScanner::ScanDir(const char *dirname, bool library_dir, char *library_depth)
{
extern bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb);
extern bool FiosIsHiddenFile(const struct dirent *ent);
struct stat sb;
struct dirent *dirent;
DIR *dir;
char d_name[MAX_PATH];
char script_name[MAX_PATH];
dir = ttd_opendir(dirname);
/* Dir not found, so do nothing */
if (dir == NULL) return;
/* Walk all dirs trying to find a dir in which 'main.nut' exists */
while ((dirent = readdir(dir)) != NULL) {
ttd_strlcpy(d_name, FS2OTTD(dirent->d_name), sizeof(d_name));
/* Valid file, not '.' or '..', not hidden */
if (!FiosIsValidFile(dirname, dirent, &sb)) continue;
if (strcmp(d_name, ".") == 0 || strcmp(d_name, "..") == 0) continue;
if (FiosIsHiddenFile(dirent) && strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) != 0) continue;
if (S_ISDIR(sb.st_mode)) {
/* Create the full-length script-name */
ttd_strlcpy(script_name, dirname, sizeof(script_name));
ttd_strlcat(script_name, d_name, sizeof(script_name));
ttd_strlcat(script_name, PATHSEP, sizeof(script_name));
if (library_dir && library_depth == NULL) {
ScanDir(script_name, library_dir, d_name);
continue;
}
}
if (S_ISREG(sb.st_mode)) {
if (library_dir) continue;
char *ext = strrchr(d_name, '.');
if (ext == NULL || strcasecmp(ext, ".tar") != 0) continue;
/* Create the full path to the tarfile */
char tarname[MAX_PATH];
ttd_strlcpy(tarname, dirname, sizeof(tarname));
ttd_strlcat(tarname, d_name, sizeof(tarname));
/* Now the script-name starts with the first dir in the tar */
if (FioTarFirstDir(tarname) == NULL) continue;
ttd_strlcpy(script_name, "%aitar%", sizeof(tarname));
ttd_strlcat(script_name, FioTarFirstDir(tarname), sizeof(script_name));
FioTarAddLink(script_name, FioTarFirstDir(tarname));
/* The name of the AI is the name of the tar minus the .tar */
*ext = '\0';
}
if (!library_dir) {
/* We look for the file 'info.nut' inside the AI dir.. if it doesn't exists, it isn't an AI */
ttd_strlcat(script_name, "info.nut", sizeof(script_name));
if (FioCheckFileExists(script_name, AI_DIR)) {
char load_script[MAX_PATH];
ttd_strlcpy(load_script, script_name, sizeof(load_script));
/* Remove the 'info.nut' part and replace it with 'main.nut' */
script_name[strlen(script_name) - 8] = '\0';
ttd_strlcat(script_name, "main.nut", sizeof(script_name));
DEBUG(ai, 6, "[script] Loading script '%s' for AI handling", load_script);
this->current_script = script_name;
this->current_dir = d_name;
this->engine->LoadScript(load_script);
}
} else {
/* We look for the file 'library.nut' inside the library dir.. */
ttd_strlcat(script_name, "library.nut", sizeof(script_name));
if (FioCheckFileExists(script_name, AI_DIR)) {
char load_script[MAX_PATH];
char dir_name[MAX_PATH];
char d_name_2[MAX_PATH];
/* In case the directory has a dot in it, ignore it, as that is the
* indicator for multiple versions of the same library */
ttd_strlcpy(d_name_2, d_name, sizeof(d_name_2));
char *e = strrchr(d_name_2, '.');
if (e != NULL) *e = '\0';
ttd_strlcpy(load_script, script_name, sizeof(load_script));
ttd_strlcpy(dir_name, library_depth, sizeof(dir_name));
ttd_strlcat(dir_name, ".", sizeof(dir_name));
ttd_strlcat(dir_name, d_name_2, sizeof(dir_name));
/* Remove the 'library.nut' part and replace it with 'main.nut' */
script_name[strlen(script_name) - 11] = '\0';
ttd_strlcat(script_name, "main.nut", sizeof(script_name));
DEBUG(ai, 6, "[script] Loading script '%s' for Squirrel library", load_script);
this->current_script = script_name;
this->current_dir = dir_name;
this->engine->LoadScript(load_script);
}
}
}
closedir(dir);
}
void AIScanner::ScanAIDir()
{
char buf[MAX_PATH];
Searchpath sp;
FOR_ALL_SEARCHPATHS(sp) {
FioAppendDirectory(buf, MAX_PATH, sp, AI_DIR);
if (FileExists(buf)) this->ScanDir(buf, false);
ttd_strlcat(buf, "library" PATHSEP, MAX_PATH);
if (FileExists(buf)) this->ScanDir(buf, true);
}
}
void AIScanner::RescanAIDir()
{
extern void ScanForTarFiles();
ScanForTarFiles();
this->ScanAIDir();
}
AIScanner::AIScanner()
{
this->engine = new Squirrel();
/* Create the AIInfo class, and add the RegisterAI function */
DefSQClass <AIInfo> SQAIInfo("AIInfo");
SQAIInfo.PreRegister(engine);
SQAIInfo.AddConstructor<void (AIInfo::*)(), 1>(engine, "x");
SQAIInfo.DefSQAdvancedMethod(this->engine, &AIInfo::AddSetting, "AddSetting");
SQAIInfo.PostRegister(engine);
this->engine->AddMethod("RegisterAI", &AIInfo::Constructor, 2, "tx");
/* Create the AILibrary class, and add the RegisterLibrary function */
this->engine->AddClassBegin("AILibrary");
this->engine->AddClassEnd();
this->engine->AddMethod("RegisterLibrary", &AILibrary::Constructor, 2, "tx");
/* Mark this class as global pointer */
this->engine->SetGlobalPointer(this);
/* Scan the AI dir for scripts */
this->ScanAIDir();
/* Create the dummy AI */
this->engine->AddMethod("RegisterDummyAI", &AIInfo::DummyConstructor, 2, "tx");
this->current_script = (char *)"%_dummy";
this->current_dir = (char *)"%_dummy";
extern void AI_CreateAIInfoDummy(HSQUIRRELVM vm);
AI_CreateAIInfoDummy(this->engine->GetVM());
}
AIScanner::~AIScanner()
{
AIInfoList::iterator it = this->info_list.begin();
for (; it != this->info_list.end(); it++) {
AIInfo *i = (*it).second;
delete i;
}
delete this->engine;
}
bool AIScanner::ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm, AIController *controller)
{
/* Internally we store libraries as 'library.version' */
char library_name[1024];
snprintf(library_name, sizeof(library_name), "%s.%d", library, version);
/* Check if the library + version exists */
AILibraryList::iterator iter = this->library_list.find(library_name);
if (iter == this->library_list.end()) {
char error[1024];
/* Now see if the version doesn't exist, or the library */
iter = this->library_list.find(library);
if (iter == this->library_list.end()) {
snprintf(error, sizeof(error), "couldn't find library '%s'", library);
} else {
snprintf(error, sizeof(error), "this AI is expecting library '%s' to be version %d, but the latest available is version %d", library, version, (*iter).second->GetVersion());
}
sq_throwerror(vm, OTTD2FS(error));
return false;
}
/* Get the current table/class we belong to */
HSQOBJECT parent;
sq_getstackobj(vm, 1, &parent);
char fake_class[1024];
int next_number;
/* Check if we already have this library loaded.. if so, fill fake_class
* with the class-name it is nested in */
if (!controller->LoadedLibrary(library_name, &next_number, &fake_class[0], sizeof(fake_class))) {
/* Create a new fake internal name */
snprintf(fake_class, sizeof(fake_class), "_internalNA%d", next_number);
/* Load the library in a 'fake' namespace, so we can link it to the name the user requested */
sq_pushroottable(vm);
sq_pushstring(vm, OTTD2FS(fake_class), -1);
sq_newclass(vm, SQFalse);
/* Load the library */
if (!Squirrel::LoadScript(vm, (*iter).second->GetScriptName(), false)) {
char error[1024];
snprintf(error, sizeof(error), "there was a compile error when importing '%s' version %d", library, version);
sq_throwerror(vm, OTTD2FS(error));
return false;
}
/* Create the fake class */
sq_newslot(vm, -3, SQFalse);
sq_pop(vm, 1);
controller->AddLoadedLibrary(library_name, fake_class);
}
/* Find the real class inside the fake class (like 'sets.Vector') */
sq_pushroottable(vm);
sq_pushstring(vm, OTTD2FS(fake_class), -1);
if (SQ_FAILED(sq_get(vm, -2))) {
sq_throwerror(vm, _SC("internal error assigning library class"));
return false;
}
sq_pushstring(vm, OTTD2FS((*iter).second->GetInstanceName()), -1);
if (SQ_FAILED(sq_get(vm, -2))) {
char error[1024];
snprintf(error, sizeof(error), "unable to find class '%s' in the library '%s' version %d", (*iter).second->GetInstanceName(), library, version);
sq_throwerror(vm, OTTD2FS(error));
return false;
}
HSQOBJECT obj;
sq_getstackobj(vm, -1, &obj);
sq_pop(vm, 3);
if (StrEmpty(class_name)) {
sq_pushobject(vm, obj);
return true;
}
/* Now link the name the user wanted to our 'fake' class */
sq_pushobject(vm, parent);
sq_pushstring(vm, OTTD2FS(class_name), -1);
sq_pushobject(vm, obj);
sq_newclass(vm, SQTrue);
sq_newslot(vm, -3, SQFalse);
sq_pop(vm, 1);
sq_pushobject(vm, obj);
return true;
}
void AIScanner::RegisterLibrary(AILibrary *library)
{
const char *ai_name_without_version = library->GetDirName();
char ai_name[1024];
snprintf(ai_name, sizeof(ai_name), "%s.%d", library->GetDirName(), library->GetVersion());
/* Check if we register twice; than the first always wins */
if (this->library_list.find(ai_name) != this->library_list.end()) {
/* In case they are not the same dir, give a warning */
if (strcasecmp(library->GetScriptName(), this->library_list[ai_name]->GetScriptName()) != 0) {
DEBUG(ai, 0, "Registering two libraries with the same name");
DEBUG(ai, 0, " 1: %s", this->library_list[ai_name]->GetScriptName());
DEBUG(ai, 0, " 2: %s", library->GetScriptName());
DEBUG(ai, 0, "The first is taking precedence");
}
/* Delete the new AILibrary, as we will be using the old one */
delete library;
return;
}
this->library_list[strdup(ai_name)] = library;
/* Insert the global name too, so we if the library is known at all */
if (this->library_list.find(ai_name_without_version) == this->library_list.end()) {
this->library_list[strdup(ai_name_without_version)] = library;
} else if (this->library_list[ai_name_without_version]->GetVersion() < library->GetVersion()) {
this->library_list[ai_name_without_version] = library;
}
}
void AIScanner::RegisterAI(AIInfo *info)
{
const char *ai_name = info->GetDirName();
/* Check if we register twice; than the first always wins */
if (this->info_list.find(ai_name) != this->info_list.end()) {
/* In case they are not the same dir, give a warning */
if (strcasecmp(info->GetScriptName(), this->info_list[ai_name]->GetScriptName()) != 0) {
DEBUG(ai, 0, "Registering two AIs with the same name");
DEBUG(ai, 0, " 1: %s", this->info_list[ai_name]->GetScriptName());
DEBUG(ai, 0, " 2: %s", info->GetScriptName());
DEBUG(ai, 0, "The first is taking precedence");
}
/* Delete the new AIInfo, as we will be using the old one */
delete info;
return;
}
this->info_list[strdup(ai_name)] = info;
}
void AIScanner::UnregisterAI(AIInfo *info)
{
this->info_list.erase(info->GetDirName());
}
AIInfo *AIScanner::SelectRandomAI()
{
if (this->info_list.size() == 0) {
DEBUG(ai, 0, "No suitable AI found, loading 'dummy' AI.");
return this->info_dummy;
}
/* Find a random AI */
uint pos;
if (_networking) pos = InteractiveRandomRange((uint16)this->info_list.size());
else pos = RandomRange((uint16)this->info_list.size());
/* Find the Nth item from the array */
AIInfoList::iterator it = this->info_list.begin();
for (; pos > 0; pos--) it++;
AIInfoList::iterator first_it = it;
AIInfo *i = (*it).second;
if (!i->AllowStartup()) {
/* We can't start this AI, try to find the next best */
do {
it++;
if (it == this->info_list.end()) it = this->info_list.begin();
/* Back at the beginning? We can't start an AI. */
if (first_it == it) {
DEBUG(ai, 0, "No suitable AI found, loading 'dummy' AI.");
return this->info_dummy;
}
i = (*it).second;
} while (!i->AllowStartup());
}
return i;
}
AIInfo *AIScanner::FindAI(const char *name)
{
if (this->info_list.size() == 0) return NULL;
if (name == NULL) return NULL;
AIInfoList::iterator it = this->info_list.begin();
for (; it != this->info_list.end(); it++) {
AIInfo *i = (*it).second;
if (strcasecmp(name, (*it).first) == 0 && i->AllowStartup()) {
return i;
}
}
return NULL;
}
char *AIScanner::GetAIConsoleList(char *p, const char *last)
{
p += seprintf(p, last, "List of AIs:\n");
AIInfoList::iterator it = this->info_list.begin();
for (; it != this->info_list.end(); it++) {
AIInfo *i = (*it).second;
if (!i->AllowStartup()) continue;
p += seprintf(p, last, "%10s: %s\n", (*it).first, i->GetDescription());
}
p += seprintf(p, last, "\n");
return p;
}

102
src/ai/ai_scanner.hpp Normal file
View File

@@ -0,0 +1,102 @@
/* $Id$ */
/** @file ai_scanner.hpp declarations of the class for AI scanner */
#ifndef AI_SCANNER_HPP
#define AI_SCANNER_HPP
#include <map>
class AIScanner {
public:
AIScanner();
~AIScanner();
/**
* Import a library inside the Squirrel VM.
*/
bool ImportLibrary(const char *library, const char *class_name, int version, HSQUIRRELVM vm, class AIController *controller);
/**
* Register a library to be put in the available list.
*/
void RegisterLibrary(class AILibrary *library);
/**
* Register an AI to be put in the available list.
*/
void RegisterAI(class AIInfo *info);
void SetDummyAI(class AIInfo *info) { this->info_dummy = info; }
/**
* Remove an AI from the available list.
*/
void UnregisterAI(class AIInfo *info);
/**
* Select a Random AI.
*/
class AIInfo *SelectRandomAI();
/**
* Find an AI by name.
*/
class AIInfo *FindAI(const char *name);
/**
* Get the list of available AIs for the console.
*/
char *GetAIConsoleList(char *p, const char *last);
/**
* Get the list of all registered AIs.
*/
const AIInfoList *GetAIInfoList() { return &this->info_list; }
/**
* Get the engine of the main squirrel handler (it indexes all avialable squirrels).
*/
class Squirrel *GetEngine() { return this->engine; }
/**
* Get the current script the ScanDir is looking at.
*/
const char *GetCurrentScript() { return this->current_script; }
/**
* Get the directory of the current script the ScanDir is looking at.
*/
const char *GetCurrentDirName() { return this->current_dir; }
/**
* Rescan the AI dir for scripts.
*/
void RescanAIDir();
private:
typedef std::map<const char *, class AILibrary *, ltstr> AILibraryList;
/**
* Scan the AI dir for scripts.
*/
void ScanAIDir();
/**
* Scan a dir for AIs.
* For non-library-scan, if an AI is found, AIInfo is created, and the AI
* is registered to the central system.
* For library-scan, if a library is found, AILibrary is created, and the
* library is registered to the central system.
*/
void ScanDir(const char *dirname, bool library_dir, char *library_depth = NULL);
AIInfoList info_list;
AIInfo *info_dummy;
AILibraryList library_list;
class Squirrel *engine;
char *current_script;
char *current_dir;
};
#endif /* AI_SCANNER_HPP */

78
src/ai/ai_storage.hpp Normal file
View File

@@ -0,0 +1,78 @@
/* $Id$ */
/** @file ai_storage.hpp Defines AIStorage and includes all files required for it. */
#ifndef AI_STORAGE_HPP
#define AI_STORAGE_HPP
#include "../command_func.h"
#include "../map_func.h"
#include "../network/network.h"
#include "../company_func.h"
#include "../signs_func.h"
#include "../tunnelbridge.h"
#include "../vehicle_func.h"
#include "../group.h"
#include <vector>
/**
* The callback function for Mode-classes.
*/
typedef bool (AIModeProc)(TileIndex tile, uint32 p1, uint32 p2, uint procc, CommandCost costs);
/**
* The storage for each AI. It keeps track of important information.
*/
class AIStorage {
friend class AIObject;
private:
AIModeProc *mode; //!< The current build mode we are int.
class AIObject *mode_instance; //!< The instance belonging to the current build mode.
uint delay; //!< The ticks of delay each DoCommand has.
bool allow_do_command; //!< Is the usage of DoCommands restricted?
CommandCost costs; //!< The costs the AI is tracking.
Money last_cost; //!< The last cost of the command.
uint last_error; //!< The last error of the command.
bool last_command_res; //!< The last result of the command.
VehicleID new_vehicle_id; //!< The ID of the new Vehicle.
SignID new_sign_id; //!< The ID of the new Sign.
TileIndex new_tunnel_endtile; //!< The TileIndex of the new Tunnel.
GroupID new_group_id; //!< The ID of the new Group.
std::vector<int> callback_value; //!< The values which need to survive a callback.
RoadType road_type; //!< The current roadtype we build.
RailType rail_type; //!< The current railtype we build.
void *event_data; //!< Pointer to the event data storage.
void *log_data; //!< Pointer to the log data storage.
public:
AIStorage() :
mode (NULL),
mode_instance (NULL),
delay (1),
allow_do_command (true),
/* costs (can't be set) */
last_cost (0),
last_error (STR_NULL),
last_command_res (true),
new_vehicle_id (0),
new_sign_id (0),
new_tunnel_endtile(INVALID_TILE),
new_group_id (0),
/* calback_value (can't be set) */
road_type (INVALID_ROADTYPE),
rail_type (INVALID_RAILTYPE),
event_data (NULL),
log_data (NULL)
{ }
~AIStorage();
};
#endif /* AI_STORAGE_HPP */

244
src/ai/api/Doxyfile Normal file
View File

@@ -0,0 +1,244 @@
# Doxyfile 1.5.4
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "OpenTTD NoAI API "
PROJECT_NUMBER =
OUTPUT_DIRECTORY = ../../../docs/aidocs/
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class " \
"The $name widget " \
"The $name file " \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = ./
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 2
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = YES
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = YES
INTERNAL_DOCS = YES
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = NO
GENERATE_DEPRECATEDLIST= NO
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = NO
SHOW_DIRECTORIES = NO
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = YES
WARN_FORMAT = "$file:$line: $text "
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = .
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.h \
*.hpp
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS = GetClassName DECLARE_ENUM_AS_BIT_SET DECLARE_POSTFIX_INCREMENT
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = NO
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
HTML_DYNAMIC_SECTIONS = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 1
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = DOXYGEN_SKIP
EXPAND_AS_DEFINED = DEF_COMMAND
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE = openttd.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = NO
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

View File

@@ -0,0 +1,818 @@
/* $Id$ */
/** @file ai_abstractlist.cpp Implementation of AIAbstractList. */
#include <squirrel.h>
#include "ai_abstractlist.hpp"
#include "../../debug.h"
#include "../../core/alloc_func.hpp"
/**
* Base class for any AIAbstractList sorter.
*/
class AIAbstractListSorter {
protected:
AIAbstractList *list;
public:
/**
* Virtual dtor, needed to mute warnings.
*/
virtual ~AIAbstractListSorter() { }
/**
* Get the first item of the sorter.
*/
virtual int32 Begin() = 0;
/**
* Stop iterating a sorter.
*/
virtual void End() = 0;
/**
* Get the next item of the sorter.
*/
virtual int32 Next() = 0;
/**
* See if there is a next item of the sorter.
*/
virtual bool HasNext() = 0;
/**
* Callback from the list if an item gets removed.
*/
virtual void Remove(int item) = 0;
};
/**
* Sort by value, ascending.
*/
class AIAbstractListSorterValueAscending : public AIAbstractListSorter {
private:
AIAbstractList::AIAbstractListBucket::iterator bucket_iter;
AIAbstractList::AIItemList *bucket_list;
AIAbstractList::AIItemList::iterator bucket_list_iter;
bool has_no_more_items;
int32 item_next;
public:
AIAbstractListSorterValueAscending(AIAbstractList *list)
{
this->list = list;
this->End();
}
int32 Begin()
{
if (this->list->buckets.empty()) return 0;
this->has_no_more_items = false;
this->bucket_iter = this->list->buckets.begin();
this->bucket_list = &(*this->bucket_iter).second;
this->bucket_list_iter = this->bucket_list->begin();
this->item_next = *this->bucket_list_iter;
int32 item_current = this->item_next;
FindNext();
return item_current;
}
void End()
{
this->bucket_list = NULL;
this->has_no_more_items = true;
this->item_next = 0;
}
void FindNext()
{
if (this->bucket_list == NULL) {
this->has_no_more_items = true;
return;
}
this->bucket_list_iter++;
if (this->bucket_list_iter == this->bucket_list->end()) {
this->bucket_iter++;
if (this->bucket_iter == this->list->buckets.end()) {
this->bucket_list = NULL;
return;
}
this->bucket_list = &(*this->bucket_iter).second;
this->bucket_list_iter = this->bucket_list->begin();
}
this->item_next = *this->bucket_list_iter;
}
int32 Next()
{
if (!this->HasNext()) return 0;
int32 item_current = this->item_next;
FindNext();
return item_current;
}
void Remove(int item)
{
if (!this->HasNext()) return;
/* If we remove the 'next' item, skip to the next */
if (item == this->item_next) {
FindNext();
return;
}
}
bool HasNext()
{
return !(this->list->buckets.empty() || this->has_no_more_items);
}
};
/**
* Sort by value, descending.
*/
class AIAbstractListSorterValueDescending : public AIAbstractListSorter {
private:
AIAbstractList::AIAbstractListBucket::iterator bucket_iter;
AIAbstractList::AIItemList *bucket_list;
AIAbstractList::AIItemList::iterator bucket_list_iter;
bool has_no_more_items;
int32 item_next;
public:
AIAbstractListSorterValueDescending(AIAbstractList *list)
{
this->list = list;
this->End();
}
int32 Begin()
{
if (this->list->buckets.empty()) return 0;
this->has_no_more_items = false;
/* Go to the end of the bucket-list */
this->bucket_iter = this->list->buckets.begin();
for (size_t i = this->list->buckets.size(); i > 1; i--) this->bucket_iter++;
this->bucket_list = &(*this->bucket_iter).second;
/* Go to the end of the items in the bucket */
this->bucket_list_iter = this->bucket_list->begin();
for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++;
this->item_next = *this->bucket_list_iter;
int32 item_current = this->item_next;
FindNext();
return item_current;
}
void End() {
this->bucket_list = NULL;
this->has_no_more_items = true;
this->item_next = 0;
}
void FindNext()
{
if (this->bucket_list == NULL) {
this->has_no_more_items = true;
return;
}
if (this->bucket_list_iter == this->bucket_list->begin()) {
if (this->bucket_iter == this->list->buckets.begin()) {
this->bucket_list = NULL;
return;
}
this->bucket_iter--;
this->bucket_list = &(*this->bucket_iter).second;
/* Go to the end of the items in the bucket */
this->bucket_list_iter = this->bucket_list->begin();
for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++;
} else {
this->bucket_list_iter--;
}
this->item_next = *this->bucket_list_iter;
}
int32 Next()
{
if (!this->HasNext()) return 0;
int32 item_current = this->item_next;
FindNext();
return item_current;
}
void Remove(int item)
{
if (!this->HasNext()) return;
/* If we remove the 'next' item, skip to the next */
if (item == this->item_next) {
FindNext();
return;
}
}
bool HasNext()
{
return !(this->list->buckets.empty() || this->has_no_more_items);
}
};
/**
* Sort by item, ascending.
*/
class AIAbstractListSorterItemAscending : public AIAbstractListSorter {
private:
AIAbstractList::AIAbstractListMap::iterator item_iter;
bool has_no_more_items;
int32 item_next;
public:
AIAbstractListSorterItemAscending(AIAbstractList *list)
{
this->list = list;
this->End();
}
int32 Begin()
{
if (this->list->items.empty()) return 0;
this->has_no_more_items = false;
this->item_iter = this->list->items.begin();
this->item_next = (*this->item_iter).first;
int32 item_current = this->item_next;
FindNext();
return item_current;
}
void End()
{
this->has_no_more_items = true;
}
void FindNext()
{
if (this->item_iter == this->list->items.end()) {
this->has_no_more_items = true;
return;
}
this->item_iter++;
if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first;
}
int32 Next()
{
if (!this->HasNext()) return 0;
int32 item_current = this->item_next;
FindNext();
return item_current;
}
void Remove(int item) {
if (!this->HasNext()) return;
/* If we remove the 'next' item, skip to the next */
if (item == this->item_next) {
FindNext();
return;
}
}
bool HasNext()
{
return !(this->list->items.empty() || this->has_no_more_items);
}
};
/**
* Sort by item, descending.
*/
class AIAbstractListSorterItemDescending : public AIAbstractListSorter {
private:
AIAbstractList::AIAbstractListMap::iterator item_iter;
bool has_no_more_items;
int32 item_next;
public:
AIAbstractListSorterItemDescending(AIAbstractList *list)
{
this->list = list;
this->End();
}
int32 Begin()
{
if (this->list->items.empty()) return 0;
this->has_no_more_items = false;
this->item_iter = this->list->items.begin();
for (size_t i = this->list->items.size(); i > 1; i--) this->item_iter++;
this->item_next = (*this->item_iter).first;
int32 item_current = this->item_next;
FindNext();
return item_current;
}
void End()
{
this->has_no_more_items = true;
}
void FindNext()
{
if (this->item_iter == this->list->items.end()) {
this->has_no_more_items = true;
return;
}
this->item_iter--;
if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first;
}
int32 Next()
{
if (!this->HasNext()) return 0;
int32 item_current = this->item_next;
FindNext();
return item_current;
}
void Remove(int item)
{
if (!this->HasNext()) return;
/* If we remove the 'next' item, skip to the next */
if (item == this->item_next) {
FindNext();
return;
}
}
bool HasNext()
{
return !(this->list->items.empty() || this->has_no_more_items);
}
};
AIAbstractList::AIAbstractList()
{
/* Default sorter */
this->sorter = new AIAbstractListSorterValueDescending(this);
this->sorter_type = SORT_BY_VALUE;
this->sort_ascending = false;
this->initialized = false;
}
AIAbstractList::~AIAbstractList()
{
delete this->sorter;
}
bool AIAbstractList::HasItem(int32 item)
{
return this->items.count(item) == 1;
}
void AIAbstractList::Clear()
{
this->items.clear();
this->buckets.clear();
this->sorter->End();
}
void AIAbstractList::AddItem(int32 item)
{
if (this->HasItem(item)) return;
this->items[item] = 0;
this->buckets[0].insert(item);
}
void AIAbstractList::RemoveItem(int32 item)
{
if (!this->HasItem(item)) return;
int32 value = this->GetValue(item);
this->sorter->Remove(item);
this->buckets[value].erase(item);
if (this->buckets[value].empty()) this->buckets.erase(value);
this->items.erase(item);
}
int32 AIAbstractList::Begin()
{
this->initialized = true;
return this->sorter->Begin();
}
int32 AIAbstractList::Next()
{
if (this->initialized == false) {
DEBUG(ai, 0, "ERROR: Next() is invalid as Begin() is never called");
return false;
}
return this->sorter->Next();
}
bool AIAbstractList::IsEmpty()
{
return this->items.empty();
}
bool AIAbstractList::HasNext()
{
if (this->initialized == false) {
DEBUG(ai, 0, "ERROR: HasNext() is invalid as Begin() is never called");
return false;
}
return this->sorter->HasNext();
}
int32 AIAbstractList::Count()
{
return (int32)this->items.size();
}
int32 AIAbstractList::GetValue(int32 item)
{
if (!this->HasItem(item)) return 0;
return this->items[item];
}
bool AIAbstractList::SetValue(int32 item, int32 value)
{
if (!this->HasItem(item)) return false;
int32 value_old = this->GetValue(item);
this->sorter->Remove(item);
this->buckets[value_old].erase(item);
if (this->buckets[value_old].empty()) this->buckets.erase(value_old);
this->items[item] = value;
this->buckets[value].insert(item);
return true;
}
void AIAbstractList::Sort(SorterType sorter, bool ascending)
{
if (sorter != SORT_BY_VALUE && sorter != SORT_BY_ITEM) return;
if (sorter == this->sorter_type && ascending == this->sort_ascending) return;
delete this->sorter;
switch (sorter) {
case SORT_BY_ITEM:
if (ascending) this->sorter = new AIAbstractListSorterItemAscending(this);
else this->sorter = new AIAbstractListSorterItemDescending(this);
break;
case SORT_BY_VALUE:
if (ascending) this->sorter = new AIAbstractListSorterValueAscending(this);
else this->sorter = new AIAbstractListSorterValueDescending(this);
break;
default:
this->Sort(SORT_BY_ITEM, false);
return;
}
this->sorter_type = sorter;
this->sort_ascending = ascending;
}
void AIAbstractList::AddList(AIAbstractList *list)
{
AIAbstractListMap *list_items = &list->items;
for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
this->AddItem((*iter).first);
this->SetValue((*iter).first, (*iter).second);
}
}
void AIAbstractList::RemoveAboveValue(int32 value)
{
for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).second > value) this->items.erase(iter);
}
for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).first > value) this->buckets.erase(iter);
}
}
void AIAbstractList::RemoveBelowValue(int32 value)
{
for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).second < value) this->items.erase(iter);
}
for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).first < value) this->buckets.erase(iter);
}
}
void AIAbstractList::RemoveBetweenValue(int32 start, int32 end)
{
for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).second > start && (*iter).second < end) this->items.erase(iter);
}
for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).first > start && (*iter).first < end) this->buckets.erase(iter);
}
}
void AIAbstractList::RemoveValue(int32 value)
{
for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).second == value) this->items.erase(iter);
}
for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).first == value) this->buckets.erase(iter);
}
}
void AIAbstractList::RemoveTop(int32 count)
{
if (!this->sort_ascending) {
this->Sort(this->sorter_type, !this->sort_ascending);
this->RemoveBottom(count);
this->Sort(this->sorter_type, !this->sort_ascending);
return;
}
switch (this->sorter_type) {
default: NOT_REACHED();
case SORT_BY_VALUE:
for (AIAbstractListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) {
AIItemList *items = &(*iter).second;
size_t size = items->size();
for (AIItemList::iterator iter = items->begin(); iter != items->end(); iter = items->begin()) {
if (--count < 0) return;
this->RemoveItem(*iter);
/* When the last item is removed from the bucket, the bucket itself is removed.
* This means that the iterators can be invalid after a call to RemoveItem.
*/
if (--size == 0) break;
}
}
break;
case SORT_BY_ITEM:
for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) {
if (--count < 0) return;
this->RemoveItem((*iter).first);
}
break;
}
}
void AIAbstractList::RemoveBottom(int32 count)
{
if (!this->sort_ascending) {
this->Sort(this->sorter_type, !this->sort_ascending);
this->RemoveTop(count);
this->Sort(this->sorter_type, !this->sort_ascending);
return;
}
switch (this->sorter_type) {
default: NOT_REACHED();
case SORT_BY_VALUE:
for (AIAbstractListBucket::reverse_iterator iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) {
AIItemList *items = &(*iter).second;
size_t size = items->size();
for (AIItemList::reverse_iterator iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) {
if (--count < 0) return;
this->RemoveItem(*iter);
/* When the last item is removed from the bucket, the bucket itself is removed.
* This means that the iterators can be invalid after a call to RemoveItem.
*/
if (--size == 0) break;
}
}
case SORT_BY_ITEM:
for (AIAbstractListMap::reverse_iterator iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) {
if (--count < 0) return;
this->RemoveItem((*iter).first);
}
break;
}
}
void AIAbstractList::RemoveList(AIAbstractList *list)
{
AIAbstractListMap *list_items = &list->items;
for (AIAbstractListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) {
this->RemoveItem((*iter).first);
}
}
void AIAbstractList::KeepAboveValue(int32 value)
{
for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).second <= value) this->items.erase(iter);
}
for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).first <= value) this->buckets.erase(iter);
}
}
void AIAbstractList::KeepBelowValue(int32 value)
{
for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).second >= value) this->items.erase(iter);
}
for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).first >= value) this->buckets.erase(iter);
}
}
void AIAbstractList::KeepBetweenValue(int32 start, int32 end)
{
for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).second <= start || (*iter).second >= end) this->items.erase(iter);
}
for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).first <= start || (*iter).first >= end) this->buckets.erase(iter);
}
}
void AIAbstractList::KeepValue(int32 value)
{
for (AIAbstractListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).second != value) this->items.erase(iter);
}
for (AIAbstractListBucket::iterator next_iter, iter = this->buckets.begin(); iter != this->buckets.end(); iter = next_iter) {
next_iter = iter; next_iter++;
if ((*iter).first != value) this->buckets.erase(iter);
}
}
void AIAbstractList::KeepTop(int32 count)
{
this->RemoveBottom(this->Count() - count);
}
void AIAbstractList::KeepBottom(int32 count)
{
this->RemoveTop(this->Count() - count);
}
void AIAbstractList::KeepList(AIAbstractList *list)
{
AIAbstractList tmp;
for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
tmp.AddItem((*iter).first);
tmp.SetValue((*iter).first, (*iter).second);
}
tmp.RemoveList(list);
this->RemoveList(&tmp);
}
SQInteger AIAbstractList::_get(HSQUIRRELVM vm) {
if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
SQInteger idx;
sq_getinteger(vm, 2, &idx);
if (!this->HasItem(idx)) return SQ_ERROR;
sq_pushinteger(vm, this->GetValue(idx));
return 1;
}
SQInteger AIAbstractList::_nexti(HSQUIRRELVM vm) {
if (sq_gettype(vm, 2) == OT_NULL) {
if (this->IsEmpty()) {
sq_pushnull(vm);
return 1;
}
sq_pushinteger(vm, this->Begin());
return 1;
}
SQInteger idx;
sq_getinteger(vm, 2, &idx);
int val = this->Next();
if (!this->HasNext()) {
sq_pushnull(vm);
return 1;
}
sq_pushinteger(vm, val);
return 1;
}
SQInteger AIAbstractList::Valuate(HSQUIRRELVM vm) {
int nparam = sq_gettop(vm) - 2;
/* Get the list instance and the function to call */
HSQOBJECT obj_list, obj_func;
sq_getstackobj(vm, 1, &obj_list);
sq_getstackobj(vm, 2, &obj_func);
if (sq_isclass(obj_list)) {
return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected instance)"));
}
if (sq_isfunction(obj_func)) {
return sq_throwerror(vm, _SC("parameter 2 has an invalid type (expected function)"));
}
sq_addref(vm, &obj_func);
/* Read the params */
HSQOBJECT *obj_params = AllocaM(HSQOBJECT, nparam);
for (int i = 0; i < nparam; i++) {
sq_getstackobj(vm, i + 3, &obj_params[i]);
sq_addref(vm, &obj_params[i]);
}
/* Remove all unneeded stuff */
sq_pop(vm, nparam + 1);
/* Walk all items, and query the result */
this->buckets.clear();
for (AIAbstractListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) {
/* The function to call */
sq_pushobject(vm, obj_func);
/* The 'list' instance; this is most likely wrong, but we need to send something ;) */
sq_pushobject(vm, obj_list);
/* Now send the params */
sq_pushinteger(vm, (*iter).first);
for (int i = 0; i < nparam; i++) {
sq_pushobject(vm, obj_params[i]);
}
/* Call the function */
if (SQ_FAILED(sq_call(vm, nparam + 2, SQTrue, SQTrue))) return SQ_ERROR;
/* Retreive the return value */
SQInteger value;
switch (sq_gettype(vm, -1)) {
case OT_INTEGER: {
sq_getinteger(vm, -1, &value);
} break;
case OT_BOOL: {
SQBool v;
sq_getbool(vm, -1, &v);
value = v ? 1 : 0;
} break;
default: {
sq_pop(vm, 3);
sq_release(vm, &obj_func);
for (int i = 0; i < nparam; i++) sq_release(vm, &obj_params[i]);
return sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)"));
}
}
/* Remove junk */
sq_pop(vm, 2);
(*iter).second = (int32)value;
this->buckets[(int32)value].insert((*iter).first);
}
sq_release(vm, &obj_func);
for (int i = 0; i < nparam; i++) sq_release(vm, &obj_params[i]);
return 0;
}

View File

@@ -0,0 +1,263 @@
/* $Id$ */
/** @file ai_abstractlist.hpp A list which can keep item/value pairs, which you can walk. */
/** @defgroup AIList Classes that create a list of items. */
#ifndef AI_ABSTRACTLIST_HPP
#define AI_ABSTRACTLIST_HPP
#include "ai_object.hpp"
#include <map>
#include <set>
class AIAbstractListSorter;
/**
* Class that creates a list which can keep item/value pairs, which you can walk.
*/
class AIAbstractList : public AIObject {
public:
static const char *GetClassName() { return "AIAbstractList"; }
/** Type of sorter */
enum SorterType {
SORT_BY_VALUE, ///< Sort the list based on the value of the item.
SORT_BY_ITEM, ///< Sort the list based on the item itself.
};
private:
AIAbstractListSorter *sorter;
SorterType sorter_type;
bool sort_ascending;
bool initialized;
public:
typedef std::set<int32> AIItemList; //!< The list of items inside the bucket
typedef std::map<int32, AIItemList> AIAbstractListBucket; //!< The bucket list per value
typedef std::map<int32, int32> AIAbstractListMap; //!< List per item
AIAbstractListMap items; //!< The items in the list
AIAbstractListBucket buckets; //!< The items in the list, sorted by value
protected:
/**
* Add a single item to the list.
* @param item the item to add. Should be unique, otherwise it is ignored.
* @note the value is set to 0 by default.
*/
void AddItem(int32 item);
/**
* Remove a single item from the list.
* @param item the item to remove. If not existing, it is ignored.
*/
void RemoveItem(int32 item);
public:
AIAbstractList();
~AIAbstractList();
/**
* Clear the list, making Count() returning 0 and IsEmpty() returning true.
*/
void Clear();
/**
* Check if an item is in the list.
* @param item the item to check for.
* @return true if the item is in the list.
*/
bool HasItem(int32 item);
/**
* Go to the beginning of the list.
* @return the item value of the first item.
*/
int32 Begin();
/**
* Go to the next item in the list.
* @return the item value of the next item.
* @note returns 0 if beyond end-of-list. Use HasNext() to check for end-of-list.
*/
int32 Next();
/**
* Check if a list is empty.
* @return true if the list is empty.
*/
bool IsEmpty();
/**
* Check if there is a next element. In other words, if this is true,
* Next() will return a valid item.
* @return true if there is a next item.
*/
bool HasNext();
/**
* Returns the amount of items in the list.
* @return amount of items in the list.
*/
int32 Count();
/**
* Get the value that belongs to this item.
* @param item the item to get the value from
* @return the value that belongs to this item.
*/
int32 GetValue(int32 item);
/**
* Set a value of an item directly.
* @param item the item to set the value for.
* @param value the value to give to the item
* @return true if we could set the item to value, false otherwise.
* @note Changing values of items while looping through a list might cause
* entries to be skipped. Be very careful with such operations.
*/
bool SetValue(int32 item, int32 value);
/**
* Sort this list by the given sorter and direction.
* @param sorter the type of sorter to use
* @param ascending if true, lowest value is on top, else at bottom.
* @note the current item stays at the same place.
*/
void Sort(SorterType sorter, bool ascending);
/**
* Add one list to an other one.
* @param list The list that will be added to the caller.
* @post The list to be added ('list') stays unmodified.
* @note All added items keep their value as it was in 'list'.
* @note If the item already exists inside the caller, the value of the
* list that is added is set on the item.
*/
void AddList(AIAbstractList *list);
/**
* Removes all items with a higher value than 'value'.
* @param value the value above which all items are removed.
*/
void RemoveAboveValue(int32 value);
/**
* Removes all items with a lower value than 'value'.
* @param value the value below which all items are removed.
*/
void RemoveBelowValue(int32 value);
/**
* Removes all items with a value above start and below end.
* @param start the lower bound of the to be removed values (exclusive).
* @param end the upper bound of the to be removed valuens (exclusive).
*/
void RemoveBetweenValue(int32 start, int32 end);
/**
* Remove all items with this value.
* @param value the value to remove.
*/
void RemoveValue(int32 value);
/**
* Remove the first count items.
* @param count the amount of items to remove.
*/
void RemoveTop(int32 count);
/**
* Remove the last count items.
* @param count the amount of items to remove.
*/
void RemoveBottom(int32 count);
/**
* Remove everything that is in the given list from this list (same item index that is).
* @param list the list of items to remove.
* @pre list != NULL
*/
void RemoveList(AIAbstractList *list);
/**
* Keep all items with a higher value than 'value'.
* @param value the value above which all items are kept.
*/
void KeepAboveValue(int32 value);
/**
* Keep all items with a lower value than 'value'.
* @param value the value below which all items are kept.
*/
void KeepBelowValue(int32 value);
/**
* Keep all items with a value above start and below end.
* @param start the lower bound of the to be kept values (exclusive).
* @param end the upper bound of the to be kept values (exclusive).
*/
void KeepBetweenValue(int32 start, int32 end);
/**
* Keep all items with this value.
* @param value the value to keep.
**/
void KeepValue(int32 value);
/**
* Keep the first count items, i.e. remove everything except the first count items.
* @param count the amount of items to keep.
*/
void KeepTop(int32 count);
/**
* Keep the last count items, i.e. remove everything except the last count items.
* @param count the amount of items to keep.
*/
void KeepBottom(int32 count);
/**
* Keeps everything that is in the given list from this list (same item index that is).
* @param list the list of items to keep.
* @pre list != NULL
*/
void KeepList(AIAbstractList *list);
#ifndef DOXYGEN_SKIP
/**
* Used for 'foreach()' and [] get from Squirrel.
*/
SQInteger _get(HSQUIRRELVM vm);
/**
* Used for 'foreach()' from Squirrel.
*/
SQInteger _nexti(HSQUIRRELVM vm);
/**
* The Valuate() wrapper from Squirrel.
*/
SQInteger Valuate(HSQUIRRELVM vm);
#else
/**
* Give all items a value defined by the valuator you give.
* @param valuator_function The function which will be doing the valuation.
* @param params The params to give to the valuators (minus the first param,
* which is always the index-value we are valuating).
* @note You can write your own valuators and use them. Just remember that
* the first parameter should be the index-value, and it should return
* an integer.
* @note Example:
* list.Valuate(AIBridge.GetPrice, 5);
* list.Valuate(AIBridge.GetMaxLength);
* function MyVal(bridge_id, myparam) {
* return myparam * bridge_id; // This is silly
* }
* list.Valuate(MyVal, 12);
*/
void Valuate(void *valuator_function, int params, ...);
#endif /* DOXYGEN_SKIP */
};
#endif /* AI_LIST_HPP */

View File

@@ -0,0 +1,59 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_abstractlist.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AIAbstractList::SorterType GetParam(ForceType<AIAbstractList::SorterType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIAbstractList::SorterType)tmp; }
template <> int Return<AIAbstractList::SorterType>(HSQUIRRELVM vm, AIAbstractList::SorterType res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AIAbstractList to be used as Squirrel parameter */
template <> AIAbstractList *GetParam(ForceType<AIAbstractList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIAbstractList *)instance; }
template <> AIAbstractList &GetParam(ForceType<AIAbstractList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAbstractList *)instance; }
template <> const AIAbstractList *GetParam(ForceType<const AIAbstractList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIAbstractList *)instance; }
template <> const AIAbstractList &GetParam(ForceType<const AIAbstractList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAbstractList *)instance; }
template <> int Return<AIAbstractList *>(HSQUIRRELVM vm, AIAbstractList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIAbstractList", res, NULL, DefSQDestructorCallback<AIAbstractList>); return 1; }
}; // namespace SQConvert
void SQAIAbstractList_Register(Squirrel *engine) {
DefSQClass <AIAbstractList> SQAIAbstractList("AIAbstractList");
SQAIAbstractList.PreRegister(engine);
SQAIAbstractList.AddConstructor<void (AIAbstractList::*)(), 1>(engine, "x");
SQAIAbstractList.DefSQConst(engine, AIAbstractList::SORT_BY_VALUE, "SORT_BY_VALUE");
SQAIAbstractList.DefSQConst(engine, AIAbstractList::SORT_BY_ITEM, "SORT_BY_ITEM");
SQAIAbstractList.DefSQStaticMethod(engine, &AIAbstractList::GetClassName, "GetClassName", 1, "x");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Clear, "Clear", 1, "x");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::HasItem, "HasItem", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Begin, "Begin", 1, "x");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Next, "Next", 1, "x");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::IsEmpty, "IsEmpty", 1, "x");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::HasNext, "HasNext", 1, "x");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Count, "Count", 1, "x");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::GetValue, "GetValue", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::SetValue, "SetValue", 3, "xii");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::Sort, "Sort", 3, "xib");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::AddList, "AddList", 2, "xx");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveAboveValue, "RemoveAboveValue", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBelowValue, "RemoveBelowValue", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBetweenValue, "RemoveBetweenValue", 3, "xii");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveValue, "RemoveValue", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveTop, "RemoveTop", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveBottom, "RemoveBottom", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::RemoveList, "RemoveList", 2, "xx");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepAboveValue, "KeepAboveValue", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBelowValue, "KeepBelowValue", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBetweenValue, "KeepBetweenValue", 3, "xii");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepValue, "KeepValue", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepTop, "KeepTop", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepBottom, "KeepBottom", 2, "xi");
SQAIAbstractList.DefSQMethod(engine, &AIAbstractList::KeepList, "KeepList", 2, "xx");
SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::_get, "_get");
SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::_nexti, "_nexti");
SQAIAbstractList.DefSQAdvancedMethod(engine, &AIAbstractList::Valuate, "Valuate");
SQAIAbstractList.PostRegister(engine);
}

View File

@@ -0,0 +1,26 @@
/* $Id$ */
/** @file ai_accounting.cpp Implementation of AIAccounting. */
#include "ai_accounting.hpp"
Money AIAccounting::GetCosts()
{
return this->GetDoCommandCosts();
}
void AIAccounting::ResetCosts()
{
this->SetDoCommandCosts(0);
}
AIAccounting::AIAccounting()
{
this->last_costs = this->GetDoCommandCosts();
this->SetDoCommandCosts(0);
}
AIAccounting::~AIAccounting()
{
this->SetDoCommandCosts(this->last_costs);
}

View File

@@ -0,0 +1,54 @@
/* $Id$ */
/** @file ai_accounting.hpp Everything to handle AI accounting things. */
#ifndef AI_ACCOUNTING_HPP
#define AI_ACCOUNTING_HPP
#include "ai_object.hpp"
/**
* Class that keeps track of the costs, so you can request how much a block of
* commands did cost in total. Works in both Execute as in Test mode.
* Example:
* {
* local costs = AIAccounting();
* BuildRoad(from_here, to_here);
* BuildRoad(from_there, to_there);
* print("Costs for route is: " + costs.GetCosts());
* }
*/
class AIAccounting : public AIObject {
public:
static const char *GetClassName() { return "AIAccounting"; }
/**
* Creating instance of this class starts counting the costs of commands
* from zero.
* @note when the instance is destroyed, he restores the costs that was
* current when the instance was created!
*/
AIAccounting();
/**
* Destroying this instance reset the costs to the value it was
* in when the instance was created.
*/
~AIAccounting();
/**
* Get the current value of the costs.
* @return The current costs.
*/
Money GetCosts();
/**
* Reset the costs to zero.
*/
void ResetCosts();
private:
Money last_costs;
};
#endif /* AI_ACCOUNTING_HPP */

View File

@@ -0,0 +1,26 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_accounting.hpp"
namespace SQConvert {
/* Allow AIAccounting to be used as Squirrel parameter */
template <> AIAccounting *GetParam(ForceType<AIAccounting *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIAccounting *)instance; }
template <> AIAccounting &GetParam(ForceType<AIAccounting &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAccounting *)instance; }
template <> const AIAccounting *GetParam(ForceType<const AIAccounting *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIAccounting *)instance; }
template <> const AIAccounting &GetParam(ForceType<const AIAccounting &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAccounting *)instance; }
template <> int Return<AIAccounting *>(HSQUIRRELVM vm, AIAccounting *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIAccounting", res, NULL, DefSQDestructorCallback<AIAccounting>); return 1; }
}; // namespace SQConvert
void SQAIAccounting_Register(Squirrel *engine) {
DefSQClass <AIAccounting> SQAIAccounting("AIAccounting");
SQAIAccounting.PreRegister(engine);
SQAIAccounting.AddConstructor<void (AIAccounting::*)(), 1>(engine, "x");
SQAIAccounting.DefSQStaticMethod(engine, &AIAccounting::GetClassName, "GetClassName", 1, "x");
SQAIAccounting.DefSQMethod(engine, &AIAccounting::GetCosts, "GetCosts", 1, "x");
SQAIAccounting.DefSQMethod(engine, &AIAccounting::ResetCosts, "ResetCosts", 1, "x");
SQAIAccounting.PostRegister(engine);
}

130
src/ai/api/ai_airport.cpp Normal file
View File

@@ -0,0 +1,130 @@
/* $Id$ */
/** @file ai_airport.cpp Implementation of AIAirport. */
#include "ai_airport.hpp"
#include "ai_station.hpp"
#include "ai_error.hpp"
#include "../../openttd.h"
#include "../../variables.h"
#include "../../station_map.h"
#include "../../company_func.h"
#include "../../settings_type.h"
#include "../../command_type.h"
#include "../../town.h"
/* static */ bool AIAirport::IsValidAirportType(AirportType type)
{
return type >= AT_SMALL && type <= AT_HELISTATION;
}
/* static */ bool AIAirport::IsHangarTile(TileIndex tile)
{
if (!::IsValidTile(tile)) return false;
return ::IsTileType(tile, MP_STATION) && ::IsHangar(tile);
}
/* static */ bool AIAirport::IsAirportTile(TileIndex tile)
{
if (!::IsValidTile(tile)) return false;
return ::IsTileType(tile, MP_STATION) && ::IsAirport(tile);
}
/* static */ bool AIAirport::AirportAvailable(AirportType type)
{
if (!IsValidAirportType(type)) return false;
return HasBit(::GetValidAirports(), type);
}
/* static */ int32 AIAirport::GetAirportWidth(AirportType type)
{
if (!IsValidAirportType(type)) return -1;
return ::GetAirport(type)->size_x;
}
/* static */ int32 AIAirport::GetAirportHeight(AirportType type)
{
if (!IsValidAirportType(type)) return -1;
return ::GetAirport(type)->size_y;
}
/* static */ int32 AIAirport::GetAirportCoverageRadius(AirportType type)
{
if (!IsValidAirportType(type)) return -1;
return _settings_game.station.modified_catchment ? ::GetAirport(type)->catchment : (uint)CA_UNMODIFIED;
}
/* static */ bool AIAirport::BuildAirport(TileIndex tile, AirportType type, bool join_adjacent)
{
EnforcePrecondition(false, ::IsValidTile(tile));
EnforcePrecondition(false, IsValidAirportType(type));
return AIObject::DoCommand(tile, type, (INVALID_STATION << 16) | (join_adjacent ? 0 : 1), CMD_BUILD_AIRPORT);
}
/* static */ bool AIAirport::RemoveAirport(TileIndex tile)
{
EnforcePrecondition(false, ::IsValidTile(tile))
EnforcePrecondition(false, IsAirportTile(tile) || IsHangarTile(tile));
return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
}
/* static */ int32 AIAirport::GetNumHangars(TileIndex tile)
{
if (!::IsValidTile(tile)) return -1;
if (!::IsTileType(tile, MP_STATION)) return -1;
const Station *st = ::GetStationByTile(tile);
if (st->owner != _current_company) return -1;
if ((st->facilities & FACIL_AIRPORT) == 0) return -1;
return st->Airport()->nof_depots;
}
/* static */ TileIndex AIAirport::GetHangarOfAirport(TileIndex tile)
{
if (!::IsValidTile(tile)) return INVALID_TILE;
if (!::IsTileType(tile, MP_STATION)) return INVALID_TILE;
if (GetNumHangars(tile) < 1) return INVALID_TILE;
const Station *st = ::GetStationByTile(tile);
if (st->owner != _current_company) return INVALID_TILE;
if ((st->facilities & FACIL_AIRPORT) == 0) return INVALID_TILE;
return ::ToTileIndexDiff(st->Airport()->airport_depots[0]) + st->xy;
}
/* static */ AIAirport::AirportType AIAirport::GetAirportType(TileIndex tile)
{
if (!AITile::IsStationTile(tile)) return AT_INVALID;
StationID station_id = ::GetStationIndex(tile);
if (!AIStation::HasStationType(station_id, AIStation::STATION_AIRPORT)) return AT_INVALID;
return (AirportType)::GetStation(station_id)->airport_type;
}
/* static */ int AIAirport::GetNoiseLevelIncrease(TileIndex tile, AirportType type)
{
extern uint8 GetAirportNoiseLevelForTown(const AirportFTAClass *afc, TileIndex town_tile, TileIndex tile);
if (!::IsValidTile(tile)) return -1;
if (!IsValidAirportType(type)) return -1;
if (_settings_game.economy.station_noise_level) {
const AirportFTAClass *afc = ::GetAirport(type);
const Town *t = ::ClosestTownFromTile(tile, UINT_MAX);
return GetAirportNoiseLevelForTown(afc, t->xy, tile);
}
return 1;
}

164
src/ai/api/ai_airport.hpp Normal file
View File

@@ -0,0 +1,164 @@
/* $Id$ */
/** @file ai_airport.hpp Everything to query and build airports. */
#ifndef AI_AIRPORT_HPP
#define AI_AIRPORT_HPP
#include "ai_object.hpp"
/**
* Class that handles all airport related functions.
*/
class AIAirport : public AIObject {
public:
static const char *GetClassName() { return "AIAirport"; }
/**
* The types of airports available in the game.
*/
enum AirportType {
/* Note: the values _are_ important as they represent an in-game value */
AT_SMALL = 0, //!< The small airport.
AT_LARGE = 1, //!< The large airport.
AT_METROPOLITAN = 3, //!< The metropolitan airport.
AT_INTERNATIONAL = 4, //!< The international airport.
AT_COMMUTER = 5, //!< The commuter airport.
AT_INTERCON = 7, //!< The intercontinental airport.
/* Next are the airports which only have helicopter platforms */
AT_HELIPORT = 2, //!< The heliport.
AT_HELISTATION = 8, //!< The helistation.
AT_HELIDEPOT = 6, //!< The helidepot.
AT_INVALID = 255, //!< Invalid airport.
};
/**
* All plane types available.
*/
enum PlaneType {
/* Note: the values _are_ important as they represent an in-game value */
PT_HELICOPTER = 0, //!< A helicopter.
PT_SMALL_PLANE = 1, //!< A small plane.
PT_BIG_PLANE = 3, //!< A big plane.
PT_INVALID = -1, //!< An invalid PlaneType
};
/**
* Checks whether the given AirportType is valid.
* @param type The AirportType to check.
* @return True if and only if the AirportTypeis valid.
*/
static bool IsValidAirportType(AirportType type);
/**
* Checks whether the given tile is actually a tile with a hangar.
* @param tile The tile to check.
* @pre AIMap::IsValidTile(tile).
* @return True if and only if the tile has a hangar.
*/
static bool IsHangarTile(TileIndex tile);
/**
* Checks whether the given tile is actually a tile with a airport.
* @param tile The tile to check.
* @pre AIMap::IsValidTile(tile).
* @return True if and only if the tile has a airport.
*/
static bool IsAirportTile(TileIndex tile);
/**
* Check if a certain airport type is already available.
* @param type The type of airport to check.
*/
static bool AirportAvailable(AirportType type);
/**
* Get the width of this type of airport.
* @param type The type of airport.
* @return The width in tiles.
*/
static int32 GetAirportWidth(AirportType type);
/**
* Get the height of this type of airport.
* @param type The type of airport.
* @return The height in tiles.
*/
static int32 GetAirportHeight(AirportType type);
/**
* Get the coverage radius of this type of airport.
* @param type The type of airport.
* @return The radius in tiles.
*/
static int32 GetAirportCoverageRadius(AirportType type);
/**
* Get the number of hangars of the airport.
* @param tile Any tile of the airport.
* @pre AIMap::IsValidTile(tile).
* @return The number of hangars of the airport.
*/
static int32 GetNumHangars(TileIndex tile);
/**
* Get the first hanger tile of the airport.
* @param tile Any tile of the airport.
* @pre AIMap::IsValidTile(tile).
* @pre GetNumHangars(tile) > 0.
* @return The first hanger tile of the airport.
* @note Possible there are more hangars, but you won't be able to find them
* without walking over all the tiles of the airport and using
* IsHangarTile() on them.
*/
static TileIndex GetHangarOfAirport(TileIndex tile);
/**
* Builds a airport with tile at the topleft corner.
* @param tile The topleft corner of the airport.
* @param type The type of airport to build.
* @param join_adjacent When building next to an other station, don't create a new station when this flag is true.
* @pre AIMap::IsValidTile(tile).
* @pre AirportAvailable(type).
* @exception AIError::ERR_AREA_NOT_CLEAR
* @exception AIError::ERR_FLAT_LAND_REQUIRED
* @exception AIError::ERR_LOCAL_AUTHORITY_REFUSES
* @exception AIStation::ERR_STATION_TOO_LARGE
* @exception AIStation::ERR_STATION_TOO_CLOSE_TO_OTHER_STATION
* @return Whether the airport has been/can be build or not.
*/
static bool BuildAirport(TileIndex tile, AirportType type, bool join_adjacent);
/**
* Removes a airport.
* @param tile Any tile of the airport.
* @pre AIMap::IsValidTile(tile).
* @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
* @return Whether the airport has been/can be removed or not.
*/
static bool RemoveAirport(TileIndex tile);
/**
* Get the AirportType of an existing airport.
* @param tile Any tile of the airport.
* @pre AITile::IsStationTile(tile).
* @pre AIStation::HasStationType(AIStation.GetStationID(tile), AIStation::STATION_AIRPORT).
* @return The AirportType of the airport.
*/
static AirportType GetAirportType(TileIndex tile);
/**
* Get the noise that will be added to the nearest town if an airport was
* built at this tile.
* @param tile The tile to check.
* @param type The AirportType to check.
* @return The TownID of the town closest to the tile.
* @note The noise will be added to the town with TownID AITile.GetClosestTown(tile).
*/
static int GetNoiseLevelIncrease(TileIndex tile, AirportType type);
};
#endif /* AI_AIRPORT_HPP */

View File

@@ -0,0 +1,57 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_airport.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AIAirport::AirportType GetParam(ForceType<AIAirport::AirportType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIAirport::AirportType)tmp; }
template <> int Return<AIAirport::AirportType>(HSQUIRRELVM vm, AIAirport::AirportType res) { sq_pushinteger(vm, (int32)res); return 1; }
template <> AIAirport::PlaneType GetParam(ForceType<AIAirport::PlaneType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIAirport::PlaneType)tmp; }
template <> int Return<AIAirport::PlaneType>(HSQUIRRELVM vm, AIAirport::PlaneType res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AIAirport to be used as Squirrel parameter */
template <> AIAirport *GetParam(ForceType<AIAirport *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIAirport *)instance; }
template <> AIAirport &GetParam(ForceType<AIAirport &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAirport *)instance; }
template <> const AIAirport *GetParam(ForceType<const AIAirport *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIAirport *)instance; }
template <> const AIAirport &GetParam(ForceType<const AIAirport &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIAirport *)instance; }
template <> int Return<AIAirport *>(HSQUIRRELVM vm, AIAirport *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIAirport", res, NULL, DefSQDestructorCallback<AIAirport>); return 1; }
}; // namespace SQConvert
void SQAIAirport_Register(Squirrel *engine) {
DefSQClass <AIAirport> SQAIAirport("AIAirport");
SQAIAirport.PreRegister(engine);
SQAIAirport.AddConstructor<void (AIAirport::*)(), 1>(engine, "x");
SQAIAirport.DefSQConst(engine, AIAirport::AT_SMALL, "AT_SMALL");
SQAIAirport.DefSQConst(engine, AIAirport::AT_LARGE, "AT_LARGE");
SQAIAirport.DefSQConst(engine, AIAirport::AT_METROPOLITAN, "AT_METROPOLITAN");
SQAIAirport.DefSQConst(engine, AIAirport::AT_INTERNATIONAL, "AT_INTERNATIONAL");
SQAIAirport.DefSQConst(engine, AIAirport::AT_COMMUTER, "AT_COMMUTER");
SQAIAirport.DefSQConst(engine, AIAirport::AT_INTERCON, "AT_INTERCON");
SQAIAirport.DefSQConst(engine, AIAirport::AT_HELIPORT, "AT_HELIPORT");
SQAIAirport.DefSQConst(engine, AIAirport::AT_HELISTATION, "AT_HELISTATION");
SQAIAirport.DefSQConst(engine, AIAirport::AT_HELIDEPOT, "AT_HELIDEPOT");
SQAIAirport.DefSQConst(engine, AIAirport::AT_INVALID, "AT_INVALID");
SQAIAirport.DefSQConst(engine, AIAirport::PT_HELICOPTER, "PT_HELICOPTER");
SQAIAirport.DefSQConst(engine, AIAirport::PT_SMALL_PLANE, "PT_SMALL_PLANE");
SQAIAirport.DefSQConst(engine, AIAirport::PT_BIG_PLANE, "PT_BIG_PLANE");
SQAIAirport.DefSQConst(engine, AIAirport::PT_INVALID, "PT_INVALID");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::GetClassName, "GetClassName", 1, "x");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::IsValidAirportType, "IsValidAirportType", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::IsHangarTile, "IsHangarTile", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::IsAirportTile, "IsAirportTile", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::AirportAvailable, "AirportAvailable", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::GetAirportWidth, "GetAirportWidth", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::GetAirportHeight, "GetAirportHeight", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::GetAirportCoverageRadius, "GetAirportCoverageRadius", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::GetNumHangars, "GetNumHangars", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::GetHangarOfAirport, "GetHangarOfAirport", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::BuildAirport, "BuildAirport", 4, "xiib");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::RemoveAirport, "RemoveAirport", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::GetAirportType, "GetAirportType", 2, "xi");
SQAIAirport.DefSQStaticMethod(engine, &AIAirport::GetNoiseLevelIncrease, "GetNoiseLevelIncrease", 3, "xii");
SQAIAirport.PostRegister(engine);
}

43
src/ai/api/ai_base.cpp Normal file
View File

@@ -0,0 +1,43 @@
/* $Id$ */
/** @file ai_base.cpp Implementation of AIBase. */
#include "ai_base.hpp"
#include "../../network/network.h"
#include "../../core/random_func.hpp"
/* static */ uint32 AIBase::Rand()
{
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
* but we pick InteractiveRandomRange if we are a network_server or network-client. */
if (_networking) return ::InteractiveRandom();
return ::Random();
}
/* static */ uint32 AIBase::RandItem(int unused_param)
{
return AIBase::Rand();
}
/* static */ uint AIBase::RandRange(uint max)
{
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
* but we pick InteractiveRandomRange if we are a network_server or network-client. */
if (_networking) return ::InteractiveRandomRange(max);
return ::RandomRange(max);
}
/* static */ uint32 AIBase::RandRangeItem(int unused_param, uint max)
{
return AIBase::RandRange(max);
}
/* static */ bool AIBase::Chance(uint out, uint max)
{
return (uint16)Rand() <= (uint16)((65536 * out) / max);
}
/* static */ bool AIBase::ChanceItem(int unused_param, uint out, uint max)
{
return AIBase::Chance(out, max);
}

71
src/ai/api/ai_base.hpp Normal file
View File

@@ -0,0 +1,71 @@
/* $Id$ */
/** @file ai_base.hpp Everything to query basic things. */
#ifndef AI_BASE_HPP
#define AI_BASE_HPP
#include "ai_object.hpp"
/**
* Class that handles some basic functions.
*
* @note The random functions are not called Random and RandomRange, because
* RANDOM_DEBUG does some tricky stuff, which messes with those names.
* @note In MP we cannot use Random because that will cause desyncs (AIs are
* ran on the server only, not on all clients). This means that
* we use InteractiveRandom in MP. Rand() takes care of this for you.
*/
class AIBase : public AIObject {
public:
static const char *GetClassName() { return "AIBase"; }
/**
* Get a random value.
* @return A random value between 0 and MAX(uint32).
*/
static uint32 Rand();
/**
* Get a random value.
* @param unused_param This param is not used, but is needed to work with lists.
* @return A random value between 0 and MAX(uint32).
*/
static uint32 RandItem(int unused_param);
/**
* Get a random value in a range.
* @param max The first number this function will never return (the maximum it returns is max - 1).
* @return A random value between 0 .. max - 1.
*/
static uint RandRange(uint max);
/**
* Get a random value in a range.
* @param unused_param This param is not used, but is needed to work with lists.
* @param max The first number this function will never return (the maximum it returns is max - 1).
* @return A random value between 0 .. max - 1.
*/
static uint RandRangeItem(int unused_param, uint max);
/**
* Returns approximatelly 'out' times true when called 'max' times.
* After all, it is a random function.
* @param out How many times it should return true.
* @param max Out of this many times.
* @return True if the chance worked out.
*/
static bool Chance(uint out, uint max);
/**
* Returns approximatelly 'out' times true when called 'max' times.
* After all, it is a random function.
* @param unused_param This param is not used, but is needed to work with lists.
* @param out How many times it should return true.
* @param max Out of this many times.
* @return True if the chance worked out.
*/
static bool ChanceItem(int unused_param, uint out, uint max);
};
#endif /* AI_BASE_HPP */

29
src/ai/api/ai_base.hpp.sq Normal file
View File

@@ -0,0 +1,29 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_base.hpp"
namespace SQConvert {
/* Allow AIBase to be used as Squirrel parameter */
template <> AIBase *GetParam(ForceType<AIBase *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIBase *)instance; }
template <> AIBase &GetParam(ForceType<AIBase &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIBase *)instance; }
template <> const AIBase *GetParam(ForceType<const AIBase *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIBase *)instance; }
template <> const AIBase &GetParam(ForceType<const AIBase &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIBase *)instance; }
template <> int Return<AIBase *>(HSQUIRRELVM vm, AIBase *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIBase", res, NULL, DefSQDestructorCallback<AIBase>); return 1; }
}; // namespace SQConvert
void SQAIBase_Register(Squirrel *engine) {
DefSQClass <AIBase> SQAIBase("AIBase");
SQAIBase.PreRegister(engine);
SQAIBase.AddConstructor<void (AIBase::*)(), 1>(engine, "x");
SQAIBase.DefSQStaticMethod(engine, &AIBase::GetClassName, "GetClassName", 1, "x");
SQAIBase.DefSQStaticMethod(engine, &AIBase::Rand, "Rand", 1, "x");
SQAIBase.DefSQStaticMethod(engine, &AIBase::RandItem, "RandItem", 2, "xi");
SQAIBase.DefSQStaticMethod(engine, &AIBase::RandRange, "RandRange", 2, "xi");
SQAIBase.DefSQStaticMethod(engine, &AIBase::RandRangeItem, "RandRangeItem", 3, "xii");
SQAIBase.DefSQStaticMethod(engine, &AIBase::Chance, "Chance", 3, "xii");
SQAIBase.DefSQStaticMethod(engine, &AIBase::ChanceItem, "ChanceItem", 4, "xiii");
SQAIBase.PostRegister(engine);
}

177
src/ai/api/ai_bridge.cpp Normal file
View File

@@ -0,0 +1,177 @@
/* $Id$ */
/** @file ai_bridge.cpp Implementation of AIBridge. */
#include "ai_bridge.hpp"
#include "ai_rail.hpp"
#include "../ai_instance.hpp"
#include "../../openttd.h"
#include "../../bridge_map.h"
#include "../../strings_func.h"
#include "../../core/alloc_func.hpp"
#include "../../economy_func.h"
#include "../../settings_type.h"
#include "../../road_map.h"
#include "table/strings.h"
/* static */ bool AIBridge::IsValidBridge(BridgeID bridge_id)
{
return bridge_id < MAX_BRIDGES;
}
/* static */ bool AIBridge::IsBridgeTile(TileIndex tile)
{
if (!::IsValidTile(tile)) return false;
return ::IsBridgeTile(tile);
}
static void _DoCommandReturnBuildBridge2(class AIInstance *instance)
{
if (!AIBridge::_BuildBridgeRoad2()) {
AIObject::SetLastCommandRes(false);
AIInstance::DoCommandReturn(instance);
return;
}
/* This can never happen, as in test-mode this callback is never executed,
* and in execute-mode, the other callback is called. */
NOT_REACHED();
}
static void _DoCommandReturnBuildBridge1(class AIInstance *instance)
{
if (!AIBridge::_BuildBridgeRoad1()) {
AIObject::SetLastCommandRes(false);
AIInstance::DoCommandReturn(instance);
return;
}
/* This can never happen, as in test-mode this callback is never executed,
* and in execute-mode, the other callback is called. */
NOT_REACHED();
}
/* static */ bool AIBridge::BuildBridge(AIVehicle::VehicleType vehicle_type, BridgeID bridge_id, TileIndex start, TileIndex end)
{
EnforcePrecondition(false, start != end);
EnforcePrecondition(false, ::IsValidTile(start) && ::IsValidTile(end));
EnforcePrecondition(false, TileX(start) == TileX(end) || TileY(start) == TileY(end));
EnforcePrecondition(false, vehicle_type == AIVehicle::VEHICLE_ROAD || vehicle_type == AIVehicle::VEHICLE_RAIL || vehicle_type == AIVehicle::VEHICLE_WATER);
EnforcePrecondition(false, vehicle_type != AIVehicle::VEHICLE_RAIL || AIRail::IsRailTypeAvailable(AIRail::GetCurrentRailType()));
uint type = 0;
switch (vehicle_type) {
case AIVehicle::VEHICLE_ROAD:
type |= (TRANSPORT_ROAD << 15);
type |= (RoadTypeToRoadTypes((::RoadType)AIObject::GetRoadType()) << 8);
break;
case AIVehicle::VEHICLE_RAIL:
type |= (TRANSPORT_RAIL << 15);
type |= (AIRail::GetCurrentRailType() << 8);
break;
case AIVehicle::VEHICLE_WATER:
type |= (TRANSPORT_WATER << 15);
break;
default: NOT_REACHED();
}
/* For rail and water we do nothing special */
if (vehicle_type == AIVehicle::VEHICLE_RAIL || vehicle_type == AIVehicle::VEHICLE_WATER) {
return AIObject::DoCommand(end, start, type | bridge_id, CMD_BUILD_BRIDGE);
}
AIObject::SetCallbackVariable(0, start);
if (!AIObject::DoCommand(end, start, type | bridge_id, CMD_BUILD_BRIDGE, NULL, &_DoCommandReturnBuildBridge1)) return false;
/* In case of test-mode, test if we can build both road pieces */
return _BuildBridgeRoad1();
}
/* static */ bool AIBridge::_BuildBridgeRoad1()
{
/* Build the piece of road on the 'start' side of the bridge */
TileIndex end = AIObject::GetCallbackVariable(0);
TileIndex start = AIBridge::GetOtherBridgeEnd(end);
DiagDirection dir_1 = (DiagDirection)((::TileX(start) == ::TileX(end)) ? (::TileY(start) < ::TileY(end) ? DIAGDIR_NW : DIAGDIR_SE) : (::TileX(start) < ::TileX(end) ? DIAGDIR_NE : DIAGDIR_SW));
DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
if (!AIObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (AIObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD, NULL, &_DoCommandReturnBuildBridge2)) return false;
/* In case of test-mode, test the other road piece too */
return _BuildBridgeRoad2();
}
/* static */ bool AIBridge::_BuildBridgeRoad2()
{
/* Build the piece of road on the 'end' side of the bridge */
TileIndex end = AIObject::GetCallbackVariable(0);
TileIndex start = AIBridge::GetOtherBridgeEnd(end);
DiagDirection dir_1 = (DiagDirection)((::TileX(start) == ::TileX(end)) ? (::TileY(start) < ::TileY(end) ? DIAGDIR_NW : DIAGDIR_SE) : (::TileX(start) < ::TileX(end) ? DIAGDIR_NE : DIAGDIR_SW));
DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
return AIObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (AIObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD);
}
/* static */ bool AIBridge::RemoveBridge(TileIndex tile)
{
EnforcePrecondition(false, IsBridgeTile(tile));
return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
}
/* static */ const char *AIBridge::GetName(BridgeID bridge_id)
{
if (!IsValidBridge(bridge_id)) return NULL;
static const int len = 64;
char *bridge_name = MallocT<char>(len);
::GetString(bridge_name, ::GetBridgeSpec(bridge_id)->transport_name[0], &bridge_name[len - 1]);
return bridge_name;
}
/* static */ int32 AIBridge::GetMaxSpeed(BridgeID bridge_id)
{
if (!IsValidBridge(bridge_id)) return -1;
return ::GetBridgeSpec(bridge_id)->speed;
}
/* static */ Money AIBridge::GetPrice(BridgeID bridge_id, uint length)
{
if (!IsValidBridge(bridge_id)) return -1;
return length * _price.build_bridge * ::GetBridgeSpec(bridge_id)->price >> 8;
}
/* static */ int32 AIBridge::GetMaxLength(BridgeID bridge_id)
{
if (!IsValidBridge(bridge_id)) return -1;
uint max = ::GetBridgeSpec(bridge_id)->max_length;
if (max >= 16 && _settings_game.construction.longbridges) max = 100;
return max + 2;
}
/* static */ int32 AIBridge::GetMinLength(BridgeID bridge_id)
{
if (!IsValidBridge(bridge_id)) return -1;
return ::GetBridgeSpec(bridge_id)->min_length + 2;
}
/* static */ int32 AIBridge::GetYearAvailable(BridgeID bridge_id)
{
if (!IsValidBridge(bridge_id)) return -1;
return ::GetBridgeSpec(bridge_id)->avail_year;
}
/* static */ TileIndex AIBridge::GetOtherBridgeEnd(TileIndex tile)
{
if (!::IsValidTile(tile)) return INVALID_TILE;
if (!IsBridgeTile(tile)) return INVALID_TILE;
return ::GetOtherBridgeEnd(tile);
}

164
src/ai/api/ai_bridge.hpp Normal file
View File

@@ -0,0 +1,164 @@
/* $Id$ */
/** @file ai_bridge.hpp Everything to query and build bridges. */
#ifndef AI_BRIDGE_HPP
#define AI_BRIDGE_HPP
#include "ai_object.hpp"
#include "ai_vehicle.hpp"
#include "ai_error.hpp"
/**
* Class that handles all bridge related functions.
*/
class AIBridge : public AIObject {
public:
/**
* All bridge related error messages.
*/
enum ErrorMessages {
/** Base for bridge related errors */
ERR_BRIDGE_BASE = AIError::ERR_CAT_BRIDGE << AIError::ERR_CAT_BIT_SIZE,
/**
* The bridge you want to build is not available yet,
* or it is not available for the requested length.
*/
ERR_BRIDGE_TYPE_UNAVAILABLE, // [STR_5015_CAN_T_BUILD_BRIDGE_HERE]
/** One (or more) of the bridge head(s) ends in water. */
ERR_BRIDGE_CANNOT_END_IN_WATER, // [STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH]
/** The bride heads need to be on the same height */
ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT, // [STR_BRIDGEHEADS_NOT_SAME_HEIGHT]
};
static const char *GetClassName() { return "AIBridge"; }
/**
* Checks whether the given bridge type is valid.
* @param bridge_id The bridge to check.
* @return True if and only if the bridge type is valid.
*/
static bool IsValidBridge(BridgeID bridge_id);
/**
* Checks whether the given tile is actually a bridge start or end tile.
* @param tile The tile to check.
* @pre AIMap::IsValidTile(tile).
* @return True if and only if the tile is the beginning or end of a bridge.
*/
static bool IsBridgeTile(TileIndex tile);
/**
* Get the name of a bridge.
* @param bridge_id The bridge to get the name of.
* @pre IsValidBridge(bridge_id).
* @return The name the bridge has.
*/
static const char *GetName(BridgeID bridge_id);
/**
* Get the maximum speed of a bridge (in km/h).
* @param bridge_id The bridge to get the maximum speed of.
* @pre IsValidBridge(bridge_id).
* @return The maximum speed the bridge has.
*/
static int32 GetMaxSpeed(BridgeID bridge_id);
/**
* Get the new cost of a bridge.
* @param bridge_id The bridge to get the new cost of.
* @param length The length of the bridge.
* @pre IsValidBridge(bridge_id).
* @return The new cost the bridge has.
*/
static Money GetPrice(BridgeID bridge_id, uint length);
/**
* Get the maximum length of a bridge.
* @param bridge_id The bridge to get the maximum length of.
* @pre IsValidBridge(bridge_id).
* @returns The maximum length the bridge has.
*/
static int32 GetMaxLength(BridgeID bridge_id);
/**
* Get the minimum length of a bridge.
* @param bridge_id The bridge to get the minimum length of.
* @pre IsValidBridge(bridge_id).
* @returns The minimum length the bridge has.
*/
static int32 GetMinLength(BridgeID bridge_id);
/**
* Get the year in which a bridge becomes available.
* @param bridge_id The bridge to get the year of availability of.
* @pre IsValidBridge(bridge_id).
* @returns The year of availability the bridge has.
* @note Years are like 2010, -10 (10 B.C.), 1950, ..
*/
static int32 GetYearAvailable(BridgeID bridge_id);
#ifndef DOXYGEN_SKIP
/**
* Internal function to help BuildBridge in case of road.
*/
static bool _BuildBridgeRoad1();
/**
* Internal function to help BuildBridge in case of road.
*/
static bool _BuildBridgeRoad2();
#endif
/**
* Build a bridge from one tile to the other.
* As an extra for road, this functions builds two half-pieces of road on
* each end of the bridge, making it easier for you to connect it to your
* network.
* @param vehicle_type The vehicle-type of bridge to build.
* @param bridge_id The bridge-type to build.
* @param start Where to start the bridge.
* @param end Where to end the bridge.
* @pre AIMap::IsValidTile(start).
* @pre AIMap::IsValidTile(end).
* @pre 'start' and 'end' are in a straight line, i.e.
* AIMap::GetTileX(start) == AIMap::GetTileX(end) or
* AIMap::GetTileY(start) == AIMap::GetTileY(end).
* @pre vehicle_type == AIVehicle::VEHICLE_ROAD || (vehicle_type == AIVehicle::VEHICLE_RAIL &&
* AIRail::IsRailTypeAvailable(AIRail::GetCurrentRailType())) || vehicle_type == AIVehicle::VEHICLE_WATER.
* @exception AIError::ERR_ALREADY_BUILT
* @exception AIError::ERR_AREA_NOT_CLEAR
* @exception AIError::ERR_LAND_SLOPED_WRONG
* @exception AIError::ERR_VEHICLE_IN_THE_WAY
* @exception AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE
* @exception AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER
* @exception AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT
* @return Whether the bridge has been/can be build or not.
* @note No matter if the road pieces were build or not, if building the
* bridge succeeded, this function returns true.
*/
static bool BuildBridge(AIVehicle::VehicleType vehicle_type, BridgeID bridge_id, TileIndex start, TileIndex end);
/**
* Removes a bridge, by executing it on either the start or end tile.
* @param tile An end or start tile of the bridge.
* @pre AIMap::IsValidTile(tile).
* @exception AIError::ERR_OWNED_BY_ANOTHER_COMPANY
* @return Whether the bridge has been/can be removed or not.
*/
static bool RemoveBridge(TileIndex tile);
/**
* Get the tile that is on the other end of a bridge starting at tile.
* @param tile The tile that is an end of a bridge.
* @pre AIMap::IsValidTile(tile).
* @pre IsBridgeTile(tile).
* @return The TileIndex that is the other end of the bridge.
*/
static TileIndex GetOtherBridgeEnd(TileIndex tile);
};
#endif /* AI_BRIDGE_HPP */

View File

@@ -0,0 +1,51 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_bridge.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AIBridge::ErrorMessages GetParam(ForceType<AIBridge::ErrorMessages>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIBridge::ErrorMessages)tmp; }
template <> int Return<AIBridge::ErrorMessages>(HSQUIRRELVM vm, AIBridge::ErrorMessages res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AIBridge to be used as Squirrel parameter */
template <> AIBridge *GetParam(ForceType<AIBridge *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIBridge *)instance; }
template <> AIBridge &GetParam(ForceType<AIBridge &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIBridge *)instance; }
template <> const AIBridge *GetParam(ForceType<const AIBridge *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIBridge *)instance; }
template <> const AIBridge &GetParam(ForceType<const AIBridge &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIBridge *)instance; }
template <> int Return<AIBridge *>(HSQUIRRELVM vm, AIBridge *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIBridge", res, NULL, DefSQDestructorCallback<AIBridge>); return 1; }
}; // namespace SQConvert
void SQAIBridge_Register(Squirrel *engine) {
DefSQClass <AIBridge> SQAIBridge("AIBridge");
SQAIBridge.PreRegister(engine);
SQAIBridge.AddConstructor<void (AIBridge::*)(), 1>(engine, "x");
SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_BASE, "ERR_BRIDGE_BASE");
SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE, "ERR_BRIDGE_TYPE_UNAVAILABLE");
SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER, "ERR_BRIDGE_CANNOT_END_IN_WATER");
SQAIBridge.DefSQConst(engine, AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT, "ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT");
AIError::RegisterErrorMap(STR_5015_CAN_T_BUILD_BRIDGE_HERE, AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE);
AIError::RegisterErrorMap(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH, AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER);
AIError::RegisterErrorMap(STR_BRIDGEHEADS_NOT_SAME_HEIGHT, AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT);
AIError::RegisterErrorMapString(AIBridge::ERR_BRIDGE_TYPE_UNAVAILABLE, "ERR_BRIDGE_TYPE_UNAVAILABLE");
AIError::RegisterErrorMapString(AIBridge::ERR_BRIDGE_CANNOT_END_IN_WATER, "ERR_BRIDGE_CANNOT_END_IN_WATER");
AIError::RegisterErrorMapString(AIBridge::ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT, "ERR_BRIDGE_HEADS_NOT_ON_SAME_HEIGHT");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetClassName, "GetClassName", 1, "x");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::IsValidBridge, "IsValidBridge", 2, "xi");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::IsBridgeTile, "IsBridgeTile", 2, "xi");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetName, "GetName", 2, "xi");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetMaxSpeed, "GetMaxSpeed", 2, "xi");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetPrice, "GetPrice", 3, "xii");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetMaxLength, "GetMaxLength", 2, "xi");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetMinLength, "GetMinLength", 2, "xi");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetYearAvailable, "GetYearAvailable", 2, "xi");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::BuildBridge, "BuildBridge", 5, "xiiii");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::RemoveBridge, "RemoveBridge", 2, "xi");
SQAIBridge.DefSQStaticMethod(engine, &AIBridge::GetOtherBridgeEnd, "GetOtherBridgeEnd", 2, "xi");
SQAIBridge.PostRegister(engine);
}

View File

@@ -0,0 +1,25 @@
/* $Id$ */
/** @file ai_bridgelist.cpp Implementation of AIBridgeList and friends. */
#include "ai_bridgelist.hpp"
#include "ai_bridge.hpp"
#include "../../openttd.h"
#include "../../bridge.h"
#include "../../date_func.h"
AIBridgeList::AIBridgeList()
{
/* Add all bridges, no matter if they are available or not */
for (byte j = 0; j < MAX_BRIDGES; j++)
if (::GetBridgeSpec(j)->avail_year <= _cur_year)
this->AddItem(j);
}
AIBridgeList_Length::AIBridgeList_Length(uint length)
{
for (byte j = 0; j < MAX_BRIDGES; j++)
if (::GetBridgeSpec(j)->avail_year <= _cur_year)
if (length >= (uint)AIBridge::GetMinLength(j) && length <= (uint)AIBridge::GetMaxLength(j))
this->AddItem(j);
}

View File

@@ -0,0 +1,34 @@
/* $Id$ */
/** @file ai_bridgelist.hpp List all the bridges. */
#ifndef AI_BRIDGELIST_HPP
#define AI_BRIDGELIST_HPP
#include "ai_abstractlist.hpp"
/**
* Create a list of bridges.
* @ingroup AIList
*/
class AIBridgeList : public AIAbstractList {
public:
static const char *GetClassName() { return "AIBridgeList"; }
AIBridgeList();
};
/**
* Create a list of bridges that can be built on a specific length.
* @ingroup AIList
*/
class AIBridgeList_Length : public AIAbstractList {
public:
static const char *GetClassName() { return "AIBridgeList_Length"; }
/**
* @param length The length of the bridge you want to build.
*/
AIBridgeList_Length(uint length);
};
#endif /* AI_BRIDGELIST_HPP */

View File

@@ -0,0 +1,42 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_bridgelist.hpp"
namespace SQConvert {
/* Allow AIBridgeList to be used as Squirrel parameter */
template <> AIBridgeList *GetParam(ForceType<AIBridgeList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIBridgeList *)instance; }
template <> AIBridgeList &GetParam(ForceType<AIBridgeList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIBridgeList *)instance; }
template <> const AIBridgeList *GetParam(ForceType<const AIBridgeList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIBridgeList *)instance; }
template <> const AIBridgeList &GetParam(ForceType<const AIBridgeList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIBridgeList *)instance; }
template <> int Return<AIBridgeList *>(HSQUIRRELVM vm, AIBridgeList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIBridgeList", res, NULL, DefSQDestructorCallback<AIBridgeList>); return 1; }
}; // namespace SQConvert
void SQAIBridgeList_Register(Squirrel *engine) {
DefSQClass <AIBridgeList> SQAIBridgeList("AIBridgeList");
SQAIBridgeList.PreRegister(engine, "AIAbstractList");
SQAIBridgeList.AddConstructor<void (AIBridgeList::*)(), 1>(engine, "x");
SQAIBridgeList.DefSQStaticMethod(engine, &AIBridgeList::GetClassName, "GetClassName", 1, "x");
SQAIBridgeList.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIBridgeList_Length to be used as Squirrel parameter */
template <> AIBridgeList_Length *GetParam(ForceType<AIBridgeList_Length *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIBridgeList_Length *)instance; }
template <> AIBridgeList_Length &GetParam(ForceType<AIBridgeList_Length &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIBridgeList_Length *)instance; }
template <> const AIBridgeList_Length *GetParam(ForceType<const AIBridgeList_Length *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIBridgeList_Length *)instance; }
template <> const AIBridgeList_Length &GetParam(ForceType<const AIBridgeList_Length &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIBridgeList_Length *)instance; }
template <> int Return<AIBridgeList_Length *>(HSQUIRRELVM vm, AIBridgeList_Length *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIBridgeList_Length", res, NULL, DefSQDestructorCallback<AIBridgeList_Length>); return 1; }
}; // namespace SQConvert
void SQAIBridgeList_Length_Register(Squirrel *engine) {
DefSQClass <AIBridgeList_Length> SQAIBridgeList_Length("AIBridgeList_Length");
SQAIBridgeList_Length.PreRegister(engine, "AIAbstractList");
SQAIBridgeList_Length.AddConstructor<void (AIBridgeList_Length::*)(uint length), 2>(engine, "xi");
SQAIBridgeList_Length.DefSQStaticMethod(engine, &AIBridgeList_Length::GetClassName, "GetClassName", 1, "x");
SQAIBridgeList_Length.PostRegister(engine);
}

57
src/ai/api/ai_cargo.cpp Normal file
View File

@@ -0,0 +1,57 @@
/* $Id$ */
/** @file ai_cargo.cpp Implementation of AICargo. */
#include "ai_cargo.hpp"
#include "../../openttd.h"
#include "../../cargotype.h"
#include "../../economy_func.h"
#include "../../core/alloc_func.hpp"
#include "../../core/bitmath_func.hpp"
#include "../../newgrf_cargo.h"
/* static */ bool AICargo::IsValidCargo(CargoID cargo_type)
{
return (cargo_type < NUM_CARGO && ::GetCargo(cargo_type)->IsValid());
}
/* static */ const char *AICargo::GetCargoLabel(CargoID cargo_type)
{
if (!IsValidCargo(cargo_type)) return NULL;
const CargoSpec *cargo = ::GetCargo(cargo_type);
/* cargo->label is a uint32 packing a 4 character non-terminated string,
* like "PASS", "COAL", "OIL_". New ones can be defined by NewGRFs */
char *cargo_label = MallocT<char>(sizeof(cargo->label) + 1);
for (uint i = 0; i < sizeof(cargo->label); i++) {
cargo_label[i] = GB(cargo->label, (uint8)(sizeof(cargo->label) - i - 1) * 8, 8);
}
cargo_label[sizeof(cargo->label)] = '\0';
return cargo_label;
}
/* static */ bool AICargo::IsFreight(CargoID cargo_type)
{
if (!IsValidCargo(cargo_type)) return false;
const CargoSpec *cargo = ::GetCargo(cargo_type);
return cargo->is_freight;
}
/* static */ bool AICargo::HasCargoClass(CargoID cargo_type, CargoClass cargo_class)
{
if (!IsValidCargo(cargo_type)) return false;
return ::IsCargoInClass(cargo_type, (::CargoClass)cargo_class);
}
/* static */ AICargo::TownEffect AICargo::GetTownEffect(CargoID cargo_type)
{
if (!IsValidCargo(cargo_type)) return TE_NONE;
return (AICargo::TownEffect)GetCargo(cargo_type)->town_effect;
}
/* static */ Money AICargo::GetCargoIncome(CargoID cargo_type, uint32 distance, uint32 days_in_transit)
{
if (!IsValidCargo(cargo_type)) return -1;
return ::GetTransportedGoodsIncome(1, distance, Clamp(days_in_transit * 2 / 5, 0, 255), cargo_type);
}

94
src/ai/api/ai_cargo.hpp Normal file
View File

@@ -0,0 +1,94 @@
/* $Id$ */
/** @file ai_cargo.hpp Everything to query cargos. */
#ifndef AI_CARGO_HPP
#define AI_CARGO_HPP
#include "ai_object.hpp"
/**
* Class that handles all cargo related functions.
*/
class AICargo : public AIObject {
public:
static const char *GetClassName() { return "AICargo"; }
/**
* The classes of cargo (from newgrf_cargo.h).
*/
enum CargoClass {
CC_PASSENGERS = 1 << 0, ///< Passengers
CC_MAIL = 1 << 1, ///< Mail
CC_EXPRESS = 1 << 2, ///< Express cargo (Goods, Food, Candy, but also possible for passengers)
CC_ARMOURED = 1 << 3, ///< Armoured cargo (Valuables, Gold, Diamonds)
CC_BULK = 1 << 4, ///< Bulk cargo (Coal, Grain etc., Ores, Fruit)
CC_PIECE_GOODS = 1 << 5, ///< Piece goods (Livestock, Wood, Steel, Paper)
CC_LIQUID = 1 << 6, ///< Liquids (Oil, Water, Rubber)
CC_REFRIGERATED = 1 << 7, ///< Refrigerated cargo (Food, Fruit)
CC_HAZARDOUS = 1 << 8, ///< Hazardous cargo (Nuclear Fuel, Explosives, etc.)
CC_COVERED = 1 << 9, ///< Covered/Sheltered Freight (Transporation in Box Vans, Silo Wagons, etc.)
};
/**
* The effects a cargo can have on a town.
*/
enum TownEffect {
TE_NONE = 0, ///< This cargo has no effect on a town
TE_PASSENGERS = 1, ///< This cargo supplies passengers to a town
TE_MAIL = 2, ///< This cargo supplies mail to a town
TE_GOODS = 3, ///< This cargo supplies goods to a town
TE_WATER = 4, ///< This cargo supplies water to a town
TE_FOOD = 5, ///< This cargo supplies food to a town
};
/**
* Checks whether the given cargo type is valid.
* @param cargo_type The cargo to check.
* @return True if and only if the cargo type is valid.
*/
static bool IsValidCargo(CargoID cargo_type);
/**
* Gets the string representation of the cargo label.
* @param cargo_type The cargo to get the string representation of.
* @return The cargo label.
* @note Never use this to check if it is a certain cargo. NewGRF can
* redefine all of the names.
*/
static const char *GetCargoLabel(CargoID cargo_type);
/**
* Checks whether the give cargo is a freight or not.
* @param cargo_type The cargo to check on.
* @return True if and only if the cargo is freight.
*/
static bool IsFreight(CargoID cargo_type);
/**
* Check if this cargo is in the requested cargo class.
* @param cargo_type The cargo to check on.
* @param cargo_class The class to check for.
* @return True if and only if the cargo is in the cargo class.
*/
static bool HasCargoClass(CargoID cargo_type, CargoClass cargo_class);
/**
* Get the effect this cargo has on a town.
* @param cargo_type The cargo to check on.
* @return The effect this cargo has on a town, or TE_NONE if it has no effect.
*/
static TownEffect GetTownEffect(CargoID cargo_type);
/**
* Get the income for transporting a piece of cargo over the
* given distance within the specified time.
* @param cargo_type The cargo to transport.
* @param distance The distance the cargo travels from begin to end.
* @param days_in_transit Amount of (game) days the cargo is in transit. The max value of this variable is 637. Any value higher returns the same as 637 would.
* @return The amount of money that would be earned by this trip.
*/
static Money GetCargoIncome(CargoID cargo_type, uint32 distance, uint32 days_in_transit);
};
#endif /* AI_CARGO_HPP */

View File

@@ -0,0 +1,52 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_cargo.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AICargo::CargoClass GetParam(ForceType<AICargo::CargoClass>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AICargo::CargoClass)tmp; }
template <> int Return<AICargo::CargoClass>(HSQUIRRELVM vm, AICargo::CargoClass res) { sq_pushinteger(vm, (int32)res); return 1; }
template <> AICargo::TownEffect GetParam(ForceType<AICargo::TownEffect>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AICargo::TownEffect)tmp; }
template <> int Return<AICargo::TownEffect>(HSQUIRRELVM vm, AICargo::TownEffect res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AICargo to be used as Squirrel parameter */
template <> AICargo *GetParam(ForceType<AICargo *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICargo *)instance; }
template <> AICargo &GetParam(ForceType<AICargo &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICargo *)instance; }
template <> const AICargo *GetParam(ForceType<const AICargo *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICargo *)instance; }
template <> const AICargo &GetParam(ForceType<const AICargo &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICargo *)instance; }
template <> int Return<AICargo *>(HSQUIRRELVM vm, AICargo *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AICargo", res, NULL, DefSQDestructorCallback<AICargo>); return 1; }
}; // namespace SQConvert
void SQAICargo_Register(Squirrel *engine) {
DefSQClass <AICargo> SQAICargo("AICargo");
SQAICargo.PreRegister(engine);
SQAICargo.AddConstructor<void (AICargo::*)(), 1>(engine, "x");
SQAICargo.DefSQConst(engine, AICargo::CC_PASSENGERS, "CC_PASSENGERS");
SQAICargo.DefSQConst(engine, AICargo::CC_MAIL, "CC_MAIL");
SQAICargo.DefSQConst(engine, AICargo::CC_EXPRESS, "CC_EXPRESS");
SQAICargo.DefSQConst(engine, AICargo::CC_ARMOURED, "CC_ARMOURED");
SQAICargo.DefSQConst(engine, AICargo::CC_BULK, "CC_BULK");
SQAICargo.DefSQConst(engine, AICargo::CC_PIECE_GOODS, "CC_PIECE_GOODS");
SQAICargo.DefSQConst(engine, AICargo::CC_LIQUID, "CC_LIQUID");
SQAICargo.DefSQConst(engine, AICargo::CC_REFRIGERATED, "CC_REFRIGERATED");
SQAICargo.DefSQConst(engine, AICargo::CC_HAZARDOUS, "CC_HAZARDOUS");
SQAICargo.DefSQConst(engine, AICargo::CC_COVERED, "CC_COVERED");
SQAICargo.DefSQConst(engine, AICargo::TE_NONE, "TE_NONE");
SQAICargo.DefSQConst(engine, AICargo::TE_PASSENGERS, "TE_PASSENGERS");
SQAICargo.DefSQConst(engine, AICargo::TE_MAIL, "TE_MAIL");
SQAICargo.DefSQConst(engine, AICargo::TE_GOODS, "TE_GOODS");
SQAICargo.DefSQConst(engine, AICargo::TE_WATER, "TE_WATER");
SQAICargo.DefSQConst(engine, AICargo::TE_FOOD, "TE_FOOD");
SQAICargo.DefSQStaticMethod(engine, &AICargo::GetClassName, "GetClassName", 1, "x");
SQAICargo.DefSQStaticMethod(engine, &AICargo::IsValidCargo, "IsValidCargo", 2, "xi");
SQAICargo.DefSQStaticMethod(engine, &AICargo::GetCargoLabel, "GetCargoLabel", 2, "xi");
SQAICargo.DefSQStaticMethod(engine, &AICargo::IsFreight, "IsFreight", 2, "xi");
SQAICargo.DefSQStaticMethod(engine, &AICargo::HasCargoClass, "HasCargoClass", 3, "xii");
SQAICargo.DefSQStaticMethod(engine, &AICargo::GetTownEffect, "GetTownEffect", 2, "xi");
SQAICargo.DefSQStaticMethod(engine, &AICargo::GetCargoIncome, "GetCargoIncome", 4, "xiii");
SQAICargo.PostRegister(engine);
}

View File

@@ -0,0 +1,46 @@
/* $Id$ */
/** @file ai_cargolist.cpp Implementation of AICargoList and friends. */
#include "ai_cargolist.hpp"
#include "ai_industry.hpp"
#include "../../openttd.h"
#include "../../cargotype.h"
#include "../../tile_type.h"
#include "../../industry.h"
AICargoList::AICargoList()
{
for (byte i = 0; i < NUM_CARGO; i++) {
const CargoSpec *c = ::GetCargo(i);
if (c->IsValid()) {
this->AddItem(i);
}
}
}
AICargoList_IndustryAccepting::AICargoList_IndustryAccepting(IndustryID industry_id)
{
if (!AIIndustry::IsValidIndustry(industry_id)) return;
Industry *ind = ::GetIndustry(industry_id);
for (uint i = 0; i < lengthof(ind->accepts_cargo); i++) {
CargoID cargo_id = ind->accepts_cargo[i];
if (cargo_id != CT_INVALID) {
this->AddItem(cargo_id);
}
}
}
AICargoList_IndustryProducing::AICargoList_IndustryProducing(IndustryID industry_id)
{
if (!AIIndustry::IsValidIndustry(industry_id)) return;
Industry *ind = ::GetIndustry(industry_id);
for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
CargoID cargo_id = ind->produced_cargo[i];
if (cargo_id != CT_INVALID) {
this->AddItem(cargo_id);
}
}
}

View File

@@ -0,0 +1,48 @@
/* $Id$ */
/** @file ai_cargolist.hpp List all the cargos. */
#ifndef AI_CARGOLIST_HPP
#define AI_CARGOLIST_HPP
#include "ai_abstractlist.hpp"
/**
* Creates a list of cargos that can be produced in the current game.
* @ingroup AIList
*/
class AICargoList : public AIAbstractList {
public:
static const char *GetClassName() { return "AICargoList"; }
AICargoList();
};
/**
* Creates a list of cargos that the given industry accepts.
* @ingroup AIList
*/
class AICargoList_IndustryAccepting : public AIAbstractList {
public:
static const char *GetClassName() { return "AICargoList_IndustryAccepting"; }
/**
* @param industry_id The industry to get the list of cargos it accepts from.
*/
AICargoList_IndustryAccepting(IndustryID industry_id);
};
/**
* Creates a list of cargos that the given industry can produce.
* @ingroup AIList
*/
class AICargoList_IndustryProducing : public AIAbstractList {
public:
static const char *GetClassName() { return "AICargoList_IndustryProducing"; }
/**
* @param industry_id The industry to get the list of cargos it produces from.
*/
AICargoList_IndustryProducing(IndustryID industry_id);
};
#endif /* AI_CARGOLIST_HPP */

View File

@@ -0,0 +1,61 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_cargolist.hpp"
namespace SQConvert {
/* Allow AICargoList to be used as Squirrel parameter */
template <> AICargoList *GetParam(ForceType<AICargoList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICargoList *)instance; }
template <> AICargoList &GetParam(ForceType<AICargoList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICargoList *)instance; }
template <> const AICargoList *GetParam(ForceType<const AICargoList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICargoList *)instance; }
template <> const AICargoList &GetParam(ForceType<const AICargoList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICargoList *)instance; }
template <> int Return<AICargoList *>(HSQUIRRELVM vm, AICargoList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AICargoList", res, NULL, DefSQDestructorCallback<AICargoList>); return 1; }
}; // namespace SQConvert
void SQAICargoList_Register(Squirrel *engine) {
DefSQClass <AICargoList> SQAICargoList("AICargoList");
SQAICargoList.PreRegister(engine, "AIAbstractList");
SQAICargoList.AddConstructor<void (AICargoList::*)(), 1>(engine, "x");
SQAICargoList.DefSQStaticMethod(engine, &AICargoList::GetClassName, "GetClassName", 1, "x");
SQAICargoList.PostRegister(engine);
}
namespace SQConvert {
/* Allow AICargoList_IndustryAccepting to be used as Squirrel parameter */
template <> AICargoList_IndustryAccepting *GetParam(ForceType<AICargoList_IndustryAccepting *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICargoList_IndustryAccepting *)instance; }
template <> AICargoList_IndustryAccepting &GetParam(ForceType<AICargoList_IndustryAccepting &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICargoList_IndustryAccepting *)instance; }
template <> const AICargoList_IndustryAccepting *GetParam(ForceType<const AICargoList_IndustryAccepting *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICargoList_IndustryAccepting *)instance; }
template <> const AICargoList_IndustryAccepting &GetParam(ForceType<const AICargoList_IndustryAccepting &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICargoList_IndustryAccepting *)instance; }
template <> int Return<AICargoList_IndustryAccepting *>(HSQUIRRELVM vm, AICargoList_IndustryAccepting *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AICargoList_IndustryAccepting", res, NULL, DefSQDestructorCallback<AICargoList_IndustryAccepting>); return 1; }
}; // namespace SQConvert
void SQAICargoList_IndustryAccepting_Register(Squirrel *engine) {
DefSQClass <AICargoList_IndustryAccepting> SQAICargoList_IndustryAccepting("AICargoList_IndustryAccepting");
SQAICargoList_IndustryAccepting.PreRegister(engine, "AIAbstractList");
SQAICargoList_IndustryAccepting.AddConstructor<void (AICargoList_IndustryAccepting::*)(IndustryID industry_id), 2>(engine, "xi");
SQAICargoList_IndustryAccepting.DefSQStaticMethod(engine, &AICargoList_IndustryAccepting::GetClassName, "GetClassName", 1, "x");
SQAICargoList_IndustryAccepting.PostRegister(engine);
}
namespace SQConvert {
/* Allow AICargoList_IndustryProducing to be used as Squirrel parameter */
template <> AICargoList_IndustryProducing *GetParam(ForceType<AICargoList_IndustryProducing *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICargoList_IndustryProducing *)instance; }
template <> AICargoList_IndustryProducing &GetParam(ForceType<AICargoList_IndustryProducing &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICargoList_IndustryProducing *)instance; }
template <> const AICargoList_IndustryProducing *GetParam(ForceType<const AICargoList_IndustryProducing *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICargoList_IndustryProducing *)instance; }
template <> const AICargoList_IndustryProducing &GetParam(ForceType<const AICargoList_IndustryProducing &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICargoList_IndustryProducing *)instance; }
template <> int Return<AICargoList_IndustryProducing *>(HSQUIRRELVM vm, AICargoList_IndustryProducing *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AICargoList_IndustryProducing", res, NULL, DefSQDestructorCallback<AICargoList_IndustryProducing>); return 1; }
}; // namespace SQConvert
void SQAICargoList_IndustryProducing_Register(Squirrel *engine) {
DefSQClass <AICargoList_IndustryProducing> SQAICargoList_IndustryProducing("AICargoList_IndustryProducing");
SQAICargoList_IndustryProducing.PreRegister(engine, "AIAbstractList");
SQAICargoList_IndustryProducing.AddConstructor<void (AICargoList_IndustryProducing::*)(IndustryID industry_id), 2>(engine, "xi");
SQAICargoList_IndustryProducing.DefSQStaticMethod(engine, &AICargoList_IndustryProducing::GetClassName, "GetClassName", 1, "x");
SQAICargoList_IndustryProducing.PostRegister(engine);
}

200
src/ai/api/ai_company.cpp Normal file
View File

@@ -0,0 +1,200 @@
/* $Id$ */
/** @file ai_company.cpp Implementation of AICompany. */
#include "ai_company.hpp"
#include "ai_error.hpp"
#include "ai_log.hpp"
#include "../../openttd.h"
#include "../../command_func.h"
#include "../../company_func.h"
#include "../../company_base.h"
#include "../../economy_func.h"
#include "../../strings_func.h"
#include "../../tile_map.h"
#include "../../variables.h"
#include "../../core/alloc_func.hpp"
#include "../../string_func.h"
#include "table/strings.h"
/* static */ AICompany::CompanyID AICompany::ResolveCompanyID(AICompany::CompanyID company)
{
if (company == MY_COMPANY) return (CompanyID)((byte)_current_company);
return ::IsValidCompanyID((::CompanyID)company) ? company : INVALID_COMPANY;
}
/* static */ bool AICompany::IsMine(AICompany::CompanyID company)
{
return ResolveCompanyID(company) == ResolveCompanyID(MY_COMPANY);
}
/* static */ bool AICompany::SetCompanyName(const char *name)
{
AILog::Error("AICompany::SetCompanyName is obsolete. Use AICompany::SetName instead.");
return AICompany::SetName(name);
}
/* static */ bool AICompany::SetName(const char *name)
{
EnforcePrecondition(false, !::StrEmpty(name));
EnforcePreconditionCustomError(false, ::strlen(name) < MAX_LENGTH_COMPANY_NAME_BYTES, AIError::ERR_PRECONDITION_STRING_TOO_LONG);
return AIObject::DoCommand(0, 0, 0, CMD_RENAME_COMPANY, name);
}
/* static */ const char *AICompany::GetCompanyName(AICompany::CompanyID company)
{
AILog::Error("AICompany::GetCompanyName is obsolete. Use AICompany::GetName instead.");
return AICompany::GetName(company);
}
/* static */ const char *AICompany::GetName(AICompany::CompanyID company)
{
company = ResolveCompanyID(company);
if (company == INVALID_COMPANY) return NULL;
static const int len = 64;
char *company_name = MallocT<char>(len);
::SetDParam(0, company);
::GetString(company_name, STR_COMPANY_NAME, &company_name[len - 1]);
return company_name;
}
/* static */ bool AICompany::SetPresidentName(const char *name)
{
EnforcePrecondition(false, !::StrEmpty(name));
return AIObject::DoCommand(0, 0, 0, CMD_RENAME_PRESIDENT, name);
}
/* static */ const char *AICompany::GetPresidentName(AICompany::CompanyID company)
{
company = ResolveCompanyID(company);
static const int len = 64;
char *president_name = MallocT<char>(len);
if (company != INVALID_COMPANY) {
::SetDParam(0, company);
::GetString(president_name, STR_PRESIDENT_NAME, &president_name[len - 1]);
} else {
*president_name = '\0';
}
return president_name;
}
/* static */ Money AICompany::GetCompanyValue(AICompany::CompanyID company)
{
company = ResolveCompanyID(company);
if (company == INVALID_COMPANY) return -1;
return ::CalculateCompanyValue(::GetCompany((CompanyID)company));
}
/* static */ Money AICompany::GetBankBalance(AICompany::CompanyID company)
{
company = ResolveCompanyID(company);
if (company == INVALID_COMPANY) return -1;
return ::GetCompany((CompanyID)company)->money;
}
/* static */ Money AICompany::GetLoanAmount()
{
return ::GetCompany(_current_company)->current_loan;
}
/* static */ Money AICompany::GetMaxLoanAmount()
{
return _economy.max_loan;
}
/* static */ Money AICompany::GetLoanInterval()
{
return LOAN_INTERVAL;
}
/* static */ bool AICompany::SetLoanAmount(int32 loan)
{
EnforcePrecondition(false, loan >= 0);
EnforcePrecondition(false, (loan % GetLoanInterval()) == 0);
EnforcePrecondition(false, loan <= GetMaxLoanAmount());
EnforcePrecondition(false, (loan - GetLoanAmount() + GetBankBalance(MY_COMPANY)) >= 0);
if (loan == GetLoanAmount()) return true;
return AIObject::DoCommand(0,
abs(loan - GetLoanAmount()), 2,
(loan > GetLoanAmount()) ? CMD_INCREASE_LOAN : CMD_DECREASE_LOAN);
}
/* static */ bool AICompany::SetMinimumLoanAmount(int32 loan)
{
EnforcePrecondition(false, loan >= 0);
int32 over_interval = loan % GetLoanInterval();
if (over_interval != 0) loan += GetLoanInterval() - over_interval;
EnforcePrecondition(false, loan <= GetMaxLoanAmount());
SetLoanAmount(loan);
return GetLoanAmount() == loan;
}
/* static */ bool AICompany::BuildCompanyHQ(TileIndex tile)
{
EnforcePrecondition(false, ::IsValidTile(tile));
return AIObject::DoCommand(tile, 0, 0, CMD_BUILD_COMPANY_HQ);
}
/* static */ TileIndex AICompany::GetCompanyHQ(CompanyID company)
{
company = ResolveCompanyID(company);
if (company == INVALID_COMPANY) return INVALID_TILE;
TileIndex loc = ::GetCompany((CompanyID)company)->location_of_HQ;
return (loc == 0) ? INVALID_TILE : loc;
}
/* static */ bool AICompany::SetAutoRenewStatus(bool autorenew)
{
return AIObject::DoCommand(0, 0, autorenew ? 1 : 0, CMD_SET_AUTOREPLACE);
}
/* static */ bool AICompany::GetAutoRenewStatus(CompanyID company)
{
company = ResolveCompanyID(company);
if (company == INVALID_COMPANY) return false;
return ::GetCompany((CompanyID)company)->engine_renew;
}
/* static */ bool AICompany::SetAutoRenewMonths(int16 months)
{
return AIObject::DoCommand(0, 1, months, CMD_SET_AUTOREPLACE);
}
/* static */ int16 AICompany::GetAutoRenewMonths(CompanyID company)
{
company = ResolveCompanyID(company);
if (company == INVALID_COMPANY) return 0;
return ::GetCompany((CompanyID)company)->engine_renew_months;
}
/* static */ bool AICompany::SetAutoRenewMoney(uint32 money)
{
return AIObject::DoCommand(0, 2, money, CMD_SET_AUTOREPLACE);
}
/* static */ uint32 AICompany::GetAutoRenewMoney(CompanyID company)
{
company = ResolveCompanyID(company);
if (company == INVALID_COMPANY) return 0;
return ::GetCompany((CompanyID)company)->engine_renew_money;
}

214
src/ai/api/ai_company.hpp Normal file
View File

@@ -0,0 +1,214 @@
/* $Id$ */
/** @file ai_company.hpp Everything to query a company's financials and statistics or build company related buildings. */
#ifndef AI_COMPANY_HPP
#define AI_COMPANY_HPP
#include "ai_object.hpp"
/**
* Class that handles all company related functions.
*/
class AICompany : public AIObject {
public:
static const char *GetClassName() { return "AICompany"; }
/** Different constants related to CompanyID. */
enum CompanyID {
INVALID_COMPANY = -1, //!< An invalid company.
FIRST_COMPANY = 0, //!< The first available company.
LAST_COMPANY = 7, //!< The last available company.
MY_COMPANY = 8, //!< Constant that gets resolved to the correct company index for your company.
};
/**
* Resolved the given company index to the correct index for the company. If
* the company index was MY_COMPANY it will be resolved to the index of
* your company. If the company with the given index does not exist it will
* return INVALID_COMPANY.
* @param company The company index to resolve.
* @return The resolved company index.
*/
static CompanyID ResolveCompanyID(CompanyID company);
/**
* Check if a CompanyID is your CompanyID, to ease up checks.
* @param company The company index to check.
* @return True if and only if this company is your CompanyID.
*/
static bool IsMine(CompanyID company);
/**
* Obsolete, use AICompany::SetName instead.
*/
static bool SetCompanyName(const char *name);
/**
* Set the name of your company.
* @param name The new name of the company.
* @pre 'name' must have at least one character.
* @pre 'name' must have at most 30 characters.
* @exception AIError::ERR_NAME_IS_NOT_UNIQUE
* @return True if the name was changed.
*/
static bool SetName(const char *name);
/**
* Obsolete, use AICompany::GetName instead.
*/
static const char *GetCompanyName(CompanyID company);
/**
* Get the name of the given company.
* @param company The company to get the name for.
* @pre ResolveCompanyID(company) != INVALID_COMPANY
* @return The name of the given company.
*/
static const char *GetName(CompanyID company);
/**
* Set the name of your president.
* @param name The new name of the president.
* @pre 'name' must have at least one character.
* @exception AIError::ERR_NAME_IS_NOT_UNIQUE
* @return True if the name was changed.
*/
static bool SetPresidentName(const char *name);
/**
* Get the name of the president of the given company.
* @param company The company to get the president's name for.
* @pre ResolveCompanyID(company) != INVALID_COMPANY
* @return The name of the president of the given company.
*/
static const char *GetPresidentName(CompanyID company);
/**
* Sets the amount to loan.
* @param loan The amount to loan (multiplier of GetLoanInterval()).
* @pre 'loan' must be non-negative.
* @pre GetLoanInterval() must be a multiplier of GetLoanInterval().
* @pre 'loan' must be below GetMaxLoanAmount().
* @pre 'loan' - GetLoanAmount() + GetBankBalance() must be non-negative.
* @return True if the loan could be set to your requested amount.
*/
static bool SetLoanAmount(int32 loan);
/**
* Sets the minimum amount to loan, i.e. the given amount of loan rounded up.
* @param loan The amount to loan (any positive number).
* @pre 'loan' must be non-negative.
* @pre 'loan' must be below GetMaxLoanAmount().
* @return True if we could allocate a minimum of "loan" loan.
*/
static bool SetMinimumLoanAmount(int32 loan);
/**
* Gets the amount your company have loaned.
* @return The amount loaned money.
* @post The return value is always non-negative.
* @post GetLoanInterval() is always a multiplier of the return value.
*/
static Money GetLoanAmount();
/**
* Gets the maximum amount your company can loan.
* @return The maximum amount your company can loan.
* @post The return value is always non-negative.
* @post GetLoanInterval() is always a multiplier of the return value.
*/
static Money GetMaxLoanAmount();
/**
* Gets the interval/loan step.
* @return The loan step.
* @post Return value is always positive.
*/
static Money GetLoanInterval();
/**
* Gets the current value of the given company.
* @param company The company to get the company value of.
* @pre ResolveCompanyID(company) != INVALID_COMPANY
* @return The current value of the given company.
*/
static Money GetCompanyValue(CompanyID company);
/**
* Gets the bank balance. In other words, the amount of money the given company can spent.
* @param company The company to get the bank balance of.
* @pre ResolveCompanyID(company) != INVALID_COMPANY
* @return The actual bank balance.
*/
static Money GetBankBalance(CompanyID company);
/**
* Build your company's HQ on the given tile.
* @param tile The tile to build your HQ on, this tile is the most nothern tile of your HQ.
* @pre AIMap::IsValidTile(tile).
* @exception AIError::ERR_AREA_NOT_CLEAR
* @exception AIError::ERR_FLAT_LAND_REQUIRED
* @return True if the HQ could be build.
* @note An HQ can not be removed, only by water or rebuilding; If an HQ is
* build again, the old one is removed.
*/
static bool BuildCompanyHQ(TileIndex tile);
/**
* Return the location of a company's HQ.
* @param company The company the get the HQ of.
* @pre ResolveCompanyID(company) != INVALID_COMPANY.
* @return The tile of the company's HQ, this tile is the most nothern tile of that HQ, or INVALID_TILE if there is no HQ yet.
*/
static TileIndex GetCompanyHQ(CompanyID company);
/**
* Set whether autorenew is enabled for your company.
* @param autorenew The new autorenew status.
* @return True if autorenew status has been modified.
*/
static bool SetAutoRenewStatus(bool autorenew);
/**
* Return whether autorenew is enabled for a company.
* @param company The company to get the autorenew status of.
* @pre ResolveCompanyID(company) != INVALID_COMPANY.
* @return True if autorenew is enabled.
*/
static bool GetAutoRenewStatus(CompanyID company);
/**
* Set the number of months before/after max age to autorenew an engine for your company.
* @param months The new months between autorenew.
* @return True if autorenew months has been modified.
*/
static bool SetAutoRenewMonths(int16 months);
/**
* Return the number of months before/after max age to autorenew an engine for a company.
* @param company The company to get the autorenew months of.
* @pre ResolveCompanyID(company) != INVALID_COMPANY.
* @return The months before/after max age of engine.
*/
static int16 GetAutoRenewMonths(CompanyID company);
/**
* Set the minimum money needed to autorenew an engine for your company.
* @param money The new minimum required money for autorenew to work.
* @return True if autorenew money has been modified.
*/
static bool SetAutoRenewMoney(uint32 money);
/**
* Return the minimum money needed to autorenew an engine for a company.
* @param company The company to get the autorenew money of.
* @pre ResolveCompanyID(company) != INVALID_COMPANY.
* @return The minimum required money for autorenew to work.
*/
static uint32 GetAutoRenewMoney(CompanyID company);
};
DECLARE_POSTFIX_INCREMENT(AICompany::CompanyID);
#endif /* AI_COMPANY_HPP */

View File

@@ -0,0 +1,55 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_company.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AICompany::CompanyID GetParam(ForceType<AICompany::CompanyID>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AICompany::CompanyID)tmp; }
template <> int Return<AICompany::CompanyID>(HSQUIRRELVM vm, AICompany::CompanyID res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AICompany to be used as Squirrel parameter */
template <> AICompany *GetParam(ForceType<AICompany *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICompany *)instance; }
template <> AICompany &GetParam(ForceType<AICompany &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICompany *)instance; }
template <> const AICompany *GetParam(ForceType<const AICompany *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AICompany *)instance; }
template <> const AICompany &GetParam(ForceType<const AICompany &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AICompany *)instance; }
template <> int Return<AICompany *>(HSQUIRRELVM vm, AICompany *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AICompany", res, NULL, DefSQDestructorCallback<AICompany>); return 1; }
}; // namespace SQConvert
void SQAICompany_Register(Squirrel *engine) {
DefSQClass <AICompany> SQAICompany("AICompany");
SQAICompany.PreRegister(engine);
SQAICompany.AddConstructor<void (AICompany::*)(), 1>(engine, "x");
SQAICompany.DefSQConst(engine, AICompany::INVALID_COMPANY, "INVALID_COMPANY");
SQAICompany.DefSQConst(engine, AICompany::FIRST_COMPANY, "FIRST_COMPANY");
SQAICompany.DefSQConst(engine, AICompany::LAST_COMPANY, "LAST_COMPANY");
SQAICompany.DefSQConst(engine, AICompany::MY_COMPANY, "MY_COMPANY");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetClassName, "GetClassName", 1, "x");
SQAICompany.DefSQStaticMethod(engine, &AICompany::ResolveCompanyID, "ResolveCompanyID", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::IsMine, "IsMine", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::SetCompanyName, "SetCompanyName", 2, "xs");
SQAICompany.DefSQStaticMethod(engine, &AICompany::SetName, "SetName", 2, "xs");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetCompanyName, "GetCompanyName", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetName, "GetName", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::SetPresidentName, "SetPresidentName", 2, "xs");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetPresidentName, "GetPresidentName", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::SetLoanAmount, "SetLoanAmount", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::SetMinimumLoanAmount, "SetMinimumLoanAmount", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetLoanAmount, "GetLoanAmount", 1, "x");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetMaxLoanAmount, "GetMaxLoanAmount", 1, "x");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetLoanInterval, "GetLoanInterval", 1, "x");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetCompanyValue, "GetCompanyValue", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetBankBalance, "GetBankBalance", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::BuildCompanyHQ, "BuildCompanyHQ", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetCompanyHQ, "GetCompanyHQ", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::SetAutoRenewStatus, "SetAutoRenewStatus", 2, "xb");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetAutoRenewStatus, "GetAutoRenewStatus", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::SetAutoRenewMonths, "SetAutoRenewMonths", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetAutoRenewMonths, "GetAutoRenewMonths", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::SetAutoRenewMoney, "SetAutoRenewMoney", 2, "xi");
SQAICompany.DefSQStaticMethod(engine, &AICompany::GetAutoRenewMoney, "GetAutoRenewMoney", 2, "xi");
SQAICompany.PostRegister(engine);
}

View File

@@ -0,0 +1,85 @@
/* $Id$ */
/** @file ai_controller.cpp Implementation of AIControler. */
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../company_func.h"
#include "../../core/alloc_func.hpp"
#include "../../string_func.h"
#include "../../settings_type.h"
#include "../../company_base.h"
#include "../../saveload/saveload.h"
#include "table/strings.h"
#include "../ai.hpp"
#include "ai_controller.hpp"
#include "../ai_info.hpp"
#include "../ai_storage.hpp"
#include "../ai_instance.hpp"
#include "../ai_config.hpp"
#include "ai_log.hpp"
/* static */ void AIController::SetCommandDelay(int ticks)
{
if (ticks <= 0) return;
AIObject::SetDoCommandDelay(ticks);
}
/* static */ void AIController::Sleep(int ticks)
{
if (ticks <= 0) {
AILog::Warning("Sleep() value should be > 0. Assuming value 1.");
ticks = 1;
}
throw AI_VMSuspend(ticks, NULL);
}
/* static */ void AIController::Print(bool error_msg, const char *message)
{
AILog::Log(error_msg ? AILog::LOG_SQ_ERROR : AILog::LOG_SQ_INFO, message);
}
AIController::AIController() :
ticks(0),
loaded_library_count(0)
{
}
AIController::~AIController()
{
for (LoadedLibraryList::iterator iter = this->loaded_library.begin(); iter != this->loaded_library.end(); iter++) {
free((void *)(*iter).second);
free((void *)(*iter).first);
}
this->loaded_library.clear();
}
uint AIController::GetTick()
{
return this->ticks;
}
int AIController::GetSetting(const char *name)
{
return AIConfig::GetConfig(_current_company)->GetSetting(name);
}
bool AIController::LoadedLibrary(const char *library_name, int *next_number, char *fake_class_name, int fake_class_name_len)
{
LoadedLibraryList::iterator iter = this->loaded_library.find(library_name);
if (iter == this->loaded_library.end()) {
*next_number = ++this->loaded_library_count;
return false;
}
ttd_strlcpy(fake_class_name, (*iter).second, fake_class_name_len);
return true;
}
void AIController::AddLoadedLibrary(const char *library_name, const char *fake_class_name)
{
this->loaded_library[strdup(library_name)] = strdup(fake_class_name);
}

View File

@@ -0,0 +1,117 @@
/* $Id$ */
/** @file ai_controller.hpp The controller of the AI. */
#ifndef AI_CONTROLLER_HPP
#define AI_CONTROLLER_HPP
#include <map>
#ifndef AI_HPP
struct ltstr { bool operator()(const char *s1, const char *s2) const { return strcmp(s1, s2) < 0; } };
#endif /* AI_HPP */
/**
* The Controller, the class each AI should extend. It creates the AI, makes
* sure the logic kicks in correctly, and that GetTick() has a valid value.
*/
class AIController {
friend class AIScanner;
friend class AIInstance;
public:
static const char *GetClassName() { return "AIController"; }
/**
* Initializer of the AIController.
*/
AIController();
/**
* Destructor of the AIController.
*/
~AIController();
/**
* This function is called to start your AI. Your AI starts here. If you
* return from this function, your AI dies, so make sure that doesn't
* happen.
* @note Cannot be called from within your AI.
*/
void Start();
/**
* Find at which tick your AI currently is.
* @return returns the current tick.
*/
uint GetTick();
/**
* Get the value of one of your settings you set via info.nut.
* @param name The name of the setting.
* @return the value for the setting, or -1 if the setting is not known.
*/
int GetSetting(const char *name);
/**
* Change the minimum amount of time the AI should be put in suspend mode
* when you execute a command. Normally in SP this is 1, and in MP it is
* what ever delay the server has been programmed to delay commands
* (normally between 1 and 5). To give a more 'real' effect to your AI,
* you can control that number here.
* @param ticks The minimum amount of ticks to wait.
* @pre Ticks should be positive. Too big values will influence performance of the AI.
* @note If the number is lower then the MP setting, the MP setting wins.
*/
static void SetCommandDelay(int ticks);
/**
* Sleep for X ticks. The code continues after this line when the X AI ticks
* are passed. Mind that an AI tick is different from in-game ticks and
* differ per AI speed.
* @param ticks the ticks to wait
* @pre ticks > 0.
* @post the value of GetTick() will be changed exactly 'ticks' in value after
* calling this.
*/
static void Sleep(int ticks);
/**
* When Squirrel triggers a print, this function is called.
* Squirrel calls this when 'print' is used, or when the script made an error.
* @param error_msg If true, it is a Squirrel error message.
* @param message The message Squirrel logged.
* @note Use AILog.Info/Warning/Error instead of 'print'.
*/
static void Print(bool error_msg, const char *message);
private:
typedef std::map<const char *, const char *, ltstr> LoadedLibraryList;
uint ticks;
LoadedLibraryList loaded_library;
int loaded_library_count;
/**
* Register all classes that are known inside the NoAI API.
*/
void RegisterClasses();
/**
* Check if a library is already loaded. If found, fake_class_name is filled
* with the fake class name as given via AddLoadedLibrary. If not found,
* next_number is set to the next number available for the fake namespace.
* @param library_name The library to check if already loaded.
* @param next_number The next available number for a library if not already loaded.
* @param fake_class_name The name the library has if already loaded.
* @param fake_class_name_len The maximum length of fake_class_name.
* @return True if the library is already loaded.
*/
bool LoadedLibrary(const char *library_name, int *next_number, char *fake_class_name, int fake_class_name_len);
/**
* Add a library as loaded.
*/
void AddLoadedLibrary(const char *library_name, const char *fake_class_name);
};
#endif /* AI_CONTROLLER_HPP */

View File

@@ -0,0 +1,12 @@
#include "ai_controller.hpp"
void SQAIController_Register(Squirrel *engine) {
DefSQClass <AIController> SQAIController("AIController");
SQAIController.PreRegister(engine);
SQAIController.DefSQMethod(engine, &AIController::GetTick, "GetTick", 1, "x");
SQAIController.DefSQStaticMethod(engine, &AIController::SetCommandDelay, "SetCommandDelay", 2, "xi");
SQAIController.DefSQStaticMethod(engine, &AIController::Sleep, "Sleep", 2, "xi");
SQAIController.DefSQStaticMethod(engine, &AIController::GetSetting, "GetSetting", 2, "xs");
SQAIController.DefSQStaticMethod(engine, &AIController::Print, "Print", 3, "xbs");
SQAIController.PostRegister(engine);
}

47
src/ai/api/ai_date.cpp Normal file
View File

@@ -0,0 +1,47 @@
/* $Id$ */
/** @file ai_date.cpp Implementation of AIDate. */
#include "ai_date.hpp"
#include "../../date_func.h"
/* static */ int32 AIDate::GetCurrentDate()
{
return ::_date;
}
/* static */ int32 AIDate::GetYear(int32 date)
{
if (date < 0) return -1;
::YearMonthDay ymd;
::ConvertDateToYMD(date, &ymd);
return ymd.year;
}
/* static */ int32 AIDate::GetMonth(int32 date)
{
if (date < 0) return -1;
::YearMonthDay ymd;
::ConvertDateToYMD(date, &ymd);
return ymd.month + 1;
}
/* static */ int32 AIDate::GetDayOfMonth(int32 date)
{
if (date < 0) return -1;
::YearMonthDay ymd;
::ConvertDateToYMD(date, &ymd);
return ymd.day;
}
/* static */ int32 AIDate::GetDate(int32 year, int32 month, int32 day_of_month)
{
if (month < 1 || month > 12) return -1;
if (day_of_month < 1 || day_of_month > 31) return -1;
if (year < 0 || year > MAX_YEAR) return -1;
return ::ConvertYMDToDate(year, month - 1, day_of_month);
}

64
src/ai/api/ai_date.hpp Normal file
View File

@@ -0,0 +1,64 @@
/* $Id$ */
/** @file ai_date.hpp Everything to query and manipulate date related information. */
#ifndef AI_DATE_HPP
#define AI_DATE_HPP
#include "ai_object.hpp"
/**
* Class that handles all date related (calculation) functions.
*
* @note Months and days of month are 1-based; the first month of the
* year is 1 and the first day of the month is also 1.
* @note Years are zero based; they start with the year 0.
* @note Dates can be used to determine the number of days between
* two different moments in time because they count the number
* of days since the year 0.
*/
class AIDate : public AIObject {
public:
static const char *GetClassName() { return "AIDate"; }
/**
* Get the current date.
* This is the number of days since epoch under the assumption that
* there is a leap year every 4 years, except when dividable by
* 100 but not by 400.
* @return The current date.
*/
static int32 GetCurrentDate();
/**
* Get the year of the given date.
* @param date The date to get the year of.
* @return The year.
*/
static int32 GetYear(int32 date);
/**
* Get the month of the given date.
* @param date The date to get the month of.
* @return The month.
*/
static int32 GetMonth(int32 date);
/**
* Get the day (of the month) of the given date.
* @param date The date to get the day of.
* @return The day.
*/
static int32 GetDayOfMonth(int32 date);
/**
* Get the date given a year, month and day of month.
* @param year The year of the to-be determined date.
* @param month The month of the to-be determined date.
* @param day_of_month The day of month of the to-be determined date.
* @return The date.
*/
static int32 GetDate(int32 year, int32 month, int32 day_of_month);
};
#endif /* AI_DATE_HPP */

28
src/ai/api/ai_date.hpp.sq Normal file
View File

@@ -0,0 +1,28 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_date.hpp"
namespace SQConvert {
/* Allow AIDate to be used as Squirrel parameter */
template <> AIDate *GetParam(ForceType<AIDate *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIDate *)instance; }
template <> AIDate &GetParam(ForceType<AIDate &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIDate *)instance; }
template <> const AIDate *GetParam(ForceType<const AIDate *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIDate *)instance; }
template <> const AIDate &GetParam(ForceType<const AIDate &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIDate *)instance; }
template <> int Return<AIDate *>(HSQUIRRELVM vm, AIDate *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIDate", res, NULL, DefSQDestructorCallback<AIDate>); return 1; }
}; // namespace SQConvert
void SQAIDate_Register(Squirrel *engine) {
DefSQClass <AIDate> SQAIDate("AIDate");
SQAIDate.PreRegister(engine);
SQAIDate.AddConstructor<void (AIDate::*)(), 1>(engine, "x");
SQAIDate.DefSQStaticMethod(engine, &AIDate::GetClassName, "GetClassName", 1, "x");
SQAIDate.DefSQStaticMethod(engine, &AIDate::GetCurrentDate, "GetCurrentDate", 1, "x");
SQAIDate.DefSQStaticMethod(engine, &AIDate::GetYear, "GetYear", 2, "xi");
SQAIDate.DefSQStaticMethod(engine, &AIDate::GetMonth, "GetMonth", 2, "xi");
SQAIDate.DefSQStaticMethod(engine, &AIDate::GetDayOfMonth, "GetDayOfMonth", 2, "xi");
SQAIDate.DefSQStaticMethod(engine, &AIDate::GetDate, "GetDate", 4, "xiii");
SQAIDate.PostRegister(engine);
}

View File

@@ -0,0 +1,42 @@
/* $Id$ */
/** @file ai_depotlist.cpp Implementation of AIDepotList and friends. */
#include "ai_depotlist.hpp"
#include "../../core/math_func.hpp"
#include "../../tile_map.h"
#include "../../company_func.h"
#include "../../depot_base.h"
#include "../../station_base.h"
AIDepotList::AIDepotList(AITile::TransportType transport_type)
{
::TileType tile_type;
switch (transport_type) {
default: return;
case AITile::TRANSPORT_ROAD: tile_type = ::MP_ROAD; break;
case AITile::TRANSPORT_RAIL: tile_type = ::MP_RAILWAY; break;
case AITile::TRANSPORT_WATER: tile_type = ::MP_WATER; break;
case AITile::TRANSPORT_AIR: {
/* Hangars are not seen as real depots by the depot code. */
const Station *st;
FOR_ALL_STATIONS(st) {
if (st->owner == ::_current_company) {
const AirportFTAClass *afc = st->Airport();
for (uint i = 0; i < afc->nof_depots; i++) {
this->AddItem(st->xy + ToTileIndexDiff(afc->airport_depots[i]));
}
}
}
return;
}
}
/* Handle 'standard' depots. */
const Depot *depot;
FOR_ALL_DEPOTS(depot) {
if (::GetTileOwner(depot->xy) == ::_current_company && ::IsTileType(depot->xy, tile_type)) this->AddItem(depot->xy);
}
}

View File

@@ -0,0 +1,25 @@
/* $Id$ */
/** @file ai_depotlist.hpp List all the depots (you own). */
#ifndef AI_DEPOTLIST_HPP
#define AI_DEPOTLIST_HPP
#include "ai_abstractlist.hpp"
#include "ai_tile.hpp"
/**
* Creates a list of the locations of the depots (and hangars) of which you are the owner.
* @ingroup AIList
*/
class AIDepotList : public AIAbstractList {
public:
static const char *GetClassName() { return "AIDepotList"; }
/**
* @param transport_type The type of transport to make a list of depots for.
*/
AIDepotList(AITile::TransportType transport_type);
};
#endif /* AI_DEPOTLIST_HPP */

View File

@@ -0,0 +1,23 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_depotlist.hpp"
namespace SQConvert {
/* Allow AIDepotList to be used as Squirrel parameter */
template <> AIDepotList *GetParam(ForceType<AIDepotList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIDepotList *)instance; }
template <> AIDepotList &GetParam(ForceType<AIDepotList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIDepotList *)instance; }
template <> const AIDepotList *GetParam(ForceType<const AIDepotList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIDepotList *)instance; }
template <> const AIDepotList &GetParam(ForceType<const AIDepotList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIDepotList *)instance; }
template <> int Return<AIDepotList *>(HSQUIRRELVM vm, AIDepotList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIDepotList", res, NULL, DefSQDestructorCallback<AIDepotList>); return 1; }
}; // namespace SQConvert
void SQAIDepotList_Register(Squirrel *engine) {
DefSQClass <AIDepotList> SQAIDepotList("AIDepotList");
SQAIDepotList.PreRegister(engine, "AIAbstractList");
SQAIDepotList.AddConstructor<void (AIDepotList::*)(AITile::TransportType transport_type), 2>(engine, "xi");
SQAIDepotList.DefSQStaticMethod(engine, &AIDepotList::GetClassName, "GetClassName", 1, "x");
SQAIDepotList.PostRegister(engine);
}

295
src/ai/api/ai_engine.cpp Normal file
View File

@@ -0,0 +1,295 @@
/* $Id$ */
/** @file ai_engine.cpp Implementation of AIEngine. */
#include "ai_engine.hpp"
#include "ai_cargo.hpp"
#include "ai_rail.hpp"
#include "../../openttd.h"
#include "../../company_func.h"
#include "../../strings_func.h"
#include "../../roadveh.h"
#include "../../train.h"
#include "../../ship.h"
#include "../../aircraft.h"
#include "../../vehicle_func.h"
#include "../../core/alloc_func.hpp"
#include "../../economy_func.h"
#include "../../core/bitmath_func.hpp"
#include "../../settings_type.h"
#include "../../articulated_vehicles.h"
#include "table/strings.h"
/* static */ bool AIEngine::IsValidEngine(EngineID engine_id)
{
return ::IsEngineIndex(engine_id) && HasBit(::GetEngine(engine_id)->company_avail, _current_company);
}
/* static */ const char *AIEngine::GetName(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return NULL;
static const int len = 64;
char *engine_name = MallocT<char>(len);
::SetDParam(0, engine_id);
::GetString(engine_name, STR_ENGINE_NAME, &engine_name[len - 1]);
return engine_name;
}
/* static */ CargoID AIEngine::GetCargoType(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return CT_INVALID;
switch (::GetEngine(engine_id)->type) {
case VEH_ROAD: {
const RoadVehicleInfo *vi = ::RoadVehInfo(engine_id);
return vi->cargo_type;
} break;
case VEH_TRAIN: {
const RailVehicleInfo *vi = ::RailVehInfo(engine_id);
return vi->cargo_type;
} break;
case VEH_SHIP: {
const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id);
return vi->cargo_type;
} break;
case VEH_AIRCRAFT: {
return CT_PASSENGERS;
} break;
default: NOT_REACHED();
}
}
/* static */ bool AIEngine::CanRefitCargo(EngineID engine_id, CargoID cargo_id)
{
if (!IsValidEngine(engine_id)) return false;
if (!AICargo::IsValidCargo(cargo_id)) return false;
if (GetCargoType(engine_id) == cargo_id) return true;
if (cargo_id == CT_MAIL && ::GetEngine(engine_id)->type == VEH_AIRCRAFT) return true;
if (::GetEngine(engine_id)->type == VEH_SHIP && !ShipVehInfo(engine_id)->refittable) return false;
return ::CanRefitTo(engine_id, cargo_id);
}
/* static */ bool AIEngine::CanPullCargo(EngineID engine_id, CargoID cargo_id)
{
if (!IsValidEngine(engine_id)) return false;
if (GetVehicleType(engine_id) != AIVehicle::VEHICLE_RAIL) return false;
if (!AICargo::IsValidCargo(cargo_id)) return false;
return (::RailVehInfo(engine_id)->ai_passenger_only != 1) || AICargo::HasCargoClass(cargo_id, AICargo::CC_PASSENGERS);
}
/* static */ int32 AIEngine::GetCapacity(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return -1;
switch (::GetEngine(engine_id)->type) {
case VEH_ROAD:
case VEH_TRAIN: {
uint16 *capacities = GetCapacityOfArticulatedParts(engine_id, ::GetEngine(engine_id)->type);
for (CargoID c = 0; c < NUM_CARGO; c++) {
if (capacities[c] == 0) continue;
return capacities[c];
}
return -1;
} break;
case VEH_SHIP: {
const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id);
return vi->capacity;
} break;
case VEH_AIRCRAFT: {
const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine_id);
return vi->passenger_capacity;
} break;
default: NOT_REACHED();
}
}
/* static */ int32 AIEngine::GetReliability(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return -1;
return (::GetEngine(engine_id)->reliability * 100 >> 16);
}
/* static */ int32 AIEngine::GetMaxSpeed(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return -1;
switch (::GetEngine(engine_id)->type) {
case VEH_ROAD: {
const RoadVehicleInfo *vi = ::RoadVehInfo(engine_id);
/* Internal speeds are km/h * 2 */
return vi->max_speed / 2;
} break;
case VEH_TRAIN: {
const RailVehicleInfo *vi = ::RailVehInfo(engine_id);
return vi->max_speed;
} break;
case VEH_SHIP: {
const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id);
/* Internal speeds are km/h * 2 */
return vi->max_speed / 2;
} break;
case VEH_AIRCRAFT: {
const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine_id);
return vi->max_speed / _settings_game.vehicle.plane_speed;
} break;
default: NOT_REACHED();
}
}
/* static */ Money AIEngine::GetPrice(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return -1;
switch (::GetEngine(engine_id)->type) {
case VEH_ROAD: {
const RoadVehicleInfo *vi = ::RoadVehInfo(engine_id);
return (_price.roadveh_base >> 3) * vi->cost_factor >> 5;
} break;
case VEH_TRAIN: {
const RailVehicleInfo *vi = ::RailVehInfo(engine_id);
return (_price.build_railvehicle >> 3) * vi->cost_factor >> 5;
} break;
case VEH_SHIP: {
const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id);
return (_price.ship_base >> 3) * vi->cost_factor >> 5;
} break;
case VEH_AIRCRAFT: {
const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine_id);
return (_price.aircraft_base >> 3) * vi->cost_factor >> 5;
} break;
default: NOT_REACHED();
}
}
/* static */ int32 AIEngine::GetMaxAge(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return -1;
return ::GetEngine(engine_id)->lifelength * 366;
}
/* static */ Money AIEngine::GetRunningCost(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return -1;
/* We need to create an instance in order to obtain GetRunningCost.
* This means we temporary allocate a vehicle in the pool, but
* there is no other way.. */
Vehicle *vehicle;
switch (::GetEngine(engine_id)->type) {
case VEH_ROAD: {
vehicle = new RoadVehicle();
} break;
case VEH_TRAIN: {
vehicle = new Train();
} break;
case VEH_SHIP: {
vehicle = new Ship();
} break;
case VEH_AIRCRAFT: {
vehicle = new Aircraft();
} break;
default: NOT_REACHED();
}
vehicle->engine_type = engine_id;
Money runningCost = vehicle->GetRunningCost();
delete vehicle;
return runningCost >> 8;
}
/* static */ AIVehicle::VehicleType AIEngine::GetVehicleType(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return AIVehicle::VEHICLE_INVALID;
switch (::GetEngine(engine_id)->type) {
case VEH_ROAD: return AIVehicle::VEHICLE_ROAD;
case VEH_TRAIN: return AIVehicle::VEHICLE_RAIL;
case VEH_SHIP: return AIVehicle::VEHICLE_WATER;
case VEH_AIRCRAFT: return AIVehicle::VEHICLE_AIR;
default: NOT_REACHED();
}
}
/* static */ bool AIEngine::IsWagon(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return false;
if (GetVehicleType(engine_id) != AIVehicle::VEHICLE_RAIL) return false;
return ::RailVehInfo(engine_id)->power == 0;
}
/* static */ bool AIEngine::CanRunOnRail(EngineID engine_id, AIRail::RailType track_rail_type)
{
if (!IsValidEngine(engine_id)) return false;
if (GetVehicleType(engine_id) != AIVehicle::VEHICLE_RAIL) return false;
if (!AIRail::IsRailTypeAvailable(track_rail_type)) return false;
return ::IsCompatibleRail((::RailType)::RailVehInfo(engine_id)->railtype, (::RailType)track_rail_type);
}
/* static */ bool AIEngine::HasPowerOnRail(EngineID engine_id, AIRail::RailType track_rail_type)
{
if (!IsValidEngine(engine_id)) return false;
if (GetVehicleType(engine_id) != AIVehicle::VEHICLE_RAIL) return false;
if (!AIRail::IsRailTypeAvailable(track_rail_type)) return false;
return ::HasPowerOnRail((::RailType)::RailVehInfo(engine_id)->railtype, (::RailType)track_rail_type);
}
/* static */ AIRoad::RoadType AIEngine::GetRoadType(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return AIRoad::ROADTYPE_INVALID;
if (GetVehicleType(engine_id) != AIVehicle::VEHICLE_ROAD) return AIRoad::ROADTYPE_INVALID;
return HasBit(::EngInfo(engine_id)->misc_flags, EF_ROAD_TRAM) ? AIRoad::ROADTYPE_TRAM : AIRoad::ROADTYPE_ROAD;
}
/* static */ AIRail::RailType AIEngine::GetRailType(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return AIRail::RAILTYPE_INVALID;
if (GetVehicleType(engine_id) != AIVehicle::VEHICLE_RAIL) return AIRail::RAILTYPE_INVALID;
return (AIRail::RailType)(uint)::RailVehInfo(engine_id)->railtype;
}
/* static */ bool AIEngine::IsArticulated(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return false;
if (GetVehicleType(engine_id) != AIVehicle::VEHICLE_ROAD && GetVehicleType(engine_id) != AIVehicle::VEHICLE_RAIL) return false;
return CountArticulatedParts(engine_id, true) != 0;
}
/* static */ AIAirport::PlaneType AIEngine::GetPlaneType(EngineID engine_id)
{
if (!IsValidEngine(engine_id)) return AIAirport::PT_INVALID;
if (GetVehicleType(engine_id) != AIVehicle::VEHICLE_AIR) return AIAirport::PT_INVALID;
return (AIAirport::PlaneType)::AircraftVehInfo(engine_id)->subtype;
}

202
src/ai/api/ai_engine.hpp Normal file
View File

@@ -0,0 +1,202 @@
/* $Id$ */
/** @file ai_engine.hpp Everything to query and build engines. */
#ifndef AI_ENGINE_HPP
#define AI_ENGINE_HPP
#include "ai_object.hpp"
#include "ai_vehicle.hpp"
#include "ai_road.hpp"
#include "ai_rail.hpp"
#include "ai_airport.hpp"
/**
* Class that handles all engine related functions.
*/
class AIEngine : public AIObject {
public:
static const char *GetClassName() { return "AIEngine"; }
/**
* Checks whether the given engine type is valid and buildable by you.
* @param engine_id The engine to check.
* @return True if and only if the engine type is valid.
*/
static bool IsValidEngine(EngineID engine_id);
/**
* Get the name of an engine.
* @param engine_id The engine to get the name of.
* @pre IsValidEngine(engine_id).
* @return The name the engine has.
*/
static const char *GetName(EngineID engine_id);
/**
* Get the cargo-type of an engine. In case it can transport 2 cargos, it
* returns the first.
* @param engine_id The engine to get the cargo-type of.
* @pre IsValidEngine(engine_id).
* @return The cargo-type of the engine.
*/
static CargoID GetCargoType(EngineID engine_id);
/**
* Check if the cargo of an engine can be refitted to your requested. If
* the engine already allows this cargo, the function also returns true.
* @param engine_id The engine to check for refitting.
* @param cargo_id The cargo to check for refitting.
* @pre IsValidEngine(engine_id).
* @pre AICargo::IsValidCargo(cargo_id).
* @return True if the engine can carry this cargo, either via refit, or
* by default.
*/
static bool CanRefitCargo(EngineID engine_id, CargoID cargo_id);
/**
* Check if the engine can pull a wagon with the given cargo.
* @param engine_id The engine to check.
* @param cargo_id The cargo to check.
* @pre IsValidEngine(engine_id).
* @pre GetVehicleType(engine_id) == AIVehicle.VEHICLE_RAIL.
* @pre AICargo::IsValidCargo(cargo_id).
* @return True if the engine can pull wagons carrying this cargo.
* @note This function is not exhaustive; a true here does not mean
* that the vehicle can pull the wagons, a false does mean it can't.
*/
static bool CanPullCargo(EngineID engine_id, CargoID cargo_id);
/**
* Get the capacity of an engine. In case it can transport 2 cargos, it
* returns the first.
* @param engine_id The engine to get the capacity of.
* @pre IsValidEngine(engine_id).
* @return The capacity of the engine.
*/
static int32 GetCapacity(EngineID engine_id);
/**
* Get the reliability of an engine. The value is between 0 and 100, where
* 100 means 100% reliability (never breaks down) and 0 means 0%
* reliability (you most likely don't want to buy it).
* @param engine_id The engine to get the reliability of.
* @pre IsValidEngine(engine_id).
* @return The reliability the engine has.
*/
static int32 GetReliability(EngineID engine_id);
/**
* Get the maximum speed of an engine.
* @param engine_id The engine to get the maximum speed of.
* @pre IsValidEngine(engine_id).
* @return The maximum speed the engine has.
* @note The speed is in km/h.
*/
static int32 GetMaxSpeed(EngineID engine_id);
/**
* Get the new cost of an engine.
* @param engine_id The engine to get the new cost of.
* @pre IsValidEngine(engine_id).
* @return The new cost the engine has.
*/
static Money GetPrice(EngineID engine_id);
/**
* Get the maximum age of a brand new engine.
* @param engine_id The engine to get the maximum age of.
* @pre IsValidEngine(engine_id).
* @returns The maximum age of a new engine in days.
* @note Age is in days; divide by 366 to get per year.
*/
static int32 GetMaxAge(EngineID engine_id);
/**
* Get the running cost of an engine.
* @param engine_id The engine to get the running cost of.
* @pre IsValidEngine(engine_id).
* @return The running cost of a vehicle per year.
* @note Cost is per year; divide by 364 to get per day.
*/
static Money GetRunningCost(EngineID engine_id);
/**
* Get the type of an engine.
* @param engine_id The engine to get the type of.
* @pre IsValidEngine(engine_id).
* @return The type the engine has.
*/
static AIVehicle::VehicleType GetVehicleType(EngineID engine_id);
/**
* Check if an engine is a wagon.
* @param engine_id The engine to check.
* @pre IsValidEngine(engine_id).
* @pre GetVehicleType(engine_id) == AIVehicle.VEHICLE_RAIL.
* @return Whether or not the engine is a wagon.
*/
static bool IsWagon(EngineID engine_id);
/**
* Check if a train vehicle can run on a RailType.
* @param engine_id The engine to check.
* @param track_rail_type The type you want to check.
* @pre IsValidEngine(engine_id).
* @pre GetVehicleType(engine_id) == AIVehicle::VEHICLE_RAIL.
* @pre AIRail::IsRailTypeAvailable(track_rail_type).
* @return Whether an engine of type 'engine_id' can run on 'track_rail_type'.
* @note Even if a train can run on a RailType that doesn't mean that it'll be
* able to power the train. Use HasPowerOnRail for that.
*/
static bool CanRunOnRail(EngineID engine_id, AIRail::RailType track_rail_type);
/**
* Check if a train engine has power on a RailType.
* @param engine_id The engine to check.
* @param track_rail_type Another RailType.
* @pre IsValidEngine(engine_id).
* @pre GetVehicleType(engine_id) == AIVehicle::VEHICLE_RAIL.
* @pre AIRail::IsRailTypeAvailable(track_rail_type).
* @return Whether an engine of type 'engine_id' has power on 'track_rail_type'.
*/
static bool HasPowerOnRail(EngineID engine_id, AIRail::RailType track_rail_type);
/**
* Get the RoadType of the engine.
* @param engine_id The engine to get the RoadType of.
* @pre IsValidEngine(engine_id).
* @pre GetVehicleType(engine_id) == AIVehicle.VEHICLE_ROAD.
* @return The RoadType the engine has.
*/
static AIRoad::RoadType GetRoadType(EngineID engine_id);
/**
* Get the RailType of the engine.
* @param engine_id The engine to get the RailType of.
* @pre IsValidEngine(engine_id).
* @pre GetVehicleType(engine_id) == AIVehicle.VEHICLE_RAIL.
* @return The RailType the engine has.
*/
static AIRail::RailType GetRailType(EngineID engine_id);
/**
* Check if the engine is articulated.
* @param engine_id The engine to check.
* @pre IsValidEngine(engine_id).
* @pre GetVehicleType(engine_id) == AIVehicle.VEHICLE_ROAD || GetVehicleType(engine_id) == AIVehicle.VEHICLE_RAIL.
* @return True if the engine is articulated.
*/
static bool IsArticulated(EngineID engine_id);
/**
* Get the PlaneType of the engine.
* @param engine_id The engine to get the PlaneType of.
* @pre IsValidEngine(engine_id).
* @pre GetVehicleType(engine_id) == AIVehicle.VEHICLE_AIR.
* @return The PlaneType the engine has.
*/
static AIAirport::PlaneType GetPlaneType(EngineID engine_id);
};
#endif /* AI_ENGINE_HPP */

View File

@@ -0,0 +1,42 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_engine.hpp"
namespace SQConvert {
/* Allow AIEngine to be used as Squirrel parameter */
template <> AIEngine *GetParam(ForceType<AIEngine *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEngine *)instance; }
template <> AIEngine &GetParam(ForceType<AIEngine &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEngine *)instance; }
template <> const AIEngine *GetParam(ForceType<const AIEngine *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEngine *)instance; }
template <> const AIEngine &GetParam(ForceType<const AIEngine &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEngine *)instance; }
template <> int Return<AIEngine *>(HSQUIRRELVM vm, AIEngine *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEngine", res, NULL, DefSQDestructorCallback<AIEngine>); return 1; }
}; // namespace SQConvert
void SQAIEngine_Register(Squirrel *engine) {
DefSQClass <AIEngine> SQAIEngine("AIEngine");
SQAIEngine.PreRegister(engine);
SQAIEngine.AddConstructor<void (AIEngine::*)(), 1>(engine, "x");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetClassName, "GetClassName", 1, "x");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::IsValidEngine, "IsValidEngine", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetName, "GetName", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetCargoType, "GetCargoType", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::CanRefitCargo, "CanRefitCargo", 3, "xii");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::CanPullCargo, "CanPullCargo", 3, "xii");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetCapacity, "GetCapacity", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetReliability, "GetReliability", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetMaxSpeed, "GetMaxSpeed", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetPrice, "GetPrice", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetMaxAge, "GetMaxAge", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetRunningCost, "GetRunningCost", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetVehicleType, "GetVehicleType", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::IsWagon, "IsWagon", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::CanRunOnRail, "CanRunOnRail", 3, "xii");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::HasPowerOnRail, "HasPowerOnRail", 3, "xii");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetRoadType, "GetRoadType", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetRailType, "GetRailType", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::IsArticulated, "IsArticulated", 2, "xi");
SQAIEngine.DefSQStaticMethod(engine, &AIEngine::GetPlaneType, "GetPlaneType", 2, "xi");
SQAIEngine.PostRegister(engine);
}

View File

@@ -0,0 +1,16 @@
/* $Id$ */
/** @file ai_enginelist.cpp Implementation of AIEngineList and friends. */
#include "ai_enginelist.hpp"
#include "../../company_func.h"
#include "../../engine_base.h"
#include "../../core/bitmath_func.hpp"
AIEngineList::AIEngineList(AIVehicle::VehicleType vehicle_type)
{
Engine *e;
FOR_ALL_ENGINES_OF_TYPE(e, (::VehicleType)vehicle_type) {
if (HasBit(e->company_avail, _current_company)) this->AddItem(e->index);
}
}

View File

@@ -0,0 +1,25 @@
/* $Id$ */
/** @file ai_enginelist.hpp List all the engines. */
#ifndef AI_ENGINELIST_HPP
#define AI_ENGINELIST_HPP
#include "ai_abstractlist.hpp"
#include "ai_vehicle.hpp"
/**
* Create a list of engines based on a vehicle type.
* @ingroup AIList
*/
class AIEngineList : public AIAbstractList {
public:
static const char *GetClassName() { return "AIEngineList"; }
/**
* @param vehicle_type The type of vehicle to make a list of engines for.
*/
AIEngineList(AIVehicle::VehicleType vehicle_type);
};
#endif /* AI_ENGINELIST_HPP */

View File

@@ -0,0 +1,23 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_enginelist.hpp"
namespace SQConvert {
/* Allow AIEngineList to be used as Squirrel parameter */
template <> AIEngineList *GetParam(ForceType<AIEngineList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEngineList *)instance; }
template <> AIEngineList &GetParam(ForceType<AIEngineList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEngineList *)instance; }
template <> const AIEngineList *GetParam(ForceType<const AIEngineList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEngineList *)instance; }
template <> const AIEngineList &GetParam(ForceType<const AIEngineList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEngineList *)instance; }
template <> int Return<AIEngineList *>(HSQUIRRELVM vm, AIEngineList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEngineList", res, NULL, DefSQDestructorCallback<AIEngineList>); return 1; }
}; // namespace SQConvert
void SQAIEngineList_Register(Squirrel *engine) {
DefSQClass <AIEngineList> SQAIEngineList("AIEngineList");
SQAIEngineList.PreRegister(engine, "AIAbstractList");
SQAIEngineList.AddConstructor<void (AIEngineList::*)(AIVehicle::VehicleType vehicle_type), 2>(engine, "xi");
SQAIEngineList.DefSQStaticMethod(engine, &AIEngineList::GetClassName, "GetClassName", 1, "x");
SQAIEngineList.PostRegister(engine);
}

60
src/ai/api/ai_error.cpp Normal file
View File

@@ -0,0 +1,60 @@
/* $Id$ */
/** @file ai_error.cpp Implementation of AIError. */
#include "ai_error.hpp"
#include "table/strings.h"
#include "../../core/bitmath_func.hpp"
AIError::AIErrorMap AIError::error_map = AIError::AIErrorMap();
AIError::AIErrorMapString AIError::error_map_string = AIError::AIErrorMapString();
/* static */ AIErrorType AIError::GetLastError()
{
return AIObject::GetLastError();
}
/* static */ const char *AIError::GetLastErrorString()
{
return (*error_map_string.find(AIError::GetLastError())).second;
}
/* static */ AIErrorType AIError::StringToError(StringID internal_string_id)
{
uint index = GB(internal_string_id, 11, 5);
switch (GB(internal_string_id, 11, 5)) {
case 26: case 28: case 29: case 30: // NewGRF strings.
return ERR_NEWGRF_SUPPLIED_ERROR;
/* DO NOT SWAP case 14 and 4 because that will break StringToError due
* to the index dependency that relies on FALL THROUGHs. */
case 14: if (index < 0xE4) break; // Player name
case 4: if (index < 0xC0) break; // Town name
case 15: // Custom name
case 31: // Dynamic strings
/* These strings are 'random' and have no meaning.
* They actually shouldn't even be returned as error messages. */
return ERR_UNKNOWN;
default:
break;
}
AIErrorMap::iterator it = error_map.find(internal_string_id);
if (it == error_map.end()) return ERR_UNKNOWN;
return (*it).second;
}
/* static */ void AIError::RegisterErrorMap(StringID internal_string_id, AIErrorType ai_error_msg)
{
error_map[internal_string_id] = ai_error_msg;
}
/* static */ void AIError::RegisterErrorMapString(AIErrorType ai_error_msg, const char *message)
{
error_map_string[ai_error_msg] = message;
}
/* static */ AIError::ErrorCategories AIError::GetErrorCategory() {
return (AIError::ErrorCategories)(GetLastError() >> (uint)ERR_CAT_BIT_SIZE);
}

171
src/ai/api/ai_error.hpp Normal file
View File

@@ -0,0 +1,171 @@
/* $Id$ */
/** @file ai_error.hpp Everything to query errors. */
#ifndef AI_ERROR_HPP
#define AI_ERROR_HPP
#include "ai_object.hpp"
#include <map>
/**
* Helper to write precondition enforcers for the AI API in an abbreviated manner.
* @param returnval The value to return on failure.
* @param condition The condition that must be obeyed.
*/
#define EnforcePrecondition(returnval, condition) \
if (!(condition)) { \
AIObject::SetLastError(AIError::ERR_PRECONDITION_FAILED); \
return returnval; \
}
/**
* Helper to write precondition enforcers for the AI API in an abbreviated manner.
* @param returnval The value to return on failure.
* @param condition The condition that must be obeyed.
* @param error_code The error code passed to AIObject::SetLastError.
*/
#define EnforcePreconditionCustomError(returnval, condition, error_code) \
if (!(condition)) { \
AIObject::SetLastError(error_code); \
return returnval; \
}
/**
* Class that handles all error related functions.
*/
class AIError : public AIObject {
public:
static const char *GetClassName() { return "AIError"; }
/**
* All categories errors can be divided in.
*/
enum ErrorCategories {
ERR_CAT_NONE = 0, //!< Error messages not related to any category.
ERR_CAT_GENERAL, //!< Error messages related to general things.
ERR_CAT_VEHICLE, //!< Error messages related to building / maintaining vehicles.
ERR_CAT_STATION, //!< Error messages related to building / maintaining stations.
ERR_CAT_BRIDGE, //!< Error messages related to building / removing bridges.
ERR_CAT_TUNNEL, //!< Error messages related to building / removing tunnels.
ERR_CAT_TILE, //!< Error messages related to raising / lowering and demolishing tiles.
ERR_CAT_SIGN, //!< Error messages related to building / removing signs.
ERR_CAT_RAIL, //!< Error messages related to building / maintaining rails.
ERR_CAT_ROAD, //!< Error messages related to building / maintaining roads.
ERR_CAT_ORDER, //!< Error messages related to managing orders.
ERR_CAT_MARINE, //!< Error messages related to building / removing ships, docks and channels.
/**
* DO NOT USE! The error bitsize determines how many errors can be stored in
* a category and what the offsets are of all categories.
*/
ERR_CAT_BIT_SIZE = 8,
};
/**
* All general related error messages.
*/
enum ErrorMessages {
/** Initial error value */
ERR_NONE = ERR_CAT_NONE << ERR_CAT_BIT_SIZE, // []
/** If an error occured and the error wasn't mapped */
ERR_UNKNOWN, // []
/** If a precondition is not met */
ERR_PRECONDITION_FAILED, // []
/** A string supplied was too long */
ERR_PRECONDITION_STRING_TOO_LONG, // []
/** An error returned by a NewGRF. No possibility to get the exact error in an AI readable format */
ERR_NEWGRF_SUPPLIED_ERROR, // []
/** Base for general errors */
ERR_GENERAL_BASE = ERR_CAT_GENERAL << ERR_CAT_BIT_SIZE,
/** Not enough cash to perform the previous action */
ERR_NOT_ENOUGH_CASH, // [STR_0003_NOT_ENOUGH_CASH_REQUIRES]
/** Local authority won't allow the previous action */
ERR_LOCAL_AUTHORITY_REFUSES, // [STR_2009_LOCAL_AUTHORITY_REFUSES]
/** The piece of infrastructure you tried to build is already in place */
ERR_ALREADY_BUILT, // [STR_1007_ALREADY_BUILT, STR_5007_MUST_DEMOLISH_BRIDGE_FIRST]
/** Area isn't clear, try to demolish the building on it */
ERR_AREA_NOT_CLEAR, // [STR_2004_BUILDING_MUST_BE_DEMOLISHED, STR_5007_MUST_DEMOLISH_BRIDGE_FIRST, STR_300B_MUST_DEMOLISH_RAILROAD, STR_300E_MUST_DEMOLISH_AIRPORT_FIRST, STR_MUST_DEMOLISH_CARGO_TRAM_STATION, STR_3047_MUST_DEMOLISH_TRUCK_STATION, STR_MUST_DEMOLISH_PASSENGER_TRAM_STATION, STR_3046_MUST_DEMOLISH_BUS_STATION, STR_306A_BUOY_IN_THE_WAY, STR_304D_MUST_DEMOLISH_DOCK_FIRST, STR_4800_IN_THE_WAY, STR_5804_COMPANY_HEADQUARTERS_IN, STR_5800_OBJECT_IN_THE_WAY, STR_1801_MUST_REMOVE_ROAD_FIRST, STR_1008_MUST_REMOVE_RAILROAD_TRACK, STR_5007_MUST_DEMOLISH_BRIDGE_FIRST, STR_5006_MUST_DEMOLISH_TUNNEL_FIRST, STR_1002_EXCAVATION_WOULD_DAMAGE]
/** Area / property is owned by another company */
ERR_OWNED_BY_ANOTHER_COMPANY, // [STR_1024_AREA_IS_OWNED_BY_ANOTHER, STR_013B_OWNED_BY]
/** The name given is not unique for the object type */
ERR_NAME_IS_NOT_UNIQUE, // [STR_NAME_MUST_BE_UNIQUE]
/** The building you want to build requires flat land */
ERR_FLAT_LAND_REQUIRED, // [STR_0007_FLAT_LAND_REQUIRED]
/** Land is sloped in the wrong direction for this build action */
ERR_LAND_SLOPED_WRONG, // [STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION]
/** A vehicle is in the way */
ERR_VEHICLE_IN_THE_WAY, // [STR_8803_TRAIN_IN_THE_WAY, STR_9000_ROAD_VEHICLE_IN_THE_WAY, STR_980E_SHIP_IN_THE_WAY, STR_A015_AIRCRAFT_IN_THE_WAY]
/** Site is unsuitable */
ERR_SITE_UNSUITABLE, // [STR_0239_SITE_UNSUITABLE, STR_304B_SITE_UNSUITABLE]
/** Too close to the edge of the map */
ERR_TOO_CLOSE_TO_EDGE, // [STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP]
/** Station is too spread out */
ERR_STATION_TOO_SPREAD_OUT, // [STR_306C_STATION_TOO_SPREAD_OUT]
};
/**
* Check the membership of the last thrown error.
* @return The category the error belongs to.
* @note The last throw error can be aquired by calling GetLastError().
*/
static ErrorCategories GetErrorCategory();
/**
* Get the last error.
* @return An ErrorMessages enum value.
*/
static AIErrorType GetLastError();
/**
* Get the last error in string format (for human readability).
* @return An ErrorMessage enum item, as string.
*/
static const char *GetLastErrorString();
/**
* Get the error based on the OpenTTD StringID.
* @note DO NOT INVOKE THIS METHOD YOURSELF!
* @param internal_string_id The string to convert.
* @return The NoAI equivalent error message.
*/
static AIErrorType StringToError(StringID internal_string_id);
/**
* Map an internal OpenTTD error message to it's NoAI equivalent.
* @note DO NOT INVOKE THIS METHOD YOURSELF! The calls are autogenerated.
* @param internal_string_id The OpenTTD StringID used for an error.
* @param ai_error_msg The NoAI equivalent error message.
*/
static void RegisterErrorMap(StringID internal_string_id, AIErrorType ai_error_msg);
/**
* Map an internal OpenTTD error message to it's NoAI equivalent.
* @note DO NOT INVOKE THIS METHOD YOURSELF! The calls are autogenerated.
* @param ai_error_msg The NoAI error message representation.
* @param message The string representation of this error message, used for debug purposes.
*/
static void RegisterErrorMapString(AIErrorType ai_error_msg, const char *message);
private:
typedef std::map<StringID, AIErrorType> AIErrorMap;
typedef std::map<AIErrorType, const char *> AIErrorMapString;
static AIErrorMap error_map;
static AIErrorMapString error_map_string;
};
#endif /* AI_ERROR_HPP */

121
src/ai/api/ai_error.hpp.sq Normal file
View File

@@ -0,0 +1,121 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_error.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AIError::ErrorCategories GetParam(ForceType<AIError::ErrorCategories>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIError::ErrorCategories)tmp; }
template <> int Return<AIError::ErrorCategories>(HSQUIRRELVM vm, AIError::ErrorCategories res) { sq_pushinteger(vm, (int32)res); return 1; }
template <> AIError::ErrorMessages GetParam(ForceType<AIError::ErrorMessages>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIError::ErrorMessages)tmp; }
template <> int Return<AIError::ErrorMessages>(HSQUIRRELVM vm, AIError::ErrorMessages res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AIError to be used as Squirrel parameter */
template <> AIError *GetParam(ForceType<AIError *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIError *)instance; }
template <> AIError &GetParam(ForceType<AIError &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIError *)instance; }
template <> const AIError *GetParam(ForceType<const AIError *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIError *)instance; }
template <> const AIError &GetParam(ForceType<const AIError &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIError *)instance; }
template <> int Return<AIError *>(HSQUIRRELVM vm, AIError *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIError", res, NULL, DefSQDestructorCallback<AIError>); return 1; }
}; // namespace SQConvert
void SQAIError_Register(Squirrel *engine) {
DefSQClass <AIError> SQAIError("AIError");
SQAIError.PreRegister(engine);
SQAIError.AddConstructor<void (AIError::*)(), 1>(engine, "x");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_NONE, "ERR_CAT_NONE");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_GENERAL, "ERR_CAT_GENERAL");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_VEHICLE, "ERR_CAT_VEHICLE");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_STATION, "ERR_CAT_STATION");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_BRIDGE, "ERR_CAT_BRIDGE");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_TUNNEL, "ERR_CAT_TUNNEL");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_TILE, "ERR_CAT_TILE");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_SIGN, "ERR_CAT_SIGN");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_RAIL, "ERR_CAT_RAIL");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_ROAD, "ERR_CAT_ROAD");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_ORDER, "ERR_CAT_ORDER");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_MARINE, "ERR_CAT_MARINE");
SQAIError.DefSQConst(engine, AIError::ERR_CAT_BIT_SIZE, "ERR_CAT_BIT_SIZE");
SQAIError.DefSQConst(engine, AIError::ERR_NONE, "ERR_NONE");
SQAIError.DefSQConst(engine, AIError::ERR_UNKNOWN, "ERR_UNKNOWN");
SQAIError.DefSQConst(engine, AIError::ERR_PRECONDITION_FAILED, "ERR_PRECONDITION_FAILED");
SQAIError.DefSQConst(engine, AIError::ERR_PRECONDITION_STRING_TOO_LONG, "ERR_PRECONDITION_STRING_TOO_LONG");
SQAIError.DefSQConst(engine, AIError::ERR_NEWGRF_SUPPLIED_ERROR, "ERR_NEWGRF_SUPPLIED_ERROR");
SQAIError.DefSQConst(engine, AIError::ERR_GENERAL_BASE, "ERR_GENERAL_BASE");
SQAIError.DefSQConst(engine, AIError::ERR_NOT_ENOUGH_CASH, "ERR_NOT_ENOUGH_CASH");
SQAIError.DefSQConst(engine, AIError::ERR_LOCAL_AUTHORITY_REFUSES, "ERR_LOCAL_AUTHORITY_REFUSES");
SQAIError.DefSQConst(engine, AIError::ERR_ALREADY_BUILT, "ERR_ALREADY_BUILT");
SQAIError.DefSQConst(engine, AIError::ERR_AREA_NOT_CLEAR, "ERR_AREA_NOT_CLEAR");
SQAIError.DefSQConst(engine, AIError::ERR_OWNED_BY_ANOTHER_COMPANY, "ERR_OWNED_BY_ANOTHER_COMPANY");
SQAIError.DefSQConst(engine, AIError::ERR_NAME_IS_NOT_UNIQUE, "ERR_NAME_IS_NOT_UNIQUE");
SQAIError.DefSQConst(engine, AIError::ERR_FLAT_LAND_REQUIRED, "ERR_FLAT_LAND_REQUIRED");
SQAIError.DefSQConst(engine, AIError::ERR_LAND_SLOPED_WRONG, "ERR_LAND_SLOPED_WRONG");
SQAIError.DefSQConst(engine, AIError::ERR_VEHICLE_IN_THE_WAY, "ERR_VEHICLE_IN_THE_WAY");
SQAIError.DefSQConst(engine, AIError::ERR_SITE_UNSUITABLE, "ERR_SITE_UNSUITABLE");
SQAIError.DefSQConst(engine, AIError::ERR_TOO_CLOSE_TO_EDGE, "ERR_TOO_CLOSE_TO_EDGE");
SQAIError.DefSQConst(engine, AIError::ERR_STATION_TOO_SPREAD_OUT, "ERR_STATION_TOO_SPREAD_OUT");
AIError::RegisterErrorMap(STR_0003_NOT_ENOUGH_CASH_REQUIRES, AIError::ERR_NOT_ENOUGH_CASH);
AIError::RegisterErrorMap(STR_2009_LOCAL_AUTHORITY_REFUSES, AIError::ERR_LOCAL_AUTHORITY_REFUSES);
AIError::RegisterErrorMap(STR_1007_ALREADY_BUILT, AIError::ERR_ALREADY_BUILT);
AIError::RegisterErrorMap(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST, AIError::ERR_ALREADY_BUILT);
AIError::RegisterErrorMap(STR_2004_BUILDING_MUST_BE_DEMOLISHED, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_300B_MUST_DEMOLISH_RAILROAD, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_MUST_DEMOLISH_CARGO_TRAM_STATION, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_3047_MUST_DEMOLISH_TRUCK_STATION, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_MUST_DEMOLISH_PASSENGER_TRAM_STATION, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_3046_MUST_DEMOLISH_BUS_STATION, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_306A_BUOY_IN_THE_WAY, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_304D_MUST_DEMOLISH_DOCK_FIRST, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_4800_IN_THE_WAY, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_5804_COMPANY_HEADQUARTERS_IN, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_5800_OBJECT_IN_THE_WAY, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_1801_MUST_REMOVE_ROAD_FIRST, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_1008_MUST_REMOVE_RAILROAD_TRACK, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_1002_EXCAVATION_WOULD_DAMAGE, AIError::ERR_AREA_NOT_CLEAR);
AIError::RegisterErrorMap(STR_1024_AREA_IS_OWNED_BY_ANOTHER, AIError::ERR_OWNED_BY_ANOTHER_COMPANY);
AIError::RegisterErrorMap(STR_013B_OWNED_BY, AIError::ERR_OWNED_BY_ANOTHER_COMPANY);
AIError::RegisterErrorMap(STR_NAME_MUST_BE_UNIQUE, AIError::ERR_NAME_IS_NOT_UNIQUE);
AIError::RegisterErrorMap(STR_0007_FLAT_LAND_REQUIRED, AIError::ERR_FLAT_LAND_REQUIRED);
AIError::RegisterErrorMap(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION, AIError::ERR_LAND_SLOPED_WRONG);
AIError::RegisterErrorMap(STR_8803_TRAIN_IN_THE_WAY, AIError::ERR_VEHICLE_IN_THE_WAY);
AIError::RegisterErrorMap(STR_9000_ROAD_VEHICLE_IN_THE_WAY, AIError::ERR_VEHICLE_IN_THE_WAY);
AIError::RegisterErrorMap(STR_980E_SHIP_IN_THE_WAY, AIError::ERR_VEHICLE_IN_THE_WAY);
AIError::RegisterErrorMap(STR_A015_AIRCRAFT_IN_THE_WAY, AIError::ERR_VEHICLE_IN_THE_WAY);
AIError::RegisterErrorMap(STR_0239_SITE_UNSUITABLE, AIError::ERR_SITE_UNSUITABLE);
AIError::RegisterErrorMap(STR_304B_SITE_UNSUITABLE, AIError::ERR_SITE_UNSUITABLE);
AIError::RegisterErrorMap(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP, AIError::ERR_TOO_CLOSE_TO_EDGE);
AIError::RegisterErrorMap(STR_306C_STATION_TOO_SPREAD_OUT, AIError::ERR_STATION_TOO_SPREAD_OUT);
AIError::RegisterErrorMapString(AIError::ERR_NONE, "ERR_NONE");
AIError::RegisterErrorMapString(AIError::ERR_UNKNOWN, "ERR_UNKNOWN");
AIError::RegisterErrorMapString(AIError::ERR_PRECONDITION_FAILED, "ERR_PRECONDITION_FAILED");
AIError::RegisterErrorMapString(AIError::ERR_PRECONDITION_STRING_TOO_LONG, "ERR_PRECONDITION_STRING_TOO_LONG");
AIError::RegisterErrorMapString(AIError::ERR_NEWGRF_SUPPLIED_ERROR, "ERR_NEWGRF_SUPPLIED_ERROR");
AIError::RegisterErrorMapString(AIError::ERR_NOT_ENOUGH_CASH, "ERR_NOT_ENOUGH_CASH");
AIError::RegisterErrorMapString(AIError::ERR_LOCAL_AUTHORITY_REFUSES, "ERR_LOCAL_AUTHORITY_REFUSES");
AIError::RegisterErrorMapString(AIError::ERR_ALREADY_BUILT, "ERR_ALREADY_BUILT");
AIError::RegisterErrorMapString(AIError::ERR_AREA_NOT_CLEAR, "ERR_AREA_NOT_CLEAR");
AIError::RegisterErrorMapString(AIError::ERR_OWNED_BY_ANOTHER_COMPANY, "ERR_OWNED_BY_ANOTHER_COMPANY");
AIError::RegisterErrorMapString(AIError::ERR_NAME_IS_NOT_UNIQUE, "ERR_NAME_IS_NOT_UNIQUE");
AIError::RegisterErrorMapString(AIError::ERR_FLAT_LAND_REQUIRED, "ERR_FLAT_LAND_REQUIRED");
AIError::RegisterErrorMapString(AIError::ERR_LAND_SLOPED_WRONG, "ERR_LAND_SLOPED_WRONG");
AIError::RegisterErrorMapString(AIError::ERR_VEHICLE_IN_THE_WAY, "ERR_VEHICLE_IN_THE_WAY");
AIError::RegisterErrorMapString(AIError::ERR_SITE_UNSUITABLE, "ERR_SITE_UNSUITABLE");
AIError::RegisterErrorMapString(AIError::ERR_TOO_CLOSE_TO_EDGE, "ERR_TOO_CLOSE_TO_EDGE");
AIError::RegisterErrorMapString(AIError::ERR_STATION_TOO_SPREAD_OUT, "ERR_STATION_TOO_SPREAD_OUT");
SQAIError.DefSQStaticMethod(engine, &AIError::GetClassName, "GetClassName", 1, "x");
SQAIError.DefSQStaticMethod(engine, &AIError::GetErrorCategory, "GetErrorCategory", 1, "x");
SQAIError.DefSQStaticMethod(engine, &AIError::GetLastError, "GetLastError", 1, "x");
SQAIError.DefSQStaticMethod(engine, &AIError::GetLastErrorString, "GetLastErrorString", 1, "x");
SQAIError.DefSQStaticMethod(engine, &AIError::StringToError, "StringToError", 2, "xi");
SQAIError.DefSQStaticMethod(engine, &AIError::RegisterErrorMap, "RegisterErrorMap", 3, "xii");
SQAIError.DefSQStaticMethod(engine, &AIError::RegisterErrorMapString, "RegisterErrorMapString", 3, "xis");
SQAIError.PostRegister(engine);
}

65
src/ai/api/ai_event.cpp Normal file
View File

@@ -0,0 +1,65 @@
/* $Id$ */
/** @file ai_event.cpp Implementation of AIEvent. */
#include "ai_event.hpp"
#include "ai_event_types.hpp"
#include <queue>
#include <set>
struct AIEventData {
std::queue<AIEvent *> stack;
};
/* static */ void AIEventController::CreateEventPointer()
{
assert(AIObject::GetEventPointer() == NULL);
AIObject::GetEventPointer() = new AIEventData();
}
/* static */ void AIEventController::FreeEventPointer()
{
AIEventData *data = (AIEventData *)AIObject::GetEventPointer();
/* Free all waiting events (if any) */
while (!data->stack.empty()) {
AIEvent *e = data->stack.front();
data->stack.pop();
e->Release();
}
/* Now kill our data pointer */
delete data;
}
/* static */ bool AIEventController::IsEventWaiting()
{
if (AIObject::GetEventPointer() == NULL) AIEventController::CreateEventPointer();
AIEventData *data = (AIEventData *)AIObject::GetEventPointer();
return !data->stack.empty();
}
/* static */ AIEvent *AIEventController::GetNextEvent()
{
if (AIObject::GetEventPointer() == NULL) AIEventController::CreateEventPointer();
AIEventData *data = (AIEventData *)AIObject::GetEventPointer();
if (data->stack.empty()) return NULL;
AIEvent *e = data->stack.front();
data->stack.pop();
return e;
}
/* static */ void AIEventController::InsertEvent(AIEvent *event)
{
if (AIObject::GetEventPointer() == NULL) AIEventController::CreateEventPointer();
AIEventData *data = (AIEventData *)AIObject::GetEventPointer();
event->AddRef();
data->stack.push(event);
}

107
src/ai/api/ai_event.hpp Normal file
View File

@@ -0,0 +1,107 @@
/* $Id$ */
/** @file ai_event.hpp Everything to handle events from the game. */
#ifndef AI_EVENT_HPP
#define AI_EVENT_HPP
#include "ai_object.hpp"
/**
* Class that handles all event related functions.
* You can lookup the type, and than convert it to the real event-class.
* That way you can request more detailed information about the event.
*/
class AIEvent : public AIObject {
public:
static const char *GetClassName() { return "AIEvent"; }
/**
* The type of event. Needed to lookup the detailed class.
*/
enum AIEventType {
AI_ET_INVALID = 0,
AI_ET_TEST,
AI_ET_SUBSIDY_OFFER,
AI_ET_SUBSIDY_OFFER_EXPIRED,
AI_ET_SUBSIDY_AWARDED,
AI_ET_SUBSIDY_EXPIRED,
AI_ET_ENGINE_PREVIEW,
AI_ET_COMPANY_NEW,
AI_ET_COMPANY_IN_TROUBLE,
AI_ET_COMPANY_MERGER,
AI_ET_COMPANY_BANKRUPT,
AI_ET_VEHICLE_CRASHED,
AI_ET_VEHICLE_LOST,
AI_ET_VEHICLE_WAITING_IN_DEPOT,
AI_ET_VEHICLE_UNPROFITABLE,
AI_ET_INDUSTRY_OPEN,
AI_ET_INDUSTRY_CLOSE,
AI_ET_ENGINE_AVAILABLE,
AI_ET_STATION_FIRST_VEHICLE,
};
/**
* Constructor of AIEvent, to get the type of event.
*/
AIEvent(AIEvent::AIEventType type) :
type(type)
{}
/**
* Get the event-type.
* @return The @c AIEventType.
*/
AIEventType GetEventType() { return this->type; }
protected:
/**
* The type of this event.
*/
AIEventType type;
};
/**
* Class that handles all event related functions.
* @note it is not needed to create an instance of AIEvent to access it, as
* all members are static, and all data is stored AI-wide.
*/
class AIEventController : public AIObject {
public:
/**
* The name of the class, needed by several sub-processes.
*/
static const char *GetClassName() { return "AIEventController"; }
/**
* Check if there is an event waiting.
* @return true if there is an event on the stack.
*/
static bool IsEventWaiting();
/**
* Get the next event.
* @return a class of the event-child issues.
*/
static AIEvent *GetNextEvent();
/**
* Insert an event to the queue for the company.
* @param event The event to insert.
*/
static void InsertEvent(AIEvent *event);
/**
* Free the event pointer.
* @note DO NOT CALL YOURSELF; leave it to the internal AI programming.
*/
static void FreeEventPointer();
private:
/**
* Create the event pointer.
*/
static void CreateEventPointer();
};
#endif /* AI_EVENT_HPP */

View File

@@ -0,0 +1,72 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_event.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AIEvent::AIEventType GetParam(ForceType<AIEvent::AIEventType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIEvent::AIEventType)tmp; }
template <> int Return<AIEvent::AIEventType>(HSQUIRRELVM vm, AIEvent::AIEventType res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AIEvent to be used as Squirrel parameter */
template <> AIEvent *GetParam(ForceType<AIEvent *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEvent *)instance; }
template <> AIEvent &GetParam(ForceType<AIEvent &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEvent *)instance; }
template <> const AIEvent *GetParam(ForceType<const AIEvent *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEvent *)instance; }
template <> const AIEvent &GetParam(ForceType<const AIEvent &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEvent *)instance; }
template <> int Return<AIEvent *>(HSQUIRRELVM vm, AIEvent *res) { if (res == NULL) { sq_pushnull(vm); return 1; } Squirrel::CreateClassInstanceVM(vm, "AIEvent", res, NULL, DefSQDestructorCallback<AIEvent>); return 1; }
}; // namespace SQConvert
void SQAIEvent_Register(Squirrel *engine) {
DefSQClass <AIEvent> SQAIEvent("AIEvent");
SQAIEvent.PreRegister(engine);
SQAIEvent.AddConstructor<void (AIEvent::*)(AIEvent::AIEventType type), 2>(engine, "xi");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_INVALID, "AI_ET_INVALID");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_TEST, "AI_ET_TEST");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_OFFER, "AI_ET_SUBSIDY_OFFER");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_OFFER_EXPIRED, "AI_ET_SUBSIDY_OFFER_EXPIRED");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_AWARDED, "AI_ET_SUBSIDY_AWARDED");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_SUBSIDY_EXPIRED, "AI_ET_SUBSIDY_EXPIRED");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_ENGINE_PREVIEW, "AI_ET_ENGINE_PREVIEW");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_NEW, "AI_ET_COMPANY_NEW");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_IN_TROUBLE, "AI_ET_COMPANY_IN_TROUBLE");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_MERGER, "AI_ET_COMPANY_MERGER");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_BANKRUPT, "AI_ET_COMPANY_BANKRUPT");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_VEHICLE_CRASHED, "AI_ET_VEHICLE_CRASHED");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_VEHICLE_LOST, "AI_ET_VEHICLE_LOST");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_VEHICLE_WAITING_IN_DEPOT, "AI_ET_VEHICLE_WAITING_IN_DEPOT");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_VEHICLE_UNPROFITABLE, "AI_ET_VEHICLE_UNPROFITABLE");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_INDUSTRY_OPEN, "AI_ET_INDUSTRY_OPEN");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_INDUSTRY_CLOSE, "AI_ET_INDUSTRY_CLOSE");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_ENGINE_AVAILABLE, "AI_ET_ENGINE_AVAILABLE");
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_STATION_FIRST_VEHICLE, "AI_ET_STATION_FIRST_VEHICLE");
SQAIEvent.DefSQStaticMethod(engine, &AIEvent::GetClassName, "GetClassName", 1, "x");
SQAIEvent.DefSQMethod(engine, &AIEvent::GetEventType, "GetEventType", 1, "x");
SQAIEvent.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventController to be used as Squirrel parameter */
template <> AIEventController *GetParam(ForceType<AIEventController *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventController *)instance; }
template <> AIEventController &GetParam(ForceType<AIEventController &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventController *)instance; }
template <> const AIEventController *GetParam(ForceType<const AIEventController *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventController *)instance; }
template <> const AIEventController &GetParam(ForceType<const AIEventController &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventController *)instance; }
template <> int Return<AIEventController *>(HSQUIRRELVM vm, AIEventController *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventController", res, NULL, DefSQDestructorCallback<AIEventController>); return 1; }
}; // namespace SQConvert
void SQAIEventController_Register(Squirrel *engine) {
DefSQClass <AIEventController> SQAIEventController("AIEventController");
SQAIEventController.PreRegister(engine);
SQAIEventController.AddConstructor<void (AIEventController::*)(), 1>(engine, "x");
SQAIEventController.DefSQStaticMethod(engine, &AIEventController::GetClassName, "GetClassName", 1, "x");
SQAIEventController.DefSQStaticMethod(engine, &AIEventController::IsEventWaiting, "IsEventWaiting", 1, "x");
SQAIEventController.DefSQStaticMethod(engine, &AIEventController::GetNextEvent, "GetNextEvent", 1, "x");
SQAIEventController.DefSQStaticMethod(engine, &AIEventController::InsertEvent, "InsertEvent", 2, "xx");
SQAIEventController.DefSQStaticMethod(engine, &AIEventController::FreeEventPointer, "FreeEventPointer", 1, "x");
SQAIEventController.PostRegister(engine);
}

View File

@@ -0,0 +1,187 @@
/* $Id$ */
/** @file ai_event_types.cpp Implementation of all EventTypes. */
#include "ai_event_types.hpp"
#include "../../openttd.h"
#include "../../core/alloc_func.hpp"
#include "../../strings_func.h"
#include "../../roadveh.h"
#include "../../train.h"
#include "../../ship.h"
#include "../../aircraft.h"
#include "../../settings_type.h"
#include "../../articulated_vehicles.h"
#include "table/strings.h"
bool AIEventVehicleCrashed::CloneCrashedVehicle(TileIndex depot)
{
return false;
}
const char *AIEventEnginePreview::GetName()
{
static const int len = 64;
char *engine_name = MallocT<char>(len);
::SetDParam(0, engine);
::GetString(engine_name, STR_ENGINE_NAME, &engine_name[len - 1]);
return engine_name;
}
CargoID AIEventEnginePreview::GetCargoType()
{
switch (::GetEngine(engine)->type) {
case VEH_ROAD: {
const RoadVehicleInfo *vi = ::RoadVehInfo(engine);
return vi->cargo_type;
} break;
case VEH_TRAIN: {
const RailVehicleInfo *vi = ::RailVehInfo(engine);
return vi->cargo_type;
} break;
case VEH_SHIP: {
const ShipVehicleInfo *vi = ::ShipVehInfo(engine);
return vi->cargo_type;
} break;
case VEH_AIRCRAFT: {
return CT_PASSENGERS;
} break;
default: NOT_REACHED();
}
}
int32 AIEventEnginePreview::GetCapacity()
{
switch (::GetEngine(engine)->type) {
case VEH_ROAD:
case VEH_TRAIN: {
uint16 *capacities = GetCapacityOfArticulatedParts(engine, ::GetEngine(engine)->type);
for (CargoID c = 0; c < NUM_CARGO; c++) {
if (capacities[c] == 0) continue;
return capacities[c];
}
return -1;
} break;
case VEH_SHIP: {
const ShipVehicleInfo *vi = ::ShipVehInfo(engine);
return vi->capacity;
} break;
case VEH_AIRCRAFT: {
const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine);
return vi->passenger_capacity;
} break;
default: NOT_REACHED();
}
}
int32 AIEventEnginePreview::GetMaxSpeed()
{
switch (::GetEngine(engine)->type) {
case VEH_ROAD: {
const RoadVehicleInfo *vi = ::RoadVehInfo(engine);
/* Internal speeds are km/h * 2 */
return vi->max_speed / 2;
} break;
case VEH_TRAIN: {
const RailVehicleInfo *vi = ::RailVehInfo(engine);
return vi->max_speed;
} break;
case VEH_SHIP: {
const ShipVehicleInfo *vi = ::ShipVehInfo(engine);
/* Internal speeds are km/h * 2 */
return vi->max_speed / 2;
} break;
case VEH_AIRCRAFT: {
const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine);
return vi->max_speed / _settings_game.vehicle.plane_speed;
} break;
default: NOT_REACHED();
}
}
Money AIEventEnginePreview::GetPrice()
{
switch (::GetEngine(engine)->type) {
case VEH_ROAD: {
const RoadVehicleInfo *vi = ::RoadVehInfo(engine);
return (_price.roadveh_base >> 3) * vi->cost_factor >> 5;
} break;
case VEH_TRAIN: {
const RailVehicleInfo *vi = ::RailVehInfo(engine);
return (_price.build_railvehicle >> 3) * vi->cost_factor >> 5;
} break;
case VEH_SHIP: {
const ShipVehicleInfo *vi = ::ShipVehInfo(engine);
return (_price.ship_base >> 3) * vi->cost_factor >> 5;
} break;
case VEH_AIRCRAFT: {
const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine);
return (_price.aircraft_base >> 3) * vi->cost_factor >> 5;
} break;
default: NOT_REACHED();
}
}
Money AIEventEnginePreview::GetRunningCost()
{
/* We need to create an instance in order to obtain GetRunningCost.
* This means we temporary allocate a vehicle in the pool, but
* there is no other way.. */
Vehicle *vehicle;
switch (::GetEngine(engine)->type) {
case VEH_ROAD: {
vehicle = new RoadVehicle();
} break;
case VEH_TRAIN: {
vehicle = new Train();
} break;
case VEH_SHIP: {
vehicle = new Ship();
} break;
case VEH_AIRCRAFT: {
vehicle = new Aircraft();
} break;
default: NOT_REACHED();
}
vehicle->engine_type = engine;
Money runningCost = vehicle->GetRunningCost();
delete vehicle;
return runningCost >> 8;
}
AIVehicle::VehicleType AIEventEnginePreview::GetVehicleType()
{
switch (::GetEngine(engine)->type) {
case VEH_ROAD: return AIVehicle::VEHICLE_ROAD;
case VEH_TRAIN: return AIVehicle::VEHICLE_RAIL;
case VEH_SHIP: return AIVehicle::VEHICLE_WATER;
case VEH_AIRCRAFT: return AIVehicle::VEHICLE_AIR;
default: NOT_REACHED();
}
}
bool AIEventEnginePreview::AcceptPreview()
{
return AIObject::DoCommand(0, engine, 0, CMD_WANT_ENGINE_PREVIEW);
}

View File

@@ -0,0 +1,684 @@
/* $Id$ */
/** @file ai_event_types.hpp The detailed types of all events. */
#ifndef AI_EVENT_TYPES_HPP
#define AI_EVENT_TYPES_HPP
#include "ai_object.hpp"
#include "ai_event.hpp"
#include "ai_town.hpp"
#include "ai_industry.hpp"
#include "ai_engine.hpp"
#include "ai_subsidy.hpp"
/**
* Event Test: a simple test event, to see if the event system is working.
* Triggered via AIEventController::Test();
*/
class AIEventTest : public AIEvent {
public:
static const char *GetClassName() { return "AIEventTest"; }
/**
* @param test A test value.
*/
AIEventTest(uint test) :
AIEvent(AI_ET_TEST),
test(test)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventTest *Convert(AIEvent *instance) { return (AIEventTest *)instance; }
/**
* Return the test value.
* @return The test value.
*/
uint GetTest() { return this->test; }
private:
uint test;
};
/**
* Event Vehicle Crash, indicating a vehicle of yours is crashed.
* It contains both the crash site as the vehicle crashed. It has a nice
* helper that creates a new vehicle in a depot with the same type
* and orders as the crashed one. In case the vehicle type isn't available
* anymore, it will find the next best.
*/
class AIEventVehicleCrashed : public AIEvent {
public:
static const char *GetClassName() { return "AIEventVehicleCrashed"; }
/**
* @param vehicle The vehicle that crashed.
* @param crash_site Where the vehicle crashed.
*/
AIEventVehicleCrashed(VehicleID vehicle, TileIndex crash_site) :
AIEvent(AI_ET_VEHICLE_CRASHED),
crash_site(crash_site),
vehicle(vehicle)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventVehicleCrashed *Convert(AIEvent *instance) { return (AIEventVehicleCrashed *)instance; }
/**
* Get the VehicleID of the crashed vehicle.
* @return The crashed vehicle.
*/
VehicleID GetVehicleID() { return vehicle; }
/**
* Find the tile the vehicle crashed.
* @return The crash site.
*/
TileIndex GetCrashSite() { return crash_site; }
/**
* Clone the crashed vehicle and send it on its way again.
* @param depot the depot to build the vehicle in.
* @return True when the cloning succeeded.
* @note This function isn't implemented yet.
*/
bool CloneCrashedVehicle(TileIndex depot);
private:
TileIndex crash_site;
VehicleID vehicle;
};
/**
* Event Subsidy Offered, indicating someone offered a subsidy.
*/
class AIEventSubsidyOffer : public AIEvent {
public:
static const char *GetClassName() { return "AIEventSubsidyOffer"; }
/**
* @param subsidy_id The index of this subsidy in the _subsidies array.
*/
AIEventSubsidyOffer(SubsidyID subsidy_id) :
AIEvent(AI_ET_SUBSIDY_OFFER),
subsidy_id(subsidy_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventSubsidyOffer *Convert(AIEvent *instance) { return (AIEventSubsidyOffer *)instance; }
/**
* Get the SubsidyID of the subsidy.
* @return The subsidy id.
*/
SubsidyID GetSubsidyID() { return subsidy_id; }
private:
SubsidyID subsidy_id;
};
/**
* Event Subsidy Offer Expired, indicating a subsidy will no longer be awarded.
*/
class AIEventSubsidyOfferExpired : public AIEvent {
public:
static const char *GetClassName() { return "AIEventSubsidyOfferExpired"; }
/**
* @param subsidy_id The index of this subsidy in the _subsidies array.
*/
AIEventSubsidyOfferExpired(SubsidyID subsidy_id) :
AIEvent(AI_ET_SUBSIDY_OFFER_EXPIRED),
subsidy_id(subsidy_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventSubsidyOfferExpired *Convert(AIEvent *instance) { return (AIEventSubsidyOfferExpired *)instance; }
/**
* Get the SubsidyID of the subsidy.
* @return The subsidy id.
*/
SubsidyID GetSubsidyID() { return subsidy_id; }
private:
SubsidyID subsidy_id;
};
/**
* Event Subidy Awarded, indicating a subsidy is awarded to some company.
*/
class AIEventSubsidyAwarded : public AIEvent {
public:
static const char *GetClassName() { return "AIEventSubsidyAwarded"; }
/**
* @param subsidy_id The index of this subsidy in the _subsidies array.
*/
AIEventSubsidyAwarded(SubsidyID subsidy_id) :
AIEvent(AI_ET_SUBSIDY_AWARDED),
subsidy_id(subsidy_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventSubsidyAwarded *Convert(AIEvent *instance) { return (AIEventSubsidyAwarded *)instance; }
/**
* Get the SubsidyID of the subsidy.
* @return The subsidy id.
*/
SubsidyID GetSubsidyID() { return subsidy_id; }
private:
SubsidyID subsidy_id;
};
/**
* Event Subsidy Expired, indicating a route that was once subsidized no longer is.
*/
class AIEventSubsidyExpired : public AIEvent {
public:
static const char *GetClassName() { return "AIEventSubsidyExpired"; }
/**
* @param subsidy_id The index of this subsidy in the _subsidies array.
*/
AIEventSubsidyExpired(SubsidyID subsidy_id) :
AIEvent(AI_ET_SUBSIDY_EXPIRED),
subsidy_id(subsidy_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventSubsidyExpired *Convert(AIEvent *instance) { return (AIEventSubsidyExpired *)instance; }
/**
* Get the SubsidyID of the subsidy.
* @return The subsidy id.
*/
SubsidyID GetSubsidyID() { return subsidy_id; }
private:
SubsidyID subsidy_id;
};
/**
* Event Engine Preview, indicating a manufacturer offer you to test a new engine.
* You can get the same information about the offered engine as a real user
* would see in the offer window. And you can also accept the offer.
*/
class AIEventEnginePreview : public AIEvent {
public:
static const char *GetClassName() { return "AIEventEnginePreview"; }
/**
* @param engine The engine offered to test.
*/
AIEventEnginePreview(EngineID engine) :
AIEvent(AI_ET_ENGINE_PREVIEW),
engine(engine)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventEnginePreview *Convert(AIEvent *instance) { return (AIEventEnginePreview *)instance; }
/**
* Get the name of the offered engine.
* @return The name the engine has.
*/
const char *GetName();
/**
* Get the cargo-type of the offered engine. In case it can transport 2 cargos, it
* returns the first.
* @return The cargo-type of the engine.
*/
CargoID GetCargoType();
/**
* Get the capacity of the offered engine. In case it can transport 2 cargos, it
* returns the first.
* @return The capacity of the engine.
*/
int32 GetCapacity();
/**
* Get the maximum speed of the offered engine.
* @return The maximum speed the engine has.
* @note The speed is in km/h.
*/
int32 GetMaxSpeed();
/**
* Get the new cost of the offered engine.
* @return The new cost the engine has.
*/
Money GetPrice();
/**
* Get the running cost of the offered engine.
* @return The running cost of the vehicle per year.
* @note Cost is per year; divide by 364 to get per day.
*/
Money GetRunningCost();
/**
* Get the type of the offered engine.
* @return The type the engine has.
*/
AIVehicle::VehicleType GetVehicleType();
/**
* Accept the engine preview.
* @return True when the accepting succeeded.
*/
bool AcceptPreview();
private:
EngineID engine;
};
/**
* Event Company New, indicating a new company has been created.
*/
class AIEventCompanyNew : public AIEvent {
public:
static const char *GetClassName() { return "AIEventCompanyNew"; }
/**
* @param owner The new company.
*/
AIEventCompanyNew(Owner owner) :
AIEvent(AI_ET_COMPANY_NEW),
owner((AICompany::CompanyID)(byte)owner)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventCompanyNew *Convert(AIEvent *instance) { return (AIEventCompanyNew *)instance; }
/**
* Get the CompanyID of the company that has been created.
* @return The CompanyID of the company.
*/
AICompany::CompanyID GetCompanyID() { return owner; }
private:
AICompany::CompanyID owner;
};
/**
* Event Company In Trouble, indicating a company is in trouble and might go
* bankrupt soon.
*/
class AIEventCompanyInTrouble : public AIEvent {
public:
static const char *GetClassName() { return "AIEventCompanyInTrouble"; }
/**
* @param owner The company that is in trouble.
*/
AIEventCompanyInTrouble(Owner owner) :
AIEvent(AI_ET_COMPANY_IN_TROUBLE),
owner((AICompany::CompanyID)(byte)owner)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventCompanyInTrouble *Convert(AIEvent *instance) { return (AIEventCompanyInTrouble *)instance; }
/**
* Get the CompanyID of the company that is in trouble.
* @return The CompanyID of the company in trouble.
*/
AICompany::CompanyID GetCompanyID() { return owner; }
private:
AICompany::CompanyID owner;
};
/**
* Event Company Merger, indicating a company has been bought by another
* company.
*/
class AIEventCompanyMerger : public AIEvent {
public:
static const char *GetClassName() { return "AIEventCompanyMerger"; }
/**
* @param old_owner The company bought off.
* @param new_owner The company that bougth owner.
*/
AIEventCompanyMerger(Owner old_owner, Owner new_owner) :
AIEvent(AI_ET_COMPANY_MERGER),
old_owner((AICompany::CompanyID)(byte)old_owner),
new_owner((AICompany::CompanyID)(byte)new_owner)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventCompanyMerger *Convert(AIEvent *instance) { return (AIEventCompanyMerger *)instance; }
/**
* Get the CompanyID of the company that has been bought.
* @return The CompanyID of the company that has been bought.
* @note: The value below is not valid anymore as CompanyID, and
* AICompany::ResolveCompanyID will return INVALID_COMPANY. It's
* only usefull if you're keeping track of company's yourself.
*/
AICompany::CompanyID GetOldCompanyID() { return old_owner; }
/**
* Get the CompanyID of the new owner.
* @return The CompanyID of the new owner.
*/
AICompany::CompanyID GetNewCompanyID() { return new_owner; }
private:
AICompany::CompanyID old_owner;
AICompany::CompanyID new_owner;
};
/**
* Event Company Bankrupt, indicating a company has gone bankrupt.
*/
class AIEventCompanyBankrupt : public AIEvent {
public:
static const char *GetClassName() { return "AIEventCompanyBankrupt"; }
/**
* @param owner The company that has gone bankrupt.
*/
AIEventCompanyBankrupt(Owner owner) :
AIEvent(AI_ET_COMPANY_BANKRUPT),
owner((AICompany::CompanyID)(byte)owner)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventCompanyBankrupt *Convert(AIEvent *instance) { return (AIEventCompanyBankrupt *)instance; }
/**
* Get the CompanyID of the company that has gone bankrupt.
* @return The CompanyID of the company that has gone bankrupt.
*/
AICompany::CompanyID GetCompanyID() { return owner; }
private:
AICompany::CompanyID owner;
};
/**
* Event Vehicle Lost, indicating a vehicle can't find its way to its destination.
*/
class AIEventVehicleLost : public AIEvent {
public:
static const char *GetClassName() { return "AIEventVehicleLost"; }
/**
* @param vehicle_id The vehicle that is lost.
*/
AIEventVehicleLost(VehicleID vehicle_id) :
AIEvent(AI_ET_VEHICLE_LOST),
vehicle_id(vehicle_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventVehicleLost *Convert(AIEvent *instance) { return (AIEventVehicleLost *)instance; }
/**
* Get the VehicleID of the vehicle that is lost.
* @return The VehicleID of the vehicle that is lost.
*/
VehicleID GetVehicleID() { return vehicle_id; }
private:
VehicleID vehicle_id;
};
/**
* Event VehicleWaitingInDepot, indicating a vehicle has arrived a depot and is now waiting there.
*/
class AIEventVehicleWaitingInDepot : public AIEvent {
public:
static const char *GetClassName() { return "AIEventVehicleWaitingInDepot"; }
/**
* @param vehicle_id The vehicle that is waiting in a depot.
*/
AIEventVehicleWaitingInDepot(VehicleID vehicle_id) :
AIEvent(AI_ET_VEHICLE_WAITING_IN_DEPOT),
vehicle_id(vehicle_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventVehicleWaitingInDepot *Convert(AIEvent *instance) { return (AIEventVehicleWaitingInDepot *)instance; }
/**
* Get the VehicleID of the vehicle that is waiting in a depot.
* @return The VehicleID of the vehicle that is waiting in a depot.
*/
VehicleID GetVehicleID() { return vehicle_id; }
private:
VehicleID vehicle_id;
};
/**
* Event Vehicle Unprofitable, indicating a vehicle lost money last year.
*/
class AIEventVehicleUnprofitable : public AIEvent {
public:
static const char *GetClassName() { return "AIEventVehicleUnprofitable"; }
/**
* @param vehicle_id The vehicle that was unprofitable.
*/
AIEventVehicleUnprofitable(VehicleID vehicle_id) :
AIEvent(AI_ET_VEHICLE_UNPROFITABLE),
vehicle_id(vehicle_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventVehicleUnprofitable *Convert(AIEvent *instance) { return (AIEventVehicleUnprofitable *)instance; }
/**
* Get the VehicleID of the vehicle that lost money.
* @return The VehicleID of the vehicle that lost money.
*/
VehicleID GetVehicleID() { return vehicle_id; }
private:
VehicleID vehicle_id;
};
/**
* Event Industry Open, indicating a new industry has been created.
*/
class AIEventIndustryOpen : public AIEvent {
public:
static const char *GetClassName() { return "AIEventIndustryOpen"; }
/**
* @param industry_id The new industry.
*/
AIEventIndustryOpen(IndustryID industry_id) :
AIEvent(AI_ET_INDUSTRY_OPEN),
industry_id(industry_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventIndustryOpen *Convert(AIEvent *instance) { return (AIEventIndustryOpen *)instance; }
/**
* Get the IndustryID of the new industry.
* @return The IndustryID of the industry.
*/
IndustryID GetIndustryID() { return industry_id; }
private:
IndustryID industry_id;
};
/**
* Event Industry Close, indicating an industry is going to be closed.
*/
class AIEventIndustryClose : public AIEvent {
public:
static const char *GetClassName() { return "AIEventIndustryClose"; }
/**
* @param industry_id The new industry.
*/
AIEventIndustryClose(IndustryID industry_id) :
AIEvent(AI_ET_INDUSTRY_CLOSE),
industry_id(industry_id)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventIndustryClose *Convert(AIEvent *instance) { return (AIEventIndustryClose *)instance; }
/**
* Get the IndustryID of the closing industry.
* @return The IndustryID of the industry.
*/
IndustryID GetIndustryID() { return industry_id; }
private:
IndustryID industry_id;
};
/**
* Event Engine Available, indicating a new engine is available.
*/
class AIEventEngineAvailable : public AIEvent {
public:
static const char *GetClassName() { return "AIEventEngineAvailable"; }
/**
* @param engine The engine that is available.
*/
AIEventEngineAvailable(EngineID engine) :
AIEvent(AI_ET_ENGINE_AVAILABLE),
engine(engine)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventEngineAvailable *Convert(AIEvent *instance) { return (AIEventEngineAvailable *)instance; }
/**
* Get the EngineID of the new engine.
* @return The EngineID of the new engine.
*/
EngineID GetEngineID() { return engine; }
private:
EngineID engine;
};
/**
* Event Station First Vehicle, indicating a station has been visited by a vehicle for the first time.
*/
class AIEventStationFirstVehicle : public AIEvent {
public:
static const char *GetClassName() { return "AIEventStationFirstVehicle"; }
/**
* @param station The station visited for the first time.
* @param vehicle The vehicle visiting the station.
*/
AIEventStationFirstVehicle(StationID station, VehicleID vehicle) :
AIEvent(AI_ET_STATION_FIRST_VEHICLE),
station(station),
vehicle(vehicle)
{}
/**
* Convert an AIEvent to the real instance.
* @param instance The instance to convert.
* @return The converted instance.
*/
static AIEventStationFirstVehicle *Convert(AIEvent *instance) { return (AIEventStationFirstVehicle *)instance; }
/**
* Get the StationID of the visited station.
* @return The StationID of the visited station.
*/
StationID GetStationID() { return station; }
/**
* Get the VehicleID of the first vehicle.
* @return The VehicleID of the first vehicle.
*/
VehicleID GetVehicleID() { return vehicle; }
private:
StationID station;
VehicleID vehicle;
};
#endif /* AI_EVENT_TYPES_HPP */

View File

@@ -0,0 +1,393 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_event_types.hpp"
namespace SQConvert {
/* Allow AIEventTest to be used as Squirrel parameter */
template <> AIEventTest *GetParam(ForceType<AIEventTest *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventTest *)instance; }
template <> AIEventTest &GetParam(ForceType<AIEventTest &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventTest *)instance; }
template <> const AIEventTest *GetParam(ForceType<const AIEventTest *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventTest *)instance; }
template <> const AIEventTest &GetParam(ForceType<const AIEventTest &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventTest *)instance; }
template <> int Return<AIEventTest *>(HSQUIRRELVM vm, AIEventTest *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventTest", res, NULL, DefSQDestructorCallback<AIEventTest>); return 1; }
}; // namespace SQConvert
void SQAIEventTest_Register(Squirrel *engine) {
DefSQClass <AIEventTest> SQAIEventTest("AIEventTest");
SQAIEventTest.PreRegister(engine, "AIEvent");
SQAIEventTest.DefSQStaticMethod(engine, &AIEventTest::GetClassName, "GetClassName", 1, "x");
SQAIEventTest.DefSQStaticMethod(engine, &AIEventTest::Convert, "Convert", 2, "xx");
SQAIEventTest.DefSQMethod(engine, &AIEventTest::GetTest, "GetTest", 1, "x");
SQAIEventTest.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventVehicleCrashed to be used as Squirrel parameter */
template <> AIEventVehicleCrashed *GetParam(ForceType<AIEventVehicleCrashed *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventVehicleCrashed *)instance; }
template <> AIEventVehicleCrashed &GetParam(ForceType<AIEventVehicleCrashed &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventVehicleCrashed *)instance; }
template <> const AIEventVehicleCrashed *GetParam(ForceType<const AIEventVehicleCrashed *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventVehicleCrashed *)instance; }
template <> const AIEventVehicleCrashed &GetParam(ForceType<const AIEventVehicleCrashed &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventVehicleCrashed *)instance; }
template <> int Return<AIEventVehicleCrashed *>(HSQUIRRELVM vm, AIEventVehicleCrashed *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventVehicleCrashed", res, NULL, DefSQDestructorCallback<AIEventVehicleCrashed>); return 1; }
}; // namespace SQConvert
void SQAIEventVehicleCrashed_Register(Squirrel *engine) {
DefSQClass <AIEventVehicleCrashed> SQAIEventVehicleCrashed("AIEventVehicleCrashed");
SQAIEventVehicleCrashed.PreRegister(engine, "AIEvent");
SQAIEventVehicleCrashed.DefSQStaticMethod(engine, &AIEventVehicleCrashed::GetClassName, "GetClassName", 1, "x");
SQAIEventVehicleCrashed.DefSQStaticMethod(engine, &AIEventVehicleCrashed::Convert, "Convert", 2, "xx");
SQAIEventVehicleCrashed.DefSQMethod(engine, &AIEventVehicleCrashed::GetVehicleID, "GetVehicleID", 1, "x");
SQAIEventVehicleCrashed.DefSQMethod(engine, &AIEventVehicleCrashed::GetCrashSite, "GetCrashSite", 1, "x");
SQAIEventVehicleCrashed.DefSQMethod(engine, &AIEventVehicleCrashed::CloneCrashedVehicle, "CloneCrashedVehicle", 2, "xi");
SQAIEventVehicleCrashed.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventSubsidyOffer to be used as Squirrel parameter */
template <> AIEventSubsidyOffer *GetParam(ForceType<AIEventSubsidyOffer *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventSubsidyOffer *)instance; }
template <> AIEventSubsidyOffer &GetParam(ForceType<AIEventSubsidyOffer &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyOffer *)instance; }
template <> const AIEventSubsidyOffer *GetParam(ForceType<const AIEventSubsidyOffer *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventSubsidyOffer *)instance; }
template <> const AIEventSubsidyOffer &GetParam(ForceType<const AIEventSubsidyOffer &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyOffer *)instance; }
template <> int Return<AIEventSubsidyOffer *>(HSQUIRRELVM vm, AIEventSubsidyOffer *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventSubsidyOffer", res, NULL, DefSQDestructorCallback<AIEventSubsidyOffer>); return 1; }
}; // namespace SQConvert
void SQAIEventSubsidyOffer_Register(Squirrel *engine) {
DefSQClass <AIEventSubsidyOffer> SQAIEventSubsidyOffer("AIEventSubsidyOffer");
SQAIEventSubsidyOffer.PreRegister(engine, "AIEvent");
SQAIEventSubsidyOffer.DefSQStaticMethod(engine, &AIEventSubsidyOffer::GetClassName, "GetClassName", 1, "x");
SQAIEventSubsidyOffer.DefSQStaticMethod(engine, &AIEventSubsidyOffer::Convert, "Convert", 2, "xx");
SQAIEventSubsidyOffer.DefSQMethod(engine, &AIEventSubsidyOffer::GetSubsidyID, "GetSubsidyID", 1, "x");
SQAIEventSubsidyOffer.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventSubsidyOfferExpired to be used as Squirrel parameter */
template <> AIEventSubsidyOfferExpired *GetParam(ForceType<AIEventSubsidyOfferExpired *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventSubsidyOfferExpired *)instance; }
template <> AIEventSubsidyOfferExpired &GetParam(ForceType<AIEventSubsidyOfferExpired &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyOfferExpired *)instance; }
template <> const AIEventSubsidyOfferExpired *GetParam(ForceType<const AIEventSubsidyOfferExpired *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventSubsidyOfferExpired *)instance; }
template <> const AIEventSubsidyOfferExpired &GetParam(ForceType<const AIEventSubsidyOfferExpired &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyOfferExpired *)instance; }
template <> int Return<AIEventSubsidyOfferExpired *>(HSQUIRRELVM vm, AIEventSubsidyOfferExpired *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventSubsidyOfferExpired", res, NULL, DefSQDestructorCallback<AIEventSubsidyOfferExpired>); return 1; }
}; // namespace SQConvert
void SQAIEventSubsidyOfferExpired_Register(Squirrel *engine) {
DefSQClass <AIEventSubsidyOfferExpired> SQAIEventSubsidyOfferExpired("AIEventSubsidyOfferExpired");
SQAIEventSubsidyOfferExpired.PreRegister(engine, "AIEvent");
SQAIEventSubsidyOfferExpired.DefSQStaticMethod(engine, &AIEventSubsidyOfferExpired::GetClassName, "GetClassName", 1, "x");
SQAIEventSubsidyOfferExpired.DefSQStaticMethod(engine, &AIEventSubsidyOfferExpired::Convert, "Convert", 2, "xx");
SQAIEventSubsidyOfferExpired.DefSQMethod(engine, &AIEventSubsidyOfferExpired::GetSubsidyID, "GetSubsidyID", 1, "x");
SQAIEventSubsidyOfferExpired.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventSubsidyAwarded to be used as Squirrel parameter */
template <> AIEventSubsidyAwarded *GetParam(ForceType<AIEventSubsidyAwarded *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventSubsidyAwarded *)instance; }
template <> AIEventSubsidyAwarded &GetParam(ForceType<AIEventSubsidyAwarded &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyAwarded *)instance; }
template <> const AIEventSubsidyAwarded *GetParam(ForceType<const AIEventSubsidyAwarded *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventSubsidyAwarded *)instance; }
template <> const AIEventSubsidyAwarded &GetParam(ForceType<const AIEventSubsidyAwarded &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyAwarded *)instance; }
template <> int Return<AIEventSubsidyAwarded *>(HSQUIRRELVM vm, AIEventSubsidyAwarded *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventSubsidyAwarded", res, NULL, DefSQDestructorCallback<AIEventSubsidyAwarded>); return 1; }
}; // namespace SQConvert
void SQAIEventSubsidyAwarded_Register(Squirrel *engine) {
DefSQClass <AIEventSubsidyAwarded> SQAIEventSubsidyAwarded("AIEventSubsidyAwarded");
SQAIEventSubsidyAwarded.PreRegister(engine, "AIEvent");
SQAIEventSubsidyAwarded.DefSQStaticMethod(engine, &AIEventSubsidyAwarded::GetClassName, "GetClassName", 1, "x");
SQAIEventSubsidyAwarded.DefSQStaticMethod(engine, &AIEventSubsidyAwarded::Convert, "Convert", 2, "xx");
SQAIEventSubsidyAwarded.DefSQMethod(engine, &AIEventSubsidyAwarded::GetSubsidyID, "GetSubsidyID", 1, "x");
SQAIEventSubsidyAwarded.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventSubsidyExpired to be used as Squirrel parameter */
template <> AIEventSubsidyExpired *GetParam(ForceType<AIEventSubsidyExpired *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventSubsidyExpired *)instance; }
template <> AIEventSubsidyExpired &GetParam(ForceType<AIEventSubsidyExpired &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyExpired *)instance; }
template <> const AIEventSubsidyExpired *GetParam(ForceType<const AIEventSubsidyExpired *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventSubsidyExpired *)instance; }
template <> const AIEventSubsidyExpired &GetParam(ForceType<const AIEventSubsidyExpired &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventSubsidyExpired *)instance; }
template <> int Return<AIEventSubsidyExpired *>(HSQUIRRELVM vm, AIEventSubsidyExpired *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventSubsidyExpired", res, NULL, DefSQDestructorCallback<AIEventSubsidyExpired>); return 1; }
}; // namespace SQConvert
void SQAIEventSubsidyExpired_Register(Squirrel *engine) {
DefSQClass <AIEventSubsidyExpired> SQAIEventSubsidyExpired("AIEventSubsidyExpired");
SQAIEventSubsidyExpired.PreRegister(engine, "AIEvent");
SQAIEventSubsidyExpired.DefSQStaticMethod(engine, &AIEventSubsidyExpired::GetClassName, "GetClassName", 1, "x");
SQAIEventSubsidyExpired.DefSQStaticMethod(engine, &AIEventSubsidyExpired::Convert, "Convert", 2, "xx");
SQAIEventSubsidyExpired.DefSQMethod(engine, &AIEventSubsidyExpired::GetSubsidyID, "GetSubsidyID", 1, "x");
SQAIEventSubsidyExpired.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventEnginePreview to be used as Squirrel parameter */
template <> AIEventEnginePreview *GetParam(ForceType<AIEventEnginePreview *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventEnginePreview *)instance; }
template <> AIEventEnginePreview &GetParam(ForceType<AIEventEnginePreview &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventEnginePreview *)instance; }
template <> const AIEventEnginePreview *GetParam(ForceType<const AIEventEnginePreview *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventEnginePreview *)instance; }
template <> const AIEventEnginePreview &GetParam(ForceType<const AIEventEnginePreview &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventEnginePreview *)instance; }
template <> int Return<AIEventEnginePreview *>(HSQUIRRELVM vm, AIEventEnginePreview *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventEnginePreview", res, NULL, DefSQDestructorCallback<AIEventEnginePreview>); return 1; }
}; // namespace SQConvert
void SQAIEventEnginePreview_Register(Squirrel *engine) {
DefSQClass <AIEventEnginePreview> SQAIEventEnginePreview("AIEventEnginePreview");
SQAIEventEnginePreview.PreRegister(engine, "AIEvent");
SQAIEventEnginePreview.DefSQStaticMethod(engine, &AIEventEnginePreview::GetClassName, "GetClassName", 1, "x");
SQAIEventEnginePreview.DefSQStaticMethod(engine, &AIEventEnginePreview::Convert, "Convert", 2, "xx");
SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetName, "GetName", 1, "x");
SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetCargoType, "GetCargoType", 1, "x");
SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetCapacity, "GetCapacity", 1, "x");
SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetMaxSpeed, "GetMaxSpeed", 1, "x");
SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetPrice, "GetPrice", 1, "x");
SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetRunningCost, "GetRunningCost", 1, "x");
SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::GetVehicleType, "GetVehicleType", 1, "x");
SQAIEventEnginePreview.DefSQMethod(engine, &AIEventEnginePreview::AcceptPreview, "AcceptPreview", 1, "x");
SQAIEventEnginePreview.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventCompanyNew to be used as Squirrel parameter */
template <> AIEventCompanyNew *GetParam(ForceType<AIEventCompanyNew *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyNew *)instance; }
template <> AIEventCompanyNew &GetParam(ForceType<AIEventCompanyNew &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyNew *)instance; }
template <> const AIEventCompanyNew *GetParam(ForceType<const AIEventCompanyNew *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyNew *)instance; }
template <> const AIEventCompanyNew &GetParam(ForceType<const AIEventCompanyNew &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyNew *)instance; }
template <> int Return<AIEventCompanyNew *>(HSQUIRRELVM vm, AIEventCompanyNew *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventCompanyNew", res, NULL, DefSQDestructorCallback<AIEventCompanyNew>); return 1; }
}; // namespace SQConvert
void SQAIEventCompanyNew_Register(Squirrel *engine) {
DefSQClass <AIEventCompanyNew> SQAIEventCompanyNew("AIEventCompanyNew");
SQAIEventCompanyNew.PreRegister(engine, "AIEvent");
SQAIEventCompanyNew.DefSQStaticMethod(engine, &AIEventCompanyNew::GetClassName, "GetClassName", 1, "x");
SQAIEventCompanyNew.DefSQStaticMethod(engine, &AIEventCompanyNew::Convert, "Convert", 2, "xx");
SQAIEventCompanyNew.DefSQMethod(engine, &AIEventCompanyNew::GetCompanyID, "GetCompanyID", 1, "x");
SQAIEventCompanyNew.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventCompanyInTrouble to be used as Squirrel parameter */
template <> AIEventCompanyInTrouble *GetParam(ForceType<AIEventCompanyInTrouble *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyInTrouble *)instance; }
template <> AIEventCompanyInTrouble &GetParam(ForceType<AIEventCompanyInTrouble &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyInTrouble *)instance; }
template <> const AIEventCompanyInTrouble *GetParam(ForceType<const AIEventCompanyInTrouble *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyInTrouble *)instance; }
template <> const AIEventCompanyInTrouble &GetParam(ForceType<const AIEventCompanyInTrouble &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyInTrouble *)instance; }
template <> int Return<AIEventCompanyInTrouble *>(HSQUIRRELVM vm, AIEventCompanyInTrouble *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventCompanyInTrouble", res, NULL, DefSQDestructorCallback<AIEventCompanyInTrouble>); return 1; }
}; // namespace SQConvert
void SQAIEventCompanyInTrouble_Register(Squirrel *engine) {
DefSQClass <AIEventCompanyInTrouble> SQAIEventCompanyInTrouble("AIEventCompanyInTrouble");
SQAIEventCompanyInTrouble.PreRegister(engine, "AIEvent");
SQAIEventCompanyInTrouble.DefSQStaticMethod(engine, &AIEventCompanyInTrouble::GetClassName, "GetClassName", 1, "x");
SQAIEventCompanyInTrouble.DefSQStaticMethod(engine, &AIEventCompanyInTrouble::Convert, "Convert", 2, "xx");
SQAIEventCompanyInTrouble.DefSQMethod(engine, &AIEventCompanyInTrouble::GetCompanyID, "GetCompanyID", 1, "x");
SQAIEventCompanyInTrouble.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventCompanyMerger to be used as Squirrel parameter */
template <> AIEventCompanyMerger *GetParam(ForceType<AIEventCompanyMerger *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyMerger *)instance; }
template <> AIEventCompanyMerger &GetParam(ForceType<AIEventCompanyMerger &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyMerger *)instance; }
template <> const AIEventCompanyMerger *GetParam(ForceType<const AIEventCompanyMerger *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyMerger *)instance; }
template <> const AIEventCompanyMerger &GetParam(ForceType<const AIEventCompanyMerger &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyMerger *)instance; }
template <> int Return<AIEventCompanyMerger *>(HSQUIRRELVM vm, AIEventCompanyMerger *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventCompanyMerger", res, NULL, DefSQDestructorCallback<AIEventCompanyMerger>); return 1; }
}; // namespace SQConvert
void SQAIEventCompanyMerger_Register(Squirrel *engine) {
DefSQClass <AIEventCompanyMerger> SQAIEventCompanyMerger("AIEventCompanyMerger");
SQAIEventCompanyMerger.PreRegister(engine, "AIEvent");
SQAIEventCompanyMerger.DefSQStaticMethod(engine, &AIEventCompanyMerger::GetClassName, "GetClassName", 1, "x");
SQAIEventCompanyMerger.DefSQStaticMethod(engine, &AIEventCompanyMerger::Convert, "Convert", 2, "xx");
SQAIEventCompanyMerger.DefSQMethod(engine, &AIEventCompanyMerger::GetOldCompanyID, "GetOldCompanyID", 1, "x");
SQAIEventCompanyMerger.DefSQMethod(engine, &AIEventCompanyMerger::GetNewCompanyID, "GetNewCompanyID", 1, "x");
SQAIEventCompanyMerger.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventCompanyBankrupt to be used as Squirrel parameter */
template <> AIEventCompanyBankrupt *GetParam(ForceType<AIEventCompanyBankrupt *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyBankrupt *)instance; }
template <> AIEventCompanyBankrupt &GetParam(ForceType<AIEventCompanyBankrupt &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyBankrupt *)instance; }
template <> const AIEventCompanyBankrupt *GetParam(ForceType<const AIEventCompanyBankrupt *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyBankrupt *)instance; }
template <> const AIEventCompanyBankrupt &GetParam(ForceType<const AIEventCompanyBankrupt &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyBankrupt *)instance; }
template <> int Return<AIEventCompanyBankrupt *>(HSQUIRRELVM vm, AIEventCompanyBankrupt *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventCompanyBankrupt", res, NULL, DefSQDestructorCallback<AIEventCompanyBankrupt>); return 1; }
}; // namespace SQConvert
void SQAIEventCompanyBankrupt_Register(Squirrel *engine) {
DefSQClass <AIEventCompanyBankrupt> SQAIEventCompanyBankrupt("AIEventCompanyBankrupt");
SQAIEventCompanyBankrupt.PreRegister(engine, "AIEvent");
SQAIEventCompanyBankrupt.DefSQStaticMethod(engine, &AIEventCompanyBankrupt::GetClassName, "GetClassName", 1, "x");
SQAIEventCompanyBankrupt.DefSQStaticMethod(engine, &AIEventCompanyBankrupt::Convert, "Convert", 2, "xx");
SQAIEventCompanyBankrupt.DefSQMethod(engine, &AIEventCompanyBankrupt::GetCompanyID, "GetCompanyID", 1, "x");
SQAIEventCompanyBankrupt.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventVehicleLost to be used as Squirrel parameter */
template <> AIEventVehicleLost *GetParam(ForceType<AIEventVehicleLost *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventVehicleLost *)instance; }
template <> AIEventVehicleLost &GetParam(ForceType<AIEventVehicleLost &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventVehicleLost *)instance; }
template <> const AIEventVehicleLost *GetParam(ForceType<const AIEventVehicleLost *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventVehicleLost *)instance; }
template <> const AIEventVehicleLost &GetParam(ForceType<const AIEventVehicleLost &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventVehicleLost *)instance; }
template <> int Return<AIEventVehicleLost *>(HSQUIRRELVM vm, AIEventVehicleLost *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventVehicleLost", res, NULL, DefSQDestructorCallback<AIEventVehicleLost>); return 1; }
}; // namespace SQConvert
void SQAIEventVehicleLost_Register(Squirrel *engine) {
DefSQClass <AIEventVehicleLost> SQAIEventVehicleLost("AIEventVehicleLost");
SQAIEventVehicleLost.PreRegister(engine, "AIEvent");
SQAIEventVehicleLost.DefSQStaticMethod(engine, &AIEventVehicleLost::GetClassName, "GetClassName", 1, "x");
SQAIEventVehicleLost.DefSQStaticMethod(engine, &AIEventVehicleLost::Convert, "Convert", 2, "xx");
SQAIEventVehicleLost.DefSQMethod(engine, &AIEventVehicleLost::GetVehicleID, "GetVehicleID", 1, "x");
SQAIEventVehicleLost.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventVehicleWaitingInDepot to be used as Squirrel parameter */
template <> AIEventVehicleWaitingInDepot *GetParam(ForceType<AIEventVehicleWaitingInDepot *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventVehicleWaitingInDepot *)instance; }
template <> AIEventVehicleWaitingInDepot &GetParam(ForceType<AIEventVehicleWaitingInDepot &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventVehicleWaitingInDepot *)instance; }
template <> const AIEventVehicleWaitingInDepot *GetParam(ForceType<const AIEventVehicleWaitingInDepot *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventVehicleWaitingInDepot *)instance; }
template <> const AIEventVehicleWaitingInDepot &GetParam(ForceType<const AIEventVehicleWaitingInDepot &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventVehicleWaitingInDepot *)instance; }
template <> int Return<AIEventVehicleWaitingInDepot *>(HSQUIRRELVM vm, AIEventVehicleWaitingInDepot *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventVehicleWaitingInDepot", res, NULL, DefSQDestructorCallback<AIEventVehicleWaitingInDepot>); return 1; }
}; // namespace SQConvert
void SQAIEventVehicleWaitingInDepot_Register(Squirrel *engine) {
DefSQClass <AIEventVehicleWaitingInDepot> SQAIEventVehicleWaitingInDepot("AIEventVehicleWaitingInDepot");
SQAIEventVehicleWaitingInDepot.PreRegister(engine, "AIEvent");
SQAIEventVehicleWaitingInDepot.DefSQStaticMethod(engine, &AIEventVehicleWaitingInDepot::GetClassName, "GetClassName", 1, "x");
SQAIEventVehicleWaitingInDepot.DefSQStaticMethod(engine, &AIEventVehicleWaitingInDepot::Convert, "Convert", 2, "xx");
SQAIEventVehicleWaitingInDepot.DefSQMethod(engine, &AIEventVehicleWaitingInDepot::GetVehicleID, "GetVehicleID", 1, "x");
SQAIEventVehicleWaitingInDepot.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventVehicleUnprofitable to be used as Squirrel parameter */
template <> AIEventVehicleUnprofitable *GetParam(ForceType<AIEventVehicleUnprofitable *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventVehicleUnprofitable *)instance; }
template <> AIEventVehicleUnprofitable &GetParam(ForceType<AIEventVehicleUnprofitable &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventVehicleUnprofitable *)instance; }
template <> const AIEventVehicleUnprofitable *GetParam(ForceType<const AIEventVehicleUnprofitable *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventVehicleUnprofitable *)instance; }
template <> const AIEventVehicleUnprofitable &GetParam(ForceType<const AIEventVehicleUnprofitable &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventVehicleUnprofitable *)instance; }
template <> int Return<AIEventVehicleUnprofitable *>(HSQUIRRELVM vm, AIEventVehicleUnprofitable *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventVehicleUnprofitable", res, NULL, DefSQDestructorCallback<AIEventVehicleUnprofitable>); return 1; }
}; // namespace SQConvert
void SQAIEventVehicleUnprofitable_Register(Squirrel *engine) {
DefSQClass <AIEventVehicleUnprofitable> SQAIEventVehicleUnprofitable("AIEventVehicleUnprofitable");
SQAIEventVehicleUnprofitable.PreRegister(engine, "AIEvent");
SQAIEventVehicleUnprofitable.DefSQStaticMethod(engine, &AIEventVehicleUnprofitable::GetClassName, "GetClassName", 1, "x");
SQAIEventVehicleUnprofitable.DefSQStaticMethod(engine, &AIEventVehicleUnprofitable::Convert, "Convert", 2, "xx");
SQAIEventVehicleUnprofitable.DefSQMethod(engine, &AIEventVehicleUnprofitable::GetVehicleID, "GetVehicleID", 1, "x");
SQAIEventVehicleUnprofitable.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventIndustryOpen to be used as Squirrel parameter */
template <> AIEventIndustryOpen *GetParam(ForceType<AIEventIndustryOpen *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventIndustryOpen *)instance; }
template <> AIEventIndustryOpen &GetParam(ForceType<AIEventIndustryOpen &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventIndustryOpen *)instance; }
template <> const AIEventIndustryOpen *GetParam(ForceType<const AIEventIndustryOpen *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventIndustryOpen *)instance; }
template <> const AIEventIndustryOpen &GetParam(ForceType<const AIEventIndustryOpen &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventIndustryOpen *)instance; }
template <> int Return<AIEventIndustryOpen *>(HSQUIRRELVM vm, AIEventIndustryOpen *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventIndustryOpen", res, NULL, DefSQDestructorCallback<AIEventIndustryOpen>); return 1; }
}; // namespace SQConvert
void SQAIEventIndustryOpen_Register(Squirrel *engine) {
DefSQClass <AIEventIndustryOpen> SQAIEventIndustryOpen("AIEventIndustryOpen");
SQAIEventIndustryOpen.PreRegister(engine, "AIEvent");
SQAIEventIndustryOpen.DefSQStaticMethod(engine, &AIEventIndustryOpen::GetClassName, "GetClassName", 1, "x");
SQAIEventIndustryOpen.DefSQStaticMethod(engine, &AIEventIndustryOpen::Convert, "Convert", 2, "xx");
SQAIEventIndustryOpen.DefSQMethod(engine, &AIEventIndustryOpen::GetIndustryID, "GetIndustryID", 1, "x");
SQAIEventIndustryOpen.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventIndustryClose to be used as Squirrel parameter */
template <> AIEventIndustryClose *GetParam(ForceType<AIEventIndustryClose *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventIndustryClose *)instance; }
template <> AIEventIndustryClose &GetParam(ForceType<AIEventIndustryClose &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventIndustryClose *)instance; }
template <> const AIEventIndustryClose *GetParam(ForceType<const AIEventIndustryClose *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventIndustryClose *)instance; }
template <> const AIEventIndustryClose &GetParam(ForceType<const AIEventIndustryClose &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventIndustryClose *)instance; }
template <> int Return<AIEventIndustryClose *>(HSQUIRRELVM vm, AIEventIndustryClose *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventIndustryClose", res, NULL, DefSQDestructorCallback<AIEventIndustryClose>); return 1; }
}; // namespace SQConvert
void SQAIEventIndustryClose_Register(Squirrel *engine) {
DefSQClass <AIEventIndustryClose> SQAIEventIndustryClose("AIEventIndustryClose");
SQAIEventIndustryClose.PreRegister(engine, "AIEvent");
SQAIEventIndustryClose.DefSQStaticMethod(engine, &AIEventIndustryClose::GetClassName, "GetClassName", 1, "x");
SQAIEventIndustryClose.DefSQStaticMethod(engine, &AIEventIndustryClose::Convert, "Convert", 2, "xx");
SQAIEventIndustryClose.DefSQMethod(engine, &AIEventIndustryClose::GetIndustryID, "GetIndustryID", 1, "x");
SQAIEventIndustryClose.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventEngineAvailable to be used as Squirrel parameter */
template <> AIEventEngineAvailable *GetParam(ForceType<AIEventEngineAvailable *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventEngineAvailable *)instance; }
template <> AIEventEngineAvailable &GetParam(ForceType<AIEventEngineAvailable &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventEngineAvailable *)instance; }
template <> const AIEventEngineAvailable *GetParam(ForceType<const AIEventEngineAvailable *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventEngineAvailable *)instance; }
template <> const AIEventEngineAvailable &GetParam(ForceType<const AIEventEngineAvailable &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventEngineAvailable *)instance; }
template <> int Return<AIEventEngineAvailable *>(HSQUIRRELVM vm, AIEventEngineAvailable *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventEngineAvailable", res, NULL, DefSQDestructorCallback<AIEventEngineAvailable>); return 1; }
}; // namespace SQConvert
void SQAIEventEngineAvailable_Register(Squirrel *engine) {
DefSQClass <AIEventEngineAvailable> SQAIEventEngineAvailable("AIEventEngineAvailable");
SQAIEventEngineAvailable.PreRegister(engine, "AIEvent");
SQAIEventEngineAvailable.DefSQStaticMethod(engine, &AIEventEngineAvailable::GetClassName, "GetClassName", 1, "x");
SQAIEventEngineAvailable.DefSQStaticMethod(engine, &AIEventEngineAvailable::Convert, "Convert", 2, "xx");
SQAIEventEngineAvailable.DefSQMethod(engine, &AIEventEngineAvailable::GetEngineID, "GetEngineID", 1, "x");
SQAIEventEngineAvailable.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIEventStationFirstVehicle to be used as Squirrel parameter */
template <> AIEventStationFirstVehicle *GetParam(ForceType<AIEventStationFirstVehicle *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventStationFirstVehicle *)instance; }
template <> AIEventStationFirstVehicle &GetParam(ForceType<AIEventStationFirstVehicle &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventStationFirstVehicle *)instance; }
template <> const AIEventStationFirstVehicle *GetParam(ForceType<const AIEventStationFirstVehicle *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventStationFirstVehicle *)instance; }
template <> const AIEventStationFirstVehicle &GetParam(ForceType<const AIEventStationFirstVehicle &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventStationFirstVehicle *)instance; }
template <> int Return<AIEventStationFirstVehicle *>(HSQUIRRELVM vm, AIEventStationFirstVehicle *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventStationFirstVehicle", res, NULL, DefSQDestructorCallback<AIEventStationFirstVehicle>); return 1; }
}; // namespace SQConvert
void SQAIEventStationFirstVehicle_Register(Squirrel *engine) {
DefSQClass <AIEventStationFirstVehicle> SQAIEventStationFirstVehicle("AIEventStationFirstVehicle");
SQAIEventStationFirstVehicle.PreRegister(engine, "AIEvent");
SQAIEventStationFirstVehicle.DefSQStaticMethod(engine, &AIEventStationFirstVehicle::GetClassName, "GetClassName", 1, "x");
SQAIEventStationFirstVehicle.DefSQStaticMethod(engine, &AIEventStationFirstVehicle::Convert, "Convert", 2, "xx");
SQAIEventStationFirstVehicle.DefSQMethod(engine, &AIEventStationFirstVehicle::GetStationID, "GetStationID", 1, "x");
SQAIEventStationFirstVehicle.DefSQMethod(engine, &AIEventStationFirstVehicle::GetVehicleID, "GetVehicleID", 1, "x");
SQAIEventStationFirstVehicle.PostRegister(engine);
}

View File

@@ -0,0 +1,26 @@
/* $Id$ */
/** @file ai_execmode.cpp Implementation of AIExecMode. */
#include "ai_execmode.hpp"
#include "../../command_type.h"
bool AIExecMode::ModeProc(TileIndex tile, uint32 p1, uint32 p2, uint procc, CommandCost costs)
{
/* In execution mode we only return 'true', telling the DoCommand it
* should continue with the real execution of the command. */
return true;
}
AIExecMode::AIExecMode()
{
this->last_mode = this->GetDoCommandMode();
this->last_instance = this->GetDoCommandModeInstance();
this->SetDoCommandMode(&AIExecMode::ModeProc, this);
}
AIExecMode::~AIExecMode()
{
assert(this->GetDoCommandModeInstance() == this);
this->SetDoCommandMode(this->last_mode, this->last_instance);
}

View File

@@ -0,0 +1,46 @@
/* $Id$ */
/** @file ai_execmode.hpp Switch the AI to Execute Mode. */
#ifndef AI_EXECMODE_HPP
#define AI_EXECMODE_HPP
#include "ai_object.hpp"
/**
* Class to switch current mode to Execute Mode.
* If you create an instance of this class, the mode will be switched to
* Execute. The original mode is stored and recovered from when ever the
* instance is destroyed.
* In Execute mode all commands you do are executed for real.
*/
class AIExecMode : public AIObject {
public:
static const char *GetClassName() { return "AIExecMode"; }
private:
AIModeProc *last_mode;
AIObject *last_instance;
protected:
/**
* The callback proc for Execute mode.
*/
static bool ModeProc(TileIndex tile, uint32 p1, uint32 p2, uint procc, CommandCost costs);
public:
/**
* Creating instance of this class switches the build mode to Execute.
* @note When the instance is destroyed, he restores the mode that was
* current when the instance was created!
*/
AIExecMode();
/**
* Destroying this instance reset the building mode to the mode it was
* in when the instance was created.
*/
~AIExecMode();
};
#endif /* AI_EXECMODE_HPP */

View File

@@ -0,0 +1,23 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_execmode.hpp"
namespace SQConvert {
/* Allow AIExecMode to be used as Squirrel parameter */
template <> AIExecMode *GetParam(ForceType<AIExecMode *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIExecMode *)instance; }
template <> AIExecMode &GetParam(ForceType<AIExecMode &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIExecMode *)instance; }
template <> const AIExecMode *GetParam(ForceType<const AIExecMode *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIExecMode *)instance; }
template <> const AIExecMode &GetParam(ForceType<const AIExecMode &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIExecMode *)instance; }
template <> int Return<AIExecMode *>(HSQUIRRELVM vm, AIExecMode *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIExecMode", res, NULL, DefSQDestructorCallback<AIExecMode>); return 1; }
}; // namespace SQConvert
void SQAIExecMode_Register(Squirrel *engine) {
DefSQClass <AIExecMode> SQAIExecMode("AIExecMode");
SQAIExecMode.PreRegister(engine);
SQAIExecMode.AddConstructor<void (AIExecMode::*)(), 1>(engine, "x");
SQAIExecMode.DefSQStaticMethod(engine, &AIExecMode::GetClassName, "GetClassName", 1, "x");
SQAIExecMode.PostRegister(engine);
}

View File

@@ -0,0 +1,38 @@
/* $Id$ */
/** @file ai_gamesettings.cpp Implementation of AIGameSettings. */
#include "ai_gamesettings.hpp"
#include "../../settings_internal.h"
#include "../../saveload/saveload.h"
/* static */ bool AIGameSettings::IsValid(const char *setting)
{
uint i;
const SettingDesc *sd = GetPatchFromName(setting, &i);
return sd != NULL && sd->desc.cmd != SDT_STRING;
}
/* static */ int32 AIGameSettings::GetValue(const char *setting)
{
if (!IsValid(setting)) return -1;
uint i;
const SettingDesc *sd = GetPatchFromName(setting, &i);
void *ptr = GetVariableAddress(&_settings_game, &sd->save);
if (sd->desc.cmd == SDT_BOOLX) return *(bool*)ptr;
return (int32)ReadValue(ptr, sd->save.conv);
}
/* static */ bool AIGameSettings::IsDisabledVehicleType(AIVehicle::VehicleType vehicle_type)
{
switch (vehicle_type) {
case AIVehicle::VEHICLE_RAIL: return _settings_game.ai.ai_disable_veh_train;
case AIVehicle::VEHICLE_ROAD: return _settings_game.ai.ai_disable_veh_roadveh;
case AIVehicle::VEHICLE_WATER: return _settings_game.ai.ai_disable_veh_ship;
case AIVehicle::VEHICLE_AIR: return _settings_game.ai.ai_disable_veh_aircraft;
default: return true;
}
}

View File

@@ -0,0 +1,67 @@
/* $Id$ */
/** @file ai_gamesettings.hpp Everything to read game settings. */
#ifndef AI_GAMESETTINGS_HPP
#define AI_GAMESETTINGS_HPP
#include "ai_object.hpp"
#include "ai_vehicle.hpp"
/**
* Class that handles all game settings related functions.
*
* @note AIGameSettings::IsValid and AIGameSettings::GetValue are functions
* that rely on the settings as OpenTTD stores them in savegame and
* openttd.cfg. No guarantees can be given on the long term validity,
* consistency and stability of the names, values and value ranges.
* Using these settings can be dangerous and could cause issues in
* future versions. To make sure that a setting still exists in the
* current version you have to run AIGameSettings::IsValid before
* accessing it.
*
* @note The names of the setting for AIGameSettings::IsValid and
* AIGameSettings::GetValue are the same ones as those that are shown by
* the list_patches command in the in-game console. Settings that are
* string based are NOT supported and AIGAmeSettings::IsValid will return
* false for them. These settings will not be supported either because
* they have no relevance for the AI (default client names, server IPs,
* etc.).
*/
class AIGameSettings : public AIObject {
public:
static const char *GetClassName() { return "AIGameSettings"; }
/**
* Is the given game setting a valid setting for this instance of OpenTTD?
* @param setting The setting to check for existence.
* @warning Results of this function are not governed by the API. This means
* that a setting that previously existed can be gone or has
* changed it's name.
* @note Results achieved in the past offer no gurantee for the future.
* @return True if and only if the setting is valid.
*/
static bool IsValid(const char *setting);
/**
* Gets the value of the game setting.
* @param setting The setting to get the value of.
* @pre IsValid(setting).
* @warning Results of this function are not governed by the API. This means
* that the value of settings may be out of the expected range. It
* also means that a setting that previously existed can be gone or
* has changed it's name/characteristics.
* @note Results achieved in the past offer no gurantee for the future.
* @return The value for the setting.
*/
static int32 GetValue(const char *setting);
/**
* Checks whether the given vehicle-type is disabled for AIs.
* @param vehicle_type The vehicle-type to check.
* @return True if the vehicle-type is disabled.
*/
static bool IsDisabledVehicleType(AIVehicle::VehicleType vehicle_type);
};
#endif /* AI_GAMESETTINGS_HPP */

View File

@@ -0,0 +1,26 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_gamesettings.hpp"
namespace SQConvert {
/* Allow AIGameSettings to be used as Squirrel parameter */
template <> AIGameSettings *GetParam(ForceType<AIGameSettings *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIGameSettings *)instance; }
template <> AIGameSettings &GetParam(ForceType<AIGameSettings &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIGameSettings *)instance; }
template <> const AIGameSettings *GetParam(ForceType<const AIGameSettings *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIGameSettings *)instance; }
template <> const AIGameSettings &GetParam(ForceType<const AIGameSettings &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIGameSettings *)instance; }
template <> int Return<AIGameSettings *>(HSQUIRRELVM vm, AIGameSettings *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIGameSettings", res, NULL, DefSQDestructorCallback<AIGameSettings>); return 1; }
}; // namespace SQConvert
void SQAIGameSettings_Register(Squirrel *engine) {
DefSQClass <AIGameSettings> SQAIGameSettings("AIGameSettings");
SQAIGameSettings.PreRegister(engine);
SQAIGameSettings.AddConstructor<void (AIGameSettings::*)(), 1>(engine, "x");
SQAIGameSettings.DefSQStaticMethod(engine, &AIGameSettings::GetClassName, "GetClassName", 1, "x");
SQAIGameSettings.DefSQStaticMethod(engine, &AIGameSettings::IsValid, "IsValid", 2, "xs");
SQAIGameSettings.DefSQStaticMethod(engine, &AIGameSettings::GetValue, "GetValue", 2, "xs");
SQAIGameSettings.DefSQStaticMethod(engine, &AIGameSettings::IsDisabledVehicleType, "IsDisabledVehicleType", 2, "xi");
SQAIGameSettings.PostRegister(engine);
}

128
src/ai/api/ai_group.cpp Normal file
View File

@@ -0,0 +1,128 @@
/* $Id$ */
/** @file ai_group.cpp Implementation of AIGroup. */
#include "ai_group.hpp"
#include "ai_vehicle.hpp"
#include "ai_engine.hpp"
#include "../ai_instance.hpp"
#include "../../openttd.h"
#include "../../company_func.h"
#include "../../group.h"
#include "../../string_func.h"
#include "../../strings_func.h"
#include "../../core/alloc_func.hpp"
#include "../../command_func.h"
#include "../../autoreplace_func.h"
#include "table/strings.h"
/* static */ bool AIGroup::IsValidGroup(GroupID group_id)
{
return ::IsValidGroupID(group_id) && ::GetGroup(group_id)->owner == _current_company;
}
/* static */ AIGroup::GroupID AIGroup::CreateGroup(AIVehicle::VehicleType vehicle_type)
{
if (!AIObject::DoCommand(0, (::VehicleType)vehicle_type, 0, CMD_CREATE_GROUP, NULL, &AIInstance::DoCommandReturnGroupID)) return INVALID_GROUP;
/* In case of test-mode, we return GroupID 0 */
return (AIGroup::GroupID)0;
}
/* static */ bool AIGroup::DeleteGroup(GroupID group_id)
{
EnforcePrecondition(false, IsValidGroup(group_id));
return AIObject::DoCommand(0, group_id, 0, CMD_DELETE_GROUP);
}
/* static */ AIVehicle::VehicleType AIGroup::GetVehicleType(GroupID group_id)
{
if (!IsValidGroup(group_id)) return AIVehicle::VEHICLE_INVALID;
return (AIVehicle::VehicleType)((::VehicleType)::GetGroup(group_id)->vehicle_type);
}
/* static */ bool AIGroup::SetName(GroupID group_id, const char *name)
{
EnforcePrecondition(false, IsValidGroup(group_id));
EnforcePrecondition(false, !::StrEmpty(name));
EnforcePreconditionCustomError(false, ::strlen(name) < MAX_LENGTH_GROUP_NAME_BYTES, AIError::ERR_PRECONDITION_STRING_TOO_LONG);
return AIObject::DoCommand(0, group_id, 0, CMD_RENAME_GROUP, name);
}
/* static */ const char *AIGroup::GetName(GroupID group_id)
{
if (!IsValidGroup(group_id)) return NULL;
static const int len = 64;
char *group_name = MallocT<char>(len);
::SetDParam(0, group_id);
::GetString(group_name, STR_GROUP_NAME, &group_name[len - 1]);
return group_name;
}
/* static */ bool AIGroup::EnableAutoReplaceProtection(GroupID group_id, bool enable)
{
EnforcePrecondition(false, IsValidGroup(group_id));
return AIObject::DoCommand(0, group_id, enable ? 1 : 0, CMD_SET_GROUP_REPLACE_PROTECTION);
}
/* static */ bool AIGroup::GetAutoReplaceProtection(GroupID group_id)
{
if (!IsValidGroup(group_id)) return false;
return ::GetGroup(group_id)->replace_protection;
}
/* static */ int32 AIGroup::GetNumEngines(GroupID group_id, EngineID engine_id)
{
if (!IsValidGroup(group_id) && group_id != DEFAULT_GROUP && group_id != ALL_GROUP) return -1;
return GetGroupNumEngines(_current_company, group_id, engine_id);
}
/* static */ bool AIGroup::MoveVehicle(GroupID group_id, VehicleID vehicle_id)
{
EnforcePrecondition(false, IsValidGroup(group_id) || group_id == DEFAULT_GROUP);
EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
return AIObject::DoCommand(0, group_id, vehicle_id, CMD_ADD_VEHICLE_GROUP);
}
/* static */ bool AIGroup::EnableWagonRemoval(bool enable_removal)
{
if (HasWagonRemoval() == enable_removal) return true;
return AIObject::DoCommand(0, 5, enable_removal ? 1 : 0, CMD_SET_AUTOREPLACE);
}
/* static */ bool AIGroup::HasWagonRemoval()
{
return ::GetCompany(_current_company)->renew_keep_length;
}
/* static */ bool AIGroup::SetAutoReplace(GroupID group_id, EngineID engine_id_old, EngineID engine_id_new)
{
EnforcePrecondition(false, IsValidGroup(group_id) || group_id == ALL_GROUP);
EnforcePrecondition(false, AIEngine::IsValidEngine(engine_id_new));
return AIObject::DoCommand(0, 3 | (group_id << 16), (engine_id_new << 16) | engine_id_old, CMD_SET_AUTOREPLACE);
}
/* static */ EngineID AIGroup::GetEngineReplacement(GroupID group_id, EngineID engine_id)
{
if (!IsValidGroup(group_id) && group_id != ALL_GROUP) return ::INVALID_ENGINE;
return ::EngineReplacementForCompany(GetCompany(_current_company), engine_id, group_id);
}
/* static */ bool AIGroup::StopAutoReplace(GroupID group_id, EngineID engine_id)
{
EnforcePrecondition(false, IsValidGroup(group_id) || group_id == ALL_GROUP);
return AIObject::DoCommand(0, 3 | (group_id << 16), (::INVALID_ENGINE << 16) | engine_id, CMD_SET_AUTOREPLACE);
}

170
src/ai/api/ai_group.hpp Normal file
View File

@@ -0,0 +1,170 @@
/* $Id$ */
/** @file ai_group.hpp Everything to put vehicles into groups. */
#ifndef AI_GROUP_HPP
#define AI_GROUP_HPP
#include "ai_object.hpp"
#include "ai_vehicle.hpp"
/**
* Class that handles all group related functions.
*/
class AIGroup : public AIObject {
public:
static const char *GetClassName() { return "AIGroup"; }
/**
* The group IDs of some special groups.
*/
enum GroupID {
/* Values are important, as they represent the internal state of the game (see group_type.h). */
ALL_GROUP = 0xFFFD, //!< All vehicles are in this group.
DEFAULT_GROUP = 0xFFFE, //!< Vehicles not put in any other group are in this one.
INVALID_GROUP = 0xFFFF, //!< An invalid group id.
};
/**
* Checks whether the given group is valid.
* @param group_id The group to check.
* @pre group_id != DEFAULT_GROUP && group_id != ALL_GROUP.
* @return True if and only if the group is valid.
*/
static bool IsValidGroup(GroupID group_id);
/**
* Create a new group.
* @param vehicle_type The type of vehicle to create a group for.
* @return The GroupID of the new group, or an invalid GroupID when
* it failed. Check the return value using IsValidGroup(). In test-mode
* 0 is returned if it was successful; any other value indicates failure.
*/
static GroupID CreateGroup(AIVehicle::VehicleType vehicle_type);
/**
* Delete the given group. When the deletion succeeds all vehicles in the
* given group will move to the DEFAULT_GROUP.
* @param group_id The group to delete.
* @pre IsValidGroup(group_id).
* @return True if and only if the group was succesfully deleted.
*/
static bool DeleteGroup(GroupID group_id);
/**
* Get the vehicle type of a group.
* @param group_id The group to get the type from.
* @pre IsValidGroup(group_id).
* @return The vehicletype of the given group.
*/
static AIVehicle::VehicleType GetVehicleType(GroupID group_id);
/**
* Set the name of a group.
* @param group_id The group to set the name for.
* @param name The name for the group.
* @pre IsValidGroup(group_id).
* @pre 'name' must have at least one character.
* @pre 'name' must have at most 30 characters.
* @exception AIError::ERR_NAME_IS_NOT_UNIQUE
* @return True if and only if the name was changed.
*/
static bool SetName(GroupID group_id, const char *name);
/**
* Get the name of a group.
* @param group_id The group to get the name of.
* @pre IsValidGroup(group_id).
* @return The name the group has.
*/
static const char *GetName(GroupID group_id);
/**
* Enable or disable autoreplace protected. If the protection is
* enabled, global autoreplace won't affect vehicles in this group.
* @param group_id The group to change the protection for.
* @param enable True if protection should be enabled.
* @pre IsValidGroup(group_id).
* @return True if and only if the protection was succesfully changed.
*/
static bool EnableAutoReplaceProtection(GroupID group_id, bool enable);
/**
* Get the autoreplace protection status.
* @param group_id The group to get the protection status for.
* @pre IsValidGroup(group_id).
* @return The autoreplace protection status for the given group.
*/
static bool GetAutoReplaceProtection(GroupID group_id);
/**
* Get the number of engines in a given group.
* @param group_id The group to get the number of engines in.
* @param engine_id The engine id to count.
* @pre IsValidGroup(group_id) || group_id == ALL_GROUP || group_id == DEFAULT_GROUP.
* @return The number of engines with id engine_id in the group with id group_id.
*/
static int32 GetNumEngines(GroupID group_id, EngineID engine_id);
/**
* Move a vehicle to a group.
* @param group_id The group to move the vehicel to.
* @param vehicle_id The vehicle to move to the group.
* @pre IsValidGroup(group_id) || group_id == DEFAULT_GROUP.
* @pre AIVehicle::IsValidVehicle(vehicle_id).
* @return True if and only if the vehicle was succesfully moved to the group.
* @note A vehicle can be in only one group at the same time. To remove it from
* a group, move it to another or to DEFAULT_GROUP. Moving the vehicle to the
* given group means removing it from another group.
*/
static bool MoveVehicle(GroupID group_id, VehicleID vehicle_id);
/**
* Enable or disable the removal of wagons when a (part of a) vehicle is
* (auto)replaced with a longer variant (longer wagons or longer engines)
* If enabled, wagons are removed from the end of the vehicle until it
* fits in the same number of tiles as it did before.
* @param keep_length If true, wagons will be removed if the a new engine is longer.
* @return True if and only if the value was succesfully changed.
*/
static bool EnableWagonRemoval(bool keep_length);
/**
* Get the current status of wagon removal.
* @return Whether or not wagon removal is enabled.
*/
static bool HasWagonRemoval();
/**
* Start replacing all vehicles with a specified engine with another engine.
* @param group_id The group to replace vehicles from. Use ALL_GROUP to replace
* vehicles from all groups that haven't set autoreplace protection.
* @param engine_id_old The engine id to start replacing.
* @param engine_id_new The engine id to replace with.
* @pre IsValidGroup(group_id) || group_id == ALL_GROUP.
* @pre AIEngine.IsValidEngine(engine_id_new).
* @note To stop autoreplacing engine_id_old, call StopAutoReplace(group_id, engine_id_old).
*/
static bool SetAutoReplace(GroupID group_id, EngineID engine_id_old, EngineID engine_id_new);
/**
* Get the EngineID the given EngineID is replaced with.
* @param group_id The group to get the replacement from.
* @param engine_id The engine that is being replaced.
* @pre IsValidGroup(group_id) || group_id == ALL_GROUP.
* @return The EngineID that is replacing engine_id or an invalid EngineID
* in case engine_id is not begin replaced.
*/
static EngineID GetEngineReplacement(GroupID group_id, EngineID engine_id);
/**
* Stop replacing a certain engine in the specified group.
* @param group_id The group to stop replacing the engine in.
* @param engine_id The engine id to stop replacing with another engine.
* @pre IsValidGroup(group_id) || group_id == ALL_GROUP.
* @return True if and if the replacing was succesfully stopped.
*/
static bool StopAutoReplace(GroupID group_id, EngineID engine_id);
};
#endif /* AI_GROUP_HPP */

View File

@@ -0,0 +1,46 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_group.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AIGroup::GroupID GetParam(ForceType<AIGroup::GroupID>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIGroup::GroupID)tmp; }
template <> int Return<AIGroup::GroupID>(HSQUIRRELVM vm, AIGroup::GroupID res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AIGroup to be used as Squirrel parameter */
template <> AIGroup *GetParam(ForceType<AIGroup *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIGroup *)instance; }
template <> AIGroup &GetParam(ForceType<AIGroup &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIGroup *)instance; }
template <> const AIGroup *GetParam(ForceType<const AIGroup *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIGroup *)instance; }
template <> const AIGroup &GetParam(ForceType<const AIGroup &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIGroup *)instance; }
template <> int Return<AIGroup *>(HSQUIRRELVM vm, AIGroup *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIGroup", res, NULL, DefSQDestructorCallback<AIGroup>); return 1; }
}; // namespace SQConvert
void SQAIGroup_Register(Squirrel *engine) {
DefSQClass <AIGroup> SQAIGroup("AIGroup");
SQAIGroup.PreRegister(engine);
SQAIGroup.AddConstructor<void (AIGroup::*)(), 1>(engine, "x");
SQAIGroup.DefSQConst(engine, AIGroup::ALL_GROUP, "ALL_GROUP");
SQAIGroup.DefSQConst(engine, AIGroup::DEFAULT_GROUP, "DEFAULT_GROUP");
SQAIGroup.DefSQConst(engine, AIGroup::INVALID_GROUP, "INVALID_GROUP");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::GetClassName, "GetClassName", 1, "x");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::IsValidGroup, "IsValidGroup", 2, "xi");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::CreateGroup, "CreateGroup", 2, "xi");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::DeleteGroup, "DeleteGroup", 2, "xi");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::GetVehicleType, "GetVehicleType", 2, "xi");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::SetName, "SetName", 3, "xis");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::GetName, "GetName", 2, "xi");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::EnableAutoReplaceProtection, "EnableAutoReplaceProtection", 3, "xib");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::GetAutoReplaceProtection, "GetAutoReplaceProtection", 2, "xi");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::GetNumEngines, "GetNumEngines", 3, "xii");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::MoveVehicle, "MoveVehicle", 3, "xii");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::EnableWagonRemoval, "EnableWagonRemoval", 2, "xb");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::HasWagonRemoval, "HasWagonRemoval", 1, "x");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::SetAutoReplace, "SetAutoReplace", 4, "xiii");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::GetEngineReplacement, "GetEngineReplacement", 3, "xii");
SQAIGroup.DefSQStaticMethod(engine, &AIGroup::StopAutoReplace, "StopAutoReplace", 3, "xii");
SQAIGroup.PostRegister(engine);
}

View File

@@ -0,0 +1,16 @@
/* $Id$ */
/** @file ai_grouplist.cpp Implementation of AIGroupList and friends. */
#include "ai_grouplist.hpp"
#include "../../openttd.h"
#include "../../company_func.h"
#include "../../group.h"
AIGroupList::AIGroupList()
{
Group *g;
FOR_ALL_GROUPS(g) {
if (g->owner == _current_company) this->AddItem(g->index);
}
}

View File

@@ -0,0 +1,21 @@
/* $Id$ */
/** @file ai_grouplist.hpp List all the groups (you own). */
#ifndef AI_GROUPLIST_HPP
#define AI_GROUPLIST_HPP
#include "ai_abstractlist.hpp"
/**
* Creates a list of groups of which you are the owner.
* @note Neither AIGroup.ALL_GROUP nor AIGroup.DEFAULT_GROUP is in this list.
* @ingroup AIList
*/
class AIGroupList : public AIAbstractList {
public:
static const char *GetClassName() { return "AIGroupList"; }
AIGroupList();
};
#endif /* AI_GROUPLIST_HPP */

View File

@@ -0,0 +1,23 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_grouplist.hpp"
namespace SQConvert {
/* Allow AIGroupList to be used as Squirrel parameter */
template <> AIGroupList *GetParam(ForceType<AIGroupList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIGroupList *)instance; }
template <> AIGroupList &GetParam(ForceType<AIGroupList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIGroupList *)instance; }
template <> const AIGroupList *GetParam(ForceType<const AIGroupList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIGroupList *)instance; }
template <> const AIGroupList &GetParam(ForceType<const AIGroupList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIGroupList *)instance; }
template <> int Return<AIGroupList *>(HSQUIRRELVM vm, AIGroupList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIGroupList", res, NULL, DefSQDestructorCallback<AIGroupList>); return 1; }
}; // namespace SQConvert
void SQAIGroupList_Register(Squirrel *engine) {
DefSQClass <AIGroupList> SQAIGroupList("AIGroupList");
SQAIGroupList.PreRegister(engine, "AIAbstractList");
SQAIGroupList.AddConstructor<void (AIGroupList::*)(), 1>(engine, "x");
SQAIGroupList.DefSQStaticMethod(engine, &AIGroupList::GetClassName, "GetClassName", 1, "x");
SQAIGroupList.PostRegister(engine);
}

170
src/ai/api/ai_industry.cpp Normal file
View File

@@ -0,0 +1,170 @@
/* $Id$ */
/** @file ai_industry.cpp Implementation of AIIndustry. */
#include "ai_industry.hpp"
#include "ai_cargo.hpp"
#include "ai_map.hpp"
#include "../../openttd.h"
#include "../../tile_type.h"
#include "../../industry.h"
#include "../../strings_func.h"
#include "../../station_func.h"
#include "table/strings.h"
/* static */ IndustryID AIIndustry::GetMaxIndustryID()
{
return ::GetMaxIndustryIndex();
}
/* static */ int32 AIIndustry::GetIndustryCount()
{
return ::GetNumIndustries();
}
/* static */ bool AIIndustry::IsValidIndustry(IndustryID industry_id)
{
return ::IsValidIndustryID(industry_id);
}
/* static */ const char *AIIndustry::GetName(IndustryID industry_id)
{
if (!IsValidIndustry(industry_id)) return NULL;
static const int len = 64;
char *industry_name = MallocT<char>(len);
::SetDParam(0, industry_id);
::GetString(industry_name, STR_INDUSTRY, &industry_name[len - 1]);
return industry_name;
}
/* static */ int32 AIIndustry::GetProduction(IndustryID industry_id, CargoID cargo_id)
{
if (!IsValidIndustry(industry_id)) return -1;
if (!AICargo::IsValidCargo(cargo_id)) return -1;
const Industry *i = ::GetIndustry(industry_id);
const IndustrySpec *indsp = ::GetIndustrySpec(i->type);
for (byte j = 0; j < lengthof(indsp->produced_cargo); j++)
if (indsp->produced_cargo[j] == cargo_id) return i->production_rate[j] * 8;
return -1;
}
/* static */ bool AIIndustry::IsCargoAccepted(IndustryID industry_id, CargoID cargo_id)
{
if (!IsValidIndustry(industry_id)) return false;
if (!AICargo::IsValidCargo(cargo_id)) return false;
const Industry *i = ::GetIndustry(industry_id);
const IndustrySpec *indsp = ::GetIndustrySpec(i->type);
for (byte j = 0; j < lengthof(indsp->accepts_cargo); j++)
if (indsp->accepts_cargo[j] == cargo_id) return true;
return false;
}
/* static */ int32 AIIndustry::GetStockpiledCargo(IndustryID industry_id, CargoID cargo_id)
{
if (!IsValidIndustry(industry_id)) return -1;
if (!AICargo::IsValidCargo(cargo_id)) return -1;
Industry *ind = ::GetIndustry(industry_id);
for (uint i = 0; i < lengthof(ind->accepts_cargo); i++) {
CargoID cid = ind->accepts_cargo[i];
if (cid == cargo_id) {
return ind->incoming_cargo_waiting[i];
}
}
return -1;
}
/* static */ int32 AIIndustry::GetLastMonthProduction(IndustryID industry_id, CargoID cargo_id)
{
if (!IsValidIndustry(industry_id)) return -1;
if (!AICargo::IsValidCargo(cargo_id)) return -1;
const Industry *i = ::GetIndustry(industry_id);
const IndustrySpec *indsp = ::GetIndustrySpec(i->type);
for (byte j = 0; j < lengthof(indsp->produced_cargo); j++)
if (indsp->produced_cargo[j] == cargo_id) return i->last_month_production[j];
return -1;
}
/* static */ int32 AIIndustry::GetLastMonthTransported(IndustryID industry_id, CargoID cargo_id)
{
if (!IsValidIndustry(industry_id)) return -1;
if (!AICargo::IsValidCargo(cargo_id)) return -1;
const Industry *i = ::GetIndustry(industry_id);
const IndustrySpec *indsp = ::GetIndustrySpec(i->type);
for (byte j = 0; j < lengthof(indsp->produced_cargo); j++)
if (indsp->produced_cargo[j] == cargo_id) return i->last_month_transported[j];
return -1;
}
/* static */ TileIndex AIIndustry::GetLocation(IndustryID industry_id)
{
if (!IsValidIndustry(industry_id)) return INVALID_TILE;
return ::GetIndustry(industry_id)->xy;
}
/* static */ int32 AIIndustry::GetAmountOfStationsAround(IndustryID industry_id)
{
if (!IsValidIndustry(industry_id)) return -1;
Industry *ind = ::GetIndustry(industry_id);
return (int32)::FindStationsAroundTiles(ind->xy, ind->width, ind->height).size();
}
/* static */ int32 AIIndustry::GetDistanceManhattanToTile(IndustryID industry_id, TileIndex tile)
{
if (!IsValidIndustry(industry_id)) return -1;
return AIMap::DistanceManhattan(tile, GetLocation(industry_id));
}
/* static */ int32 AIIndustry::GetDistanceSquareToTile(IndustryID industry_id, TileIndex tile)
{
if (!IsValidIndustry(industry_id)) return -1;
return AIMap::DistanceSquare(tile, GetLocation(industry_id));
}
/* static */ bool AIIndustry::IsBuiltOnWater(IndustryID industry_id)
{
if (!IsValidIndustry(industry_id)) return false;
return (::GetIndustrySpec(::GetIndustry(industry_id)->type)->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0;
}
/* static */ bool AIIndustry::HasHeliportAndDock(IndustryID industry_id)
{
if (!IsValidIndustry(industry_id)) return false;
return (::GetIndustrySpec(::GetIndustry(industry_id)->type)->behaviour & INDUSTRYBEH_AI_AIRSHIP_ROUTES) != 0;
}
/* static */ TileIndex AIIndustry::GetHeliportAndDockLocation(IndustryID industry_id)
{
if (!IsValidIndustry(industry_id)) return INVALID_TILE;
if (!HasHeliportAndDock(industry_id)) return INVALID_TILE;
return ::GetIndustry(industry_id)->xy;
}
/* static */ IndustryType AIIndustry::GetIndustryType(IndustryID industry_id)
{
if (!IsValidIndustry(industry_id)) return INVALID_INDUSTRYTYPE;
return ::GetIndustry(industry_id)->type;
}

171
src/ai/api/ai_industry.hpp Normal file
View File

@@ -0,0 +1,171 @@
/* $Id$ */
/** @file ai_industry.hpp Everything to query and build industries. */
#ifndef AI_INDUSTRY_HPP
#define AI_INDUSTRY_HPP
#include "ai_object.hpp"
/**
* Class that handles all industry related functions.
*/
class AIIndustry : public AIObject {
public:
static const char *GetClassName() { return "AIIndustry"; }
/**
* Gets the maximum industry index; there are no valid industries with a
* higher index.
* @return The maximum industry index.
* @post Return value is always non-negative.
*/
static IndustryID GetMaxIndustryID();
/**
* Gets the number of industries. This is different than GetMaxIndustryID()
* because of the way OpenTTD works internally.
* @return The number of industries.
* @post Return value is always non-negative.
*/
static int32 GetIndustryCount();
/**
* Checks whether the given industry index is valid.
* @param industry_id The index to check.
* @return True if and only if the industry is valid.
*/
static bool IsValidIndustry(IndustryID industry_id);
/**
* Get the name of the industry.
* @param industry_id The industry to get the name of.
* @pre IsValidIndustry(industry_id).
* @return The name of the industry.
*/
static const char *GetName(IndustryID industry_id);
/**
* Gets the production of a cargo of the industry.
* @param industry_id The index of the industry.
* @param cargo_id The index of the cargo.
* @pre IsValidIndustry(industry_id).
* @pre AICargo::IsValidCargo(cargo_id).
* @return The production of the cargo for this industry, or -1 if
* this industry doesn't produce this cargo.
*/
static int32 GetProduction(IndustryID industry_id, CargoID cargo_id);
/**
* See if an industry accepts a certain cargo.
* @param industry_id The index of the industry.
* @param cargo_id The index of the cargo.
* @pre IsValidIndustry(industry_id).
* @pre AICargo::IsValidCargo(cargo_id).
* @return The production of the cargo for this industry.
*/
static bool IsCargoAccepted(IndustryID industry_id, CargoID cargo_id);
/**
* Get the amount of cargo stockpiled for processing.
* @param industry_id The index of the industry.
* @param cargo_id The index of the cargo.
* @pre IsValidIndustry(industry_id).
* @pre AICargo::IsValidCargo(cargo_id).
* @return The amount of cargo that is waiting for processing.
*/
static int32 GetStockpiledCargo(IndustryID industry_id, CargoID cargo_id);
/**
* Get the total last month's production of the given cargo at an industry.
* @param industry_id The index of the industry.
* @param cargo_id The index of the cargo.
* @pre IsValidIndustry(industry_id).
* @pre AICargo::IsValidCargo(cargo_id).
* @return The last month's production of the given cargo for this industry.
*/
static int32 GetLastMonthProduction(IndustryID industry_id, CargoID cargo_id);
/**
* Get the total amount of cargo transported from an industry last month.
* @param industry_id The index of the industry.
* @param cargo_id The index of the cargo.
* @pre IsValidIndustry(industry_id).
* @pre AICargo::IsValidCargo(cargo_id).
* @return The amount of given cargo transported from this industry last month.
*/
static int32 GetLastMonthTransported(IndustryID industry_id, CargoID cargo_id);
/**
* Gets the location of the industry.
* @param industry_id The index of the industry.
* @pre IsValidIndustry(industry_id).
* @return The location of the industry.
*/
static TileIndex GetLocation(IndustryID industry_id);
/**
* Get the number of stations around an industry.
* @param industry_id The index of the industry.
* @pre IsValidIndustry(industry_id).
* @return The number of stations around an industry.
*/
static int32 GetAmountOfStationsAround(IndustryID industry_id);
/**
* Get the manhattan distance from the tile to the AIIndustry::GetLocation()
* of the industry.
* @param industry_id The industry to get the distance to.
* @param tile The tile to get the distance to.
* @pre IsValidIndustry(industry_id).
* @pre AIMap::IsValidTile(tile).
* @return The distance between industry and tile.
*/
static int32 GetDistanceManhattanToTile(IndustryID industry_id, TileIndex tile);
/**
* Get the square distance from the tile to the AIIndustry::GetLocation()
* of the industry.
* @param industry_id The industry to get the distance to.
* @param tile The tile to get the distance to.
* @pre IsValidIndustry(industry_id).
* @pre AIMap::IsValidTile(tile).
* @return The distance between industry and tile.
*/
static int32 GetDistanceSquareToTile(IndustryID industry_id, TileIndex tile);
/**
* Is this industry built on water.
* @param industry_id The index of the industry.
* @pre IsValidIndustry(industry_id).
* @return True when the industry is built on water.
*/
static bool IsBuiltOnWater(IndustryID industry_id);
/**
* Does this industry have a heliport and dock?
* @param industry_id The index of the industry.
* @pre IsValidIndustry(industry_id).
* @return True when the industry has a heliport and dock.
*/
static bool HasHeliportAndDock(IndustryID industry_id);
/**
* Gets the location of the industry's heliport/dock.
* @param industry_id The index of the industry.
* @pre IsValidIndustry(industry_id).
* @pre HasHeliportAndDock(industry_id).
* @return The location of the industry's heliport/dock.
*/
static TileIndex GetHeliportAndDockLocation(IndustryID industry_id);
/**
* Get the IndustryType of the industry.
* @param industry_id The index of the industry.
* @pre IsValidIndustry(industry_id).
* @return The IndustryType of the industry.
*/
static IndustryType GetIndustryType(IndustryID industry_id);
};
#endif /* AI_INDUSTRY_HPP */

View File

@@ -0,0 +1,40 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_industry.hpp"
namespace SQConvert {
/* Allow AIIndustry to be used as Squirrel parameter */
template <> AIIndustry *GetParam(ForceType<AIIndustry *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustry *)instance; }
template <> AIIndustry &GetParam(ForceType<AIIndustry &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustry *)instance; }
template <> const AIIndustry *GetParam(ForceType<const AIIndustry *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustry *)instance; }
template <> const AIIndustry &GetParam(ForceType<const AIIndustry &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustry *)instance; }
template <> int Return<AIIndustry *>(HSQUIRRELVM vm, AIIndustry *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIIndustry", res, NULL, DefSQDestructorCallback<AIIndustry>); return 1; }
}; // namespace SQConvert
void SQAIIndustry_Register(Squirrel *engine) {
DefSQClass <AIIndustry> SQAIIndustry("AIIndustry");
SQAIIndustry.PreRegister(engine);
SQAIIndustry.AddConstructor<void (AIIndustry::*)(), 1>(engine, "x");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetClassName, "GetClassName", 1, "x");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetMaxIndustryID, "GetMaxIndustryID", 1, "x");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetIndustryCount, "GetIndustryCount", 1, "x");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::IsValidIndustry, "IsValidIndustry", 2, "xi");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetName, "GetName", 2, "xi");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetProduction, "GetProduction", 3, "xii");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::IsCargoAccepted, "IsCargoAccepted", 3, "xii");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetStockpiledCargo, "GetStockpiledCargo", 3, "xii");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetLastMonthProduction, "GetLastMonthProduction", 3, "xii");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetLastMonthTransported, "GetLastMonthTransported", 3, "xii");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetLocation, "GetLocation", 2, "xi");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetAmountOfStationsAround, "GetAmountOfStationsAround", 2, "xi");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetDistanceManhattanToTile, "GetDistanceManhattanToTile", 3, "xii");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetDistanceSquareToTile, "GetDistanceSquareToTile", 3, "xii");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::IsBuiltOnWater, "IsBuiltOnWater", 2, "xi");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::HasHeliportAndDock, "HasHeliportAndDock", 2, "xi");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetHeliportAndDockLocation, "GetHeliportAndDockLocation", 2, "xi");
SQAIIndustry.DefSQStaticMethod(engine, &AIIndustry::GetIndustryType, "GetIndustryType", 2, "xi");
SQAIIndustry.PostRegister(engine);
}

View File

@@ -0,0 +1,42 @@
/* $Id$ */
/** @file ai_industrylist.cpp Implementation of AIIndustryList and friends. */
#include "ai_industrylist.hpp"
#include "../../openttd.h"
#include "../../tile_type.h"
#include "../../industry.h"
AIIndustryList::AIIndustryList()
{
Industry *i;
FOR_ALL_INDUSTRIES(i) {
this->AddItem(i->index);
}
}
AIIndustryList_CargoAccepting::AIIndustryList_CargoAccepting(CargoID cargo_id)
{
const Industry *i;
const IndustrySpec *indsp;
FOR_ALL_INDUSTRIES(i) {
indsp = ::GetIndustrySpec(i->type);
for (byte j = 0; j < lengthof(indsp->accepts_cargo); j++)
if (indsp->accepts_cargo[j] == cargo_id) this->AddItem(i->index);
}
}
AIIndustryList_CargoProducing::AIIndustryList_CargoProducing(CargoID cargo_id)
{
const Industry *i;
const IndustrySpec *indsp;
FOR_ALL_INDUSTRIES(i) {
indsp = ::GetIndustrySpec(i->type);
for (byte j = 0; j < lengthof(indsp->produced_cargo); j++)
if (indsp->produced_cargo[j] == cargo_id) this->AddItem(i->index);
}
}

View File

@@ -0,0 +1,49 @@
/* $Id$ */
/** @file ai_industrylist.hpp List all the industries. */
#ifndef AI_INDUSTRYLIST_HPP
#define AI_INDUSTRYLIST_HPP
#include "ai_abstractlist.hpp"
/**
* Creates a list of industries that are currently on the map.
* @ingroup AIList
*/
class AIIndustryList : public AIAbstractList {
public:
static const char *GetClassName() { return "AIIndustryList"; }
AIIndustryList();
};
/**
* Creates a list of industries that accepts a given cargo.
* @ingroup AIList
*/
class AIIndustryList_CargoAccepting : public AIAbstractList {
public:
static const char *GetClassName() { return "AIIndustryList_CargoAccepting"; }
/**
* @param cargo_id The cargo this industry should accept.
*/
AIIndustryList_CargoAccepting(CargoID cargo_id);
};
/**
* Creates a list of industries that can produce a given cargo.
* @note It also contains industries that currently produces 0 units of the cargo.
* @ingroup AIList
*/
class AIIndustryList_CargoProducing : public AIAbstractList {
public:
static const char *GetClassName() { return "AIIndustryList_CargoProducing"; }
/**
* @param cargo_id The cargo this industry should produce.
*/
AIIndustryList_CargoProducing(CargoID cargo_id);
};
#endif /* AI_INDUSTRYLIST_HPP */

View File

@@ -0,0 +1,61 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_industrylist.hpp"
namespace SQConvert {
/* Allow AIIndustryList to be used as Squirrel parameter */
template <> AIIndustryList *GetParam(ForceType<AIIndustryList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryList *)instance; }
template <> AIIndustryList &GetParam(ForceType<AIIndustryList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryList *)instance; }
template <> const AIIndustryList *GetParam(ForceType<const AIIndustryList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryList *)instance; }
template <> const AIIndustryList &GetParam(ForceType<const AIIndustryList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryList *)instance; }
template <> int Return<AIIndustryList *>(HSQUIRRELVM vm, AIIndustryList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIIndustryList", res, NULL, DefSQDestructorCallback<AIIndustryList>); return 1; }
}; // namespace SQConvert
void SQAIIndustryList_Register(Squirrel *engine) {
DefSQClass <AIIndustryList> SQAIIndustryList("AIIndustryList");
SQAIIndustryList.PreRegister(engine, "AIAbstractList");
SQAIIndustryList.AddConstructor<void (AIIndustryList::*)(), 1>(engine, "x");
SQAIIndustryList.DefSQStaticMethod(engine, &AIIndustryList::GetClassName, "GetClassName", 1, "x");
SQAIIndustryList.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIIndustryList_CargoAccepting to be used as Squirrel parameter */
template <> AIIndustryList_CargoAccepting *GetParam(ForceType<AIIndustryList_CargoAccepting *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryList_CargoAccepting *)instance; }
template <> AIIndustryList_CargoAccepting &GetParam(ForceType<AIIndustryList_CargoAccepting &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryList_CargoAccepting *)instance; }
template <> const AIIndustryList_CargoAccepting *GetParam(ForceType<const AIIndustryList_CargoAccepting *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryList_CargoAccepting *)instance; }
template <> const AIIndustryList_CargoAccepting &GetParam(ForceType<const AIIndustryList_CargoAccepting &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryList_CargoAccepting *)instance; }
template <> int Return<AIIndustryList_CargoAccepting *>(HSQUIRRELVM vm, AIIndustryList_CargoAccepting *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIIndustryList_CargoAccepting", res, NULL, DefSQDestructorCallback<AIIndustryList_CargoAccepting>); return 1; }
}; // namespace SQConvert
void SQAIIndustryList_CargoAccepting_Register(Squirrel *engine) {
DefSQClass <AIIndustryList_CargoAccepting> SQAIIndustryList_CargoAccepting("AIIndustryList_CargoAccepting");
SQAIIndustryList_CargoAccepting.PreRegister(engine, "AIAbstractList");
SQAIIndustryList_CargoAccepting.AddConstructor<void (AIIndustryList_CargoAccepting::*)(CargoID cargo_id), 2>(engine, "xi");
SQAIIndustryList_CargoAccepting.DefSQStaticMethod(engine, &AIIndustryList_CargoAccepting::GetClassName, "GetClassName", 1, "x");
SQAIIndustryList_CargoAccepting.PostRegister(engine);
}
namespace SQConvert {
/* Allow AIIndustryList_CargoProducing to be used as Squirrel parameter */
template <> AIIndustryList_CargoProducing *GetParam(ForceType<AIIndustryList_CargoProducing *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryList_CargoProducing *)instance; }
template <> AIIndustryList_CargoProducing &GetParam(ForceType<AIIndustryList_CargoProducing &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryList_CargoProducing *)instance; }
template <> const AIIndustryList_CargoProducing *GetParam(ForceType<const AIIndustryList_CargoProducing *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryList_CargoProducing *)instance; }
template <> const AIIndustryList_CargoProducing &GetParam(ForceType<const AIIndustryList_CargoProducing &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryList_CargoProducing *)instance; }
template <> int Return<AIIndustryList_CargoProducing *>(HSQUIRRELVM vm, AIIndustryList_CargoProducing *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIIndustryList_CargoProducing", res, NULL, DefSQDestructorCallback<AIIndustryList_CargoProducing>); return 1; }
}; // namespace SQConvert
void SQAIIndustryList_CargoProducing_Register(Squirrel *engine) {
DefSQClass <AIIndustryList_CargoProducing> SQAIIndustryList_CargoProducing("AIIndustryList_CargoProducing");
SQAIIndustryList_CargoProducing.PreRegister(engine, "AIAbstractList");
SQAIIndustryList_CargoProducing.AddConstructor<void (AIIndustryList_CargoProducing::*)(CargoID cargo_id), 2>(engine, "xi");
SQAIIndustryList_CargoProducing.DefSQStaticMethod(engine, &AIIndustryList_CargoProducing::GetClassName, "GetClassName", 1, "x");
SQAIIndustryList_CargoProducing.PostRegister(engine);
}

View File

@@ -0,0 +1,115 @@
/* $Id$ */
/** @file ai_industrytype.cpp Implementation of AIIndustryType. */
#include "ai_industrytype.hpp"
#include "ai_map.hpp"
#include "../../openttd.h"
#include "../../command_type.h"
#include "../../settings_type.h"
#include "../../strings_func.h"
#include "../../tile_type.h"
#include "../../industry.h"
/* static */ bool AIIndustryType::IsValidIndustryType(IndustryType industry_type)
{
if (industry_type >= NUM_INDUSTRYTYPES) return false;
return ::GetIndustrySpec(industry_type)->enabled;
}
/* static */ bool AIIndustryType::IsRawIndustry(IndustryType industry_type)
{
if (!IsValidIndustryType(industry_type)) return false;
return ::GetIndustrySpec(industry_type)->IsRawIndustry();
}
/* static */ bool AIIndustryType::ProductionCanIncrease(IndustryType industry_type)
{
if (!IsValidIndustryType(industry_type)) return false;
if (_settings_game.game_creation.landscape != LT_TEMPERATE) return true;
return (::GetIndustrySpec(industry_type)->behaviour & INDUSTRYBEH_DONT_INCR_PROD) == 0;
}
/* static */ Money AIIndustryType::GetConstructionCost(IndustryType industry_type)
{
if (!IsValidIndustryType(industry_type)) return false;
return ::GetIndustrySpec(industry_type)->GetConstructionCost();
}
/* static */ const char *AIIndustryType::GetName(IndustryType industry_type)
{
if (!IsValidIndustryType(industry_type)) return NULL;
static const int len = 64;
char *industrytype_name = MallocT<char>(len);
::GetString(industrytype_name, ::GetIndustrySpec(industry_type)->name, &industrytype_name[len - 1]);
return industrytype_name;
}
/* static */ AIList *AIIndustryType::GetProducedCargo(IndustryType industry_type)
{
if (!IsValidIndustryType(industry_type)) return NULL;
const IndustrySpec *ins = ::GetIndustrySpec(industry_type);
AIList *list = new AIList();
for (int i = 0; i < 2; i++) {
if (ins->produced_cargo[i] != CT_INVALID) list->AddItem(ins->produced_cargo[i], 0);
}
return list;
}
/* static */ AIList *AIIndustryType::GetAcceptedCargo(IndustryType industry_type)
{
if (!IsValidIndustryType(industry_type)) return NULL;
const IndustrySpec *ins = ::GetIndustrySpec(industry_type);
AIList *list = new AIList();
for (int i = 0; i < 3; i++) {
if (ins->accepts_cargo[i] != CT_INVALID) list->AddItem(ins->accepts_cargo[i], 0);
}
return list;
}
/* static */ bool AIIndustryType::CanBuildIndustry(IndustryType industry_type)
{
if (!IsValidIndustryType(industry_type)) return false;
if (!::GetIndustrySpec(industry_type)->IsRawIndustry()) return true;
/* raw_industry_construction == 1 means "Build as other industries" */
return _settings_game.construction.raw_industry_construction == 1;
}
/* static */ bool AIIndustryType::CanProspectIndustry(IndustryType industry_type)
{
if (!IsValidIndustryType(industry_type)) return false;
if (!::GetIndustrySpec(industry_type)->IsRawIndustry()) return false;
/* raw_industry_construction == 2 means "prospect" */
return _settings_game.construction.raw_industry_construction == 2;
}
/* static */ bool AIIndustryType::BuildIndustry(IndustryType industry_type, TileIndex tile)
{
EnforcePrecondition(false, CanBuildIndustry(industry_type));
EnforcePrecondition(false, AIMap::IsValidTile(tile));
uint32 seed = ::InteractiveRandom();
return AIObject::DoCommand(tile, (::InteractiveRandomRange(::GetIndustrySpec(industry_type)->num_table) << 16) | industry_type, seed, CMD_BUILD_INDUSTRY);
}
/* static */ bool AIIndustryType::ProspectIndustry(IndustryType industry_type)
{
EnforcePrecondition(false, CanProspectIndustry(industry_type));
uint32 seed = ::InteractiveRandom();
return AIObject::DoCommand(0, industry_type, seed, CMD_BUILD_INDUSTRY);
}

View File

@@ -0,0 +1,114 @@
/* $Id$ */
/** @file ai_industrytype.hpp Everything to query and build industries. */
#ifndef AI_INDUSTRYTYPE_HPP
#define AI_INDUSTRYTYPE_HPP
#include "ai_object.hpp"
#include "ai_error.hpp"
#include "ai_list.hpp"
/**
* Class that handles all industry-type related functions.
*/
class AIIndustryType : public AIObject {
public:
static const char *GetClassName() { return "AIIndustryType"; }
/**
* Checks whether the given industry-type is valid.
* @param industry_type The type check.
* @return True if and only if the industry-type is valid.
*/
static bool IsValidIndustryType(IndustryType industry_type);
/**
* Get the name of an industry-type.
* @param industry_type The type to get the name for.
* @pre IsValidIndustryType(industry_type).
* @return The name of an industry.
*/
static const char *GetName(IndustryType industry_type);
/**
* Get a list of CargoID possible produced by this industry-type.
* @param industry_type The type to get the CargoIDs for.
* @pre IsValidIndustryType(industry_type).
* @return The CargoIDs of all cargotypes this industry could produce.
*/
static AIList *GetProducedCargo(IndustryType industry_type);
/**
* Get a list of CargoID accepted by this industry-type.
* @param industry_type The type to get the CargoIDs for.
* @pre IsValidIndustryType(industry_type).
* @return The CargoIDs of all cargotypes this industry accepts.
*/
static AIList *GetAcceptedCargo(IndustryType industry_type);
/**
* Is this industry type a raw industry?
* @param industry_type The type of the industry.
* @pre IsValidIndustryType(industry_type).
* @return True if it should be handled as a raw industry.
*/
static bool IsRawIndustry(IndustryType industry_type);
/**
* Can the production of this industry increase?
* @param industry_type The type of the industry.
* @pre IsValidIndustryType(industry_type).
* @return True if the production of this industry can increase.
*/
static bool ProductionCanIncrease(IndustryType industry_type);
/**
* Get the cost for building this industry-type.
* @param industry_type The type of the industry.
* @pre IsValidIndustryType(industry_type).
* @return The cost for building this industry-type.
*/
static Money GetConstructionCost(IndustryType industry_type);
/**
* Can you build this type of industry?
* @param industry_type The type of the industry.
* @pre IsValidIndustryType(industry_type).
* @return True if you can prospect this type of industry.
* @note Returns false if you can only prospect this type of industry.
*/
static bool CanBuildIndustry(IndustryType industry_type);
/**
* Can you prospect this type of industry?
* @param industry_type The type of the industry.
* @pre IsValidIndustryType(industry_type).
* @return True if you can prospect this type of industry.
* @note If the patch setting "Manual primary industry construction method" is set
* to either "None" or "as other industries" this function always returns false.
*/
static bool CanProspectIndustry(IndustryType industry_type);
/**
* Build an industry of the specified type.
* @param industry_type The type of the industry to build.
* @param tile The tile to build the industry on.
* @pre CanBuildIndustry(industry_type).
* @return True if the industry was succesfully build.
*/
static bool BuildIndustry(IndustryType industry_type, TileIndex tile);
/**
* Prospect an industry of this type. Prospecting an industries let the game try to create
* an industry on a random place on the map.
* @param industry_type The type of the industry.
* @pre CanProspectIndustry(industry_type).
* @return True if no error occured while trying to prospect.
* @note Even if true is returned there is no guarantee a new industry is build.
* @note If true is returned the money is paid, whether a new industry was build or not.
*/
static bool ProspectIndustry(IndustryType industry_type);
};
#endif /* AI_INDUSTRYTYPE_HPP */

View File

@@ -0,0 +1,34 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_industrytype.hpp"
namespace SQConvert {
/* Allow AIIndustryType to be used as Squirrel parameter */
template <> AIIndustryType *GetParam(ForceType<AIIndustryType *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryType *)instance; }
template <> AIIndustryType &GetParam(ForceType<AIIndustryType &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryType *)instance; }
template <> const AIIndustryType *GetParam(ForceType<const AIIndustryType *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryType *)instance; }
template <> const AIIndustryType &GetParam(ForceType<const AIIndustryType &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryType *)instance; }
template <> int Return<AIIndustryType *>(HSQUIRRELVM vm, AIIndustryType *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIIndustryType", res, NULL, DefSQDestructorCallback<AIIndustryType>); return 1; }
}; // namespace SQConvert
void SQAIIndustryType_Register(Squirrel *engine) {
DefSQClass <AIIndustryType> SQAIIndustryType("AIIndustryType");
SQAIIndustryType.PreRegister(engine);
SQAIIndustryType.AddConstructor<void (AIIndustryType::*)(), 1>(engine, "x");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::GetClassName, "GetClassName", 1, "x");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::IsValidIndustryType, "IsValidIndustryType", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::GetName, "GetName", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::GetProducedCargo, "GetProducedCargo", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::GetAcceptedCargo, "GetAcceptedCargo", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::IsRawIndustry, "IsRawIndustry", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::ProductionCanIncrease, "ProductionCanIncrease", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::GetConstructionCost, "GetConstructionCost", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::CanBuildIndustry, "CanBuildIndustry", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::CanProspectIndustry, "CanProspectIndustry", 2, "xi");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::BuildIndustry, "BuildIndustry", 3, "xii");
SQAIIndustryType.DefSQStaticMethod(engine, &AIIndustryType::ProspectIndustry, "ProspectIndustry", 2, "xi");
SQAIIndustryType.PostRegister(engine);
}

View File

@@ -0,0 +1,15 @@
/* $Id$ */
/** @file ai_industrytypelist.cpp Implementation of AIIndustryTypeList. */
#include "ai_industrytypelist.hpp"
#include "../../openttd.h"
#include "../../tile_type.h"
#include "../../industry.h"
AIIndustryTypeList::AIIndustryTypeList()
{
for (int i = 0; i < NUM_INDUSTRYTYPES; i++) {
if (AIIndustryType::IsValidIndustryType(i)) this->AddItem(i);
}
}

View File

@@ -0,0 +1,22 @@
/* $Id$ */
/** @file ai_industrytypelist.hpp List all available industry types. */
#ifndef AI_INDUSTRYTYPELIST_HPP
#define AI_INDUSTRYTYPELIST_HPP
#include "ai_abstractlist.hpp"
#include "ai_industrytype.hpp"
/**
* Creates a list of valid industry types.
* @ingroup AIList
*/
class AIIndustryTypeList : public AIAbstractList {
public:
static const char *GetClassName() { return "AIIndustryTypeList"; }
AIIndustryTypeList();
};
#endif /* AI_INDUSTRYTYPELIST_HPP */

View File

@@ -0,0 +1,23 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_industrytypelist.hpp"
namespace SQConvert {
/* Allow AIIndustryTypeList to be used as Squirrel parameter */
template <> AIIndustryTypeList *GetParam(ForceType<AIIndustryTypeList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryTypeList *)instance; }
template <> AIIndustryTypeList &GetParam(ForceType<AIIndustryTypeList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryTypeList *)instance; }
template <> const AIIndustryTypeList *GetParam(ForceType<const AIIndustryTypeList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIIndustryTypeList *)instance; }
template <> const AIIndustryTypeList &GetParam(ForceType<const AIIndustryTypeList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIIndustryTypeList *)instance; }
template <> int Return<AIIndustryTypeList *>(HSQUIRRELVM vm, AIIndustryTypeList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIIndustryTypeList", res, NULL, DefSQDestructorCallback<AIIndustryTypeList>); return 1; }
}; // namespace SQConvert
void SQAIIndustryTypeList_Register(Squirrel *engine) {
DefSQClass <AIIndustryTypeList> SQAIIndustryTypeList("AIIndustryTypeList");
SQAIIndustryTypeList.PreRegister(engine, "AIAbstractList");
SQAIIndustryTypeList.AddConstructor<void (AIIndustryTypeList::*)(), 1>(engine, "x");
SQAIIndustryTypeList.DefSQStaticMethod(engine, &AIIndustryTypeList::GetClassName, "GetClassName", 1, "x");
SQAIIndustryTypeList.PostRegister(engine);
}

45
src/ai/api/ai_list.cpp Normal file
View File

@@ -0,0 +1,45 @@
/* $Id$ */
/** @file ai_list.cpp Implementation of AIList. */
#include <squirrel.h>
#include "ai_list.hpp"
void AIList::AddItem(int32 item, int32 value)
{
AIAbstractList::AddItem(item);
this->SetValue(item, value);
}
void AIList::ChangeItem(int32 item, int32 value)
{
this->SetValue(item, value);
}
void AIList::RemoveItem(int32 item)
{
AIAbstractList::RemoveItem(item);
}
SQInteger AIList::_set(HSQUIRRELVM vm) {
if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR;
if (sq_gettype(vm, 3) != OT_INTEGER || sq_gettype(vm, 3) == OT_NULL) {
return sq_throwerror(vm, _SC("you can only assign integers to this list"));
}
SQInteger idx, val;
sq_getinteger(vm, 2, &idx);
if (sq_gettype(vm, 3) == OT_NULL) {
this->RemoveItem(idx);
return 0;
}
sq_getinteger(vm, 3, &val);
if (!this->HasItem(idx)) {
this->AddItem(idx, val);
return 0;
}
this->ChangeItem(idx, val);
return 0;
}

47
src/ai/api/ai_list.hpp Normal file
View File

@@ -0,0 +1,47 @@
/* $Id$ */
/** @file ai_list.hpp List custom entries. */
#ifndef AI_LIST_HPP
#define AI_LIST_HPP
#include "ai_abstractlist.hpp"
/**
* Creates an empty list, in which you can add integers.
* @ingroup AIList
*/
class AIList : public AIAbstractList {
public:
static const char *GetClassName() { return "AIList"; }
public:
/**
* Add an item to the list.
* @param item the item to add.
* @param value the value to assign.
*/
void AddItem(int32 item, int32 value);
/**
* Change the value of an item in the list.
* @param item the item to change
* @param value the value to assign.
*/
void ChangeItem(int32 item, int32 value);
/**
* Remove the item from the list.
* @param item the item to remove.
*/
void RemoveItem(int32 item);
#ifndef DOXYGEN_SKIP
/**
* Used for [] set from Squirrel.
*/
SQInteger _set(HSQUIRRELVM vm);
#endif /* DOXYGEN_SKIP */
};
#endif /* AI_LIST_HPP */

28
src/ai/api/ai_list.hpp.sq Normal file
View File

@@ -0,0 +1,28 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_list.hpp"
namespace SQConvert {
/* Allow AIList to be used as Squirrel parameter */
template <> AIList *GetParam(ForceType<AIList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIList *)instance; }
template <> AIList &GetParam(ForceType<AIList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIList *)instance; }
template <> const AIList *GetParam(ForceType<const AIList *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIList *)instance; }
template <> const AIList &GetParam(ForceType<const AIList &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIList *)instance; }
template <> int Return<AIList *>(HSQUIRRELVM vm, AIList *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIList", res, NULL, DefSQDestructorCallback<AIList>); return 1; }
}; // namespace SQConvert
void SQAIList_Register(Squirrel *engine) {
DefSQClass <AIList> SQAIList("AIList");
SQAIList.PreRegister(engine, "AIAbstractList");
SQAIList.AddConstructor<void (AIList::*)(), 1>(engine, "x");
SQAIList.DefSQStaticMethod(engine, &AIList::GetClassName, "GetClassName", 1, "x");
SQAIList.DefSQMethod(engine, &AIList::AddItem, "AddItem", 3, "xii");
SQAIList.DefSQMethod(engine, &AIList::ChangeItem, "ChangeItem", 3, "xii");
SQAIList.DefSQMethod(engine, &AIList::RemoveItem, "RemoveItem", 2, "xi");
SQAIList.DefSQAdvancedMethod(engine, &AIList::_set, "_set");
SQAIList.PostRegister(engine);
}

84
src/ai/api/ai_log.cpp Normal file
View File

@@ -0,0 +1,84 @@
/* $Id$ */
/** @file ai_log.cpp Implementation of AILog. */
#include "ai_log.hpp"
#include "../../core/alloc_func.hpp"
#include "../../company_func.h"
#include "../../debug.h"
#include "../../window_func.h"
/* static */ void AILog::Info(const char *message)
{
AILog::Log(LOG_INFO, message);
}
/* static */ void AILog::Warning(const char *message)
{
AILog::Log(LOG_WARNING, message);
}
/* static */ void AILog::Error(const char *message)
{
AILog::Log(LOG_ERROR, message);
}
/* static */ void AILog::Log(AILog::AILogType level, const char *message)
{
if (AIObject::GetLogPointer() == NULL) {
AIObject::GetLogPointer() = new LogData();
LogData *log = (LogData *)AIObject::GetLogPointer();
log->lines = CallocT<char *>(80);
log->type = CallocT<AILog::AILogType>(80);
log->count = 80;
log->pos = log->count;
log->used = 0;
}
LogData *log = (LogData *)AIObject::GetLogPointer();
/* Go to the next log-line */
log->pos = (log->pos + 1) % log->count;
if (log->used != log->count) log->used++;
/* Free last message, and write new message */
free(log->lines[log->pos]);
log->lines[log->pos] = strdup(message);
log->type[log->pos] = level;
/* Cut string after first \n */
char *p;
while ((p = strchr(log->lines[log->pos], '\n')) != NULL) {
*p = '\0';
break;
}
char logc;
switch (level) {
case LOG_SQ_ERROR: logc = 'S'; break;
case LOG_ERROR: logc = 'E'; break;
case LOG_SQ_INFO: logc = 'P'; break;
case LOG_WARNING: logc = 'W'; break;
case LOG_INFO: logc = 'I'; break;
default: logc = '?'; break;
}
/* Also still print to debug window */
DEBUG(ai, level, "[%d] [%c] %s", (uint)_current_company, logc, log->lines[log->pos]);
InvalidateWindowData(WC_AI_DEBUG, 0, _current_company);
}
/* static */ void AILog::FreeLogPointer()
{
LogData *log = (LogData *)AIObject::GetLogPointer();
for (int i = 0; i < log->count; i++) {
free(log->lines[i]);
}
free(log->lines);
free(log->type);
delete log;
}

76
src/ai/api/ai_log.hpp Normal file
View File

@@ -0,0 +1,76 @@
/* $Id$ */
/** @file ai_log.hpp Everything to handle and issue log messages. */
#ifndef AI_LOG_HPP
#define AI_LOG_HPP
#include "ai_object.hpp"
/**
* Class that handles all log related functions.
*/
class AILog : public AIObject {
/* AIController needs access to Enum and Log, in order to keep the flow from
* OpenTTD core to NoAI API clear and simple. */
friend class AIController;
public:
static const char *GetClassName() { return "AILog"; }
/**
* Log levels; The value is also feed to DEBUG() lvl.
* This has no use for you, as AI writer.
*/
enum AILogType {
LOG_SQ_ERROR = 0, //!< Squirrel printed an error.
LOG_ERROR = 1, //!< User printed an error.
LOG_SQ_INFO = 2, //!< Squirrel printed some info.
LOG_WARNING = 3, //!< User printed some warning.
LOG_INFO = 4, //!< User printed some info.
};
/**
* Internal representation of the log-data inside the AI.
* This has no use for you, as AI writer.
*/
struct LogData {
char **lines; //!< The log-lines.
AILog::AILogType *type; //!< Per line, which type of log it was.
int count; //!< Total amount of log-lines possible.
int pos; //!< Current position in lines.
int used; //!< Total amount of used log-lines.
};
/**
* Print an Info message to the logs.
* @param message The message to log.
*/
static void Info(const char *message);
/**
* Print a Warning message to the logs.
* @param message The message to log.
*/
static void Warning(const char *message);
/**
* Print an Error message to the logs.
* @param message The message to log.
*/
static void Error(const char *message);
/**
* Free the log pointer.
* @note DO NOT CALL YOURSELF; leave it to the internal AI programming.
*/
static void FreeLogPointer();
private:
/**
* Internal command to log the message in a common way.
*/
static void Log(AILog::AILogType level, const char *message);
};
#endif /* AI_LOG_HPP */

37
src/ai/api/ai_log.hpp.sq Normal file
View File

@@ -0,0 +1,37 @@
/* $Id$ */
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
#include "ai_log.hpp"
namespace SQConvert {
/* Allow enums to be used as Squirrel parameters */
template <> AILog::AILogType GetParam(ForceType<AILog::AILogType>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AILog::AILogType)tmp; }
template <> int Return<AILog::AILogType>(HSQUIRRELVM vm, AILog::AILogType res) { sq_pushinteger(vm, (int32)res); return 1; }
/* Allow AILog to be used as Squirrel parameter */
template <> AILog *GetParam(ForceType<AILog *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AILog *)instance; }
template <> AILog &GetParam(ForceType<AILog &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AILog *)instance; }
template <> const AILog *GetParam(ForceType<const AILog *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AILog *)instance; }
template <> const AILog &GetParam(ForceType<const AILog &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AILog *)instance; }
template <> int Return<AILog *>(HSQUIRRELVM vm, AILog *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AILog", res, NULL, DefSQDestructorCallback<AILog>); return 1; }
}; // namespace SQConvert
void SQAILog_Register(Squirrel *engine) {
DefSQClass <AILog> SQAILog("AILog");
SQAILog.PreRegister(engine);
SQAILog.AddConstructor<void (AILog::*)(), 1>(engine, "x");
SQAILog.DefSQConst(engine, AILog::LOG_SQ_ERROR, "LOG_SQ_ERROR");
SQAILog.DefSQConst(engine, AILog::LOG_ERROR, "LOG_ERROR");
SQAILog.DefSQConst(engine, AILog::LOG_SQ_INFO, "LOG_SQ_INFO");
SQAILog.DefSQConst(engine, AILog::LOG_WARNING, "LOG_WARNING");
SQAILog.DefSQConst(engine, AILog::LOG_INFO, "LOG_INFO");
SQAILog.DefSQStaticMethod(engine, &AILog::GetClassName, "GetClassName", 1, "x");
SQAILog.DefSQStaticMethod(engine, &AILog::Info, "Info", 2, "xs");
SQAILog.DefSQStaticMethod(engine, &AILog::Warning, "Warning", 2, "xs");
SQAILog.DefSQStaticMethod(engine, &AILog::Error, "Error", 2, "xs");
SQAILog.DefSQStaticMethod(engine, &AILog::FreeLogPointer, "FreeLogPointer", 1, "x");
SQAILog.PostRegister(engine);
}

62
src/ai/api/ai_map.cpp Normal file
View File

@@ -0,0 +1,62 @@
/* $Id$ */
/** @file ai_map.cpp Implementation of AIMap. */
#include "ai_map.hpp"
#include "../../map_func.h"
#include "../../tile_map.h"
/* static */ bool AIMap::IsValidTile(TileIndex t)
{
return ::IsValidTile(t);
}
/* static */ TileIndex AIMap::GetMapSize()
{
return ::MapSize();
}
/* static */ uint32 AIMap::GetMapSizeX()
{
return ::MapSizeX();
}
/* static */ uint32 AIMap::GetMapSizeY()
{
return ::MapSizeY();
}
/* static */ uint32 AIMap::GetTileX(TileIndex t)
{
return ::TileX(t);
}
/* static */ uint32 AIMap::GetTileY(TileIndex t)
{
return ::TileY(t);
}
/* static */ TileIndex AIMap::GetTileIndex(uint32 x, uint32 y)
{
return ::TileXY(x, y);
}
/* static */ uint32 AIMap::DistanceManhattan(TileIndex t1, TileIndex t2)
{
return ::DistanceManhattan(t1, t2);
}
/* static */ uint32 AIMap::DistanceMax(TileIndex t1, TileIndex t2)
{
return ::DistanceMax(t1, t2);
}
/* static */ uint32 AIMap::DistanceSquare(TileIndex t1, TileIndex t2)
{
return ::DistanceSquare(t1, t2);
}
/* static */ uint32 AIMap::DistanceFromEdge(TileIndex t)
{
return ::DistanceFromEdge(t);
}

117
src/ai/api/ai_map.hpp Normal file
View File

@@ -0,0 +1,117 @@
/* $Id$ */
/** @file ai_map.hpp Everything to query and manipulate map metadata. */
#ifndef AI_MAP_HPP
#define AI_MAP_HPP
#include "ai_object.hpp"
/**
* Class that handles all map related functions.
*/
class AIMap : public AIObject {
public:
static const char *GetClassName() { return "AIMap"; }
/**
* Checks whether the given tile is valid.
* @param tile The tile to check.
* @return True is the tile it within the boundaries of the map.
*/
static bool IsValidTile(TileIndex tile);
/**
* Gets the number of tiles in the map.
* @return The size of the map in tiles.
* @post Return value is always positive.
*/
static TileIndex GetMapSize();
/**
* Gets the amount of tiles along the SW and NE border.
* @return The length along the SW and NE borders.
* @post Return value is always positive.
*/
static uint32 GetMapSizeX();
/**
* Gets the amount of tiles along the SE and NW border.
* @return The length along the SE and NW borders.
* @post Return value is always positive.
*/
static uint32 GetMapSizeY();
/**
* Gets the place along the SW/NE border (X-value).
* @param tile The tile to get the X-value of.
* @pre IsValidTile(tile).
* @return The X-value.
* @post Return value is always lower than GetMapSizeX().
*/
static uint32 GetTileX(TileIndex tile);
/**
* Gets the place along the SE/NW border (Y-value).
* @param tile The tile to get the Y-value of.
* @pre IsValidTile(tile).
* @return The Y-value.
* @post Return value is always lower than GetMapSizeY().
*/
static uint32 GetTileY(TileIndex tile);
/**
* Gets the TileIndex given a x,y-coordinate.
* @param x The X coordinate.
* @param y The Y coordinate.
* @pre x < GetMapSizeX().
* @pre y < GetMapSizeY().
* @return The TileIndex for the given (x,y) coordinate.
*/
static TileIndex GetTileIndex(uint32 x, uint32 y);
/**
* Calculates the Manhattan distance; the difference of
* the X and Y added together.
* @param tile_from The start tile.
* @param tile_to The destination tile.
* @pre IsValidTile(tile_from).
* @pre IsValidTile(tile_to).
* @return The Manhattan distance between the tiles.
*/
static uint32 DistanceManhattan(TileIndex tile_from, TileIndex tile_to);
/**
* Calculates the distance between two tiles via 1D calculation.
* This means the distance between X or the distance between Y, depending
* on which one is bigger.
* @param tile_from The start tile.
* @param tile_to The destination tile.
* @pre IsValidTile(tile_from).
* @pre IsValidTile(tile_to).
* @return The maximum distance between the tiles.
*/
static uint32 DistanceMax(TileIndex tile_from, TileIndex tile_to);
/**
* The squared distance between the two tiles.
* This is the distance is the length of the shortest straight line
* between both points.
* @param tile_from The start tile.
* @param tile_to The destination tile.
* @pre IsValidTile(tile_from).
* @pre IsValidTile(tile_to).
* @return The squared distance between the tiles.
*/
static uint32 DistanceSquare(TileIndex tile_from, TileIndex tile_to);
/**
* Calculates the shortest distance to the edge.
* @param tile From where the distance has to be calculated.
* @pre IsValidTile(tile).
* @return The distances to the closest edge.
*/
static uint32 DistanceFromEdge(TileIndex tile);
};
#endif /* AI_MAP_HPP */

Some files were not shown because too many files have changed in this diff Show More