vegastrike  0.5.1.r1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
galaxy.cpp
Go to the documentation of this file.
1 #include "star_system_generic.h"
2 #include "cmd/script/mission.h"
3 #include "universe_generic.h"
4 #include "galaxy_xml.h"
5 #include "galaxy_gen.h"
6 #include "vsfilesystem.h"
7 #include "configxml.h"
8 #include "vs_globals.h"
9 #include "xml_support.h"
10 #include "lin_time.h"
11 #include "star_system_generic.h"
12 
13 #include "options.h"
14 
15 #include <vector>
16 #include <string>
17 #include <map>
18 #include <deque>
19 #include <algorithm>
20 
22 
23 using namespace XMLSupport;
24 using namespace GalaxyXML;
25 using namespace std;
26 
27 string RemoveDotSystem( const char *input )
28 {
29  int sl = strlen( input );
30  if (sl == 0)
31  return string( "" );
32  char *tmp = strdup( input );
33  char *ptr = tmp+sl-1;
34  while (ptr > tmp) {
35  if (*ptr == '.') {
36  if ( 0 == strcmp( ptr, ".system" ) ) {
37  *ptr = '\0';
38 
39  char *ttmp = tmp;
40  tmp = strdup( RemoveDotSystem( tmp ).c_str() );
41  ptr = ( tmp+(ptr-ttmp) );
42  free( ttmp );
43 
44  break;
45  } else {
46  break;
47  }
48  }
49  ptr--;
50  }
51  string retval( tmp );
52  free( tmp );
53  return retval;
54 }
55 
57 {
58  char del[] = {'/', '\0'};
59  return game_options.universe_path+string( del );
60 }
61 
62 string getVarEitherSectionOrSub( Galaxy *galaxy, string section, string subsection, string variable, string defaultst )
63 {
64  string d3fault = galaxy->getVariable( section, subsection, variable,
65  galaxy->getVariable( section, variable, defaultst ) );
66  if (d3fault.length() == 0)
67  d3fault = galaxy->getVariable( section, variable, defaultst );
68  if (d3fault.length() == 0)
69  return defaultst;
70  return d3fault; //this code will prevent the empty planet lists from interfering
71 }
72 
73 void ClampIt( float &prop, float min, float max )
74 {
75  if (prop < min)
76  prop = min;
77  if (prop > max)
78  prop = max;
79 }
80 
81 void ClampIt( int &prop, int min, int max )
82 {
83  if (prop < min)
84  prop = min;
85  if (prop > max)
86  prop = max;
87 }
88 
89 static void clampSystem( SystemInfo &si, const SystemInfo &min, const SystemInfo &max )
90 {
91  ClampIt( si.sunradius, min.sunradius, max.sunradius );
93  ClampIt( si.numstars, min.numstars, max.numstars );
94  ClampIt( si.numun1, min.numun1, max.numun1 );
95  ClampIt( si.numun2, min.numun2, max.numun2 );
96 }
97 
98 void GetSystemXProp( Galaxy *galaxy, std::string sector, std::string minmax, SystemInfo &si )
99 {
100  si.sunradius = parse_float( getVarEitherSectionOrSub( galaxy, sector, minmax, "sun_radius", "5000" ) );
101  si.compactness = parse_float( getVarEitherSectionOrSub( galaxy, sector, minmax, "compactness", "1.5" ) );
102  si.numstars = parse_int( getVarEitherSectionOrSub( galaxy, sector, minmax, "num_stars", "1" ) );
103  si.nebulae = parse_bool( getVarEitherSectionOrSub( galaxy, sector, minmax, "nebulae", "true" ) );
104  si.asteroids = parse_bool( getVarEitherSectionOrSub( galaxy, sector, minmax, "asteroids", "true" ) );
105  si.numun1 = parse_int( getVarEitherSectionOrSub( galaxy, sector, minmax, "num_natural_phenomena", "0" ) );
106  si.numun2 = parse_int( getVarEitherSectionOrSub( galaxy, sector, minmax, "num_starbases", "0" ) );
107  si.faction = getVarEitherSectionOrSub( galaxy, sector, minmax, "faction", "unknown" );
108  si.seed = parse_int( getVarEitherSectionOrSub( galaxy, sector, minmax, "data", "0" ) );
109  si.names = getVarEitherSectionOrSub( galaxy, sector, minmax, "namelist", "names.txt" );
110  si.stars = getVarEitherSectionOrSub( galaxy, sector, minmax, "starlist", "stars.txt" );
111  si.planetlist = getVarEitherSectionOrSub( galaxy, sector, minmax, "planets", "" );
112  si.smallun = getVarEitherSectionOrSub( galaxy, sector, minmax, "unitlist", "smallunits.txt" );
113  si.asteroidslist = getVarEitherSectionOrSub( galaxy, sector, minmax, "asteroidlist", "asteroids.txt" );
114  si.ringlist = getVarEitherSectionOrSub( galaxy, sector, minmax, "ringlist", "rings.txt" );
115  si.nebulaelist = getVarEitherSectionOrSub( galaxy, sector, minmax, "nebulalist", "nebulae.txt" );
116  si.backgrounds = getVarEitherSectionOrSub( galaxy, sector, minmax, "backgroundlist", "background.txt" );
117  si.force = parse_bool( getVarEitherSectionOrSub( galaxy, sector, minmax, "force", "false" ) );
118 }
119 
121 {
122  SystemInfo si;
123  GetSystemXProp( galaxy, "unknown_sector", "min", si );
124  return si;
125 }
126 
128 {
129  SystemInfo si;
130  GetSystemXProp( galaxy, "unknown_sector", "max", si );
131  return si;
132 }
133 
134 static float av01()
135 {
136  return ( float( rand() ) )/( ( ( (float) RAND_MAX )+1 ) );
137 }
138 
139 static float sqav01()
140 {
141  float tmp = av01();
142  return tmp*tmp;
143 }
144 
145 static float fsqav( float in1, float in2 )
146 {
147  return sqav01()*(in2-in1)+in1;
148 }
149 
150 static int rnd( int in1, int in2 )
151 {
152  return (int) ( in1+(in2-in1)*( float( rand() ) )/( ( (float) RAND_MAX )+1 ) );
153 }
154 
155 static int iav( int in1, int in2 )
156 {
157  return rnd( in1, in2+1 );
158 }
159 
160 static int isqav( int in1, int in2 )
161 {
162  return (int) ( in1+(in2+1-in1)*sqav01() );
163 }
164 
165 void AvgSystems( const SystemInfo &a, const SystemInfo &b, SystemInfo &si )
166 {
167  si = a; //copy all stuff that cna't be averaged
168  si.sunradius = fsqav( a.sunradius, b.sunradius );
169  si.compactness = fsqav( a.compactness, b.compactness );
170  si.numstars = isqav( a.numstars, b.numstars );
171  si.nebulae = a.nebulae || b.nebulae;
172  si.asteroids = a.asteroids || b.asteroids;
173  si.numun1 = isqav( a.numun1, b.numun1 );
174  si.numun2 = isqav( a.numun2, b.numun2 );
175  si.seed = iav( a.seed, b.seed );
176  si.force = a.force || b.force;
177 }
178 const vector< string >& ParseDestinations( const string &value )
179 {
180  static vector< string >rv;
181  rv.clear();
182  string::size_type pos = 0, sep;
183  while ( ( sep = value.find( ' ', pos ) ) != string::npos ) {
184  rv.push_back( value.substr( pos, sep-pos ) );
185  pos = sep+1;
186  }
187  if ( pos < value.length() )
188  rv.push_back( value.substr( pos ) );
189  return rv;
190 }
191 
192 void MakeStarSystem( string file, Galaxy *galaxy, string origin, int forcerandom )
193 {
194  SystemInfo Ave;
195  SystemInfo si;
196  AvgSystems( GetSystemMin( galaxy ), GetSystemMax( galaxy ), Ave );
197  //Do we really need this duplicate code... or can we use GetSystemXProp()
198  si.sector = getStarSystemSector( file );
199  si.name = RemoveDotSystem( getStarSystemName( file ).c_str() );
200  si.filename = file;
201  si.sunradius = parse_float( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "sun_radius", tostring( Ave.sunradius ) ) );
202  si.compactness =
203  parse_float( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "compactness", tostring( Ave.compactness ) ) );
204  si.numstars = parse_int( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "num_stars", tostring( Ave.numstars ) ) );
205  si.nebulae = parse_bool( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "nebulae", tostring( Ave.nebulae ) ) );
206  si.asteroids = parse_bool( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "asteroids", tostring( Ave.asteroids ) ) );
207  si.numun1 =
208  parse_int( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "num_natural_phenomena", tostring( Ave.numun1 ) ) );
209  si.numun2 = parse_int( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "num_starbases", tostring( Ave.numun2 ) ) );
210  si.faction = getVarEitherSectionOrSub( galaxy, si.sector, si.name, "faction", Ave.faction );
211  si.seed = parse_int( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "data", tostring( Ave.seed ) ) );
212  si.names = getVarEitherSectionOrSub( galaxy, si.sector, si.name, "namelist", Ave.names );
213  si.stars = getVarEitherSectionOrSub( galaxy, si.sector, si.name, "starlist", Ave.stars );
214  si.planetlist = getVarEitherSectionOrSub( galaxy, si.sector, si.name, "planets", Ave.planetlist );
215  si.smallun = getVarEitherSectionOrSub( galaxy, si.sector, si.name, "unitlist", Ave.smallun );
216  si.asteroidslist = getVarEitherSectionOrSub( galaxy, si.sector, si.name, "asteroidlist", Ave.asteroidslist );
217  si.ringlist = getVarEitherSectionOrSub( galaxy, si.sector, si.ringlist, "ringlist", Ave.ringlist );
218  si.nebulaelist = getVarEitherSectionOrSub( galaxy, si.sector, si.name, "nebulalist", Ave.nebulaelist );
219  si.backgrounds = getVarEitherSectionOrSub( galaxy, si.sector, si.name, "backgroundlist", Ave.backgrounds );
220  si.force = parse_bool( getVarEitherSectionOrSub( galaxy, si.sector, si.name, "force", Ave.force ? "true" : "false" ) );
221  if (game_options.PushValuesToMean)
222  si.force = true;
223  string dest = galaxy->getVariable( si.sector, si.name, "jumps", "" );
224  if ( dest.length() )
225  si.jumps = ParseDestinations( dest );
226  bool canret = origin.length() == 0;
227  for (unsigned int i = 0; i < si.jumps.size(); i++)
228  if (si.jumps[i] == origin) {
229  canret = true;
230  break;
231  }
232  if (!canret)
233  si.jumps.push_back( origin );
234  if (!si.force) {
235  SystemInfo minlimit, maxlimit;
236  GetSystemXProp( galaxy, "unknown_sector", "minlimit", minlimit );
237  GetSystemXProp( galaxy, "unknown_sector", "maxlimit", maxlimit );
238  clampSystem( si, minlimit, maxlimit );
239  }
240  generateStarSystem( si );
241 }
242 
243 std::string Universe::getGalaxyProperty( const std::string &sys, const std::string &prop )
244 {
245  string sector = getStarSystemSector( sys );
246  string name = RemoveDotSystem( getStarSystemName( sys ).c_str() );
247  return galaxy->getVariable( sector, name, prop,
248  galaxy->getVariable( sector, prop, galaxy->getVariable( "unknown_sector", "min", prop, "" ) ) );
249 }
250 
251 std::string Universe::getGalaxyPropertyDefault( const std::string &sys, const std::string &prop, const std::string def )
252 {
253  string sector = getStarSystemSector( sys );
254  string name = RemoveDotSystem( getStarSystemName( sys ).c_str() );
255  return galaxy->getVariable( sector, name, prop, def );
256 }
257 
258 const vector< std::string >& Universe::getAdjacentStarSystems( const std::string &file ) const
259 {
260  string sector = getStarSystemSector( file );
261  string name = RemoveDotSystem( getStarSystemName( file ).c_str() );
262  return ParseDestinations( galaxy->getVariable( sector, name, "jumps", "" ) );
263 }
264 
265 void Universe::getJumpPath( const std::string &from, const std::string &to, vector< std::string > &path ) const
266 {
267  map< string, unsigned int > visited;
268  vector< const string* > origin;
269  deque< const string* > open;
270 
271  // seed with starting point
272  visited[from] = 0;
273  origin.push_back(NULL);
274  open.push_back(&from);
275 
276  // Textbook BFS search
277  while (!open.empty()) {
278  const string *system = open.front();
279  open.pop_front();
280 
281  const vector< std::string > &adjacent = getAdjacentStarSystems(*system);
282  for (vector< std::string >::const_iterator i = adjacent.begin(); i != adjacent.end(); ++i) {
283  map< string, unsigned int >::const_iterator velem = visited.find(*i);
284  if (velem == visited.end()) {
285  visited[*i] = origin.size();
286  origin.push_back(system);
287  velem = visited.find(*i);
288 
289  if (*i == to) {
290  // finished we are
291  open.clear();
292  break;
293  } else {
294  open.push_back(&velem->first);
295  }
296  }
297  }
298  }
299 
300  // Backtrack to get a reverse path
301  path.clear();
302  map< string, unsigned int >::const_iterator velem = visited.find(to);
303  while (velem != visited.end()) {
304  path.push_back(velem->first);
305  if (origin[velem->second] == NULL)
306  velem = visited.end();
307  else
308  velem = visited.find(*origin[velem->second]);
309  }
310 
311  // Reverse to get the straight path
312  reverse(path.begin(), path.end());
313 }