git-svn-id: https://scorched3d.svn.sourceforge.net/svnroot/scorched3d/trunk/scorched...
[scorched3d/parasti.git] / src / common / landscapedef / LandscapeDefinitions.cpp
blob51185e88cb5a30dd4c295c2aaedb1dea7f6c6ac1
1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2009
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <landscapedef/LandscapeDefinitions.h>
22 #include <landscapedef/LandscapeTex.h>
23 #include <landscapedef/LandscapeDefn.h>
24 #include <landscapedef/LandscapeInclude.h>
25 #include <tank/TankContainer.h>
26 #include <common/OptionsScorched.h>
27 #include <common/Defines.h>
28 #include <common/Logger.h>
29 #include <limits.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <time.h>
34 LandscapeDefinitions::LandscapeDefinitions() :
35 lastDefinition_(0),
36 texs_("Tex"),
37 defns_("Defns"),
38 include_("Include")
42 LandscapeDefinitions::~LandscapeDefinitions()
46 void LandscapeDefinitions::clearLandscapeDefinitions()
48 LandscapeDefinitionsBase::clearLandscapeDefinitions();
50 defns_.clearItems();
51 texs_.clearItems();
52 include_.clearItems();
55 LandscapeTex *LandscapeDefinitions::getTex(const char *file, bool load)
57 return texs_.getItem(this, file, load, true);
60 LandscapeInclude *LandscapeDefinitions::getInclude(const char *file, bool load)
62 return include_.getItem(this, file, load, true);
65 LandscapeDefn *LandscapeDefinitions::getDefn(const char *file, bool load)
67 return defns_.getItem(this, file, load, true);
70 bool LandscapeDefinitions::readLandscapeDefinitions()
72 // Clear existing landscapes
73 clearLandscapeDefinitions();
75 // Parse base landscape information
76 if (!LandscapeDefinitionsBase::readLandscapeDefinitions()) return false;
78 // Now check that the landscape tex and defn files parse correctly
79 std::list<LandscapeDefinitionsEntry>::iterator itor;
80 for (itor = entries_.begin();
81 itor != entries_.end();
82 itor++)
84 LandscapeDefinitionsEntry &entry = (*itor);
85 std::vector<std::string>::iterator itor2;
87 std::vector<std::string> &defns = entry.defns;
88 for (itor2 = defns.begin();
89 itor2 != defns.end();
90 itor2++)
92 const char *landscapeDefnFile = (*itor2).c_str();
93 LandscapeDefn *landscapeDefn = getDefn(landscapeDefnFile, true);
94 if (!landscapeDefn) return false;
97 std::vector<std::string> &texs = entry.texs;
98 for (itor2 = texs.begin();
99 itor2 != texs.end();
100 itor2++)
102 const char *landscapeTexFile = (*itor2).c_str();
103 LandscapeTex *landscapeTex = getTex(landscapeTexFile, true);
104 if (!landscapeTex) return false;
108 return true;
111 const char *LandscapeDefinitions::getLeastUsedFile(std::vector<std::string> &files)
113 DIALOG_ASSERT(!files.empty());
115 const char *result = "";
116 int usedTimes = INT_MAX;
118 std::vector<std::string>::iterator itor;
119 for (itor = files.begin();
120 itor != files.end();
121 itor++)
123 std::string &file = (*itor);
125 int used = 0;
126 std::map<std::string, int>::iterator findItor =
127 usedFiles_.find(file);
128 if (findItor != usedFiles_.end())
130 used = (*findItor).second;
133 if (used < usedTimes)
135 usedTimes = used;
136 result = file.c_str();
140 usedFiles_[result] = usedTimes + 1;
141 return result;
144 void LandscapeDefinitions::checkEnabled(OptionsScorched &context)
146 std::list<LandscapeDefinitionsEntry>::iterator itor;
147 for (itor = entries_.begin();
148 itor != entries_.end();
149 itor++)
151 LandscapeDefinitionsEntry &result = *itor;
152 if (landscapeEnabled(context.getMainOptions(), result.name.c_str()))
154 return;
158 context.getChangedOptions().getLandscapesEntry().setValue("");
159 Logger::log(S3D::formatStringBuffer(
160 "Warning: No existing landscapes are enabled (Landscapes : %s)",
161 context.getLandscapes()));
164 LandscapeDefinition LandscapeDefinitions::getLandscapeDefn(
165 const char *name)
167 LandscapeDefinitionsEntry *result = 0;
169 // Build a list of the maps that are enabled
170 std::list<LandscapeDefinitionsEntry>::iterator itor;
171 for (itor = entries_.begin();
172 itor != entries_.end();
173 itor++)
175 result = &(*itor);
176 if (0 == strcmp(name, result->name.c_str())) break;
179 // Return the chosen definition
180 std::string tex = result->texs[rand() % result->texs.size()];
181 std::string defn = result->defns[rand() % result->defns.size()];
182 unsigned int seed = 33;//(unsigned int) rand();
184 LandscapeDefinition entry(
185 tex.c_str(), defn.c_str(), seed, result->name.c_str());
186 return entry;
189 LandscapeDefinition LandscapeDefinitions::getRandomLandscapeDefn(
190 OptionsScorched &context, TankContainer &tankContainer)
192 // Build a list of the maps that are enabled
193 int players = tankContainer.getNoOfNonSpectatorTanks();
194 std::list<LandscapeDefinitionsEntry *> allPassedLandscapes;
195 std::list<LandscapeDefinitionsEntry *> minMaxPassedLandscapes;
196 std::list<LandscapeDefinitionsEntry>::iterator itor;
197 for (itor = entries_.begin();
198 itor != entries_.end();
199 itor++)
201 LandscapeDefinitionsEntry &current = *itor;
202 if (landscapeEnabled(context.getMainOptions(), current.name.c_str()))
204 allPassedLandscapes.push_back(&current);
206 // Check that min/max players are ok
207 std::vector<std::string>::iterator defnitor;
208 for (defnitor = current.defns.begin();
209 defnitor != current.defns.end();
210 defnitor++)
212 LandscapeDefn *defn = getDefn(defnitor->c_str());
213 if (players >= defn->getMinPlayers() && players <= defn->getMaxPlayers())
215 minMaxPassedLandscapes.push_back(&current);
216 break;
222 // Check we have a least one map
223 DIALOG_ASSERT(!allPassedLandscapes.empty());
225 // Try min max maps
226 LandscapeDefinitionsEntry *result = getRandomLandscapeDefnEntry(
227 context, minMaxPassedLandscapes);
228 if (!result)
230 // Try all maps
231 Logger::log("Warning: Cannot find any landscapes for number of players");
232 result = getRandomLandscapeDefnEntry(context, allPassedLandscapes);
235 // Check we found map
236 if (!result)
238 S3D::dialogExit("Scorched3D",
239 "Failed to select a landscape definition");
242 // Return the chosen definition
243 std::string tex = getLeastUsedFile(result->texs);
244 std::string defn = getLeastUsedFile(result->defns);
245 unsigned int seed = (unsigned int) rand();
246 LandscapeTex *landscapeTex = getTex(tex.c_str());
247 if (landscapeTex->seed != 0) seed = landscapeTex->seed;
249 LandscapeDefinition entry(
250 tex.c_str(), defn.c_str(), seed, result->name.c_str());
251 return entry;
255 LandscapeDefinitionsEntry *LandscapeDefinitions::getRandomLandscapeDefnEntry(
256 OptionsScorched &context,
257 std::list<LandscapeDefinitionsEntry *> passedLandscapes)
259 // Map cycle mode
260 LandscapeDefinitionsEntry *result = 0;
261 if (context.getCycleMaps())
263 // Just cycle through the maps
264 bool next = false;
265 result = passedLandscapes.front();
266 std::list<LandscapeDefinitionsEntry*>::iterator passedItor;
267 for (passedItor = passedLandscapes.begin();
268 passedItor != passedLandscapes.end();
269 passedItor++)
271 LandscapeDefinitionsEntry *current = *passedItor;
272 if (next)
274 result = current;
275 break;
277 if (current == lastDefinition_) next = true;
279 lastDefinition_ = result;
281 else
283 float totalWeight = 0.0f;
284 std::list<LandscapeDefinitionsEntry*>::iterator passedItor;
285 for (passedItor = passedLandscapes.begin();
286 passedItor != passedLandscapes.end();
287 passedItor++)
289 LandscapeDefinitionsEntry *current = *passedItor;
290 totalWeight += current->weight;
293 // Choose a map based on probablity
294 float pos = RAND * totalWeight;
295 float soFar = 0.0f;
296 for (passedItor = passedLandscapes.begin();
297 passedItor != passedLandscapes.end();
298 passedItor++)
300 LandscapeDefinitionsEntry *current = *passedItor;
301 soFar += current->weight;
303 if (pos <= soFar)
305 result = current;
306 break;
311 return result;