changeset 18520:bb2c3b72ca78 draft

(svn r23364) -Codechange: refactor AIConfig, moving it mostly to Scriptconfig
author truebrain <truebrain@openttd.org>
date Tue, 29 Nov 2011 23:26:35 +0000
parents dfcc8f8b1ce0
children 5812df52b5a1
files projects/openttd_vs100.vcxproj projects/openttd_vs100.vcxproj.filters projects/openttd_vs80.vcproj projects/openttd_vs90.vcproj source.list src/ai/ai_config.cpp src/ai/ai_config.hpp src/ai/ai_core.cpp src/ai/ai_gui.cpp src/ai/ai_info.cpp src/ai/ai_info.hpp src/ai/ai_instance.cpp src/ai/api/ai_changelog.hpp src/console_cmds.cpp src/saveload/ai_sl.cpp src/script/api/script_controller.cpp src/script/script_config.cpp src/script/script_config.hpp src/script/script_info.cpp src/script/script_info.hpp src/settings.cpp
diffstat 21 files changed, 817 insertions(+), 645 deletions(-) [+]
line wrap: on
line diff
--- a/projects/openttd_vs100.vcxproj
+++ b/projects/openttd_vs100.vcxproj
@@ -788,6 +788,8 @@
     <ClInclude Include="..\src\table\water_land.h" />
     <ClCompile Include="..\src\3rdparty\md5\md5.cpp" />
     <ClInclude Include="..\src\3rdparty\md5\md5.h" />
+    <ClCompile Include="..\src\script\script_config.cpp" />
+    <ClInclude Include="..\src\script\script_config.hpp" />
     <ClInclude Include="..\src\script\script_fatalerror.hpp" />
     <ClCompile Include="..\src\script\script_info.cpp" />
     <ClInclude Include="..\src\script\script_info.hpp" />
--- a/projects/openttd_vs100.vcxproj.filters
+++ b/projects/openttd_vs100.vcxproj.filters
@@ -1587,6 +1587,12 @@
     <ClInclude Include="..\src\3rdparty\md5\md5.h">
       <Filter>MD5</Filter>
     </ClInclude>
+    <ClCompile Include="..\src\script\script_config.cpp">
+      <Filter>Script</Filter>
+    </ClCompile>
+    <ClInclude Include="..\src\script\script_config.hpp">
+      <Filter>Script</Filter>
+    </ClInclude>
     <ClInclude Include="..\src\script\script_fatalerror.hpp">
       <Filter>Script</Filter>
     </ClInclude>
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -2459,6 +2459,14 @@
 			Name="Script"
 			>
 			<File
+				RelativePath=".\..\src\script\script_config.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\script\script_config.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\script\script_fatalerror.hpp"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj
+++ b/projects/openttd_vs90.vcproj
@@ -2456,6 +2456,14 @@
 			Name="Script"
 			>
 			<File
+				RelativePath=".\..\src\script\script_config.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\script\script_config.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\script\script_fatalerror.hpp"
 				>
 			</File>
--- a/source.list
+++ b/source.list
@@ -553,6 +553,8 @@
 
 #if AI
 # Script
+script/script_config.cpp
+script/script_config.hpp
 script/script_fatalerror.hpp
 script/script_info.cpp
 script/script_info.hpp
--- a/src/ai/ai_config.cpp
+++ b/src/ai/ai_config.cpp
@@ -14,87 +14,28 @@
 #include "../core/random_func.hpp"
 #include "ai.hpp"
 #include "ai_config.hpp"
-
-void AIConfig::ChangeAI(const char *name, int version, bool force_exact_match, bool is_random_ai)
-{
-	free(this->name);
-	this->name = (name == NULL) ? NULL : strdup(name);
-	this->info = (name == NULL) ? NULL : AI::FindInfo(this->name, version, force_exact_match);
-	this->version = (info == NULL) ? -1 : info->GetVersion();
-	this->is_random_ai = is_random_ai;
-	if (this->config_list != NULL) delete this->config_list;
-	this->config_list = (info == NULL) ? NULL : new AIConfigItemList();
-	if (this->config_list != NULL) this->config_list->push_back(_start_date_config);
-
-	/* The special casing for start_date is here to ensure that the
-	 *  start_date setting won't change even if you chose another AI. */
-	int start_date = this->GetSetting("start_date");
-
-	for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
-		free((*it).first);
-	}
-	this->settings.clear();
-
-	this->SetSetting("start_date", start_date);
-
-	if (_game_mode == GM_NORMAL && this->info != NULL) {
-		/* If we're in an existing game and the AI is changed, set all settings
-		 *  for the AI that have the random flag to a random value. */
-		for (AIConfigItemList::const_iterator it = this->info->GetConfigList()->begin(); it != this->info->GetConfigList()->end(); it++) {
-			if ((*it).flags & AICONFIG_RANDOM) {
-				this->SetSetting((*it).name, InteractiveRandomRange((*it).max_value - (*it).min_value) + (*it).min_value);
-			}
-		}
-		this->AddRandomDeviation();
-	}
-}
+#include "ai_info.hpp"
 
-AIConfig::AIConfig(const AIConfig *config)
-{
-	this->name = (config->name == NULL) ? NULL : strdup(config->name);
-	this->info = config->info;
-	this->version = config->version;
-	this->config_list = NULL;
-	this->is_random_ai = config->is_random_ai;
-
-	for (SettingValueList::const_iterator it = config->settings.begin(); it != config->settings.end(); it++) {
-		this->settings[strdup((*it).first)] = (*it).second;
-	}
-	this->AddRandomDeviation();
-}
-
-AIConfig::~AIConfig()
-{
-	free(this->name);
-	this->ResetSettings();
-	if (this->config_list != NULL) delete this->config_list;
-}
+/** Configuration for AI start date, every AI has this setting. */
+ScriptConfigItem _start_date_config = {
+	"start_date",
+	"Number of days to start this AI after the previous one (give or take)",
+	AI::START_NEXT_MIN,
+	AI::START_NEXT_MAX,
+	AI::START_NEXT_MEDIUM,
+	AI::START_NEXT_EASY,
+	AI::START_NEXT_MEDIUM,
+	AI::START_NEXT_HARD,
+	AI::START_NEXT_DEVIATION,
+	30,
+	SCRIPTCONFIG_NONE,
+	NULL
+};
 
