//signal handler simply runs printHist() void handle_SIGQUIT() { printHist(); }
int main (int argc, char**argv) { bool doHelp=false; if (argc<=1) { doHelp=true; } for (int i=1;i<argc;++i) { if (strcmp(argv[i],"-h")==0|| strcmp(argv[i],"-help")==0|| strcmp(argv[i],"--help")==0|| strcmp(argv[i],"/help")==0|| strcmp(argv[i],"/h")==0) { doHelp=true; } } if (doHelp) { printf("Usage Example:\n\n%s SAVE1.GAM SAVE2.GAM q0 SAVE3.GAM\nThe above example takes the planets from SAVE1.GAM applies it to the monsters and 4 player races and planet picks of SAVE2.GAM takes the 0th quadrant (numbered from 0 to 3) and saves the result into SAVE3.GAM\n\n",argv[0]); printf("Generic usage %s <planetInput> <raceInput> <quadrantSelection> <output>\n\n",argv[0]); printf("The general usage is that <planetInput> should be set to a Master of Orion II save game file, often the same file, that contains the planets and <raceInput> should be set to the save game that has the desired races. Then the quadrantSelection selects a portion of the map and rotates and mirrors it so that every player gets an even shake. <output> should be set to the final save file that may be reloaded for the fair game\n\n"); printf("quadrant selection is limited to the following options:\n"); printf("2 player options:\n"); printf("h0 assume a 2 player game and take the left half and reflect it\n"); printf("h1 assume a 2 player game and take the right half and reflect it\n"); printf("v0 assume a 2 player game and take the top half and reflect it\n"); printf("v1 assume a 2 player game and take the bottom half and reflect it\n"); printf("4 player options:\n"); printf("q0 assume a 4 player game and take the top left quarter and mirror it\n"); printf("q1 assume a 4 player game and take the bottom left quarter and mirror it\n"); printf("q2 assume a 4 player game and take the bottom right quarter and mirror it\n"); printf("q3 assume a 4 player game and take the top right quarter and mirror it\n"); printf("6 player options:\n"); printf("x0 or x1 or x2 or x3 or x4 or x5 mirror the appropriate slice\n"); return 0; } srand(0x31337); Star stars[MAX_NUM_STARS]; Planet planets[MAX_NUM_PLANETS]; Star newStars[MAX_NUM_STARS]; Planet newPlanets[MAX_NUM_PLANETS]; homeworlds.insert("Sol"); homeworlds.insert("Nazin"); homeworlds.insert("Meklon"); homeworlds.insert("Altair"); homeworlds.insert("Ursa"); homeworlds.insert("Gnol"); homeworlds.insert("Draconis"); homeworlds.insert("Kholdan"); homeworlds.insert("Sssla"); homeworlds.insert("Mentar"); homeworlds.insert("Fieras"); homeworlds.insert("Cryslon"); homeworlds.insert("Trilar"); FILE * fp = fopen(argv[1],"rb"); fseek(fp,0,SEEK_END); size_t fileSize = ftell(fp); fseek(fp,0,SEEK_SET); byt * data = (byt*)malloc(fileSize); fread(data,1,fileSize,fp); fclose(fp); FILE * output; size_t writeFileSize=0; byt * writeData; if (argc>2) { output = fopen(argv[2],"rb"); fseek(output,0,SEEK_END); writeFileSize = ftell(output); fseek(output,0,SEEK_SET); writeData = (byt*)malloc(fileSize); fread(writeData,1,writeFileSize,output); fclose(output); } for (int doInput=(argc>2?0:1);doInput<2;++doInput) { for (int i=0;i<NUM_PLANETS;++i) { const byt * curData = (doInput?data:writeData)+(PLANET_OFFSET+i*PLANET_SIZE); Planet planetA; memcpy(&planetA,curData,PLANET_SIZE); Planet planetB; planetB.readPlanet(curData); //planetB.printPlanet(NULL); if (memcmp(&planetA,&planetB,PLANET_SIZE)) { printf("Endianness Mismatch: luckily we coded for that\n"); } byt testIdempotency[PLANET_SIZE]; planetB.writePlanet(testIdempotency); planetA.readPlanet(testIdempotency); if (memcmp(&planetA,&planetB,PLANET_SIZE)) { printf("Idempotency Mismatch: FAIL\n"); } if (memcmp(testIdempotency,curData,PLANET_SIZE)) { printf("Idempotency Mismatch: FAIL Internal\n"); } if (doInput) { planets[i]=planetB; }else { newPlanets[i]=planetB; } } } int maxx = -(1<<30); int minx = (1<<30); int maxy = -(1<<30); int miny = (1<<30); nerf(stars,planets); for (int doInput=(argc>2?0:1);doInput<2;++doInput) { for (int i=0;i<NUM_STARS;++i) { const byt * curData = (doInput?data:writeData)+(STAR_OFFSET+i*STAR_SIZE); Star starA; memcpy(&starA,curData,STAR_SIZE); // starA.printStar(); Star starB; starB.readStar(curData); if (doInput) { if (starB.x!=0||starB.y!=0) { if (starB.x<minx) { minx = starB.x; } if (starB.x>maxx) { maxx = starB.x; } if (starB.y<miny) { miny = starB.y; } if (starB.y>maxy) { maxy = starB.y; } }else { //invalid system } stars[i]=starB; }else { newStars[i]=starB; } if (memcmp(&starA,&starB,STAR_SIZE)) { printf("Endianness Mismatch: luckily we coded for that\n"); } byt testIdempotency[STAR_SIZE]; starB.writeStar(testIdempotency); starA.readStar(testIdempotency); if (memcmp(&starA,&starB,STAR_SIZE)) { starB.writeStar(testIdempotency); starA.readStar(testIdempotency); printf("Idempotency Mismatch: FAIL\n"); if (!(starA==starB)) { printf("Idempotency Mismatch: FAIL B\n"); } } if (memcmp(testIdempotency,curData,STAR_SIZE)) { printf("Idempotency Mismatch: FAIL Internal\n"); } } } for (int i=0;i<NUM_STARS;++i) { if (newStars[i].isEmpty()) { NUM_STARS=i; if (i==0) NUM_STARS=71; printf("Setting num stars to %d\n",NUM_STARS); break; } } if (argc==2) { for (int i=0;i<NUM_STARS;++i) { stars[i].recordHist(); stars[i].printStar(planets,stars); } printf("Bounds: (%d,%d) - (%d,%d)\n",minx,miny,maxx,maxy); printHist(); return 0; } printf("Bounds: (%d,%d) - (%d,%d)\n",minx,miny,maxx,maxy); if (false) { for (int i=0;i<NUM_STARS;++i) { isHomeworld(stars[i],planets); } for (int i=0;i<NUM_STARS;++i) { isHomeworld(newStars[i],newPlanets); } for (std::set<std::string>::iterator i=validNames.begin(),ie=validNames.end();i!=ie;++i) { starNames.push_back(*i); } }else { for (int i=0;i<sizeof(possibleNames)/sizeof(char*);++i) { starNames.push_back(possibleNames[i]); } } //wipePlanets(newStars,newPlanets); //wipeStars(newStars,newPlanets); no longer: we now work with what we have double percent_safe_zone=0;//.03125; double wid = maxx-minx; double hei = maxy-miny; char mode = argv[3][0]; int slice=argv[3][1]-'0';//q2 is the 2nd quadrant x5 is the 5th hex zone h0 is the 0th horizontal slice v0 is the 0th vertical slice double sourceminx; double sourcemaxx; double sourceminy; double sourcemaxy; bool flipX=true; bool flipY=true; int numX=2,numY=2; if (mode=='q') { NUM_PLAYERS=4; numX=2; numY=2; flipX=true; flipY=true; } if (mode=='h') { NUM_PLAYERS=2; numX=2; numY=1; flipX=true; flipY=false; } if (mode=='v') { NUM_PLAYERS=2; numX=1; numY=2; flipX=false; flipY=true; } if (mode=='x') { NUM_PLAYERS=6; numX=3; numY=2; flipX=false; flipY=true; } { std::set<int>homeworldlessQuadrant; std::vector<int> freePlanets; std::map<int,int> starMap;//destination star to source star (multiple desitnations may reference a single source) int freeStar=0; double homeX, homeY; for (int doPlace=0;doPlace<2;++doPlace) { int count=0; for (int x=0;x<numX;++x) { for (int y=0;y<numY;++y) { double lenx = (maxx-minx)/(double)numX; double leny = (maxy-miny)/(double)numY; double localminx=minx+lenx*x; double localminy=miny+leny*y; double localmaxx=numX==1?lenx:lenx-percent_safe_zone; double localmaxy=numY==1?leny:leny-percent_safe_zone; localmaxx+=localminx; localmaxy+=localminy; if (numX>1) {//we shove things over so that we are flush with maxx by the end double del = x*percent_safe_zone/(numX-1); localminx+=del; localmaxx+=del; if (x+1==numX) { localmaxx=maxx;//we don't want a float error here } } if (numY>1) {//we shove things over so we are flush with maxx by the end double del = y*percent_safe_zone/(numY-1); localminy+=del; localmaxy+=del; if (y+1==numY) { localmaxy=maxy;//we don't want a float error here cus we need every last star } } if (!doPlace) { //printf("Searching range (%f %f, %f %f)\n",localminx,localminy,localmaxx,localmaxy); if (slice==count) { sourceminx=localminx; sourceminy=localminy; sourcemaxx=localmaxx; sourcemaxy=localmaxy; int homeIndex = findHomeworld (stars,planets,localminx,localminy,localmaxx,localmaxy); if (homeIndex==-1) { printf("Cannot find homeworld in section %d...exiting\n",slice); return -1; }else { Star homeSystem = stars[homeIndex]; homeX = ((flipX&&x)?localmaxx-homeSystem.x:homeSystem.x-localminx); homeY = ((flipY&&y)?localmaxy-homeSystem.y:homeSystem.y-localminy); printf("Homeworld located at %s %f %f (%d %d)\n",homeSystem.name,homeX,homeY,homeSystem.x,homeSystem.y); } } //wipeQuadrant(newStars,newPlanets,localminx,localminy,localmaxx,localmaxy); }else if (doPlace==1){ copyQuadrantStars(newStars,newPlanets, localminx,localminy,localmaxx,localmaxy, stars,planets,sourceminx,sourceminy,sourcemaxx,sourcemaxy,flipX,flipY,count,starMap,freePlanets, freeStar);//saves up some free planets for us int newHomeX = (flipX&&x)?localmaxx-homeX:homeX+localminx; int newHomeY = (flipY&&y)?localmaxy-homeY:homeY+localminy; printf("Placing homeworld at %d %d (From %f %f)\n",newHomeX, newHomeY, homeX, homeY); if (!fixupHomeworlds(newStars,newPlanets, localminx,localminy,localmaxx,localmaxy, newHomeX,newHomeY,count)) { printf("Could not find %d th homeworld\n",count); } } ++count; } } } {//go through and copy planets while ((freeStar=nextFreeStar(newStars,newPlanets,freeStar))!=-1) { //if (!isHomeworld(newStars[freeStar],newPlanets)) {freeStar should look for homeworlds //uSELESS STAR //strcpy(newStars[freeStar].name,"DANGER"); printf("Found a free star\n"); for (int p=0;p<5;++p) { if (newStars[freeStar].planets[p]!=-1&&newStars[freeStar].planets[p]<NUM_PLANETS) { if (newPlanets[newStars[freeStar].planets[p]].data[PARENT_STAR]==freeStar) { freePlanets.push_back(newStars[freeStar].planets[p]); }else { if (newStars[freeStar].planets[p]!=0&&newStars[freeStar].planets[p]<NUM_PLANETS) { printf("Odd syste in save file that's cross referenced\n"); } } } newStars[freeStar].planets[p]=-1; } //} ++freeStar; } printf("Orphan star size %d\n",(int)orphanStars.size()); int orphanCount=orphanStars.size()==2?1:0; for (int index=0;index<NUM_STARS;++index) { Star &dst=newStars[index]; if (starMap.find(index)!=starMap.end()) { int destStarIndex = index; Star star = stars[starMap[index]]; for (int p=0;p<5;++p) { if (dst.planets[p]!=-1&&dst.planets[p]<NUM_PLANETS) { if (newPlanets[dst.planets[p]].data[PARENT_STAR]==destStarIndex) { freePlanets.push_back(dst.planets[p]);//this will guarantee we pop these guys first to minimize change we can believe in }else if (dst.planets[p]!=0&&dst.planets[p]<NUM_PLANETS) { printf("Odder syste in save file that's cross referenced\n"); } dst.planets[p]=-1; } } bool didUltraRich=false; bool isThisOrphan = orphanStars.find(destStarIndex)!=orphanStars.end(); if(isThisOrphan) { dst.x=(minx+maxx)/2; dst.y=(miny+maxy)/2;//put this in the middle of the map if (orphanCount>0) { double angle=0; switch (orphanCount) { case 1: angle=0; break; case 2: angle=M_PI; break; case 3: angle=M_PI/2; break; case 4: angle=3*M_PI/2; break; default: angle = 3.1415926536*2*(.5+((orphanCount-5)/4.0)); break; } int del=(minx+maxx)/10; int delx = (int)(del*cos(angle)); int dely = (int)(del*sin(angle)); dst.x+=delx; dst.y+=dely; } ++orphanCount; } for (int p=0;p<5;++p) { if (star.planets[p]!=-1&&star.planets[p]<NUM_PLANETS) { if (freePlanets.size()) { int newPlanetIndex = freePlanets.back(); freePlanets.pop_back(); short originalOwner = newPlanets[newPlanetIndex].data[PARENT_STAR]; if (originalOwner>=0&&originalOwner<NUM_STARS) { const Star &check = newStars[originalOwner]; for (int pp=0;pp<5;++pp) { if (check.planets[pp]==newPlanetIndex&&check.planets[pp]!=-1) { printf("FATAL PLANETARY CROSS ALIGNMENT\n"); } } } crossMapPlanetCopy(newPlanets[newPlanetIndex],planets[star.planets[p]]); if (isThisOrphan) { if (didUltraRich==false&&newPlanets[newPlanetIndex].data[TYPE]==0x3) { didUltraRich=true; if (NUM_STARS>50) { newPlanets[newPlanetIndex].data[MINERALS]=0x4;//set to ultra rich!!!! newPlanets[newPlanetIndex].data[G]=0x2;//set to heavy G!!!! }else { newPlanets[newPlanetIndex].data[MINERALS]=0x3;//set to rich!!!! newPlanets[newPlanetIndex].data[G]=0x1;//set to normal G!!!! } newPlanets[newPlanetIndex].data[PLANETSIZECLASS]=rand()%0x5; newPlanets[newPlanetIndex].data[ENVIRONMENT]=rand()%0xa; }else { newPlanets[newPlanetIndex].data[G]=0x1;//set to normal G!!!! if (NUM_STARS>50) { newPlanets[newPlanetIndex].data[MINERALS]=rand()%0x3+1;//not ultra rich }else { newPlanets[newPlanetIndex].data[MINERALS]=rand()%0x2+1;//not ultra poor } newPlanets[newPlanetIndex].data[PLANETSIZECLASS]=rand()%0x5; newPlanets[newPlanetIndex].data[ENVIRONMENT]=rand()%0xa; } } dst.planets[p]=newPlanetIndex; newPlanets[newPlanetIndex].data[PARENT_STAR]=destStarIndex; }else { printf("Unable to allocate free planet for star %s\n",dst.name); } } } }else { printf("Could not locate source for %d\n",index); } } while (!freePlanets.empty()) { newPlanets[freePlanets.back()]=Planet(); freePlanets.pop_back(); } for (int index=0;index<NUM_STARS;++index) { bool error=false; for (int j=0;j<5;++j) { int ind = newStars[index].planets[j]; if (ind!=-1&&ind<NUM_PLANETS) { if (newPlanets[ind].data[PARENT_STAR]!=index) { newStars[index].planets[j]=-1; error=true; } } } if (error) { if (starMap.find(index)!=starMap.end()) { printf("MISMATCH ERROR in system %s index %d mapping to %s\n",newStars[index].name,index,stars[starMap[index]].name); }else { printf("MISMATCH ERROR in system %s index %d\n",newStars[index].name,index,stars[starMap[index]].name); } } } } } free(data); if (argc>4) {//if we can write to a file output = fopen(argv[4],"w+b");//overwrite the output save file fwrite(writeData,1,writeFileSize,output); free(writeData); fseek(output,PLANET_OFFSET,SEEK_SET); for (int i=0;i<NUM_PLANETS;++i) { unsigned char planetData[PLANET_SIZE]; newPlanets[i].writePlanet(planetData); fwrite(planetData,1,PLANET_SIZE,output); } fseek(output,STAR_OFFSET,SEEK_SET); for (int i=0;i<NUM_STARS;++i) { unsigned char starData[STAR_SIZE]; newStars[i].writeStar(starData); fwrite(starData,1,STAR_SIZE,output); } fclose(output); return 0; char *args[2]; args[0]=argv[0]; args[1]=argv[4]; return main(2,args); }else for (int i=0;i<NUM_STARS;++i) { newStars[i].printStar(newPlanets,newStars); } }