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 }

Generated on Wed Jul 15 20:35:56 2009 for OpenTTD by  doxygen 1.5.6