-AIInfo *AIConfig::GetInfo() const
-{
-	return this->info;
-}
-
-bool AIConfig::ResetInfo(bool force_exact_match)
-{
-	this->info = AI::FindInfo(this->name, force_exact_match ? this->version : -1, force_exact_match);
-	return this->info != NULL;
-}
-
-const AIConfigItemList *AIConfig::GetConfigList()
-{
-	if (this->info != NULL) return this->info->GetConfigList();
-	if (this->config_list == NULL) {
-		this->config_list = new AIConfigItemList();
-		this->config_list->push_back(_start_date_config);
-	}
-	return this->config_list;
-}
-
-AIConfig *AIConfig::GetConfig(CompanyID company, AISettingSource source)
+/* static */ AIConfig *AIConfig::GetConfig(CompanyID company, ScriptSettingSource source)
 {
 	AIConfig **config;
-	if (source == AISS_FORCE_NEWGAME || (source == AISS_DEFAULT && _game_mode == GM_MENU)) {
+	if (source == SSS_FORCE_NEWGAME || (source == SSS_DEFAULT && _game_mode == GM_MENU)) {
 		config = &_settings_newgame.ai_config[company];
 	} else {
 		config = &_settings_game.ai_config[company];
@@ -103,12 +44,43 @@
 	return *config;
 }
 
+class AIInfo *AIConfig::GetInfo() const
+{
+	return static_cast<class AIInfo *>(ScriptConfig::GetInfo());
+}
+
+ScriptInfo *AIConfig::FindInfo(const char *name, int version, bool force_exact_match)
+{
+	return static_cast<ScriptInfo *>(AI::FindInfo(name, version, force_exact_match));
+}
+
+bool AIConfig::ResetInfo(bool force_exact_match)
+{
+	this->info = (ScriptInfo *)AI::FindInfo(this->name, force_exact_match ? this->version : -1, force_exact_match);
+	return this->info != NULL;
+}
+
+void AIConfig::PushExtraConfigList()
+{
+	this->config_list->push_back(_start_date_config);
+}
+
+void AIConfig::ClearConfigList()
+{
+	/* The special casing for start_date is here to ensure that the
+	 *  start_date setting won't change even if you chose another Script. */
+	int start_date = this->GetSetting("start_date");
+
+	ScriptConfig::ClearConfigList();
+
+	this->SetSetting("start_date", start_date);
+}
+
 int AIConfig::GetSetting(const char *name) const
 {
-	SettingValueList::const_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() || GetGameSettings().difficulty.diff_level != 3) {
-		if (this->info == NULL) {
+	if (this->info == NULL) {
+		SettingValueList::const_iterator it = this->settings.find(name);
+		if (it == this->settings.end() || GetGameSettings().difficulty.diff_level != 3) {
 			assert(strcmp("start_date", name) == 0);
 			switch (GetGameSettings().difficulty.diff_level) {
 				case 0: return AI::START_NEXT_EASY;
@@ -118,115 +90,28 @@
 				default: NOT_REACHED();
 			}
 		}
-		return this->info->GetSettingDefaultValue(name);
+
+		return (*it).second;
 	}
-	return (*it).second;
+
+	return ScriptConfig::GetSetting(name);
 }
 
 void AIConfig::SetSetting(const char *name, int value)
 {
-	/* You can only set ai specific settings if an AI is selected. */
-	if (this->info == NULL && strcmp("start_date", name) != 0) return;
-
-	if (this->info == NULL && strcmp("start_date", name) == 0) {
+	if (this->info == NULL) {
+		if (strcmp("start_date", name) != 0) return;
 		value = Clamp(value, AI::START_NEXT_MIN, AI::START_NEXT_MAX);
-	} else {
-		const AIConfigItem *config_item = this->info->GetConfigItem(name);
-		if (config_item == NULL) return;
 
-		value = Clamp(value, config_item->min_value, config_item->max_value);
+		SettingValueList::iterator it = this->settings.find(name);
+		if (it != this->settings.end()) {
+			(*it).second = value;
+		} else {
+			this->settings[strdup(name)] = value;
+		}
+
+		return;
 	}
 
-	SettingValueList::iterator it = this->settings.find(name);
-	if (it != this->settings.end()) {
-		(*it).second = value;
-	} else {
-		this->settings[strdup(name)] = value;
-	}
-}
-
-void AIConfig::ResetSettings()
-{
-	for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
-		free((*it).first);
-	}
-	this->settings.clear();
-}
-
-void AIConfig::AddRandomDeviation()
-{
-	for (AIConfigItemList::const_iterator it = this->GetConfigList()->begin(); it != this->GetConfigList()->end(); it++) {
-		if ((*it).random_deviation != 0) {
-			this->SetSetting((*it).name, InteractiveRandomRange((*it).random_deviation * 2) - (*it).random_deviation + this->GetSetting((*it).name));
-		}
-	}
-}
-
-bool AIConfig::HasAI() const
-{
-	return this->info != NULL;
-}
-
-bool AIConfig::IsRandomAI() const
-{
-	return this->is_random_ai;
-}
-
-const char *AIConfig::GetName() const
-{
-	return this->name;
-}
-
-int AIConfig::GetVersion() const
-{
-	return this->version;
+	ScriptConfig::SetSetting(name, value);
 }
-
-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, size_t size) const
-{
-	string[0] = '\0';
-	for (SettingValueList::const_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_t needed_size = strlen((*it).first) + 1 + strlen(no) + 1;
-		/* If it doesn't fit, skip the next settings */
-		if (size <= needed_size) break;
-		size -= needed_size;
-
-		strcat(string, (*it).first);
-		strcat(string, "=");
-		strcat(string, no);
-		strcat(string, ",");
-	}
-	/* Remove the last ',', but only if at least one setting was saved. */
-	size_t len = strlen(string);
-	if (len > 0) string[len - 1] = '\0';
-}
--- a/src/ai/ai_config.hpp
+++ b/src/ai/ai_config.hpp
@@ -11,48 +11,28 @@
 
 #ifndef AI_CONFIG_HPP
 #define AI_CONFIG_HPP
-#ifdef ENABLE_AI
 
-#include <map>
-#include "ai_info.hpp"
-#include "../core/string_compare_type.hpp"
-#include "../company_type.h"
+#include "../script/script_config.hpp"
 
-/**
- * AI settings for one company slot.
- */
-class AIConfig {
-private:
-	/** List with name=>value pairs of all AI-specific settings */
-	typedef std::map<const char *, int, StringCompare> SettingValueList;
+class AIConfig : public ScriptConfig {
+public:
+	/**
+	 * Get the config of a company.
+	 */
+	static AIConfig *GetConfig(CompanyID company, ScriptSettingSource source = SSS_DEFAULT);
 
-public:
 	AIConfig() :
-		name(NULL),
-		version(-1),
-		info(NULL),
-		config_list(NULL),
-		is_random_ai(false)
+		ScriptConfig()
 	{}
 
-	/**
-	 * Create a new AI config that is a copy of an existing config.
-	 * @param config The object to copy.
-	 */
-	AIConfig(const AIConfig *config);
-
-	/** Delete an AI configuration. */
-	~AIConfig();
+	AIConfig(const AIConfig *config) :
+		ScriptConfig(config)
+	{}
 
-	/**
-	 * Set another AI to be loaded in this slot.
-	 * @param name The name of the AI.
-	 * @param version The version of the AI to load, or -1 of latest.
-	 * @param force_exact_match If true try to find the exact same version
-	 *   as specified. If false any compatible version is ok.
-	 * @param is_random Is the AI chosen randomly?
-	 */
-	void ChangeAI(const char *name, int version = -1, bool force_exact_match = false, bool is_random = false);
+	class AIInfo *GetInfo() const;
+
+	/* virtual */ int GetSetting(const char *name) const;
+	/* virtual */ void SetSetting(const char *name, int value);
 
 	/**
 	 * When ever the AI Scanner is reloaded, all infos become invalid. This
@@ -64,95 +44,10 @@
 	 */
 	bool ResetInfo(bool force_exact_match);
 
-	/**
-	 * Get the AIInfo linked to this AIConfig.
-	 */
-	class AIInfo *GetInfo() const;
-
-	/**
-	 * Get the config list for this AIConfig.
-	 */
-	const AIConfigItemList *GetConfigList();
-
-	/**
-	 * Where to get the config from, either default (depends on current game
-	 * mode) or force either newgame or normal
-	 */
-	enum AISettingSource {
-		AISS_DEFAULT,       ///< Get the AI config from the current game mode
-		AISS_FORCE_NEWGAME, ///< Get the newgame AI config
-		AISS_FORCE_GAME,    ///< Get the AI config from the current game
-	};
-
-	/**
-	 * Get the config of a company.
-	 */
-	static AIConfig *GetConfig(CompanyID company, AISettingSource source = AISS_DEFAULT);
-
-	/**
-	 * 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) const;
-
-	/**
-	 * Set the value of a setting for this config.
-	 */
-	void SetSetting(const char *name, int value);
-
-	/**
-	 * Reset all settings to their default value.
-	 */
-	void ResetSettings();
-
-	/**
-	 * Randomize all settings the AI requested to be randomized.
-	 */
-	void AddRandomDeviation();
-
-	/**
-	 * Is this config attached to an AI?
-	 */
-	bool HasAI() const;
-
-	/**
-	 * Is the current AI a randomly chosen AI?
-	 */
-	bool IsRandomAI() const;
-
-	/**
-	 * Get the name of the AI.
-	 */
-	const char *GetName() const;
-
-	/**
-	 * Get the version of the AI.
-	 */
-	int GetVersion() const;
-
-	/**
-	 * 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, size_t size) const;
-
-private:
-	const char *name;              ///< Name of the AI
-	int version;                   ///< Version of the AI
-	class AIInfo *info;            ///< AIInfo object for related to this AI version
-	SettingValueList settings;     ///< List with all setting=>value pairs that are configure for this AI
-	AIConfigItemList *config_list; ///< List with all settings defined by this AI
-	bool is_random_ai;             ///< True if the AI in this slot was randomly chosen.
+protected:
+	/* virtual */ void PushExtraConfigList();
+	/* virtual */ void ClearConfigList();
+	/* virtual */ ScriptInfo *FindInfo(const char *name, int version, bool force_exact_match);
 };
 
-#endif /* ENABLE_AI */
 #endif /* AI_CONFIG_HPP */
--- a/src/ai/ai_core.cpp
+++ b/src/ai/ai_core.cpp
@@ -21,6 +21,7 @@
 #include "ai_scanner.hpp"
 #include "ai_instance.hpp"
 #include "ai_config.hpp"
+#include "ai_info.hpp"
 #include "ai.hpp"
 #include "../script/api/script_error.hpp"
 
@@ -43,11 +44,11 @@
 
 	AIConfig *config = AIConfig::GetConfig(company);
 	AIInfo *info = config->GetInfo();
-	if (info == NULL || (rerandomise_ai && config->IsRandomAI())) {
+	if (info == NULL || (rerandomise_ai && config->IsRandom())) {
 		info = AI::scanner_info->SelectRandomAI();
 		assert(info != NULL);
 		/* Load default data and store the name in the settings */
-		config->ChangeAI(info->GetName(), -1, false, true);
+		config->Change(info->GetName(), -1, false, true);
 	}
 
 	Backup<CompanyByte> cur_company(_current_company, company, FILE_LINE);
@@ -181,10 +182,10 @@
 	 *  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] != NULL && _settings_game.ai_config[c]->HasScript()) {
 			if (!_settings_game.ai_config[c]->ResetInfo(true)) {
 				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);
+				_settings_game.ai_config[c]->Change(NULL);
 				if (Company::IsValidAiID(c)) {
 					/* The code belonging to an already running AI was deleted. We can only do
 					 * one thing here to keep everything sane and that is kill the AI. After
@@ -198,10 +199,10 @@
 				Company::Get(c)->ai_info = _settings_game.ai_config[c]->GetInfo();
 			}
 		}
-		if (_settings_newgame.ai_config[c] != NULL && _settings_newgame.ai_config[c]->HasAI()) {
+		if (_settings_newgame.ai_config[c] != NULL && _settings_newgame.ai_config[c]->HasScript()) {
 			if (!_settings_newgame.ai_config[c]->ResetInfo(false)) {
 				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);
+				_settings_newgame.ai_config[c]->Change(NULL);
 			}
 		}
 	}
--- a/src/ai/ai_gui.cpp
+++ b/src/ai/ai_gui.cpp
@@ -28,6 +28,7 @@
 #include "ai.hpp"
 #include "../script/api/script_log.hpp"
 #include "ai_config.hpp"
+#include "ai_info.hpp"
 #include "ai_instance.hpp"
 
 #include "table/strings.h"
@@ -71,7 +72,7 @@
 
 		/* Try if we can find the currently selected AI */
 		this->selected = -1;
-		if (AIConfig::GetConfig(slot)->HasAI()) {
+		if (AIConfig::GetConfig(slot)->HasScript()) {
 			AIInfo *info = AIConfig::GetConfig(slot)->GetInfo();
 			int i = 0;
 			for (ScriptInfoList::const_iterator it = this->ai_info_list->begin(); it != this->ai_info_list->end(); it++, i++) {
@@ -148,11 +149,11 @@
 	void ChangeAI()
 	{
 		if (this->selected == -1) {
-			AIConfig::GetConfig(slot)->ChangeAI(NULL);
+			AIConfig::GetConfig(slot)->Change(NULL);
 		} else {
 			ScriptInfoList::const_iterator it = this->ai_info_list->begin();
 			for (int i = 0; i < this->selected; i++) it++;
-			AIConfig::GetConfig(slot)->ChangeAI((*it).second->GetName(), (*it).second->GetVersion());
+			AIConfig::GetConfig(slot)->Change((*it).second->GetName(), (*it).second->GetVersion());
 		}
 		SetWindowDirty(WC_GAME_OPTIONS, 0);
 	}
@@ -272,7 +273,7 @@
 	int clicked_row;                      ///< The clicked row of settings.
 	int line_height;                      ///< Height of a row in the matrix widget.
 	Scrollbar *vscroll;                   ///< Cache of the vertical scrollbar.
-	typedef std::vector<const AIConfigItem *> VisibleSettingsList;
+	typedef std::vector<const ScriptConfigItem *> VisibleSettingsList;
 	VisibleSettingsList visible_settings; ///< List of visible AI settings
 
 	/**
@@ -306,9 +307,9 @@
 	{
 		visible_settings.clear();
 
-		AIConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
+		ScriptConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
 		for (; it != this->ai_config->GetConfigList()->end(); it++) {
-			bool no_hide = (it->flags & AICONFIG_AI_DEVELOPER) == 0;
+			bool no_hide = (it->flags & SCRIPTCONFIG_DEVELOPER) == 0;
 			if (no_hide || _settings_client.gui.ai_developer_tools) {
 				visible_settings.push_back(&(*it));
 			}
@@ -343,9 +344,9 @@
 
 		int y = r.top;
 		for (; this->vscroll->IsVisible(i) && it != visible_settings.end(); i++, it++) {
-			const AIConfigItem &config_item = **it;
+			const ScriptConfigItem &config_item = **it;
 			int current_value = config->GetSetting((config_item).name);
-			bool editable = _game_mode == GM_MENU || !Company::IsValidID(this->slot) || (config_item.flags & AICONFIG_INGAME) != 0;
+			bool editable = _game_mode == GM_MENU || !Company::IsValidID(this->slot) || (config_item.flags & SCRIPTCONFIG_INGAME) != 0;
 
 			StringID str;
 			TextColour colour;
@@ -359,7 +360,7 @@
 				SetDParamStr(idx++, config_item.description);
 			}
 
-			if ((config_item.flags & AICONFIG_BOOLEAN) != 0) {
+			if ((config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0) {
 				DrawFrameRect(buttons_left, y  + 2, buttons_left + 19, y + 10, (current_value != 0) ? COLOUR_GREEN : COLOUR_RED, (current_value != 0) ? FR_LOWERED : FR_NONE);
 				SetDParam(idx++, current_value == 0 ? STR_CONFIG_SETTING_OFF : STR_CONFIG_SETTING_ON);
 			} else {
@@ -403,10 +404,10 @@
 
 				VisibleSettingsList::const_iterator it = this->visible_settings.begin();
 				for (int i = 0; i < num; i++) it++;
-				const AIConfigItem config_item = **it;
-				if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot) && (config_item.flags & AICONFIG_INGAME) == 0) return;
+				const ScriptConfigItem config_item = **it;
+				if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
 
-				bool bool_item = (config_item.flags & AICONFIG_BOOLEAN) != 0;
+				bool bool_item = (config_item.flags & SCRIPTCONFIG_BOOLEAN) != 0;
 
 				int x = pt.x - wid->pos_x;
 				if (_current_text_dir == TD_RTL) x = wid->current_x - x;
@@ -462,9 +463,9 @@
 	virtual void OnQueryTextFinished(char *str)
 	{
 		if (StrEmpty(str)) return;
-		AIConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
+		ScriptConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
 		for (int i = 0; i < this->clicked_row; i++) it++;
-		if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot) && (it->flags & AICONFIG_INGAME) == 0) return;
+		if (_game_mode == GM_NORMAL && Company::IsValidID(this->slot) && (it->flags & SCRIPTCONFIG_INGAME) == 0) return;
 		int32 value = atoi(str);
 		this->ai_config->SetSetting((*it).name, value);
 		this->CheckDifficultyLevel();
--- a/src/ai/ai_info.cpp
+++ b/src/ai/ai_info.cpp
@@ -23,22 +23,6 @@
 /** Maximum number of operations allowed for getting a particular setting. */
 static const int MAX_GET_SETTING_OPS = 100000;
 
-/** Configuration for AI start date, every AI has this setting. */
-AIConfigItem _start_date_config = {
-	"start_date",
-	"Number of days to start this AI after the previous one (give or take)",
-	AI::START_NEXT_MIN,
-	AI::START_NEXT_MAX,
-	AI::START_NEXT_MEDIUM,
-	AI::START_NEXT_EASY,
-	AI::START_NEXT_MEDIUM,
-	AI::START_NEXT_HARD,
-	AI::START_NEXT_DEVIATION,
-	30,
-	AICONFIG_NONE,
-	NULL
-};
-
 /**
  * Check if the API version provided by the AI is supported.
  * @param api_version The API version as provided by the AI.
@@ -61,11 +45,18 @@
 	SQAIInfo.AddConstructor<void (AIInfo::*)(), 1>(engine, "x");
 	SQAIInfo.DefSQAdvancedMethod(engine, &AIInfo::AddSetting, "AddSetting");
 	SQAIInfo.DefSQAdvancedMethod(engine, &AIInfo::AddLabels, "AddLabels");
-	SQAIInfo.DefSQConst(engine, AICONFIG_NONE, "AICONFIG_NONE");
-	SQAIInfo.DefSQConst(engine, AICONFIG_RANDOM, "AICONFIG_RANDOM");
-	SQAIInfo.DefSQConst(engine, AICONFIG_BOOLEAN, "AICONFIG_BOOLEAN");
-	SQAIInfo.DefSQConst(engine, AICONFIG_INGAME, "AICONFIG_INGAME");
-	SQAIInfo.DefSQConst(engine, AICONFIG_AI_DEVELOPER, "AICONFIG_AI_DEVELOPER");
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_NONE, "CONFIG_NONE");
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_RANDOM, "CONFIG_RANDOM");
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_BOOLEAN, "CONFIG_BOOLEAN");
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_INGAME, "CONFIG_INGAME");
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_DEVELOPER, "CONFIG_DEVELOPER");
+
+	/* Pre 1.2 had an AI prefix */
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_NONE, "AICONFIG_NONE");
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_RANDOM, "AICONFIG_RANDOM");
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_BOOLEAN, "AICONFIG_BOOLEAN");
+	SQAIInfo.DefSQConst(engine, SCRIPTCONFIG_INGAME, "AICONFIG_INGAME");
+
 	SQAIInfo.PostRegister(engine);
 	engine->AddMethod("RegisterAI", &AIInfo::Constructor, 2, "tx");
 	engine->AddMethod("RegisterDummyAI", &AIInfo::DummyConstructor, 2, "tx");
@@ -81,15 +72,11 @@
 	SQInteger res = ScriptInfo::Constructor(vm, info);
 	if (res != 0) return res;
 
-	AIConfigItem config = _start_date_config;
+	ScriptConfigItem config = _start_date_config;
 	config.name = strdup(config.name);
 	config.description = strdup(config.description);
-	info->config_list.push_back(config);
+	info->config_list.push_front(config);
 
-	/* Check if we have settings */
-	if (info->engine->MethodExists(*info->SQ_instance, "GetSettings")) {
-		if (!info->GetSettings()) return SQ_ERROR;
-	}
 	if (info->engine->MethodExists(*info->SQ_instance, "MinVersionToLoad")) {
 		if (!info->engine->CallIntegerMethod(*info->SQ_instance, "MinVersionToLoad", &info->min_loadable_version, MAX_GET_SETTING_OPS)) return SQ_ERROR;
 	} else {
@@ -141,11 +128,6 @@
 	return 0;
 }
 
-bool AIInfo::GetSettings()
-{
-	return this->engine->CallMethod(*this->SQ_instance, "GetSettings", NULL, MAX_GET_SETTING_OPS);
-}
-
 AIInfo::AIInfo() :
 	min_loadable_version(0),
 	use_as_random(false),
@@ -155,18 +137,6 @@
 
 AIInfo::~AIInfo()
 {
-	/* Free all allocated strings */
-	for (AIConfigItemList::iterator it = this->config_list.begin(); it != this->config_list.end(); it++) {
-		free((*it).name);
-		free((*it).description);
-		if (it->labels != NULL) {
-			for (LabelMapping::iterator it2 = (*it).labels->Begin(); it2 != (*it).labels->End(); it2++) {
-				free(it2->second);
-			}
-			delete it->labels;
-		}
-	}
-	this->config_list.clear();
 	free(this->api_version);
 }
 
@@ -176,191 +146,6 @@
 	return version >= this->min_loadable_version && version <= this->GetVersion();
 }
 
-SQInteger AIInfo::AddSetting(HSQUIRRELVM vm)
-{
-	AIConfigItem config;
-	memset(&config, 0, sizeof(config));
-	config.max_value = 1;
-	config.step_size = 1;
-	uint 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;
-		if (SQ_FAILED(sq_getstring(vm, -2, &sqkey))) return SQ_ERROR;
-		const char *key = SQ2OTTD(sqkey);
-
-		if (strcmp(key, "name") == 0) {
-			const SQChar *sqvalue;
-			if (SQ_FAILED(sq_getstring(vm, -1, &sqvalue))) return SQ_ERROR;
-			char *name = strdup(SQ2OTTD(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 = strchr(name, '=')) != NULL) *s = '_';
-			while ((s = strchr(name, ',')) != NULL) *s = '_';
-			config.name = name;
-			items |= 0x001;
-		} else if (strcmp(key, "description") == 0) {
-			const SQChar *sqdescription;
-			if (SQ_FAILED(sq_getstring(vm, -1, &sqdescription))) return SQ_ERROR;
-			config.description = strdup(SQ2OTTD(sqdescription));
-			items |= 0x002;
-		} else if (strcmp(key, "min_value") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			config.min_value = res;
-			items |= 0x004;
-		} else if (strcmp(key, "max_value") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			config.max_value = res;
-			items |= 0x008;
-		} else if (strcmp(key, "easy_value") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			config.easy_value = res;
-			items |= 0x010;
-		} else if (strcmp(key, "medium_value") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			config.medium_value = res;
-			items |= 0x020;
-		} else if (strcmp(key, "hard_value") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			config.hard_value = res;
-			items |= 0x040;
-		} else if (strcmp(key, "random_deviation") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			config.random_deviation = res;
-			items |= 0x200;
-		} else if (strcmp(key, "custom_value") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			config.custom_value = res;
-			items |= 0x080;
-		} else if (strcmp(key, "step_size") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			config.step_size = res;
-		} else if (strcmp(key, "flags") == 0) {
-			SQInteger res;
-			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
-			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);
-
-	/* Don't allow both random_deviation and AICONFIG_RANDOM to
-	 * be set for the same config item. */
-	if ((items & 0x200) != 0 && (config.flags & AICONFIG_RANDOM) != 0) {
-		char error[1024];
-		snprintf(error, sizeof(error), "Setting both random_deviation and AICONFIG_RANDOM is not allowed");
-		this->engine->ThrowError(error);
-		return SQ_ERROR;
-	}
-	/* Reset the bit for random_deviation as it's optional. */
-	items &= ~0x200;
-
-	/* Make sure all properties are defined */
-	uint mask = (config.flags & AICONFIG_BOOLEAN) ? 0x1F3 : 0x1FF;
-	if (items != mask) {
-		char error[1024];
-		snprintf(error, sizeof(error), "please define all properties of a setting (min/max not allowed for booleans)");
-		this->engine->ThrowError(error);
-		return SQ_ERROR;
-	}
-
-	this->config_list.push_back(config);
-	return 0;
-}
-
-SQInteger AIInfo::AddLabels(HSQUIRRELVM vm)
-{
-	const SQChar *sq_setting_name;
-	if (SQ_FAILED(sq_getstring(vm, -2, &sq_setting_name))) return SQ_ERROR;
-	const char *setting_name = SQ2OTTD(sq_setting_name);
-
-	AIConfigItem *config = NULL;
-	for (AIConfigItemList::iterator it = this->config_list.begin(); it != this->config_list.end(); it++) {
-		if (strcmp((*it).name, setting_name) == 0) config = &(*it);
-	}
-
-	if (config == NULL) {
-		char error[1024];
-		snprintf(error, sizeof(error), "Trying to add labels for non-defined setting '%s'", setting_name);
-		this->engine->ThrowError(error);
-		return SQ_ERROR;
-	}
-	if (config->labels != NULL) return SQ_ERROR;
-
-	config->labels = new LabelMapping;
-
-	/* Read the table and find all labels */
-	sq_pushnull(vm);
-	while (SQ_SUCCEEDED(sq_next(vm, -2))) {
-		const SQChar *sq_key;
-		const SQChar *sq_label;
-		if (SQ_FAILED(sq_getstring(vm, -2, &sq_key))) return SQ_ERROR;
-		if (SQ_FAILED(sq_getstring(vm, -1, &sq_label))) return SQ_ERROR;
-		/* Because squirrel doesn't support identifiers starting with a digit,
-		 * we skip the first character. */
-		const char *key_string = SQ2OTTD(sq_key);
-		int key = atoi(key_string + 1);
-		const char *label = SQ2OTTD(sq_label);
-
-		/* !Contains() prevents strdup from leaking. */
-		if (!config->labels->Contains(key)) config->labels->Insert(key, strdup(label));
-
-		sq_pop(vm, 2);
-	}
-	sq_pop(vm, 1);
-
-	return 0;
-}
-
-const AIConfigItemList *AIInfo::GetConfigList() const
-{
-	return &this->config_list;
-}
-
-const AIConfigItem *AIInfo::GetConfigItem(const char *name) const
-{
-	for (AIConfigItemList::const_iterator it = this->config_list.begin(); it != this->config_list.end(); it++) {
-		if (strcmp((*it).name, name) == 0) return &(*it);
-	}
-	return NULL;
-}
-
-int AIInfo::GetSettingDefaultValue(const char *name) const
-{
-	for (AIConfigItemList::const_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 (GetGameSettings().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;
-}
-
 
 AILibrary::~AILibrary()
 {
--- a/src/ai/ai_info.hpp
+++ b/src/ai/ai_info.hpp
@@ -14,40 +14,8 @@
 
 #ifdef ENABLE_AI
 
-#include <list>
-#include "../core/smallmap_type.hpp"
 #include "../script/script_info.hpp"
-
-/** Bitmask of flags for AI settings. */
-enum AIConfigFlags {
-	AICONFIG_NONE         = 0x0, ///< No flags set.
-	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) ).
-	AICONFIG_INGAME       = 0x4, ///< This setting can be changed while the AI is running.
-	AICONFIG_AI_DEVELOPER = 0x8, ///< This setting will only be visible when the ai development tools are active.
-};
-
-typedef SmallMap<int, char *> LabelMapping; ///< Map-type used to map the setting numbers to labels.
-
-/** Info about a single AI setting. */
-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.
-	int random_deviation;    ///< The maximum random deviation from the default value.
-	int step_size;           ///< The step size in the gui.
-	AIConfigFlags flags;     ///< Flags for the configuration setting.
-	LabelMapping *labels;    ///< Text labels for the integer values.
-};
-
-extern AIConfigItem _start_date_config;
-
-typedef std::list<AIConfigItem> AIConfigItemList; ///< List of AIConfig items.
+#include "../script/script_config.hpp"
 
 /** All static information from an AI like name, version, etc. */
 class AIInfo : public ScriptInfo {
@@ -71,41 +39,11 @@
 	static SQInteger DummyConstructor(HSQUIRRELVM vm);
 
 	/**
-	 * Get the settings of the AI.
-	 */
-	bool GetSettings();
-
-	/**
-	 * Get the config list for this AI.
-	 */
-	const AIConfigItemList *GetConfigList() const;
-
-	/**
-	 * Get the description of a certain ai config option.
-	 */
-	const AIConfigItem *GetConfigItem(const char *name) const;
-
-	/**
 	 * Check if we can start this AI.
 	 */
 	bool CanLoadFromVersion(int version) const;
 
 	/**
-	 * Set a setting.
-	 */
-	SQInteger AddSetting(HSQUIRRELVM vm);
-
-	/**
-	 * Add labels for a setting.
-	 */
-	SQInteger AddLabels(HSQUIRRELVM vm);
-
-	/**
-	 * Get the default value for a setting.
-	 */
-	int GetSettingDefaultValue(const char *name) const;
-
-	/**
 	 * Use this AI as a random AI.
 	 */
 	bool UseAsRandomAI() const { return this->use_as_random; }
@@ -116,10 +54,9 @@
 	const char *GetAPIVersion() const { return this->api_version; }
 
 private:
-	AIConfigItemList config_list; ///< List of settings from this AI.
-	int min_loadable_version;     ///< The AI can load savegame data if the version is equal or greater than this.
-	bool use_as_random;           ///< Should this AI be used when the user wants a "random AI"?
-	const char *api_version;      ///< API version used by this AI.
+	int min_loadable_version; ///< The AI can load savegame data if the version is equal or greater than this.
+	bool use_as_random;       ///< Should this AI be used when the user wants a "random AI"?
+	const char *api_version;  ///< API version used by this AI.
 };
 
 /** All static information from an AI library like name, version, etc. */
--- a/src/ai/ai_instance.cpp
+++ b/src/ai/ai_instance.cpp
@@ -22,6 +22,7 @@
 #include "../script/script_fatalerror.hpp"
 #include "../script/script_suspend.hpp"
 #include "../script/script_storage.hpp"
+#include "ai_info.hpp"
 #include "ai_instance.hpp"
 
 /* Convert all AI related classes to Squirrel data.
--- a/src/ai/api/ai_changelog.hpp
+++ b/src/ai/api/ai_changelog.hpp
@@ -31,7 +31,7 @@
  * \li AICompany::GetQuarterlyPerformanceRating
  * \li AICompany::GetQuarterlyCompanyValue
  * \li AIController::GetOpsTillSuspend
- * \li AIInfo::AICONFIG_AI_DEVELOPER
+ * \li AIInfo::CONFIG_DEVELOPER
  * \li AIOrder::GetOrderRefit
  * \li AIOrder::IsRefitOrder
  * \li AIOrder::SetOrderRefit
@@ -44,7 +44,9 @@
  *
  * API renames:
  * \li AITown::GetLastMonthTransported to AITown::GetLastMonthSupplied to better
- *     reflect what it does
+ *     reflect what it does.
+ * \li AIInfo has all its configure settings renamed from AICONFIG to just CONFIG
+ *     like CONFIG_RANDOM.
  *
  * API removals:
  * \li AICompany::GetCompanyValue, use AICompany::GetQuarterlyCompanyValue instead.
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -1150,8 +1150,8 @@
 
 	AIConfig *config = AIConfig::GetConfig((CompanyID)n);
 	if (argc >= 2) {
-		config->ChangeAI(argv[1], -1, true);
-		if (!config->HasAI()) {
+		config->Change(argv[1], -1, true);
+		if (!config->HasScript()) {
 			IConsoleWarning("Failed to load the specified AI");
 			return true;
 		}
--- a/src/saveload/ai_sl.cpp
+++ b/src/saveload/ai_sl.cpp
@@ -39,7 +39,7 @@
 	CompanyID index = (CompanyID)*index_ptr;
 	AIConfig *config = AIConfig::GetConfig(index);
 
-	if (config->HasAI()) {
+	if (config->HasScript()) {
 		ttd_strlcpy(_ai_saveload_name, config->GetName(), lengthof(_ai_saveload_name));
 		_ai_saveload_version = config->GetVersion();
 	} else {
@@ -48,7 +48,7 @@
 		_ai_saveload_version = -1;
 	}
 
-	_ai_saveload_is_random = config->IsRandomAI();
+	_ai_saveload_is_random = config->IsRandom();
 	_ai_saveload_settings[0] = '\0';
 	config->SettingsToString(_ai_saveload_settings, lengthof(_ai_saveload_settings));
 
@@ -61,7 +61,7 @@
 {
 	/* Free all current data */
 	for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
-		AIConfig::GetConfig(c, AIConfig::AISS_FORCE_GAME)->ChangeAI(NULL);
+		AIConfig::GetConfig(c, AIConfig::SSS_FORCE_GAME)->Change(NULL);
 	}
 
 	CompanyID index;
@@ -76,17 +76,17 @@
 			continue;
 		}
 
-		AIConfig *config = AIConfig::GetConfig(index, AIConfig::AISS_FORCE_GAME);
+		AIConfig *config = AIConfig::GetConfig(index, AIConfig::SSS_FORCE_GAME);
 		if (StrEmpty(_ai_saveload_name)) {
 			/* A random AI. */
-			config->ChangeAI(NULL, -1, false, true);
+			config->Change(NULL, -1, false, true);
 		} else {
-			config->ChangeAI(_ai_saveload_name, _ai_saveload_version, false, _ai_saveload_is_random);
-			if (!config->HasAI()) {
+			config->Change(_ai_saveload_name, _ai_saveload_version, false, _ai_saveload_is_random);
+			if (!config->HasScript()) {
 				/* No version of the AI available that can load the data. Try to load the
 				 * latest version of the AI instead. */
-				config->ChangeAI(_ai_saveload_name, -1, false, _ai_saveload_is_random);
-				if (!config->HasAI()) {
+				config->Change(_ai_saveload_name, -1, false, _ai_saveload_is_random);
+				if (!config->HasScript()) {
 					if (strcmp(_ai_saveload_name, "%_dummy") != 0) {
 						DEBUG(ai, 0, "The savegame has an AI by the name '%s', version %d which is no longer available.", _ai_saveload_name, _ai_saveload_version);
 						DEBUG(ai, 0, "A random other AI will be loaded in its place.");
--- a/src/script/api/script_controller.cpp
+++ b/src/script/api/script_controller.cpp
@@ -21,6 +21,7 @@
 #include "../../ai/ai_config.hpp"
 #include "../../ai/ai.hpp"
 #include "../script_fatalerror.hpp"
+#include "../script_info.hpp"
 #include "../script_suspend.hpp"
 #include "script_log.hpp"
 
@@ -96,7 +97,7 @@
 	snprintf(library_name, sizeof(library_name), "%s.%d", library, version);
 	strtolower(library_name);
 
-	AILibrary *lib = AI::FindLibrary(library, version);
+	ScriptInfo *lib = (ScriptInfo *)AI::FindLibrary(library, version);
 	if (lib == NULL) {
 		char error[1024];
 		snprintf(error, sizeof(error), "couldn't find library '%s' with version %d", library, version);
new file mode 100644
--- /dev/null
+++ b/src/script/script_config.cpp
@@ -0,0 +1,201 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file script_config.cpp Implementation of ScriptConfig. */
+
+#include "../stdafx.h"
+#include "../settings_type.h"
+#include "../core/random_func.hpp"
+#include "script_info.hpp"
+#include "script_config.hpp"
+
+void ScriptConfig::Change(const char *name, int version, bool force_exact_match, bool is_random)
+{
+	free(this->name);
+	this->name = (name == NULL) ? NULL : strdup(name);
+	this->info = (name == NULL) ? NULL : this->FindInfo(this->name, version, force_exact_match);
+	this->version = (info == NULL) ? -1 : info->GetVersion();
+	this->is_random = is_random;
+	if (this->config_list != NULL) delete this->config_list;
+	this->config_list = (info == NULL) ? NULL : new ScriptConfigItemList();
+	if (this->config_list != NULL) this->PushExtraConfigList();
+
+	this->ClearConfigList();
+
+	if (_game_mode == GM_NORMAL && this->info != NULL) {
+		/* If we're in an existing game and the Script is changed, set all settings
+		 *  for the Script that have the random flag to a random value. */
+		for (ScriptConfigItemList::const_iterator it = this->info->GetConfigList()->begin(); it != this->info->GetConfigList()->end(); it++) {
+			if ((*it).flags & SCRIPTCONFIG_RANDOM) {
+				this->SetSetting((*it).name, InteractiveRandomRange((*it).max_value - (*it).min_value) + (*it).min_value);
+			}
+		}
+		this->AddRandomDeviation();
+	}
+}
+
+ScriptConfig::ScriptConfig(const ScriptConfig *config)
+{
+	this->name = (config->name == NULL) ? NULL : strdup(config->name);
+	this->info = config->info;
+	this->version = config->version;
+	this->config_list = NULL;
+	this->is_random = config->is_random;
+
+	for (SettingValueList::const_iterator it = config->settings.begin(); it != config->settings.end(); it++) {
+		this->settings[strdup((*it).first)] = (*it).second;
+	}
+	this->AddRandomDeviation();
+}
+
+ScriptConfig::~ScriptConfig()
+{
+	free(this->name);
+	this->ResetSettings();
+	if (this->config_list != NULL) delete this->config_list;
+}
+
+ScriptInfo *ScriptConfig::GetInfo() const
+{
+	return this->info;
+}
+
+const ScriptConfigItemList *ScriptConfig::GetConfigList()
+{
+	if (this->info != NULL) return this->info->GetConfigList();
+	if (this->config_list == NULL) {
+		this->config_list = new ScriptConfigItemList();
+		this->PushExtraConfigList();
+	}
+	return this->config_list;
+}
+
+void ScriptConfig::ClearConfigList()
+{
+	for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
+		free((*it).first);
+	}
+	this->settings.clear();
+}
+
+int ScriptConfig::GetSetting(const char *name) const
+{
+	/* Return default values if the difficulty is not set to Custom */
+	if (GetGameSettings().difficulty.diff_level != 3) {
+		return this->info->GetSettingDefaultValue(name);
+	}
+
+	SettingValueList::const_iterator it = this->settings.find(name);
+	if (it == this->settings.end()) return this->info->GetSettingDefaultValue(name);
+	return (*it).second;
+}
+
+void ScriptConfig::SetSetting(const char *name, int value)
+{
+	/* You can only set Script specific settings if an Script is selected. */
+	if (this->info == NULL) return;
+
+	const ScriptConfigItem *config_item = this->info->GetConfigItem(name);
+	if (config_item == NULL) return;
+
+	value = Clamp(value, config_item->min_value, config_item->max_value);
+
+	SettingValueList::iterator it = this->settings.find(name);
+	if (it != this->settings.end()) {
+		(*it).second = value;
+	} else {
+		this->settings[strdup(name)] = value;
+	}
+}
+
+void ScriptConfig::ResetSettings()
+{
+	for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
+		free((*it).first);
+	}
+	this->settings.clear();
+}
+
+void ScriptConfig::AddRandomDeviation()
+{
+	for (ScriptConfigItemList::const_iterator it = this->GetConfigList()->begin(); it != this->GetConfigList()->end(); it++) {
+		if ((*it).random_deviation != 0) {
+			this->SetSetting((*it).name, InteractiveRandomRange((*it).random_deviation * 2) - (*it).random_deviation + this->GetSetting((*it).name));
+		}
+	}
+}
+
+bool ScriptConfig::HasScript() const
+{
+	return this->info != NULL;
+}
+
+bool ScriptConfig::IsRandom() const
+{
+	return this->is_random;
+}
+
+const char *ScriptConfig::GetName() const
+{
+	return this->name;
+}
+
+int ScriptConfig::GetVersion() const
+{
+	return this->version;
+}
+
+void ScriptConfig::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 ScriptConfig::SettingsToString(char *string, size_t size) const
+{
+	string[0] = '\0';
+	for (SettingValueList::const_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_t needed_size = strlen((*it).first) + 1 + strlen(no) + 1;
+		/* If it doesn't fit, skip the next settings */
+		if (size <= needed_size) break;
+		size -= needed_size;
+
+		strcat(string, (*it).first);
+		strcat(string, "=");
+		strcat(string, no);
+		strcat(string, ",");
+	}
+	/* Remove the last ',', but only if at least one setting was saved. */
+	size_t len = strlen(string);
+	if (len > 0) string[len - 1] = '\0';
+}
new file mode 100644
--- /dev/null
+++ b/src/script/script_config.hpp
@@ -0,0 +1,191 @@
+/* $Id$ */
+
+/*
+ * This file is part of OpenTTD.
+ * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
+ * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file script_config.hpp ScriptConfig stores the configuration settings of every Script. */
+
+#ifndef SCRIPT_CONFIG_HPP
+#define SCRIPT_CONFIG_HPP
+
+#include <map>
+#include <list>
+#include "../core/smallmap_type.hpp"
+#include "../core/string_compare_type.hpp"
+#include "../company_type.h"
+
+/** Bitmask of flags for Script settings. */
+enum ScriptConfigFlags {
+	SCRIPTCONFIG_NONE      = 0x0, ///< No flags set.
+	SCRIPTCONFIG_RANDOM    = 0x1, ///< When randomizing the Script, pick any value between min_value and max_value when on custom difficulty setting.
+	SCRIPTCONFIG_BOOLEAN   = 0x2, ///< This value is a boolean (either 0 (false) or 1 (true) ).
+	SCRIPTCONFIG_INGAME    = 0x4, ///< This setting can be changed while the Script is running.
+	SCRIPTCONFIG_DEVELOPER = 0x8, ///< This setting will only be visible when the Script development tools are active.
+};
+
+typedef SmallMap<int, char *> LabelMapping; ///< Map-type used to map the setting numbers to labels.
+
+/** Info about a single Script setting. */
+struct ScriptConfigItem {
+	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.
+	int random_deviation;    ///< The maximum random deviation from the default value.
+	int step_size;           ///< The step size in the gui.
+	ScriptConfigFlags flags; ///< Flags for the configuration setting.
+	LabelMapping *labels;    ///< Text labels for the integer values.
+};
+
+typedef std::list<ScriptConfigItem> ScriptConfigItemList; ///< List of ScriptConfig items.
+
+extern ScriptConfigItem _start_date_config;
+
+/**
+ * Script settings.
+ */
+class ScriptConfig {
+protected:
+	/** List with name=>value pairs of all script-specific settings */
+	typedef std::map<const char *, int, StringCompare> SettingValueList;
+
+public:
+	ScriptConfig() :
+		name(NULL),
+		version(-1),
+		info(NULL),
+		config_list(NULL),
+		is_random(false)
+	{}
+
+	/**
+	 * Create a new Script config that is a copy of an existing config.
+	 * @param config The object to copy.
+	 */
+	ScriptConfig(const ScriptConfig *config);
+
+	/** Delete an Script configuration. */
+	virtual ~ScriptConfig();
+
+	/**
+	 * Set another Script to be loaded in this slot.
+	 * @param name The name of the Script.
+	 * @param version The version of the Script to load, or -1 of latest.
+	 * @param force_exact_match If true try to find the exact same version
+	 *   as specified. If false any compatible version is ok.
+	 * @param is_random Is the Script chosen randomly?
+	 */
+	void Change(const char *name, int version = -1, bool force_exact_match = false, bool is_random = false);
+
+	/**
+	 * Get the ScriptInfo linked to this ScriptConfig.
+	 */
+	class ScriptInfo *GetInfo() const;
+
+	/**
+	 * Get the config list for this ScriptConfig.
+	 */
+	const ScriptConfigItemList *GetConfigList();
+
+	/**
+	 * Where to get the config from, either default (depends on current game
+	 * mode) or force either newgame or normal
+	 */
+	enum ScriptSettingSource {
+		SSS_DEFAULT,       ///< Get the Script config from the current game mode
+		SSS_FORCE_NEWGAME, ///< Get the newgame Script config
+		SSS_FORCE_GAME,    ///< Get the Script config from the current game
+	};
+
+	/**
+	 * 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.
+	 */
+	virtual int GetSetting(const char *name) const;
+
+	/**
+	 * Set the value of a setting for this config.
+	 */
+	virtual void SetSetting(const char *name, int value);
+
+	/**
+	 * Reset all settings to their default value.
+	 */
+	void ResetSettings();
+
+	/**
+	 * Randomize all settings the Script requested to be randomized.
+	 */
+	void AddRandomDeviation();
+
+	/**
+	 * Is this config attached to an Script? In other words, is there a Script
+	 *  that is assigned to this slot.
+	 */
+	bool HasScript() const;
+
+	/**
+	 * Is the current Script a randomly chosen Script?
+	 */
+	bool IsRandom() const;
+
+	/**
+	 * Get the name of the Script.
+	 */
+	const char *GetName() const;
+
+	/**
+	 * Get the version of the Script.
+	 */
+	int GetVersion() const;
+
+	/**
+	 * Convert a string which is stored in the config file or savegames to
+	 *  custom settings of this Script.
+	 */
+	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, size_t size) const;
+
+protected:
+	const char *name;                  ///< Name of the Script
+	int version;                       ///< Version of the Script
+	class ScriptInfo *info;            ///< ScriptInfo object for related to this Script version
+	SettingValueList settings;         ///< List with all setting=>value pairs that are configure for this Script
+	ScriptConfigItemList *config_list; ///< List with all settings defined by this Script
+	bool is_random;                    ///< True if the AI in this slot was randomly chosen.
+
+	/**
+	 * In case you have mandatory non-Script-definable config entries in your
+	 *  list, add them to this function.
+	 */
+	virtual void PushExtraConfigList() {};
+
+	/**
+	 * Routine that clears the config list.
+	 */
+	virtual void ClearConfigList();
+
+	/**
+	 * This function should call back to the Scanner in charge of this Config,
+	 *  to find the ScriptInfo belonging to a name+version.
+	 */
+	virtual ScriptInfo *FindInfo(const char *name, int version, bool force_exact_match) = 0;
+};
+
+#endif /* SCRIPT_CONFIG_HPP */
--- a/src/script/script_info.cpp
+++ b/src/script/script_info.cpp
@@ -10,6 +10,7 @@
 /** @file script_info.cpp Implementation of ScriptInfo. */
 
 #include "../stdafx.h"
+#include "../settings_type.h"
 
 #include "squirrel_helper.hpp"
 
@@ -20,9 +21,25 @@
 static const int MAX_GET_OPS            =   1000;
 /** Number of operations to create an instance of a script. */
 static const int MAX_CREATEINSTANCE_OPS = 100000;
+/** Maximum number of operations allowed for getting a particular setting. */
+static const int MAX_GET_SETTING_OPS    = 100000;
+
 
 ScriptInfo::~ScriptInfo()
 {
+	/* Free all allocated strings */
+	for (ScriptConfigItemList::iterator it = this->config_list.begin(); it != this->config_list.end(); it++) {
+		free((*it).name);
+		free((*it).description);
+		if (it->labels != NULL) {
+			for (LabelMapping::iterator it2 = (*it).labels->Begin(); it2 != (*it).labels->End(); it2++) {
+				free(it2->second);
+			}
+			delete it->labels;
+		}
+	}
+	this->config_list.clear();
+
 	free(this->author);
 	free(this->name);
 	free(this->short_name);
@@ -90,5 +107,200 @@
 		if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetURL", &info->url, MAX_GET_OPS)) return SQ_ERROR;
 	}
 
+	/* Check if we have settings */
+	if (info->engine->MethodExists(*info->SQ_instance, "GetSettings")) {
+		if (!info->GetSettings()) return SQ_ERROR;
+	}
+
 	return 0;
 }
+
+bool ScriptInfo::GetSettings()
+{
+	return this->engine->CallMethod(*this->SQ_instance, "GetSettings", NULL, MAX_GET_SETTING_OPS);
+}
+
+SQInteger ScriptInfo::AddSetting(HSQUIRRELVM vm)
+{
+	ScriptConfigItem config;
+	memset(&config, 0, sizeof(config));
+	config.max_value = 1;
+	config.step_size = 1;
+	uint 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;
+		if (SQ_FAILED(sq_getstring(vm, -2, &sqkey))) return SQ_ERROR;
+		const char *key = SQ2OTTD(sqkey);
+
+		if (strcmp(key, "name") == 0) {
+			const SQChar *sqvalue;
+			if (SQ_FAILED(sq_getstring(vm, -1, &sqvalue))) return SQ_ERROR;
+			char *name = strdup(SQ2OTTD(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 = strchr(name, '=')) != NULL) *s = '_';
+			while ((s = strchr(name, ',')) != NULL) *s = '_';
+			config.name = name;
+			items |= 0x001;
+		} else if (strcmp(key, "description") == 0) {
+			const SQChar *sqdescription;
+			if (SQ_FAILED(sq_getstring(vm, -1, &sqdescription))) return SQ_ERROR;
+			config.description = strdup(SQ2OTTD(sqdescription));
+			items |= 0x002;
+		} else if (strcmp(key, "min_value") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.min_value = res;
+			items |= 0x004;
+		} else if (strcmp(key, "max_value") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.max_value = res;
+			items |= 0x008;
+		} else if (strcmp(key, "easy_value") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.easy_value = res;
+			items |= 0x010;
+		} else if (strcmp(key, "medium_value") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.medium_value = res;
+			items |= 0x020;
+		} else if (strcmp(key, "hard_value") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.hard_value = res;
+			items |= 0x040;
+		} else if (strcmp(key, "random_deviation") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.random_deviation = res;
+			items |= 0x200;
+		} else if (strcmp(key, "custom_value") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.custom_value = res;
+			items |= 0x080;
+		} else if (strcmp(key, "step_size") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.step_size = res;
+		} else if (strcmp(key, "flags") == 0) {
+			SQInteger res;
+			if (SQ_FAILED(sq_getinteger(vm, -1, &res))) return SQ_ERROR;
+			config.flags = (ScriptConfigFlags)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);
+
+	/* Don't allow both random_deviation and SCRIPTCONFIG_RANDOM to
+	 * be set for the same config item. */
+	if ((items & 0x200) != 0 && (config.flags & SCRIPTCONFIG_RANDOM) != 0) {
+		char error[1024];
+		snprintf(error, sizeof(error), "Setting both random_deviation and SCRIPTCONFIG_RANDOM is not allowed");
+		this->engine->ThrowError(error);
+		return SQ_ERROR;
+	}
+	/* Reset the bit for random_deviation as it's optional. */
+	items &= ~0x200;
+
+	/* Make sure all properties are defined */
+	uint mask = (config.flags & SCRIPTCONFIG_BOOLEAN) ? 0x1F3 : 0x1FF;
+	if (items != mask) {
+		char error[1024];
+		snprintf(error, sizeof(error), "please define all properties of a setting (min/max not allowed for booleans)");
+		this->engine->ThrowError(error);
+		return SQ_ERROR;
+	}
+
+	this->config_list.push_back(config);
+	return 0;
+}
+
+SQInteger ScriptInfo::AddLabels(HSQUIRRELVM vm)
+{
+	const SQChar *sq_setting_name;
+	if (SQ_FAILED(sq_getstring(vm, -2, &sq_setting_name))) return SQ_ERROR;
+	const char *setting_name = SQ2OTTD(sq_setting_name);
+
+	ScriptConfigItem *config = NULL;
+	for (ScriptConfigItemList::iterator it = this->config_list.begin(); it != this->config_list.end(); it++) {
+		if (strcmp((*it).name, setting_name) == 0) config = &(*it);
+	}
+
+	if (config == NULL) {
+		char error[1024];
+		snprintf(error, sizeof(error), "Trying to add labels for non-defined setting '%s'", setting_name);
+		this->engine->ThrowError(error);
+		return SQ_ERROR;
+	}
+	if (config->labels != NULL) return SQ_ERROR;
+
+	config->labels = new LabelMapping;
+
+	/* Read the table and find all labels */
+	sq_pushnull(vm);
+	while (SQ_SUCCEEDED(sq_next(vm, -2))) {
+		const SQChar *sq_key;
+		const SQChar *sq_label;
+		if (SQ_FAILED(sq_getstring(vm, -2, &sq_key))) return SQ_ERROR;
+		if (SQ_FAILED(sq_getstring(vm, -1, &sq_label))) return SQ_ERROR;
+		/* Because squirrel doesn't support identifiers starting with a digit,
+		 * we skip the first character. */
+		const char *key_string = SQ2OTTD(sq_key);
+		int key = atoi(key_string + 1);
+		const char *label = SQ2OTTD(sq_label);
+
+		/* !Contains() prevents strdup from leaking. */
+		if (!config->labels->Contains(key)) config->labels->Insert(key, strdup(label));
+
+		sq_pop(vm, 2);
+	}
+	sq_pop(vm, 1);
+
+	return 0;
+}
+
+const ScriptConfigItemList *ScriptInfo::GetConfigList() const
+{
+	return &this->config_list;
+}
+
+const ScriptConfigItem *ScriptInfo::GetConfigItem(const char *name) const
+{
+	for (ScriptConfigItemList::const_iterator it = this->config_list.begin(); it != this->config_list.end(); it++) {
+		if (strcmp((*it).name, name) == 0) return &(*it);
+	}
+	return NULL;
+}
+
+int ScriptInfo::GetSettingDefaultValue(const char *name) const
+{
+	for (ScriptConfigItemList::const_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 (GetGameSettings().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;
+}
--- a/src/script/script_info.hpp
+++ b/src/script/script_info.hpp
@@ -15,6 +15,8 @@
 #include <squirrel.h>
 #include "../misc/countedptr.hpp"
 
+#include "script_config.hpp"
+
 class ScriptInfo : public SimpleCountedObject {
 public:
 	ScriptInfo() :
@@ -98,9 +100,41 @@
 	 */
 	virtual class ScriptScanner *GetScanner() { return this->scanner; }
 
+	/**
+	 * Get the settings of the Script.
+	 */
+	bool GetSettings();
+
+	/**
+	 * Get the config list for this Script.
+	 */
+	const ScriptConfigItemList *GetConfigList() const;
+
+	/**
+	 * Get the description of a certain Script config option.
+	 */
+	const ScriptConfigItem *GetConfigItem(const char *name) const;
+
+	/**
+	 * Set a setting.
+	 */
+	SQInteger AddSetting(HSQUIRRELVM vm);
+
+	/**
+	 * Add labels for a setting.
+	 */
+	SQInteger AddLabels(HSQUIRRELVM vm);
+
+	/**
+	 * Get the default value for a setting.
+	 */
+	int GetSettingDefaultValue(const char *name) const;
+
+
 protected:
-	class Squirrel *engine;       ///< Engine used to register for Squirrel.
-	HSQOBJECT *SQ_instance;       ///< The Squirrel instance created for this info.
+	class Squirrel *engine;           ///< Engine used to register for Squirrel.
+	HSQOBJECT *SQ_instance;           ///< The Squirrel instance created for this info.
+	ScriptConfigItemList config_list; ///< List of settings from this Script.
 
 private:
 	char *main_script;            ///< The full path of the script.
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -1320,7 +1320,7 @@
 
 	/* Clean any configured AI */
 	for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
-		AIConfig::GetConfig(c, AIConfig::AISS_FORCE_NEWGAME)->ChangeAI(NULL);
+		AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME)->Change(NULL);
 	}
 
 	/* If no group exists, return */
@@ -1328,10 +1328,10 @@
 
 	CompanyID c = COMPANY_FIRST;
 	for (item = group->item; c < MAX_COMPANIES && item != NULL; c++, item = item->next) {
-		AIConfig *config = AIConfig::GetConfig(c, AIConfig::AISS_FORCE_NEWGAME);
+		AIConfig *config = AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME);
 
-		config->ChangeAI(item->name);
-		if (!config->HasAI()) {
+		config->Change(item->name);
+		if (!config->HasScript()) {
 			if (strcmp(item->name, "none") != 0) {
 				DEBUG(ai, 0, "The AI by the name '%s' was no longer found, and removed from the list.", item->name);
 				continue;
@@ -1443,12 +1443,12 @@
 	group->Clear();
 
 	for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
-		AIConfig *config = AIConfig::GetConfig(c, AIConfig::AISS_FORCE_NEWGAME);
+		AIConfig *config = AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME);
 		const char *name;
 		char value[1024];
 		config->SettingsToString(value, lengthof(value));
 
-		if (config->HasAI()) {
+		if (config->HasScript()) {
 			name = config->GetName();
 		} else {
 			name = "none";