00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <landscapedef/LandscapeDefinitions.h>
00022 #include <landscapedef/LandscapeTex.h>
00023 #include <landscapedef/LandscapeDefn.h>
00024 #include <landscapedef/LandscapeInclude.h>
00025 #include <tank/TankContainer.h>
00026 #include <common/OptionsScorched.h>
00027 #include <common/Defines.h>
00028 #include <common/Logger.h>
00029 #include <limits.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032 #include <time.h>
00033
00034 LandscapeDefinitions::LandscapeDefinitions() :
00035 lastDefinition_(0),
00036 texs_("Tex"),
00037 defns_("Defns"),
00038 include_("Include")
00039 {
00040 }
00041
00042 LandscapeDefinitions::~LandscapeDefinitions()
00043 {
00044 }
00045
00046 void LandscapeDefinitions::clearLandscapeDefinitions()
00047 {
00048 LandscapeDefinitionsBase::clearLandscapeDefinitions();
00049
00050 defns_.clearItems();
00051 texs_.clearItems();
00052 include_.clearItems();
00053 }
00054
00055 LandscapeTex *LandscapeDefinitions::getTex(const char *file, bool load)
00056 {
00057 return texs_.getItem(this, file, load, true);
00058 }
00059
00060 LandscapeInclude *LandscapeDefinitions::getInclude(const char *file, bool load)
00061 {
00062 return include_.getItem(this, file, load, true);
00063 }
00064
00065 LandscapeDefn *LandscapeDefinitions::getDefn(const char *file, bool load)
00066 {
00067 return defns_.getItem(this, file, load, true);
00068 }
00069
00070 bool LandscapeDefinitions::readLandscapeDefinitions()
00071 {
00072
00073 clearLandscapeDefinitions();
00074
00075
00076 if (!LandscapeDefinitionsBase::readLandscapeDefinitions()) return false;
00077
00078
00079 std::list<LandscapeDefinitionsEntry>::iterator itor;
00080 for (itor = entries_.begin();
00081 itor != entries_.end();
00082 itor++)
00083 {
00084 LandscapeDefinitionsEntry &entry = (*itor);
00085 std::vector<std::string>::iterator itor2;
00086
00087 std::vector<std::string> &defns = entry.defns;
00088 for (itor2 = defns.begin();
00089 itor2 != defns.end();
00090 itor2++)
00091 {
00092 const char *landscapeDefnFile = (*itor2).c_str();
00093 LandscapeDefn *landscapeDefn = getDefn(landscapeDefnFile, true);
00094 if (!landscapeDefn) return false;
00095 }
00096
00097 std::vector<std::string> &texs = entry.texs;
00098 for (itor2 = texs.begin();
00099 itor2 != texs.end();
00100 itor2++)
00101 {
00102 const char *landscapeTexFile = (*itor2).c_str();
00103 LandscapeTex *landscapeTex = getTex(landscapeTexFile, true);
00104 if (!landscapeTex) return false;
00105 }
00106 }
00107
00108 return true;
00109 }
00110
00111 const std::string LandscapeDefinitions::getLeastUsedFile(
00112 OptionsScorched &context, std::vector<std::string> &files)
00113 {
00114 DIALOG_ASSERT(!files.empty());
00115
00116 std::vector<std::string> results;
00117 int usedTimes = INT_MAX;
00118
00119 std::vector<std::string>::iterator itor;
00120 for (itor = files.begin();
00121 itor != files.end();
00122 itor++)
00123 {
00124 std::string &file = (*itor);
00125
00126 int used = 0;
00127 std::map<std::string, int>::iterator findItor =
00128 usedFiles_.find(file);
00129 if (findItor != usedFiles_.end())
00130 {
00131 used = (*findItor).second;
00132 }
00133
00134 if (used <= usedTimes)
00135 {
00136 if (used < usedTimes) results.clear();
00137 usedTimes = used;
00138 results.push_back(file);
00139 }
00140 }
00141
00142 DIALOG_ASSERT(!results.empty());
00143 std::string result = results[0];
00144 if (!context.getCycleMaps())
00145 {
00146 result = results[rand() % results.size()];
00147 }
00148
00149 usedFiles_[result] = usedTimes + 1;
00150 return result;
00151 }
00152
00153 void LandscapeDefinitions::checkEnabled(OptionsScorched &context)
00154 {
00155 std::list<LandscapeDefinitionsEntry>::iterator itor;
00156 for (itor = entries_.begin();
00157 itor != entries_.end();
00158 itor++)
00159 {
00160 LandscapeDefinitionsEntry &result = *itor;
00161 if (landscapeEnabled(context.getMainOptions(), result.name.c_str()))
00162 {
00163 return;
00164 }
00165 }
00166
00167 context.getChangedOptions().getLandscapesEntry().setValue("");
00168 Logger::log(S3D::formatStringBuffer(
00169 "Warning: No existing landscapes are enabled (Landscapes : %s)",
00170 context.getLandscapes()));
00171 }
00172
00173 LandscapeDefinition LandscapeDefinitions::getLandscapeDefn(
00174 const char *name)
00175 {
00176 LandscapeDefinitionsEntry *result = 0;
00177
00178
00179 std::list<LandscapeDefinitionsEntry>::iterator itor;
00180 for (itor = entries_.begin();
00181 itor != entries_.end();
00182 itor++)
00183 {
00184 result = &(*itor);
00185 if (0 == strcmp(name, result->name.c_str())) break;
00186 }
00187
00188
00189 std::string tex = result->texs[rand() % result->texs.size()];
00190 std::string defn = result->defns[rand() % result->defns.size()];
00191 unsigned int seed = 33;
00192
00193 LandscapeDefinition entry(
00194 tex.c_str(), defn.c_str(), seed, result->name.c_str());
00195 return entry;
00196 }
00197
00198 LandscapeDefinition LandscapeDefinitions::getRandomLandscapeDefn(
00199 OptionsScorched &context, TankContainer &tankContainer)
00200 {
00201
00202 int players = tankContainer.getNoOfNonSpectatorTanks();
00203 std::list<LandscapeDefinitionsEntry *> allPassedLandscapes;
00204 std::list<LandscapeDefinitionsEntry *> minMaxPassedLandscapes;
00205 std::list<LandscapeDefinitionsEntry>::iterator itor;
00206 for (itor = entries_.begin();
00207 itor != entries_.end();
00208 itor++)
00209 {
00210 LandscapeDefinitionsEntry ¤t = *itor;
00211 if (landscapeEnabled(context.getMainOptions(), current.name.c_str()))
00212 {
00213 allPassedLandscapes.push_back(¤t);
00214
00215
00216 std::vector<std::string>::iterator defnitor;
00217 for (defnitor = current.defns.begin();
00218 defnitor != current.defns.end();
00219 defnitor++)
00220 {
00221 LandscapeDefn *defn = getDefn(defnitor->c_str());
00222 if (players >= defn->getMinPlayers() && players <= defn->getMaxPlayers())
00223 {
00224 minMaxPassedLandscapes.push_back(¤t);
00225 break;
00226 }
00227 }
00228 }
00229 }
00230
00231
00232 DIALOG_ASSERT(!allPassedLandscapes.empty());
00233
00234
00235 LandscapeDefinitionsEntry *result = getRandomLandscapeDefnEntry(
00236 context, minMaxPassedLandscapes);
00237 if (!result)
00238 {
00239
00240 Logger::log("Warning: Cannot find any landscapes for number of players");
00241 result = getRandomLandscapeDefnEntry(context, allPassedLandscapes);
00242 }
00243
00244
00245 if (!result)
00246 {
00247 S3D::dialogExit("Scorched3D",
00248 "Failed to select a landscape definition");
00249 }
00250
00251
00252 std::string tex = getLeastUsedFile(context, result->texs);
00253 std::string defn = getLeastUsedFile(context, result->defns);
00254 unsigned int seed = (unsigned int) rand();
00255 LandscapeTex *landscapeTex = getTex(tex.c_str());
00256 if (landscapeTex->seed != 0) seed = landscapeTex->seed;
00257
00258 LandscapeDefinition entry(
00259 tex.c_str(), defn.c_str(), seed, result->name.c_str());
00260 return entry;
00261 }
00262
00263
00264 LandscapeDefinitionsEntry *LandscapeDefinitions::getRandomLandscapeDefnEntry(
00265 OptionsScorched &context,
00266 std::list<LandscapeDefinitionsEntry *> passedLandscapes)
00267 {
00268
00269 LandscapeDefinitionsEntry *result = 0;
00270 if (context.getCycleMaps())
00271 {
00272
00273 bool next = false;
00274 result = passedLandscapes.front();
00275 std::list<LandscapeDefinitionsEntry*>::iterator passedItor;
00276 for (passedItor = passedLandscapes.begin();
00277 passedItor != passedLandscapes.end();
00278 passedItor++)
00279 {
00280 LandscapeDefinitionsEntry *current = *passedItor;
00281 if (next)
00282 {
00283 result = current;
00284 break;
00285 }
00286 if (current == lastDefinition_) next = true;
00287 }
00288 lastDefinition_ = result;
00289 }
00290 else
00291 {
00292 float totalWeight = 0.0f;
00293 std::list<LandscapeDefinitionsEntry*>::iterator passedItor;
00294 for (passedItor = passedLandscapes.begin();
00295 passedItor != passedLandscapes.end();
00296 passedItor++)
00297 {
00298 LandscapeDefinitionsEntry *current = *passedItor;
00299 totalWeight += current->weight;
00300 }
00301
00302
00303 float pos = RAND * totalWeight;
00304 float soFar = 0.0f;
00305 for (passedItor = passedLandscapes.begin();
00306 passedItor != passedLandscapes.end();
00307 passedItor++)
00308 {
00309 LandscapeDefinitionsEntry *current = *passedItor;
00310 soFar += current->weight;
00311
00312 if (pos <= soFar)
00313 {
00314 result = current;
00315 break;
00316 }
00317 }
00318 }
00319
00320 return result;
00321 }
00322