# ai_config.cpp

Go to the documentation of this file.

    00001 /* $Id: ai_config.cpp 15638 2009-03-07 20:55:24Z truebrain $ */
    00002
    00005 #include "../stdafx.h"
    00006 #include "../openttd.h"
    00007 #include "../settings_type.h"
    00008 #include "../core/random_func.hpp"
    00009 #include "ai.hpp"
    00010 #include "ai_config.hpp"
    00011
    00012 void AIConfig::ChangeAI(const char *name, int version)
    00013 {
    00014   free((void *)this->name);
    00015   this->name = (name == NULL) ? NULL : strdup(name);
    00016   this->info = (name == NULL) ? NULL : AI::FindInfo(this->name, version);
    00017   this->version = (info == NULL) ? -1 : info->GetVersion();
    00018   if (this->config_list != NULL) delete this->config_list;
    00019   this->config_list = (info == NULL) ? NULL : new AIConfigItemList();
    00020   if (this->config_list != NULL) this->config_list->push_back(_start_date_config);
    00021
    00022   /* The special casing for start_date is here to ensure that the
    00023    *  start_date setting won't change even if you chose another AI. */
    00024   int start_date = this->GetSetting("start_date");
    00025
    00026   for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
    00027     free((void*)(*it).first);
    00028   }
    00029   this->settings.clear();
    00030
    00031   this->SetSetting("start_date", start_date);
    00032
    00033   if (_game_mode == GM_NORMAL && this->info != NULL) {
    00034     /* If we're in an existing game and the AI is changed, set all settings
    00035      *  for the AI that have the random flag to a random value. */
    00036     for (AIConfigItemList::const_iterator it = this->info->GetConfigList()->begin(); it != this->info->GetConfigList()->end(); it++) {
    00037       if ((*it).flags & AICONFIG_RANDOM) {
    00038         this->SetSetting((*it).name, InteractiveRandomRange((*it).max_value - (*it).min_value) + (*it).min_value);
    00039       }
    00040     }
    00041     this->AddRandomDeviation();
    00042   }
    00043
    00044 }
    00045
    00046 AIConfig::AIConfig(const AIConfig *config)
    00047 {
    00048   this->name = (config->name == NULL) ? NULL : strdup(config->name);
    00049   this->info = config->info;
    00050   this->version = config->version;
    00051   this->config_list = NULL;
    00052
    00053   for (SettingValueList::const_iterator it = config->settings.begin(); it != config->settings.end(); it++) {
    00054     this->settings[strdup((*it).first)] = (*it).second;
    00055   }
    00056   this->AddRandomDeviation();
    00057 }
    00058
    00059 AIConfig::~AIConfig()
    00060 {
    00061   free((void *)this->name);
    00062   this->ResetSettings();
    00063   if (this->config_list != NULL) delete this->config_list;
    00064 }
    00065
    00066 AIInfo *AIConfig::GetInfo()
    00067 {
    00068   return this->info;
    00069 }
    00070
    00071 bool AIConfig::ResetInfo()
    00072 {
    00073   this->info = AI::FindInfo(this->name, -1);
    00074   return this->info != NULL;
    00075 }
    00076
    00077 const AIConfigItemList *AIConfig::GetConfigList()
    00078 {
    00079   if (this->info != NULL) return this->info->GetConfigList();
    00080   if (this->config_list == NULL) {
    00081     this->config_list = new AIConfigItemList();
    00082     this->config_list->push_back(_start_date_config);
    00083   }
    00084   return this->config_list;
    00085 }
    00086
    00087 AIConfig *AIConfig::GetConfig(CompanyID company, bool forceNewgameSetting)
    00088 {
    00089   AIConfig **config;
    00090   if (!forceNewgameSetting) {
    00091     config = (_game_mode == GM_MENU) ? &_settings_newgame.ai_config[company] : &_settings_game.ai_config[company];
    00092   } else {
    00093     config = &_settings_newgame.ai_config[company];
    00094   }
    00095   if (*config == NULL) *config = new AIConfig();
    00096   return *config;
    00097 }
    00098
    00099 int AIConfig::GetSetting(const char *name)
    00100 {
    00101   SettingValueList::iterator it = this->settings.find(name);
    00102   /* Return the default value if the setting is not set, or if we are in a not-custom difficult level */
    00103   if (it == this->settings.end() || ((_game_mode == GM_MENU) ? _settings_newgame.difficulty.diff_level : _settings_game.difficulty.diff_level) != 3) {
    00104     if (this->info == NULL) {
    00105       assert(strcmp("start_date", name) == 0);
    00106       switch ((_game_mode == GM_MENU) ? _settings_newgame.difficulty.diff_level : _settings_game.difficulty.diff_level) {
    00107         case 0: return AI::START_NEXT_EASY;
    00108         case 1: return AI::START_NEXT_MEDIUM;
    00109         case 2: return AI::START_NEXT_HARD;
    00110         case 3: return AI::START_NEXT_MEDIUM;
    00111         default: NOT_REACHED();
    00112       }
    00113     }
    00114     return this->info->GetSettingDefaultValue(name);
    00115   }
    00116   return (*it).second;
    00117 }
    00118
    00119 void AIConfig::SetSetting(const char *name, int value)
    00120 {
    00121   /* You can only set ai specific settings if an AI is selected. */
    00122   if (this->info == NULL && strcmp("start_date", name) != 0) return;
    00123
    00124   if (this->info == NULL && strcmp("start_date", name) == 0) {
    00125     value = Clamp(value, AI::START_NEXT_MIN, AI::START_NEXT_MAX);
    00126   } else {
    00127     const AIConfigItem *config_item = this->info->GetConfigItem(name);
    00128     if (config_item == NULL) return;
    00129
    00130     value = Clamp(value, config_item->min_value, config_item->max_value);
    00131   }
    00132
    00133   SettingValueList::iterator it = this->settings.find(name);
    00134   if (it != this->settings.end()) {
    00135     (*it).second = value;
    00136   } else {
    00137     this->settings[strdup(name)] = value;
    00138   }
    00139 }
    00140
    00141 void AIConfig::ResetSettings()
    00142 {
    00143   for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
    00144     free((void*)(*it).first);
    00145   }
    00146   this->settings.clear();
    00147 }
    00148
    00149 void AIConfig::AddRandomDeviation()
    00150 {
    00151   for (AIConfigItemList::const_iterator it = this->GetConfigList()->begin(); it != this->GetConfigList()->end(); it++) {
    00152     if ((*it).random_deviation != 0) {
    00153       this->SetSetting((*it).name, InteractiveRandomRange((*it).random_deviation * 2) - (*it).random_deviation + this->GetSetting((*it).name));
    00154     }
    00155   }
    00156 }
    00157
    00158 bool AIConfig::HasAI()
    00159 {
    00160   return this->info != NULL;
    00161 }
    00162
    00163 const char *AIConfig::GetName()
    00164 {
    00165   return this->name;
    00166 }
    00167
    00168 int AIConfig::GetVersion()
    00169 {
    00170   return this->version;
    00171 }
    00172
    00173 void AIConfig::StringToSettings(const char *value)
    00174 {
    00175   char *value_copy = strdup(value);
    00176   char *s = value_copy;
    00177
    00178   while (s != NULL) {
    00179     /* Analyze the string ('name=value,name=value\0') */
    00180     char *item_name = s;
    00181     s = strchr(s, '=');
    00182     if (s == NULL) break;
    00183     if (*s == '\0') break;
    00184     *s = '\0';
    00185     s++;
    00186
    00187     char *item_value = s;
    00188     s = strchr(s, ',');
    00189     if (s != NULL) {
    00190       *s = '\0';
    00191       s++;
    00192     }
    00193
    00194     this->SetSetting(item_name, atoi(item_value));
    00195   }
    00196   free(value_copy);
    00197 }
    00198
    00199 void AIConfig::SettingsToString(char *string, size_t size)
    00200 {
    00201   string[0] = '\0';
    00202   for (SettingValueList::iterator it = this->settings.begin(); it != this->settings.end(); it++) {
    00203     char no[10];
    00204     snprintf(no, sizeof(no), "%d", (*it).second);
    00205
    00206     /* Check if the string would fit in the destination */
    00207     size_t needed_size = strlen((*it).first) + 1 + strlen(no) + 1;
    00208     /* If it doesn't fit, skip the next settings */
    00209     if (size <= needed_size) break;
    00210     size -= needed_size;
    00211
    00212     strcat(string, (*it).first);
    00213     strcat(string, "=");
    00214     strcat(string, no);
    00215     strcat(string, ",");
    00216   }
    00217   /* Remove the last ',', but only if at least one setting was saved. */
    00218   size_t len = strlen(string);
    00219   if (len > 0) string[len - 1] = '\0';
    00220 }