GlobalResourceMap::GlobalResourceMap(IAICallback* cb, cLogFile* l, GlobalTerrainMap* TM) : l(l) { // l = logfile; *l<<"\n Loading the Resource-Map ..."; const int RAI_MaxMetalSites = 1500; const int RAI_MaxGeoSites = 500; for( int iT=0; iT<2; iT++ ) RSize[iT] = 0; R[0] = new ResourceSite*[RAI_MaxMetalSites]; R[1] = new ResourceSite*[RAI_MaxGeoSites]; sector = 0; bool UDMetalResources = false; bool UDGeoResource = false; int udSize=cb->GetNumUnitDefs(); const UnitDef **udList = new const UnitDef*[udSize]; cb->GetUnitDefList(udList); for( int iud=udSize-1; iud>=0; iud-- ) { if( udList[iud] == 0 ) // Work-Around(Several Mods): Spring-Version(v0.72b1-0.76b1) { cb->SendTextMsg("WARNING: Mod Unit Definition Invalid.",0); *l<<"\n WARNING: (unitdef->id="<<iud+1<<") Mod UnitDefList["<<iud<<"] = 0"; udSize--; udList[iud] = udList[udSize]; } else if( udList[iud]->extractsMetal > 0 ) UDMetalResources = true; else if( udList[iud]->needGeo ) UDGeoResource = true; else { udSize--; udList[iud] = udList[udSize]; } } if( !UDGeoResource && !UDMetalResources ) { saveResourceFile = false; delete [] udList; *l<<"\n No resource units were detected for this mod."; return; } int *fList = NULL; int fSize = 0; if( UDGeoResource ) { int maxFeatures = cb->GetMaxUnits(); fList = new int[maxFeatures]; // Feature List // int fSize = cb->GetFeatures(fList,maxFeatures); // Crashes: Spring-Version(v0.75b2-v0.76b1) fSize = cb->GetFeatures(fList,maxFeatures,float3(1,1,1),999999); // Crash Work-Around if( fSize == maxFeatures ) { cb->SendTextMsg("WARNING: not all features will be searched for Geo Build Options",0); *l<<"\nWARNING: not all features will be searched for Geo Build Options"; } for(int i=0; i<fSize; i++) if( !cb->GetFeatureDef(fList[i])->geoThermal ) fList[i] = fList[--fSize]; } relResourceFileName = "cache/" + cRAI::MakeFileSystemCompatible(cb->GetModHumanName()); relResourceFileName += "-" + IntToString(cb->GetModHash(), "%x"); relResourceFileName += "-" + cRAI::MakeFileSystemCompatible(cb->GetMapName()); relResourceFileName += "-" + IntToString(cb->GetMapHash(), "%x"); relResourceFileName += ".res"; string resourceFileName_r; FILE* resourceFile_r = NULL; // get absolute file name if (cRAI::LocateFile(cb, relResourceFileName, resourceFileName_r, false)) { resourceFile_r = fopen(resourceFileName_r.c_str(), "rb"); } bool useResourceFile = false; if( resourceFile_r ) { try { useResourceFile = true; *l<<"\n Loading Resource-Site Data ..."; int udL2Size; file_read(&udL2Size, resourceFile_r); if( udSize != udL2Size ) useResourceFile = false; else { // Checks if the unit-Def list have changed int ID; for( int i=0; i<udSize; i++ ) { file_read(&ID, resourceFile_r); if( udList[i]->id != ID ) { // The order or types of definitions have changed useResourceFile = false; break; } } if( useResourceFile ) { int featureSites; file_read(&featureSites, resourceFile_r); if( fSize != featureSites ) useResourceFile = false; else { // Checks if the feature resource list has changed for( int i=0; i<fSize; i++ ) { file_read(&ID, resourceFile_r); if( fList[i] != ID ) { // The order or types of features have changed useResourceFile = false; break; } } if( useResourceFile ) { // The actual loading starts here typedef pair<ResourceSite*,ResourceSiteDistance> rrPair; typedef pair<int,float> ifPair; float3 position; float distance; int featureID; int size,dSize; int iT2,iR2; int optionID; for( int iT=0; iT<2; iT++ ) { file_read(&RSize[iT], resourceFile_r); for( int iR=0; iR<RSize[iT]; iR++ ) { file_read(&featureID, resourceFile_r); file_read(&position, resourceFile_r); if( featureID >= 0 ) R[iT][iR] = new ResourceSite(position,featureID,cb->GetFeatureDef(featureID)); else R[iT][iR] = new ResourceSite(position); file_read(&R[iT][iR]->amount, resourceFile_r); file_read(&size, resourceFile_r); for( int i=0; i<size; i++ ) { file_read(&optionID, resourceFile_r); R[iT][iR]->options.insert(optionID); } } } for( int iT=0; iT<2; iT++ ) for( int iR=0; iR<RSize[iT]; iR++ ) { file_read(&size, resourceFile_r); for( int i=0; i<size; i++ ) { file_read(&iT2, resourceFile_r); file_read(&iR2, resourceFile_r); R[iT][iR]->siteDistance.insert(rrPair(R[iT2][iR2],ResourceSiteDistance(0.0))); ResourceSiteDistance* RSD = &R[iT][iR]->siteDistance.find(R[iT2][iR2])->second; file_read(&RSD->minDistance, resourceFile_r); file_read(&RSD->bestPathType, resourceFile_r); file_read(&dSize, resourceFile_r); for( int i=0; i<dSize; i++ ) { file_read(&optionID, resourceFile_r); file_read(&distance, resourceFile_r); RSD->distance.insert(ifPair(optionID,distance)); } file_read(&dSize, resourceFile_r); for( int i=0; i<dSize; i++ ) { file_read(&position, resourceFile_r); RSD->pathDebug.push_back(position); } if( RSD->bestPathType == -2 ) RSD->bestDistance = &RSD->minDistance; else if( RSD->bestPathType >= 0 ) RSD->bestDistance = &RSD->distance.find(RSD->bestPathType)->second; } } file_read(&averageMetalSite, resourceFile_r); file_read(&isMetalMap, resourceFile_r); if( isMetalMap ) { sector = new MetalMapSector[TM->sectorXSize*TM->sectorZSize]; for( int iS=0; iS<TM->sectorXSize*TM->sectorZSize; iS++ ) { file_read(§or[iS].isMetalSector, resourceFile_r); sector[iS].S = &TM->sector[iS]; } } } } } } fclose(resourceFile_r); } catch (const std::exception& ex) { *l<<"\nERROR: failed reading the resource map: " << ex.what(); } if( !useResourceFile ) *l<<"\n A change has been detected in the map/mod, the resource data will be reloaded."; } // get absolute file name if (!cRAI::LocateFile(cb, relResourceFileName, resourceFileName_w, true)) { resourceFileName_w = ""; } if( useResourceFile || cb->GetCurrentFrame() == 0 ) { // only save the data if it was created at the beginning of a game saveResourceFile = true; for( int i=0; i<udSize; i++ ) saveUD.push_back(udList[i]->id); for( int i=0; i<fSize; i++ ) saveF.push_back(fList[i]); saveSectorSize = TM->sectorXSize*TM->sectorZSize; } else saveResourceFile = false; if( !UDGeoResource ) *l<<"\n No geo-resource units were detected for this mod."; else if( !useResourceFile ) { *l<<"\n Finding Geo-Sites ..."; float3 position; float3 buildPosition; for(int i=0; i<fSize; i++) { const FeatureDef *fd = cb->GetFeatureDef(fList[i]); if( fd->geoThermal ) { position = cb->GetFeaturePos(fList[i]); if( !TM->waterIsHarmful || cb->GetElevation(position.x,position.z) >= 0 ) { ResourceSite *RS = new ResourceSite(position,fList[i],fd); for( int iud=0; iud<udSize; iud++ ) { const UnitDef* ud = udList[iud]; if( ud->needGeo ) { buildPosition = cb->ClosestBuildSite(ud,RS->position,48.0f,0); if( cb->CanBuildAt(ud,buildPosition) ) RS->options.insert(ud->id); } } if( RS->options.empty() ) { *l<<"\n Energy Resource located at (x"<<RS->position.x<<" z"<<RS->position.z<<" y"<<RS->position.y<<") is unusable in this mod."; delete RS; } else R[1][RSize[1]++] = RS; } } } delete [] fList; *l<<"\n Geo-Sites Found: "<<RSize[1]; } else { delete [] fList; *l<<"\n Geo-Sites Loaded: "<<RSize[1]; } if( !UDMetalResources ) { *l<<"\n No metal-resource units were detected for this mod."; isMetalMap = false; averageMetalSite = 0.0; } else if( !useResourceFile ) { *l<<"\n Determining the available amount of metal ..."; *l<<"\n GetMaxMetal(): "<<cb->GetMaxMetal(); // Calculate the radius distances & ranges const float MMExtractorRadius = cb->GetExtractorRadius()/16.0; MMExtractorRadiusI = MMExtractorRadius; *l<<"\n Metal-Map Extractor Radius: "<<MMExtractorRadius; const int MMRSSize = MMExtractorRadiusI*2+1; MMRS = new sMMRadiusSquare*[MMRSSize]; for( int x=0; x<MMRSSize; x++ ) { MMRS[x] = new sMMRadiusSquare[MMRSSize]; for(int z=0; z<MMRSSize; z++) { MMRS[x][z].distance = float3(x,0,z).distance2D(float3(MMExtractorRadiusI,0,MMExtractorRadiusI)); if( MMRS[x][z].distance <= MMExtractorRadius ) MMRS[x][z].inRange = true; else MMRS[x][z].inRange = false; } } if( cb->GetExtractorRadius() <= 70.0 ) { int inRange = 0; for(int z=0; z<MMRSSize; z++) for(int x=0; x<MMRSSize; x++) if( MMRS[x][z].inRange ) inRange++; const float minimalMetalSquare = RAI_MinimalMetalSite/(inRange*cb->GetMaxMetal()); *l<<"\n Metal-Squares per Site: "<<inRange; *l<<"\n Minimal Metal-Square Value: "<<minimalMetalSquare; sector = new MetalMapSector[TM->sectorXSize*TM->sectorZSize]; const unsigned char *standardMetalMap = cb->GetMetalMap(); const int convertStoMM = TM->convertStoP/16; // * for conversion, / for reverse conversion const int metalMapXSize = TM->sectorXSize*convertStoMM; int uselessSectors = 0; int metalSectors = 0; float totalMetal = 0.0; // *l<<"\n Sector to Metal-Map Conversion: "<<convertStoMM; for(int z=0; z < TM->sectorZSize; z++) for(int x=0; x < TM->sectorXSize; x++) { //if( x == 0 ) *l<<"\n "; int i=(z*TM->sectorXSize)+x; sector[i].S = &TM->sector[i]; if( sector[i].S->maxElevation < 0 && TM->waterIsHarmful ) uselessSectors++; else { float sectorMetal = 0.0; int iMap = ((z*convertStoMM)*metalMapXSize)+x*convertStoMM; //*l<<"\t"<<standardMetalMap[iMap]; for(int zM=0; zM<convertStoMM; zM++) for(int xM=0,iM=iMap+zM*metalMapXSize+xM; xM<convertStoMM; xM++,iM=iMap+zM*metalMapXSize+xM ) if( (float)standardMetalMap[iM] > 2.0*minimalMetalSquare ) { sector[i].percentMetal++; sectorMetal += standardMetalMap[iM]; } sector[i].percentMetal *= 100.0/(convertStoMM*convertStoMM); if( sector[i].percentMetal >= 75.0 )//&& sector[i].totalMetal > 2*RAI_MinimalMetalSite ) { sector[i].isMetalSector = true; metalSectors++; totalMetal += sectorMetal; } //*l<<"\t("<<sector[i].totalMetal<<"/"<<sector[i].percentMetal<<"%)"; } } *l<<"\n Metal-Sector Percent: "<<(100.0*metalSectors)/(TM->sectorXSize*TM->sectorZSize-uselessSectors)<<"%"; if( (100.0*metalSectors)/(TM->sectorXSize*TM->sectorZSize-uselessSectors) > 40.0 ) // 40% of the sectors are metal { isMetalMap = true; *l<<" (Metal-Map Detected)"; averageMetalSite = (inRange*cb->GetMaxMetal()*totalMetal)/(metalSectors*convertStoMM*convertStoMM); } else { isMetalMap = false; delete [] sector; sector = 0; } } else isMetalMap = false; if( !isMetalMap ) { *l<<"\n Finding Metal-Sites ..."; averageMetalSite = 0.0; MMZSize = cb->GetMapHeight()/2; MMXSize = cb->GetMapWidth()/2; *l<<"\n Metal-Map Size: "<<MMXSize*MMZSize<<" (x"<<MMXSize<<",z"<<MMZSize<<")"; const float MBtoBB = 2.0; // Metal-Block to Build-Block, * for Conversion, / for the reverse const float MMMinExtractorRadius = sqrt(pow(float(udList[0]->xsize)/MBtoBB,2)+pow(float(udList[0]->zsize)/MBtoBB,2)); // If less then this value then sites could overlap *l<<"\n Minimal Metal-Map Extractor Radius: "<<MMMinExtractorRadius; // sorts the list so that the most unique size extractors are first int uniqueExtractors = 0; for( int iudU=0; iudU<=uniqueExtractors; iudU++ ) { //*l<<" "<<iudU; int uniqueExtractorIndex=-1; for( int iud=iudU; iud<udSize && uniqueExtractorIndex==-1; iud++ ) if( udList[iud]->extractsMetal > 0 ) { uniqueExtractorIndex = iud; for( int iud2=0; iud2<uniqueExtractors; iud2++ ) if( udList[iud]->xsize == udList[iud2]->xsize && udList[iud]->zsize == udList[iud2]->zsize && udList[iud]->minWaterDepth == udList[iud2]->minWaterDepth && udList[iud]->maxWaterDepth == udList[iud2]->maxWaterDepth ) { uniqueExtractorIndex = -1; break; } } if( uniqueExtractorIndex >=0 ) { //*l<<" +"<<uniqueExtractorIndex; const UnitDef* ud = udList[uniqueExtractors]; udList[uniqueExtractors] = udList[uniqueExtractorIndex]; udList[uniqueExtractorIndex] = ud; uniqueExtractors++; // make udList[0] = the smallest extractor for( int i=uniqueExtractors-1; i>0 && udList[i]->xsize*udList[i]->zsize < udList[i-1]->xsize*udList[i-1]->zsize; i-- ) { const UnitDef* ud = udList[i-1]; udList[i-1] = udList[i]; udList[i] = ud; } } } *l<<"\n Minimal Unit-Definition Size: (x"<<udList[0]->xsize<<",z"<<udList[0]->zsize<<")"; *l<<"\n Unique Extractor Unit-Definitions: "<<uniqueExtractors; // Calculate the offsets edgeOffset = new int[MMRSSize]; for( int x=0; x<MMRSSize; x++ ) for(int z=0; z<MMRSSize; z++) if( MMRS[x][z].inRange ) { edgeOffset[x] = MMExtractorRadiusI-z; break; } // Initializing MMS(.metal .assessing .x .z) int SMindex; // temp variable float percentMetal = 0.0; const unsigned char *StandardMetalMap = cb->GetMetalMap(); MMS = new sMetalMapSquare*[MMXSize]; for( int x=0; x<MMXSize; x++ ) { //*l<<"\n"; MMS[x] = new sMetalMapSquare[MMZSize]; for(int z=0; z<MMZSize; z++) { SMindex = z*MMXSize + x; if( (int)StandardMetalMap[SMindex] > 0 ) { MMS[x][z].metal = (float)StandardMetalMap[SMindex]*cb->GetMaxMetal(); percentMetal++; } else MMS[x][z].metal = 0.0; //*l<<MMS[x][z].metal<<"\t"; MMS[x][z].x = x; MMS[x][z].z = z; MMS[x][z].assessing = true; MMS[x][z].inaccuracy = -1.0; } } percentMetal *= 100.0/(MMXSize*MMZSize); *l<<"\n Percent Metal: "<<percentMetal<<"%"; bool valueAccuracy = false; if( percentMetal < 1.0 ) { valueAccuracy = true; *l<<" (metal-site accuracy will be considered important)"; } // double MSTimerTemp = clock(); // Updates MMS(.totalMetal .assessing) FindMMSTotalMetal(0,MMXSize-1,0,MMZSize-1); // *l<<"\n Metal-Site Init FindMMSTotalMetal Loading:\t"<<(clock()-MSTimerTemp)/(double)CLOCKS_PER_SEC<<" seconds"; // Updates MMS(.assessing), checks for area occupied by Geo-Sites if( UDGeoResource ) { // Find the smallest Geo UnitDef const UnitDef *ud = 0; for( int iud=0; iud<udSize; iud++ ) if( udList[iud]->needGeo ) if( ud == 0 || udList[iud]->xsize*udList[iud]->zsize < ud->xsize*ud->zsize ) ud = udList[iud]; const int MMtoMP = 16; // Metal-Map to Map-Position, * for conversion, / for the reverse int xMin,xMax,zMin,zMax; // temp variables for( int iR=0; iR<RSize[1]; iR++ ) { xMin = int(R[1][iR]->position.x)/MMtoMP; zMin = int(R[1][iR]->position.z)/MMtoMP; SetLimitBoundary(xMin,xMax,ud->xsize/MBtoBB-1,zMin,zMax,ud->zsize/MBtoBB-1); for(int z=zMin; z<=zMax; z++) for(int x=xMin; x<=xMax; x++) if( MMS[x][z].assessing ) MMS[x][z].assessing = false; } } // Updates MMS(.assessing), checks the elevation and water type const float *StandardHeightMap = cb->GetHeightMap(); const int HeightMapXSize = cb->GetMapWidth(); const int MMapToHMap = HeightMapXSize/MMXSize; MMSAssessingSize = 0; float3 position;// temp variable for( int x=0; x<MMXSize; x++ ) { for(int z=0; z<MMZSize; z++) { if( MMS[x][z].assessing ) { if( TM->waterIsHarmful && StandardHeightMap[(z*MMapToHMap+MMapToHMap/2)*HeightMapXSize+(x*MMapToHMap+MMapToHMap/2)] < 0 ) { MMS[x][z].assessing = false; } else { MMSAssessingSize++; } } } } // try cutting it down a little more, if needed if( MMSAssessingSize > 250000 ) { *l<<"\n Assessing "<<MMSAssessingSize<<" possible metal-sites."; *l<<"\n Reducing Assessment ... "; for( int x=0; x<MMXSize; x++ ) { for(int z=0; z<MMZSize; z++) { if( MMS[x][z].assessing && MMS[x][z].totalMetal < 1.75*RAI_MinimalMetalSite ) { MMS[x][z].assessing = false; } } } } // MSTimerTemp = clock(); // Updates MMS(.assessing), checks if the positions can be built at MMSAssessingSize = 0; MMSAssessing = new sMetalMapSquare*[MMXSize*MMZSize]; for( int x=0; x<MMXSize; x++ ) for(int z=0; z<MMZSize; z++) if( MMS[x][z].assessing ) { // Long Calculation: (cause: cb->CanBuildAt - probably can't be improved) MMS[x][z].assessing = false; position = float3(x*16.0+8.0, 0.0, z*16.0+8.0); for( int iud=0; iud<uniqueExtractors; iud++ ) if( udList[iud]->extractsMetal > 0 && cb->CanBuildAt(udList[iud],position) ) { MMS[x][z].assessing = true; MMSAssessing[MMSAssessingSize++] = &MMS[x][z]; break; } } // *l<<"\n Metal-Site Init CanBuildAt Loading:\t"<<(clock()-MSTimerTemp)/(double)CLOCKS_PER_SEC<<" seconds"; *l<<"\n Assessing "<<MMSAssessingSize<<" possible metal-sites."; // double MSTimer1 = 0; // double MSTimer2 = 0; // double MSTimer3 = 0; float searchDis = cb->GetExtractorRadius()/2.0; if( searchDis < 16.0 ) searchDis = 16.0; // Needs to be at least this high to work with ClosestBuildSite sMetalMapSquare *mms; // temp variable int xMin,xMax,zMin,zMax,xOffset,zOffset; // temp variables while( MMSAssessingSize > 0 && RSize[0] < RAI_MaxMetalSites ) { //*l<<"\nMMSRemaining.size()="<<MMSRemaining.size(); // MSTimerTemp = clock(); // Setting mms as the best metal-site available // Sorted by high totalMetal and then by low inaccuracy mms = MMSAssessing[0]; // [0] always has assessing = true if( valueAccuracy ) { float bestMetal = 0; for( int i=0; i<MMSAssessingSize; i++ ) if( !MMSAssessing[i]->assessing ) MMSAssessing[i--] = MMSAssessing[--MMSAssessingSize]; else if( MMSAssessing[i]->totalMetal < 0.5*bestMetal ) {} // nothing else { // slow calculations if( MMSAssessing[i]->totalMetal > bestMetal ) { bestMetal = MMSAssessing[i]->totalMetal; if( mms->totalMetal < 0.51*bestMetal ) mms = MMSAssessing[i]; } if( MMSAssessing[i]->inaccuracy <= 0.0 ) FindMMSInaccuracy(MMSAssessing[i]->x,MMSAssessing[i]->z); if( mms->inaccuracy <= 0.0 ) FindMMSInaccuracy(mms->x,mms->z); // *l<<"\n m="<<MMSAssessing[i]->totalMetal<<" ia="<<MMSAssessing[i]->inaccuracy<<" r="<<MMSAssessing[i]->totalMetal*(MMSAssessing[i]->totalMetal/MMSAssessing[i]->inaccuracy); if( MMSAssessing[i]->totalMetal*(MMSAssessing[i]->totalMetal/MMSAssessing[i]->inaccuracy) > mms->totalMetal*(mms->totalMetal/mms->inaccuracy) ) mms = MMSAssessing[i]; } } else { for( int i=0; i<MMSAssessingSize; i++ ) if( !MMSAssessing[i]->assessing ) MMSAssessing[i--] = MMSAssessing[--MMSAssessingSize]; else if( MMSAssessing[i]->totalMetal > 1.001*mms->totalMetal ) mms = MMSAssessing[i]; else if( MMSAssessing[i]->totalMetal < 0.999*mms->totalMetal ) {} // nothing else { // 0.999-1.001: fixes float rounding errors, cb->GetMaxMetal() was not a whole number // inaccuracy can take a long time to calculate so it won't be until it's needed if( MMSAssessing[i]->inaccuracy <= 0.0 ) FindMMSInaccuracy(MMSAssessing[i]->x,MMSAssessing[i]->z); if( mms->inaccuracy <= 0.0 ) FindMMSInaccuracy(mms->x,mms->z); if( MMSAssessing[i]->inaccuracy < mms->inaccuracy )//0.999*mms->inaccuracy ) mms = MMSAssessing[i]; } } if( mms->totalMetal < RAI_MinimalMetalSite ) break; // MSTimer1 += clock()-MSTimerTemp; // MSTimerTemp = clock(); // Create the metal-site position = float3(mms->x*16.0+8.0, 0.0, mms->z*16.0+8.0); ResourceSite *RS = new ResourceSite(position); RS->position.y = StandardHeightMap[(mms->z*MMapToHMap+MMapToHMap/2)*HeightMapXSize+(mms->x*MMapToHMap+MMapToHMap/2)]; RS->amount = mms->totalMetal; averageMetalSite += RS->amount; for( int iud=0; iud<udSize; iud++ ) if( udList[iud]->extractsMetal > 0.0 ) { position = cb->ClosestBuildSite(udList[iud],RS->position,searchDis,0); if( cb->CanBuildAt(udList[iud],position) && (!TM->waterIsHarmful || position.y >= 0) ) RS->options.insert(udList[iud]->id); } R[0][RSize[0]++] = RS; // MSTimer2 += clock()-MSTimerTemp; // *l<<"\n mms->(x"<<mms->x<<",z"<<mms->z<<")"; // The Extractor Radius is small enough that Sites will overlap, remove the nearby indexes being assessed // if( MMExtractorRadius < MMMinExtractorRadius ) // { SetLimitBoundary((xMin=mms->x),xMax,udList[0]->xsize/MBtoBB -1,(zMin=mms->z),zMax,udList[0]->zsize/MBtoBB -1); for(int z=zMin; z<=zMax; z++) for(int x=xMin; x<=xMax; x++) if( MMS[x][z].assessing ) MMS[x][z].assessing = false; // } // Update nearby Metal-Map positions SetLimitBoundary((xMin=mms->x),xMax,xOffset,(zMin=mms->z),zMax,zOffset,MMExtractorRadiusI); for(int z=zMin,zMMRS=zOffset; z<=zMax; z++,zMMRS++) for(int x=xMin,xMMRS=xOffset; x<=xMax; x++,xMMRS++) if( MMRS[xMMRS][zMMRS].inRange ) { // *l<<"\n (x"<<x<<",z"<<z<<") i="<<index<<" MMSRsize="<<MMSRemaining.size(); MMS[x][z].metal = 0.0; } // MSTimerTemp = clock(); // Recalculate the affected MetalMapSquares SetLimitBoundary((xMin=mms->x),xMax,xOffset,(zMin=mms->z),zMax,zOffset,2*MMExtractorRadiusI); FindMMSTotalMetal(xMin,xMax,zMin,zMax); // MSTimer3 += clock()-MSTimerTemp; // Ensures that the first element is being assessed while( MMSAssessingSize > 0 && !MMSAssessing[0]->assessing ) MMSAssessing[0] = MMSAssessing[--MMSAssessingSize]; } // *l<<"\n Metal-Site Search Loading: "<<MSTimer1/CLOCKS_PER_SEC<<" seconds"; // *l<<"\n Metal-Site CanBuildAt Loading: "<<MSTimer2/CLOCKS_PER_SEC<<" seconds"; // *l<<"\n Metal-Site FindMMSTotalMetal Loading: "<<MSTimer3/CLOCKS_PER_SEC<<" seconds"; delete [] edgeOffset; delete [] MMSAssessing; for( int x=0; x<MMXSize; x++ ) delete [] MMS[x]; delete [] MMS; if( RSize[0] > 0 ) { averageMetalSite /= RSize[0]; *l<<"\n Minimal Metal-Site Value: "<<RAI_MinimalMetalSite; } } for( int x=0; x<MMRSSize; x++ ) delete [] MMRS[x]; delete [] MMRS; *l<<"\n Average Metal-Site Value: "<<averageMetalSite; *l<<"\n Metal-Sites Found: "<<RSize[0]; } else *l<<"\n Metal-Sites Loaded: "<<RSize[0]; delete [] udList; /* // debugging for( int iT=0; iT<2; iT++ ) for( int iR=0; iR<RSize[iT]; iR++ ) { *l<<"\n R["<<iT<<"]["<<iR<<"] \tamount: "<<R[iT][iR]->amount<<" \tlocation(x"<<R[iT][iR]->position.x<<",z"<<R[iT][iR]->position.z<<"):"; *l<<"\t B("<<R[iT][iR]->options.size()<<"):"; for( set<int>::iterator RS=R[iT][iR]->options.begin(); RS!=R[iT][iR]->options.end(); RS++ ) *l<<" "<<*RS; } */ }
cBuilderPlacement::cBuilderPlacement(IAICallback* callback, cRAI* global) { G=global; l=global->l; cb=callback; *l<<"\nLoading Build-Placement ..."; const double SecondAlgorithmTimeLimit = 2.5; // seconds per RAI //double clockStart = clock(); if( int(G->Units.size()) == 0 ) *l<<"\nERROR: G->Units"; int unitLimit; cb->GetValue(AIVAL_UNIT_LIMIT,&unitLimit); if( unitLimit > 500 ) // Can't think of a reason to ever have this higher, but resource linking could take really long unitLimit = 500; float3 StartPosition=cb->GetUnitPos(G->Units.begin()->first); int MetalSiteLimit = G->RM->RSize[0]; if( MetalSiteLimit > unitLimit/6 ) MetalSiteLimit = unitLimit/6; int GeoSiteLimit = G->RM->RSize[1]; if( GeoSiteLimit > unitLimit/6 ) GeoSiteLimit = unitLimit/6; Resources = new ResourceSiteExt*[MetalSiteLimit+GeoSiteLimit]; ResourceSize = 0; *l<<"\n Metal-Site limit : "<<MetalSiteLimit; *l<<"\n Geo-Site limit : "<<GeoSiteLimit; // Finding and using the Nearest Metal-Sites set<int> Seleted; for( int iM=0; iM<MetalSiteLimit && iM<G->RM->RSize[0]; iM++ ) { int iBest=-1; float fBest=0.0f; for( int iR=0; iR<G->RM->RSize[0]; iR++ ) { // Cycles through only metal-sites if( Seleted.find(iR) == Seleted.end() ) if( iBest == -1 || StartPosition.distance2D(G->RM->R[0][iR]->position) < fBest ) { iBest=iR; fBest=StartPosition.distance2D(G->RM->R[0][iR]->position); } } Seleted.insert(iBest); Resources[ResourceSize++] = new ResourceSiteExt(G->RM->R[0][iBest],cb); } // Finding and using the Nearest Geo-Sites Seleted.clear(); for( int iG=0; iG<GeoSiteLimit && iG<G->RM->RSize[1]; iG++ ) { int iBest=-1; float fBest=0.0f; for( int iR=0; iR<G->RM->RSize[1]; iR++ ) { // Cycles through only geo-sites if( Seleted.find(iR) == Seleted.end() ) if( iBest == -1 || StartPosition.distance2D(G->RM->R[1][iR]->position) < fBest ) { iBest=iR; fBest=StartPosition.distance2D(G->RM->R[1][iR]->position); } } Seleted.insert(iBest); Resources[ResourceSize++] = new ResourceSiteExt(G->RM->R[1][iBest],cb); } // Updating BuildOptions and Resources, some units may have been disabled typedef pair<int,ResourceSiteExtBO> irbPair; typedef pair<ResourceSite*,ResourceSiteDistance> rrPair; for( int iR=0; iR<ResourceSize; iR++ ) { if( Resources[iR]->S->type == 0 ) { sRAIBuildList *BL = G->UDH->BLMetalL; for( int i=0; i<BL->UDefSize; i++ ) { sRAIUnitDef* udr=BL->UDef[i]->RUD; if( Resources[iR]->S->options.find(udr->ud->id) != Resources[iR]->S->options.end() ) Resources[iR]->BuildOptions.insert(irbPair(udr->ud->id,ResourceSiteExtBO(udr))); } } else if( Resources[iR]->S->type == 1 ) { // Units using Geo-Sites can be found in any number of build lists for( map<int,sRAIUnitDef>::iterator iUD=G->UDH->UDR.begin(); iUD!=G->UDH->UDR.end(); ++iUD ) { if( iUD->second.ud->needGeo && !iUD->second.Disabled && int(iUD->second.PrerequisiteOptions.size()) > 0 ) { if( Resources[iR]->S->options.find(iUD->second.ud->id) != Resources[iR]->S->options.end() ) Resources[iR]->BuildOptions.insert(irbPair(iUD->second.ud->id,ResourceSiteExtBO(&iUD->second))); } } } if( int(Resources[iR]->S->siteDistance.size()) == 0 || int(Resources[iR]->S->siteDistance.size()) < G->RM->RSize[0]+G->RM->RSize[1] ) { // Cheap distance calculations, although this is still too much to calculate for all map resources for( int iR2=0; iR2<ResourceSize; iR2++ ) if( Resources[iR]->S->siteDistance.find(Resources[iR2]->S) == Resources[iR]->S->siteDistance.end() ) Resources[iR]->S->siteDistance.insert(rrPair(Resources[iR2]->S,ResourceSiteDistance(Resources[iR]->S->position.distance2D(Resources[iR2]->S->position)))); } // Old Code, Unneeded? Caused by: the old RAI style's handling of a Metal-Map if( int(Resources[iR]->BuildOptions.size()) == 0 ) { float3* p = &Resources[iR]->S->position; *l<<"\nERROR: "<<(Resources[iR]->S->type==0?"Metal":"Energy")<<" Resource located at (x"<<p->x; *l<<" z"<<p->z<<" y"<<p->y<<") can not be built at."; *l<<" size="<<Resources[iR]->S->options.size(); delete Resources[iR]; Resources[iR] = Resources[ResourceSize-1]; ResourceSize--; iR--; } else RSRemaining.insert(irPair(iR,Resources[iR])); } *l<<"\n Resources in use : "<<ResourceSize; if( ResourceSize == 0 ) return; // Read all movetypes int arraySize = G->TM->mobileType.size(); basicArray<TerrainMapMobileType*> MobileTypes(arraySize); for( list<TerrainMapMobileType>::iterator iM=G->TM->mobileType.begin(); iM!=G->TM->mobileType.end(); ++iM ) MobileTypes.push_back(&*iM); // Sort them by worst to best, remove unusable movetypes for( int iM=0; iM<MobileTypes.size()-1; iM++) { if( (*MobileTypes[iM])->areaLargest == 0 ) { MobileTypes.removeE(iM); iM--; } else if( (*MobileTypes[iM+1])->areaLargest == 0 ) { MobileTypes.removeE(iM+1); iM--; } else if( (*MobileTypes[iM])->areaLargest->percentOfMap > (*MobileTypes[iM+1])->areaLargest->percentOfMap || ((*MobileTypes[iM])->areaLargest->percentOfMap == (*MobileTypes[iM+1])->areaLargest->percentOfMap && (*MobileTypes[iM])->maxSlope > (*MobileTypes[iM+1])->maxSlope) ) { //*l<<"\n MT("<<(*MobileTypes[iM])->MD->name<<" "<<iM<<"<->"<<iM+1<<" "<<(*MobileTypes[iM+1])->MD->name<<")"; MobileTypes.swap(iM,iM+1); iM--; if( iM != -1 ) iM --; } } TerrainMapMobileType* MT=NULL; // for( MobileTypes.begin(); MobileTypes.nextE(MT); ) // *l<<"\n MoveType="<<MT->MD->name<<" pathType="<<MT->MD->pathType; // First Link Algorithm double linkStartClock = clock(); TerrainMapArea* Area; for( int iR1=0; iR1<ResourceSize; iR1++ ) for( int iR2=iR1+1; iR2<ResourceSize; iR2++ ) for( MobileTypes.begin(); MobileTypes.nextE(MT); ) if( (Area = MT->sector[G->TM->GetSectorIndex(Resources[iR1]->S->position)].area) == 0 || Area != MT->sector[G->TM->GetSectorIndex(Resources[iR2]->S->position)].area ) { Resources[iR1]->S->siteDistance.find(Resources[iR2]->S)->second.distance.insert(ifPair(MT->MD->pathType,-2.0)); Resources[iR2]->S->siteDistance.find(Resources[iR1]->S)->second.distance.insert(ifPair(MT->MD->pathType,-2.0)); } set<int> RSList1; // sites that are so far connected set<int> RSList2; // sites that have yet to be connected RSList1.insert(0); for( int i=1; i<ResourceSize; i++ ) RSList2.insert(i); int iM = 0; // current moveType index while( int(RSList2.size()) > 0 ) { if( iM >= MobileTypes.size() ) iM = -1; // None of the moveTypes worked, just ignore terrain this time around int bestI1; int bestI2; int pathType; float dis; // temp bestI1 = -1; if( iM == -1 ) pathType = -1; else { MT = (*MobileTypes[iM]); pathType = MT->MD->pathType; } //*l<<"\n RSL2size="<<RSList2.size()<<" iM="<<iM; for( set<int>::iterator iR1=RSList1.begin(); iR1!=RSList1.end(); ++iR1 ) if( iM == -1 || MT->sector[G->TM->GetSectorIndex(Resources[*iR1]->S->position)].area != 0 ) { //*l<<" r1="<<*iR1; for( set<int>::iterator iR2=RSList2.begin(); iR2!=RSList2.end(); ++iR2 ) { //*l<<" r2="<<*iR2; dis = Resources[*iR1]->S->GetResourceDistance(Resources[*iR2]->S,pathType); if( dis > 0 && (bestI1 == -1 || Resources[bestI1]->S->GetResourceDistance(Resources[bestI2]->S,pathType) > dis) ) { bestI1=*iR1; bestI2=*iR2; } } } if( bestI1 == -1 ) { // Nothing selected, try again with a different moveType //*l<<"m"; iM++; } else if( iM >= 0 && Resources[bestI1]->S->siteDistance.find(Resources[bestI2]->S)->second.bestDistance == 0 ) { // The best choice distance has yet to be calculated //*l<<"r"; FindResourceDistance(Resources[bestI1]->S,Resources[bestI2]->S,MT->MD->pathType); } else { //*l<<"s"; RSList1.insert(bestI2); RSList2.erase(bestI2); Resources[bestI1]->Linked.insert(irPair(bestI2,Resources[bestI2])); Resources[bestI2]->Linked.insert(irPair(bestI1,Resources[bestI1])); if( iM == -1 ) { Resources[bestI1]->S->siteDistance.find(Resources[bestI2]->S)->second.bestDistance = &Resources[bestI1]->S->siteDistance.find(Resources[bestI2]->S)->second.minDistance; Resources[bestI2]->S->siteDistance.find(Resources[bestI1]->S)->second.bestDistance = &Resources[bestI2]->S->siteDistance.find(Resources[bestI1]->S)->second.minDistance; } iM = 0; } } *l<<"\n First Link Algorithm Loading Time: "<<(clock()-linkStartClock)/CLOCKS_PER_SEC<<"s"; // Second Link Algorithm linkStartClock = clock(); float *MTPenalty; // the moveData*->pathType is the index to MTPenalty int MTPenaltySize = 0; for( MobileTypes.begin(); MobileTypes.nextE(MT); ) { if( MTPenaltySize < MT->MD->pathType+1 ) MTPenaltySize = MT->MD->pathType+1; } MTPenalty = new float[MTPenaltySize+1]; // the last index is for the flying movetype for( int iMP=0; iMP<MTPenaltySize; iMP++) MTPenalty[iMP] = -1.0; int linkCount = 0; for( MobileTypes.begin(); MobileTypes.nextE(MT); ) // for( vector<TerrainMapMobileType*>::iterator iMT=MobileTypes.begin(); iMT!=MobileTypes.end(); iMT++ ) { MTPenalty[MT->MD->pathType] = linkCount; for( int iR=0; iR<ResourceSize; iR++ ) for(map<int,ResourceSiteExt*>::iterator iRL = Resources[iR]->Linked.begin(); iRL != Resources[iR]->Linked.end(); ++iRL ) if( iRL->second->S->siteDistance.find(Resources[iR]->S)->second.bestPathType == MT->MD->pathType ) linkCount++; } for( int iMP=0; iMP<MTPenaltySize; iMP++) if( MTPenalty[iMP] >= 0.0 ) { //*l<<"\n "<<MTPenalty[iMP]<<"/"<<linkCount; MTPenalty[iMP] = linkCount/(1+linkCount*1.10-MTPenalty[iMP]); if( MTPenalty[iMP] < 1.0 ) MTPenalty[iMP] = 1.0; else if( MTPenalty[iMP] > 5.0 ) MTPenalty[iMP] = 5.0; //*l<<" MTPenalty["<<iMP<<"]="<<MTPenalty[iMP]; } MTPenalty[MTPenaltySize] = 20.0; int **RMT = new int*[ResourceSize]; // Resource MoveType, 2 dimensional array float **RD = new float*[ResourceSize]; // Resource Distances, Local Copy, 2 dimensional array ResourceSiteDistance* RSD; for( int iR1=0; iR1<ResourceSize; iR1++ ) { RMT[iR1] = new int[ResourceSize]; RD[iR1] = new float[ResourceSize]; for( int iR2=0; iR2<ResourceSize; iR2++ ) RD[iR1][iR2] = -1.0; } for( int iR1=0; iR1<ResourceSize; iR1++ ) for( int iR2=iR1+1; iR2<ResourceSize; iR2++ ) { RMT[iR1][iR2] = MTPenaltySize; RMT[iR2][iR1] = MTPenaltySize; RSD = &Resources[iR1]->S->siteDistance.find(Resources[iR2]->S)->second; if( RSD->bestDistance != 0 ) { if( RSD->bestPathType >= 0 ) { RMT[iR1][iR2] = RSD->bestPathType; RMT[iR2][iR1] = RSD->bestPathType; } } else for( MobileTypes.begin(); MobileTypes.nextE(MT); ) if( RSD->distance.find(MT->MD->pathType) == RSD->distance.end() ) { RMT[iR1][iR2] = MT->MD->pathType; RMT[iR2][iR1] = MT->MD->pathType; break; } } basicArray<ResourceLinkInfo> RLIList(ResourceSize); ResourceLinkInfo *RLI; for( int iR=0; iR<ResourceSize; iR++ ) if( Resources[iR]->Linked.size() < 3 ) { RLI = RLIList.push_back(); RLI->index = iR; RLI->bestI = -1; RLI->restrictedR.insert(iR); for(map<int,ResourceSiteExt*>::iterator iRL = Resources[iR]->Linked.begin(); iRL != Resources[iR]->Linked.end(); ++iRL ) RLI->restrictedR.insert(iRL->first); } // *l<<"\n Second Link Loading Time 0: "<<(clock()-linkStartClock)/(double)CLOCKS_PER_SEC<<"s"; // double linkClock1 = 0; // double linkClock2 = 0; // double linkClock3 = 0; // double linkClock4 = 0; // double linkClockTemp; while( RLIList.elementSize > 0 && (clock()-linkStartClock)/(double)CLOCKS_PER_SEC <= SecondAlgorithmTimeLimit ) { //*l<<"\n"; // Cycle through RLIList to find the closest resource pair available (with consideration to other factors) bool resetLink,acceptLink; ResourceLinkInfo *bestRLI = 0; // linkClockTemp = clock(); for( RLIList.begin(); RLIList.nextE(RLI); ) { if( RLI->bestI == -2 ) // The best link was found & rejected in latter code RLIList.removeE(); else { if( RLI->bestI == -1 ) // has not been found yet { for( int iR2=0; iR2<ResourceSize; iR2++ ) if( RLI->restrictedR.find(iR2) == RLI->restrictedR.end() ) { //*l<<"\n r1="<<RLI->index<<" r2="<<iR2; if( RD[RLI->index][iR2] < 0.0 ) { RSD = &Resources[RLI->index]->S->siteDistance.find(Resources[iR2]->S)->second; //*l<<" BPT:"<<RSD->bestPathType; RD[RLI->index][iR2] = Resources[RLI->index]->S->GetResourceDistance(Resources[iR2]->S,RSD->bestPathType); //*l<<" *:"<<RD[RLI->index][iR2]; RD[RLI->index][iR2] *= MTPenalty[RMT[RLI->index][iR2]]; RD[iR2][RLI->index] = RD[RLI->index][iR2]; } //*l<<" d(1-2):"<<RD[RLI->index][iR2]; if( RLI->bestI < 0 || RD[RLI->index][iR2] < RD[RLI->index][RLI->bestI] ) { acceptLink = true; for(map<int,ResourceSiteExt*>::iterator iRL1 = Resources[RLI->index]->Linked.begin(); iRL1 != Resources[RLI->index]->Linked.end(); ++iRL1 ) { RSD = &Resources[iR2]->S->siteDistance.find(iRL1->second->S)->second; if( RSD->bestDistance != 0 ) { if( RD[iR2][iRL1->first] < 0.0 ) { RD[iR2][iRL1->first] = Resources[iR2]->S->GetResourceDistance(iRL1->second->S,RSD->bestPathType) * MTPenalty[RMT[iR2][iRL1->first]]; RD[iRL1->first][iR2] = RD[iR2][iRL1->first]; } if( RD[RLI->index][iRL1->first] < 0.0 ) { RD[RLI->index][iRL1->first] = Resources[RLI->index]->S->GetResourceDistance(iRL1->second->S,Resources[RLI->index]->S->siteDistance.find(iRL1->second->S)->second.bestPathType) * MTPenalty[RMT[RLI->index][iRL1->first]]; RD[iRL1->first][RLI->index] = RD[RLI->index][iRL1->first]; } //*l<<" d(L1-2):"<<RD[iR2][iRL1->first]; //*l<<"+"<<0.35*RD[RLI->index][iRL1->first]; if( RD[iR2][iRL1->first]+0.35*RD[RLI->index][iRL1->first] < RD[RLI->index][iR2] ) { //*l<<" rejected("<<iRL1->first<<")"; acceptLink = false; break; } } } if( acceptLink ) { //*l<<" *acceptLink*"; RLI->bestI = iR2; } } } } //if( RLI->bestI >= 0 ) *l<<"\n dis["<<RLI->index<<"]["<<RLI->bestI<<"]="<<RD[RLI->index][RLI->bestI]; if( RLI->bestI == -1 ) RLIList.removeE(); else if( bestRLI == 0 || RD[RLI->index][RLI->bestI] < RD[bestRLI->index][bestRLI->bestI] ) bestRLI = RLI; } } // linkClock1 += clock()-linkClockTemp; if( bestRLI == 0 ) break; // the loop would have ended anyway, this just jumps over the next area of code // linkClockTemp = clock(); resetLink = false; RSD = &Resources[bestRLI->index]->S->siteDistance.find(Resources[bestRLI->bestI]->S)->second; if( RSD->bestDistance == 0 ) { // The best choice distance has yet to be calculated //*l<<" r-1-2"; for( MobileTypes.begin(); RSD->bestDistance == 0 && MobileTypes.nextE(MT); ) if( RSD->distance.find(MT->MD->pathType) == RSD->distance.end() ) { FindResourceDistance(Resources[bestRLI->index]->S,Resources[bestRLI->bestI]->S,MT->MD->pathType); RMT[bestRLI->index][bestRLI->bestI] = RSD->bestPathType; RMT[bestRLI->bestI][bestRLI->index] = RSD->bestPathType; } if( RSD->bestDistance == 0 ) { RSD->bestDistance = &RSD->minDistance; RSD = &Resources[bestRLI->bestI]->S->siteDistance.find(Resources[bestRLI->index]->S)->second; RSD->bestDistance = &RSD->minDistance; RMT[bestRLI->index][bestRLI->bestI] = MTPenaltySize; RMT[bestRLI->bestI][bestRLI->index] = MTPenaltySize; } RD[bestRLI->index][bestRLI->bestI] = -1.0; RD[bestRLI->bestI][bestRLI->index] = -1.0; resetLink = true; } // linkClock2 += clock()-linkClockTemp; // linkClockTemp = clock(); for(map<int,ResourceSiteExt*>::iterator iRL1 = Resources[bestRLI->index]->Linked.begin(); iRL1 != Resources[bestRLI->index]->Linked.end(); ++iRL1 ) { RSD = &iRL1->second->S->siteDistance.find(Resources[bestRLI->bestI]->S)->second; if( RSD->bestDistance == 0 ) { // An additionally needed set of calculations //*l<<" r-L1-2"; for( MobileTypes.begin(); RSD->bestDistance == 0 && MobileTypes.nextE(MT); ) if( RSD->distance.find(MT->MD->pathType) == RSD->distance.end() ) { FindResourceDistance(iRL1->second->S,Resources[bestRLI->bestI]->S,MT->MD->pathType); RMT[iRL1->first][bestRLI->bestI] = RSD->bestPathType; RMT[bestRLI->bestI][iRL1->first] = RSD->bestPathType; } if( RSD->bestDistance == 0 ) { RSD->bestDistance = &RSD->minDistance; RSD = &Resources[bestRLI->bestI]->S->siteDistance.find(iRL1->second->S)->second; RSD->bestDistance = &RSD->minDistance; RMT[iRL1->first][bestRLI->bestI] = MTPenaltySize; RMT[bestRLI->bestI][iRL1->first] = MTPenaltySize; } RD[iRL1->first][bestRLI->bestI] = -1.0; RD[bestRLI->bestI][iRL1->first] = -1.0; resetLink = true; } } // linkClock3 += clock()-linkClockTemp; // linkClockTemp = clock(); if( resetLink ) { // New calculations have been made, distances should be reconsidered for( RLIList.begin(); RLIList.nextE(RLI); ) if( (RLI->index == bestRLI->bestI && bestRLI->restrictedR.find(RLI->bestI) != bestRLI->restrictedR.end() ) || (Resources[bestRLI->index]->Linked.find(RLI->index) != Resources[bestRLI->index]->Linked.end() && RLI->bestI == bestRLI->bestI) ) RLI->bestI = -1; bestRLI->bestI = -1; bestRLI = 0; } else { //*l<<" size1:"<<Resources[bestRLI->index]->Linked.size(); // These are an additional sets of conditions that are not checked until the best has been found for(map<int,ResourceSiteExt*>::iterator iRL1 = Resources[bestRLI->index]->Linked.begin(); iRL1 != Resources[bestRLI->index]->Linked.end(); ++iRL1 ) { //*l<<" d(L1-B):"<<RD[bestRLI->bestI][iRL1->first]; if( RD[bestRLI->bestI][iRL1->first] < RD[bestRLI->bestI][bestRLI->index] ) { // The best choose didn't work out //*l<<" *no good*"; bestRLI->bestI = -2; // this will end the search for this paticular resource bestRLI = 0; break; } } if( bestRLI != 0 ) { //*l<<" size2:"<<Resources[bestRLI->bestI]->Linked.size(); for(map<int,ResourceSiteExt*>::iterator iRLB = Resources[bestRLI->bestI]->Linked.begin(); iRLB != Resources[bestRLI->bestI]->Linked.end(); ++iRLB ) { RSD = &Resources[bestRLI->index]->S->siteDistance.find(iRLB->second->S)->second; if( RSD->bestDistance == 0 ) { // An additionally needed set of calculations for( MobileTypes.begin(); RSD->bestDistance == 0 && MobileTypes.nextE(MT); ) if( RSD->distance.find(MT->MD->pathType) == RSD->distance.end() ) { FindResourceDistance(Resources[bestRLI->index]->S,iRLB->second->S,MT->MD->pathType); RMT[bestRLI->index][iRLB->first] = RSD->bestPathType; RMT[iRLB->first][bestRLI->index] = RSD->bestPathType; } if( RSD->bestDistance == 0 ) { RSD->bestDistance = &RSD->minDistance; RSD = &iRLB->second->S->siteDistance.find(Resources[bestRLI->index]->S)->second; RSD->bestDistance = &RSD->minDistance; RMT[bestRLI->index][iRLB->first] = MTPenaltySize; RMT[iRLB->first][bestRLI->index] = MTPenaltySize; } RD[bestRLI->index][iRLB->first] = -1.0; RD[iRLB->first][bestRLI->index] = -1.0; } if( RD[bestRLI->index][iRLB->first] < 0.0 ) { RD[bestRLI->index][iRLB->first] = Resources[bestRLI->index]->S->GetResourceDistance(iRLB->second->S,RSD->bestPathType) * MTPenalty[RMT[bestRLI->index][iRLB->first]]; RD[iRLB->first][bestRLI->index] = RD[bestRLI->index][iRLB->first]; } //*l<<" d(LB-1):"<<RD[bestRLI->index][iRLB->first]; if( RD[bestRLI->index][iRLB->first] < RD[bestRLI->index][bestRLI->bestI] ) { // float3 Pos1=Resources[bestRLI->index]->S->position; // float3 Pos2=Resources[bestRLI->bestI]->S->position; // Pos1.y+=515.0; // Pos2.y+=755.0; // cb->CreateLineFigure(Pos1,Pos2,30,0,900000,0); //*l<<" *no good*"; // The best choose didn't work out bestRLI->bestI = -2; // this will end the search for this paticular resource bestRLI = 0; break; } } } if( bestRLI != 0 ) { RSD = &Resources[bestRLI->index]->S->siteDistance.find(Resources[bestRLI->bestI]->S)->second; //*l<<"\n*Best* R("<<bestRLI->index<<"<->"<<bestRLI->bestI<<") dis="; //*l<<Resources[bestRLI->index]->S->GetResourceDistance(Resources[bestRLI->bestI]->S,RSD->bestPathType); //*l<<" p="<<MTPenalty[RMT[bestRLI->index][bestRLI->bestI]]; //*l<<" d="<<RD[bestRLI->bestI][bestRLI->index]; //*l<<" d="<<RD[bestRLI->index][bestRLI->bestI]; if( RAIDEBUGGING && cb->GetMyTeam() == 0 ) // Debug Lines { vector<float3> *path = &RSD->pathDebug; if( path->empty() ) { path->push_back(Resources[bestRLI->index]->S->position); path->push_back(Resources[bestRLI->bestI]->S->position); } for( size_t i=0; i+1 < path->size(); i++ ) { float3 Pos1=path->at(i); float3 Pos2=path->at(i+1); Pos1.y+=45.0; if( i == 0 ) Pos1.y+=35.0; Pos2.y+=45.0; if( i == path->size()-2 ) Pos2.y-=75.0; cb->CreateLineFigure(Pos1,Pos2,30,0,900000,0); } } Resources[bestRLI->index]->Linked.insert(irPair(bestRLI->bestI,Resources[bestRLI->bestI])); Resources[bestRLI->bestI]->Linked.insert(irPair(bestRLI->index,Resources[bestRLI->index])); for( RLIList.begin(); RLIList.nextE(RLI); ) if( RLI->restrictedR.find(bestRLI->bestI) != RLI->restrictedR.end() ) { RLI->bestI = -1; if( RLI->index == bestRLI->bestI ) RLI->restrictedR.insert(bestRLI->index); } bestRLI->restrictedR.insert(bestRLI->bestI); bestRLI->bestI = -1; for( RLIList.begin(); RLIList.nextE(RLI); ) if( Resources[RLI->index]->Linked.size() >= 3 ) RLIList.removeE(); bestRLI = 0; } } // linkClock4 += clock()-linkClockTemp; } if( RLIList.elementSize > 0 ) *l<<"\n Second Linking Algorithm Aborted (was running for more than "<<SecondAlgorithmTimeLimit<<" seconds)"; for( int iR=0; iR<ResourceSize; iR++ ) { delete [] RMT[iR]; delete [] RD[iR]; } delete [] RMT; delete [] RD; delete [] MTPenalty; // *l<<"\n Second Link Loading Time 1: "<<linkClock1/(double)CLOCKS_PER_SEC<<"s"; // *l<<"\n Second Link Loading Time 2: "<<linkClock2/(double)CLOCKS_PER_SEC<<"s"; // *l<<"\n Second Link Loading Time 3: "<<linkClock3/(double)CLOCKS_PER_SEC<<"s"; // *l<<"\n Second Link Loading Time 4: "<<linkClock4/(double)CLOCKS_PER_SEC<<"s"; *l<<"\n Second Link Algorithm Loading Time: "<<(clock()-linkStartClock)/CLOCKS_PER_SEC<<"s"; // Setting Linked Distance 2 for( int iR=0; iR<ResourceSize; iR++ ) { for( map<int,ResourceSiteExt*>::iterator iRL=Resources[iR]->Linked.begin(); iRL!=Resources[iR]->Linked.end(); ++iRL ) { if( Resources[iR]->LinkedD2.find(iRL->first) == Resources[iR]->LinkedD2.end() ) Resources[iR]->LinkedD2.insert(irPair(iRL->first,Resources[iRL->first])); for( map<int,ResourceSiteExt*>::iterator iRL2=Resources[iRL->first]->Linked.begin(); iRL2!=Resources[iRL->first]->Linked.end(); ++iRL2 ) { if( iRL2->first != iR && Resources[iR]->LinkedD2.find(iRL2->first) == Resources[iR]->LinkedD2.end() ) Resources[iR]->LinkedD2.insert(irPair(iRL2->first,Resources[iRL2->first])); } } } for( int iR=0; iR<ResourceSize; iR++ ) Resources[iR]->SetRanged(); // Debug Lines if( RAIDEBUGGING && cb->GetMyTeam() == 0 ) for( int iR1=0; iR1<ResourceSize; iR1++ ) { for( int iR2=iR1+1; iR2<ResourceSize; iR2++ ) { if( Resources[iR1]->Linked.find(iR2) != Resources[iR1]->Linked.end() ) { vector<float3> *path = &Resources[iR1]->S->siteDistance.find(Resources[iR2]->S)->second.pathDebug; if( path->empty() ) { path->push_back(Resources[iR1]->S->position); path->push_back(Resources[iR2]->S->position); } for( int i=0; i<int(path->size())-1; i++ ) { float3 Pos1=path->at(i); float3 Pos2=path->at(i+1); Pos1.y+=15.0; Pos2.y+=15.0; cb->CreateLineFigure(Pos1,Pos2,10,0,900000,0); } } } *l<<"\n R("<<iR1<<") type="<<Resources[iR1]->S->type<<" Pos(x"<<Resources[iR1]->S->position.x<<",z"<<Resources[iR1]->S->position.z<<") L("<<Resources[iR1]->Linked.size()<<"):"; for( map<int,ResourceSiteExt*>::iterator RL=Resources[iR1]->Linked.begin(); RL!=Resources[iR1]->Linked.end(); ++RL ) *l<<" "<<RL->first; *l<<"\t B("<<Resources[iR1]->BuildOptions.size()<<"):"; for( map<int,ResourceSiteExtBO>::iterator RS=Resources[iR1]->BuildOptions.begin(); RS!=Resources[iR1]->BuildOptions.end(); ++RS ) *l<<" "<<RS->first; } }