23 #define snprintf _snprintf
27 #define M_PI 3.1415926536
31 using namespace VSFileSystem;
43 string::const_iterator
start = key.begin();
44 for (; start != key.end(); start++)
54 static string GetWrapXY(
string cname,
int &wrapx,
int &wrapy )
58 string::size_type pos = wrap.find(
"wrapx" );
59 if (pos != string::npos) {
60 string Wrapx = wrap.substr( pos+5, wrap.length() );
61 cname = cname.substr( 0, pos );
62 sscanf( Wrapx.c_str(),
"%d", &wrapx );
63 pos = Wrapx.find(
"wrapy" );
64 if (pos != string::npos) {
65 string Wrapy = Wrapx.substr( pos+5, Wrapx.length() );
66 sscanf( Wrapy.c_str(),
"%d", &wrapy );
74 namespace StarSystemGent
78 return (a > b) ? a :
b;
81 int rnd(
int lower,
int upper )
84 return lower+
ssrand()%(upper-lower);
91 return string(
nada );
92 return s[
rnd( 0, s.size() )];
98 return string(
nada );
99 unsigned int i =
rnd( 0, s.size() );
101 s.erase( s.begin()+i );
107 float nr, ng, nb, na;
108 Color(
float rr,
float gg,
float bb )
127 template <
class vec >
Vector(
const vec &in )
129 memcpy(
this, &in,
sizeof (*
this) );
133 memcpy(
this, &in,
sizeof (*
this) );
141 Vector(
float x,
float y,
float z,
float s,
float t )
151 return sqrtf(
i*
i+
j*
j+
k*
k );
156 this->k*v.
i-this->i*v.
k,
157 this->i*v.
j-this->j*v.
i );
167 else if (
k <= 0 &&
i == 0)
169 else if (
k > 0 &&
i == 0)
184 else if (
j <= 0 &&
i == 0)
186 else if (
j > 0 &&
i == 0)
201 else if (
j <= 0 &&
k == 0)
203 else if (
j > 0 &&
k == 0)
227 return sqrt( ( (inputdiffuse) ) );
234 ambient *= ambientColorFactor;
236 f.Fprintf(
"<Light>\n" );
239 f.Fprintf(
"<ambient red=\"%f\" green=\"%f\" blue=\"%f\"/>\n", ambient, ambient, ambient );
244 f.Fprintf(
"<specular red=\"%f\" green=\"%f\" blue=\"%f\"/>\n",
lights[i].nr,
lights[i].ng,
lights[i].nb );
247 f.Fprintf(
"</Light>\n" );
348 printf(
"Failed to load %s", file );
351 g.r =
g.g =
g.b = .9;
353 entity.push_back(
"white_star.png" );
358 char output_buffer[1000];
362 if (sscanf( input_buffer,
"%f %f %f %f %f %s", &g.
minrad, &g.
r, &g.
g, &g.
b, &g.
variance, output_buffer ) == 6) {
365 entity.push_back( output_buffer );
387 vector< string >entity;
388 string fullpath =
"stars.txt";
404 return Color( r, g, b );
408 unsigned int myint = 0;
411 return GFXColor( tmp.r, tmp.g, tmp.b, 1 );
429 unsigned int gradindex;
441 lights.back().r *= norm/h;
442 lights.back().g *= norm/h;
443 lights.back().b *= norm/h;
462 int i = (
rnd( 0, 8 ) );
463 r.
i = (i&1) ? -r.
i : r.
i;
464 r.
j = (i&2) ? -r.
j : r.
j;
465 r.
k = (i&4) ? -r.
k : r.
k;
471 int i = (
rnd( 0, 8 ) );
472 r.
i = (i&1) ? -r.
i : r.
i;
473 r.
j = (i&2) ? -r.
j : r.
j;
474 r.
k = (i&4) ? -r.
k : r.
k;
478 k.i = (i&1) ? -
k.i :
k.i;
479 k.j = (i&2) ? -
k.j :
k.j;
480 k.k = (i&4) ? -
k.k :
k.k;
485 return makeRS( r, s, minradii, jumppoint );
498 rm = (tmpcompactness*
grand()+1);
507 sm = (tmpcompactness*
grand()+1);
508 if (tmp) sm = (1+
grand()*.5);
513 return mmax( rm, sm );
519 orbitsize += thisplanetradius;
520 radii.back() = orbitsize;
526 if (
radii.empty() ) {
531 float tmp =
radii.back()+thisplanetradius;
538 char *mystr = strdup( input.c_str() );
540 char *oldptr = mystr;
542 while (*ptr !=
'\0') {
543 while (*ptr !=
'&' && *ptr !=
'\0')
549 ans.push_back(
string( oldptr ) );
558 const string &filename,
562 const string &nebfile,
563 const string &destination,
568 f.Fprintf(
"<%s name=\"%s\" file=\"%s\" ", tag.c_str(), name.c_str(), filename.c_str() );
569 if (nebfile.length() > 0)
570 f.Fprintf(
"nebfile=\"%s\" ", nebfile.c_str() );
571 f.Fprintf(
"ri=\"%f\" rj=\"%f\" rk=\"%f\" si=\"%f\" sj=\"%f\" sk=\"%f\" ", r.
i, r.
j, r.
k, s.
i, s.
j, s.
k );
572 f.Fprintf(
"x=\"%f\" y=\"%f\" z=\"%f\" ", center.
i, center.
j, center.
k );
575 f.Fprintf(
"year= \"%f\" ", thisloy ? thisloy : loy );
576 if ( destination.length() )
577 f.Fprintf(
"destination=\"%s\" ", destination.c_str() );
585 if ( 1 == sscanf( s.c_str(),
"Jump_To_%s", tmp ) )
586 tmp[0] = tolower( tmp[0] );
588 return string( tmp );
592 char *tmp = strdup( input.c_str() );
593 for (
unsigned int i = 0; tmp[
i] !=
'\0';
i++)
606 string ip = input.c_str();
607 char *ptr = strdup( ip.c_str() );
608 for (
unsigned int i = 0; ptr[
i] !=
'\0';
i++)
620 string AnalyzeType(
string &input,
string &nebfile,
float &radius )
624 char ptr = *input.begin();
626 if ( 0 == sscanf(
GetNebFile( input ).c_str(),
"%f", &radius ) ) {
628 ip = (input.c_str()+1);
646 retval =
"Enhancement";
659 string s = string(
"" );
660 while (s.length() == 0) {
662 if (nam.length() == 0)
665 if ( ( tmp =
starin( nam ) ).length() > 0 ) {
673 string nebfile(
"" );
678 WriteUnit( type,
"", nam, R, S, center, nebfile, s,
true );
686 0 ),
float thisloy = 0 )
701 if (thisname.length() > 8)
702 *(thisname.begin()+8) = toupper( *(thisname.begin()+8) );
706 static const char *jumpFilename = usePNGFilename ?
"jump.png" :
"jump.texture";
707 f.Fprintf(
"<Jump name=\"%s\" file=\"%s\" ", thisname.c_str(), jumpFilename );
708 f.Fprintf(
"ri=\"%f\" rj=\"%f\" rk=\"%f\" si=\"%f\" sj=\"%f\" sk=\"%f\" ", RR.
i, RR.
j, RR.
k, SS.
i, SS.
j, SS.
k );
709 f.Fprintf(
"radius=\"%f\" ", radius );
712 float temprandom = .1*fmod( loy, 10 );
713 if (loy || thisloy) {
714 f.Fprintf(
"year= \"%f\" ", thisloy ? thisloy : loy );
715 temprandom =
grand();
716 loy = 864*temprandom;
718 f.Fprintf(
"day=\"%f\" ", loy );
720 f.Fprintf(
"alpha=\"ONE ONE\" destination=\"%s\" faction=\"%s\" />\n",
getJumpTo(
726 void MakeBigUnit(
int callingentitytype,
string name =
string(),
float orbitalradius = 0 )
728 vector< string >fullname;
729 if (name.length() == 0) {
735 fullname.push_back( name );
737 if ( fullname.empty() )
747 string nebfile(
"" );
748 for (
unsigned int i = 0;
i < fullname.size();
i++) {
749 if ( 1 == sscanf( fullname[
i].c_str(),
"jump%f", &size ) ) {
755 MakeJump( size,
true, r, s, center, stdloy );
758 == sscanf( fullname[
i].c_str(),
"planet%f",
760 == sscanf( fullname[
i].c_str(),
"moon%f", &size ) || 1 == sscanf( fullname[
i].c_str(),
"gas%f", &size ) ) {
762 }
else if ( ( tmp =
starin( fullname[
i] ) ).length() > 0 ) {
769 if (S.length() > 0) {
774 string type =
AnalyzeType( fullname[i], nebfile, size );
780 WriteUnit( type,
"", fullname[i], r, s, center, nebfile,
string(
"" ), i != 0, stdloy );
784 void MakeMoons(
float callingradius,
int callingentitytype );
785 void MakeJumps(
float callingradius,
int callingentitytype,
int numberofjumps );
786 void MakePlanet(
float radius,
int entitytype,
string texturename,
string unitname,
string technique,
int texturenum,
int numberofjumps,
int numberofstarbases )
788 if (entitytype ==
JUMP) {
792 if (texturename.length() == 0)
800 "DefaultAtmosphereTexture",
801 "sol/earthcloudmaptrans.png" );
803 if (atmosphere ==
"false")
805 else if (atmosphere ==
"true")
806 atmosphere = default_atmosphere;
809 if ( !planetlites.empty() ) {
810 planetlites =
' '+planetlites;
811 vector< string::size_type >lites;
812 lites.push_back( 0 );
813 while (lites.back() != string::npos)
814 lites.push_back( planetlites.find( lites.back()+1,
' ' ) );
815 unsigned randomnum =
rnd( 0, lites.size()-1 );
816 cname = planetlites.substr( lites[randomnum]+1, lites[randomnum+1] );
818 f.Fprintf(
"<Planet name=\"%s\" file=\"%s\" unit=\"%s\" ", thisname.c_str(), texturename.c_str(), unitname.c_str() );
819 if (!technique.empty())
820 f.Fprintf(
"technique=\"%s\" ", technique.c_str() );
821 if (texturename.find_first_of(
'|') != string::npos)
822 f.Fprintf(
"Red=\"0\" Green=\"0\" Blue=\"0\" DRed=\"0.87\" DGreen=\"0.87\" DBlue=\"0.87\" SRed=\"0.85\" SGreen=\"0.85\" SBlue=\"0.85\" ");
823 f.Fprintf(
"ri=\"%f\" rj=\"%f\" rk=\"%f\" si=\"%f\" sj=\"%f\" sk=\"%f\" ", RR.
i, RR.
j, RR.
k, SS.
i, SS.
j, SS.
k );
824 f.Fprintf(
"radius=\"%f\" ", radius );
825 f.Fprintf(
"x=\"%f\" y=\"%f\" z=\"%f\" ", center.
i, center.
j, center.
k );
827 float temprandom = .1*fmod( loy, 10 );
829 f.Fprintf(
"year= \"%f\" ", loy );
830 temprandom =
grand();
831 loy = 864*temprandom;
833 f.Fprintf(
"day=\"%f\" ", loy );
837 if ( !cname.empty() ) {
840 cname =
GetWrapXY( cname, wrapx, wrapy );
842 while ( ( t = cname.find(
'*' ) ) != string::npos )
845 f.Fprintf(
"<CityLights file=\"%s\" wrapx=\"%d\" wrapy=\"%d\"/>\n", cname.c_str(), wrapx, wrapy );
848 if ( (entitytype ==
PLANET && temprandom < atmosphere_prob) && ( !atmosphere.empty() ) ) {
849 string NAME = thisname+
" Atmosphere";
851 bool doalphaatmosphere = (temprandom< .08 || temprandom >.3);
852 if (doalphaatmosphere) {
853 float fograd = radius*1.007;
854 if (.007*radius > 2500.0)
855 fograd = radius+2500.0;
857 f.Fprintf(
"<Atmosphere file=\"%s\" alpha=\"SRCALPHA INVSRCALPHA\" radius=\"%f\"/>\n",
858 atmosphere.c_str(), fograd );
860 float r = .9,
g = .9,
b = 1,
a = 1;
861 float dr = .9, dg = .9, db = 1, da = 1;
862 if (!doalphaatmosphere) {
863 if (temprandom > .26 || temprandom < .09) {
867 }
else if (temprandom > .24 || temprandom < .092) {
881 f.Fprintf(
"<Fog>\n" );
885 "<FogElement file=\"atmXatm.bfxm\" ScaleAtmosphereHeight=\"1.0\" red=\"%f\" blue=\"%f\" green=\"%f\" alpha=\"%f\" dired=\"%f\" diblue=\"%f\" digreen=\"%f\" dialpha=\"%f\" concavity=\".3\" focus=\".6\" minalpha=\"0\" maxalpha=\"0.7\"/>\n",
896 "<FogElement file=\"atmXhalo.bfxm\" ScaleAtmosphereHeight=\"1.0\" red=\"%f\" blue=\"%f\" green=\"%f\" alpha=\"%f\" dired=\"%f\" diblue=\"%f\" digreen=\"%f\" dialpha=\"%f\" concavity=\"1\" focus=\".6\" minalpha=\"0\" maxalpha=\"0.7\"/>\n",
907 f.Fprintf(
"</Fog>\n" );
911 radii.push_back( radius );
915 if (entitytype ==
PLANET) {
916 float ringrand =
grand();
917 if (ringrand < ringprob) {
921 double inner_rad = ( innerRingRadMin*(1+
grand()*.5) )*radius;
922 double outer_rad = inner_rad+( outerRingRadMin*
grand() )*radius;
925 if ( ringname.empty() ) {
927 "DefaultRingTexture",
928 "planets/ring.pngwrapx36wrapy2" );
929 ringname = defringname;
931 ringname =
GetWrapXY( ringname, wrapx, wrapy );
934 float rmag = r.
Mag();
940 float smag = s.
Mag();
946 if ( ringrand < (1-dualringprob) ) {
949 "<Ring file=\"%s\" ri=\"%f\" rj=\"%f\" rk=\"%f\" si=\"%f\" sj=\"%f\" sk=\"%f\" innerradius=\"%f\" outerradius=\"%f\" wrapx=\"%d\" wrapy=\"%d\" />\n",
962 if ( ringrand < dualringprob || ringrand >= (ringprob-dualringprob) ) {
963 double movable =
grand();
964 static float second_ring_move =
966 inner_rad = outer_rad*( 1+.1*(second_ring_move+second_ring_move*movable) );
967 outer_rad = inner_rad*(outerRingRadMin*movable);
970 "<Ring file=\"%s\" ri=\"%f\" rj=\"%f\" rk=\"%f\" si=\"%f\" sj=\"%f\" sk=\"%f\" innerradius=\"%f\" outerradius=\"%f\" wrapx=\"%d\" wrapy=\"%d\" />\n",
985 for (
int i = 0;
i < numberofstarbases;
i++)
987 static float moon_size_compared_to_planet =
989 static float moon_size_compared_to_moon =
992 MakeMoons( entitytype !=
MOON ? moon_size_compared_to_planet*radius : moon_size_compared_to_moon*radius, entitytype );
998 f.Fprintf(
"</Planet>\n" );
1003 void MakeJumps(
float callingradius,
int callingentitytype,
int numberofjumps )
1005 for (
int i = 0;
i < numberofjumps;
i++)
1008 void MakeMoons(
float callingradius,
int callingentitytype )
1031 f.Fprintf(
"ri=\"%f\" rj=\"%f\" rk=\"%f\" si=\"%f\" sj=\"%f\" sk=\"%f\" ", r.
i, r.
j, r.
k, s.
i, s.
j, s.
k );
1033 f.Fprintf(
"radius=\"%f\" x=\"%f\" y=\"%f\" z=\"%f\" ", radius, center.
i, center.
j, center.
k );
1035 f.Fprintf(
"radius=\"%f\" x=\"0\" y=\"0\" z=\"0\" ", radius );
1038 f.Fprintf(
"year= \"%f\" ", loy );
1041 f.Fprintf(
"day=\"%f\" ", loy );
1043 f.Fprintf(
" Red=\"%f\" Green=\"%f\" Blue=\"%f\" ReflectNoLight=\"true\" light=\"%d\">\n",
lights[
staroffset].r,
1046 "<fog>\n\t<FogElement file=\"atmXatm.bfxm\" ScaleAtmosphereHeight=\".900\" red=\"%f\" blue=\"%f\" green=\"%f\" alpha=\"1.0\" dired=\"%f\" diblue=\"%f\" digreen=\"%f\" dialpha=\"1\" concavity=\".3\" focus=\".6\" minalpha=\".7\" maxalpha=\"1\"/>\n\t<FogElement file=\"atmXhalo.bfxm\" ScaleAtmosphereHeight=\".9000\" red=\"%f\" blue=\"%f\" green=\"%f\" alpha=\"1.0\" dired=\"%f\" diblue=\"%f\" digreen=\"%f\" dialpha=\"1\" concavity=\".3\" focus=\".6\" minalpha=\".7\" maxalpha=\"1\"/>\n</fog>\n",
1059 radii.push_back( 1.5*radius );
1060 static float planet_size_compared_to_sun =
1073 for (i = 0; i < numu; ++i)
1080 if ( !
jumps.empty() )
1090 f.Fprintf(
"</Planet>\n" );
1125 f.Fprintf(
"<?xml version=\"1.0\" ?>\n<system name=\"%s\" background=\"%s\">\n",
systemname.c_str(),
1131 f.Fprintf(
"</system>\n" );
1134 void readentity( vector< string > &entity,
const char *filename )
1142 while ( 1 == f.
Fscanf(
"%s", input_buffer ) )
1143 entity.push_back( input_buffer );
1149 const char *tmp = in;
1150 while (*tmp !=
'\0' && *tmp !=
'/')
1156 const char *tmp2 = tmp;
1158 if (tmp2[0] !=
'\0')
1164 using namespace StarSystemGent;
1167 return input+string(
".system" );
1171 return string(
noslash( in.c_str() ) );
1175 string::size_type sep = in.find(
'/' );
1176 if (sep == string::npos)
1177 return string(
"." );
1180 return in.substr( 0, sep );
1182 void readnames( vector< string > &entity,
const char *filename )
1190 while ( !f.
Eof() ) {
1192 if (input_buffer[0] ==
'\0' || input_buffer[0] ==
'\n' || input_buffer[0] ==
'\r')
1194 for (
unsigned int i = 0; input_buffer[
i] !=
'\0' &&
i < 999;
i++) {
1195 if (input_buffer[
i] ==
'\r')
1196 input_buffer[
i] =
'\0';
1197 if (input_buffer[
i] ==
'\n') {
1198 input_buffer[
i] =
'\0';
1202 entity.push_back( input_buffer );
1207 void readplanetentity( vector< StarInfo > &starinfos,
string planetlist,
unsigned int numstars )
1211 vs_fprintf( stderr,
"No stars exist in this system!\n" );
1213 string::size_type
i,
j;
1215 starinfos.reserve( numstars );
1216 for (u = 0; u < numstars; ++u)
1219 while (i = planetlist.find(
' ' ), 1) {
1221 planetlist = planetlist.substr( 1 );
1225 for (j = 0; j < i && j < planetlist.size() && planetlist[j] ==
'*'; ++j)
1229 if ( j == string::npos || j >= planetlist.size() )
break;
1230 starinfos[u%numstars].planets.push_back(
PlanetInfo() );
1231 starinfos[u%numstars].planets.back().moonlevel = nummoon;
1235 static const string numtag(
"#num#");
1236 static const string empty;
1237 static const string::size_type numlen = numtag.length();
1238 string::size_type numpos;
1241 string planetname = galaxy->
getPlanetNameFromInitial( planetlist.substr( j, i == string::npos ? string::npos : i-j ) );
1242 string texturename = galaxy->
getPlanetVariable( planetname,
"texture",
"No texture supplied in <planets>!" );
1245 string defunitname = texturename.substr(0, texturename.find_first_of(
'|'));
1246 if (defunitname.find_last_of(
'/') != string::npos)
1247 defunitname = defunitname.substr(defunitname.find_last_of(
'/')+1);
1248 defunitname = defunitname.substr(0, defunitname.find_last_of(
'.'));
1251 while ((numpos = defunitname.find(numtag, numpos)) != string::npos)
1252 defunitname.replace(numpos, numlen, empty);
1260 starinfos[u%numstars].planets.back().num =
1265 if (starinfos[u%numstars].planets.back().num == 0)
1268 snprintf(num,
sizeof(num),
"%d", starinfos[u%numstars].planets.back().num);
1271 while ((numpos = texturename.find(numtag, numpos)) != string::npos)
1272 texturename.replace(numpos, numlen, num);
1275 starinfos[u%numstars].planets.back().name = texturename;
1276 starinfos[u%numstars].planets.back().unitname = unitname;
1277 starinfos[u%numstars].planets.back().technique = techniquename;
1279 starinfos[u%numstars].planets.back().numstarbases = 0;
1280 starinfos[u%numstars].planets.back().numjumps = 0;
1281 if (i == string::npos)
break;
1282 planetlist = planetlist.substr( i+1 );
1285 if ( starinfos.size() ) {
1287 for (k = 0; k < starinfos.size(); ++k)
1288 if ( starinfos[k].planets.size() ) {
1293 int oldjumps =
jumps.size();
1296 for (k = starinfos.size(); k > 0; --k) {
1297 newstuff = oldjumps/k;
1298 starinfos[k-1].numjumps = newstuff;
1299 oldjumps -= newstuff;
1300 newstuff = oldstarbases/k;
1301 starinfos[k-1].numstarbases = newstuff;
1302 oldstarbases -= newstuff;
1305 for (k = 0; k <
jumps.size(); ++k) {
1306 vector< PlanetInfo > *temp;
1308 temp = &starinfos[
rnd( 0, starinfos.size() )].planets;
1309 while ( !temp->size() );
1310 (*temp)[
rnd( 0, temp->size() )].numjumps++;
1313 vector< PlanetInfo > *temp;
1315 temp = &starinfos[
rnd( 0, starinfos.size() )].planets;
1316 while ( !temp->size() );
1317 (*temp)[
rnd( 0, temp->size() )].numstarbases++;
1325 while (
grand() > (1/val) )
1332 return delta+
pushDown( val-delta );
1337 if (!dopushingtomean)
1351 static float jump_compactness_scale =
1380 for (
unsigned int i = 0;
i < si.
jumps.size();
i++)
1399 int main(
int argc,
char **argv )
1404 "Usage: starsysgen <seed> <sector>/<system> <sunradius>/<compactness> <numstars> [N][A]<numnaturalphenomena> <numstarbases> <faction> <namelist> [OtherSystemJumpNodes]...\n" );
1408 if ( 1 != sscanf( argv[1],
"%d", &seed ) )
1415 bool asteroid =
true;
1418 sscanf( argv[3],
"%f/%f", &srad&comp );
1419 vector< string >
jumps;
1420 for (
unsigned int i = 12;
i < argc;
i++)
1421 jumps.push_back(
string( argv[i] ) );
1422 if ( 1 == sscanf( argv[8],
"AN%d", &numbigthings ) || 1 == sscanf( argv[8],
"NA%d", &numun[0] ) )
1423 nebula = asteroid =
true;
1424 else if ( 1 == sscanf( argv[8],
"A%d", &numbigthings ) )
1426 else if ( 1 == sscanf( argv[8],
"N%d", &numbigthings ) )
1428 else if ( 1 == sscanf( argv[8],
"%d", &numbigthings ) )
1429 nebula = asteroid =
true;
1438 strtol( argv[4], NULL, 10 ),
1439 strtol( argv[5], NULL, 10 ),
1440 strtol( argv[6], NULL, 10 ),
1441 strtol( argv[7], NULL, 10 ),
1445 strtol( argv[9], NULL, 10 ),