LandscapeDefinitions.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         // Clear existing landscapes
00073         clearLandscapeDefinitions();
00074 
00075         // Parse base landscape information
00076         if (!LandscapeDefinitionsBase::readLandscapeDefinitions()) return false;
00077 
00078         // Now check that the landscape tex and defn files parse correctly
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         // Build a list of the maps that are enabled
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         // Return the chosen definition
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;//(unsigned int) rand();
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         // Build a list of the maps that are enabled
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 &current = *itor;
00211                 if (landscapeEnabled(context.getMainOptions(), current.name.c_str()))
00212                 {
00213                         allPassedLandscapes.push_back(&current);
00214 
00215                         // Check that min/max players are ok
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(&current);
00225                                         break;
00226                                 }
00227                         }
00228                 }
00229         }
00230 
00231         // Check we have a least one map
00232         DIALOG_ASSERT(!allPassedLandscapes.empty());
00233 
00234         // Try min max maps
00235         LandscapeDefinitionsEntry *result = getRandomLandscapeDefnEntry(
00236                 context, minMaxPassedLandscapes);
00237         if (!result)
00238         {
00239                 // Try all maps
00240                 Logger::log("Warning: Cannot find any landscapes for number of players");
00241                 result = getRandomLandscapeDefnEntry(context, allPassedLandscapes);
00242         }
00243 
00244         // Check we found map
00245         if (!result)
00246         {
00247                 S3D::dialogExit("Scorched3D",
00248                         "Failed to select a landscape definition");
00249         }
00250 
00251         // Return the chosen definition
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         // Map cycle mode
00269         LandscapeDefinitionsEntry *result = 0;
00270         if (context.getCycleMaps())
00271         {
00272                 // Just cycle through the maps
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                 // Choose a map based on probablity
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 

Generated on Mon Feb 16 15:14:50 2009 for Scorched3D by  doxygen 1.5.3