//compares the vector (start,destA) with (start,destB). returns a value between 0 (perfect agreement) and 60 (polar opposite direction) int angularDeviation(int iStartX, int iStartY, int iDestAX, int iDestAY, int iDestBX, int iDestBY) { //undefined if (iStartX==iDestAX && iStartY==iDestAY) return 0; if (iStartX==iDestBX && iStartY==iDestBY) return 0; int iStartXHex = xToHexspaceX(iStartX,iStartY); int iDestAXHex = xToHexspaceX(iDestAX,iDestAY); int iDestBXHex = xToHexspaceX(iDestBX,iDestBY); int iDXA = dxWrap(iDestAXHex - iStartXHex); int iDYA = dyWrap(iDestAY - iStartY); int iDXB = dxWrap(iDestBXHex - iStartXHex); int iDYB = dyWrap(iDestBY - iStartY); //reconstruct the Z coordinate int iStartZ = -iStartXHex-iStartY; int iDestAZ = -iDestAXHex-iDestAY; int iDestBZ = -iDestBXHex-iDestBY; int iDZA = iDestAZ - iStartZ; int iDZB = iDestBZ - iStartZ; float fRawDotProduct = (float) iDXA *iDXB + iDYA * iDYB + iDZA * iDZB; float fNormA2 = (float) iDXA*iDXA + iDYA*iDYA + iDZA*iDZA; float fNormB2 = (float) iDXB*iDXB + iDYB*iDYB + iDZB*iDZB; //this should be between -1 and +1 float fNormDotProduct = fRawDotProduct / sqrtf( fNormA2*fNormB2 ); //this should be between 0 and 60 return (int)((fNormDotProduct-1)*(-30)); }
int plotCityXY(const CvCity* pCity, const CvPlot* pPlot) { int iDX; int iWrappedDX = dxWrap(pPlot->getX() - pCity->getX()); int iWrappedDY = dyWrap(pPlot->getY() - pCity->getY()); int iDY = iWrappedDY; // convert to hex-space coordinates - the coordinate system axes are E and NE (not orthogonal) int iCityHexX = xToHexspaceX(pCity->getX(), pCity->getY()); int iPlotHexX = xToHexspaceX(pCity->getX() + iWrappedDX, pCity->getY() + iWrappedDY); iDX = dxWrap(iPlotHexX - iCityHexX); #if defined(MOD_GLOBAL_CITY_WORKING) if(hexDistance(iDX, iDY) > pCity->getWorkPlotDistance()) #else if(hexDistance(iDX, iDY) > CITY_PLOTS_RADIUS) #endif { return -1; } else { #if defined(MOD_GLOBAL_CITY_WORKING) // Regardless of the working radius, we need to offset into the array by the maximum radius return GC.getXYCityPlot((iDX + MAX_CITY_RADIUS), (iDY + MAX_CITY_RADIUS)); #else return GC.getXYCityPlot((iDX + CITY_PLOTS_RADIUS), (iDY + CITY_PLOTS_RADIUS)); #endif } }
DirectionTypes estimateDirection(int iStartX, int iStartY, int iDestX, int iDestY) { int iStartXHex = xToHexspaceX(iStartX,iStartY); int iDestXHex = xToHexspaceX(iDestX,iDestY); int iDX = dxWrap(iDestXHex - iStartXHex); int iDY = dyWrap(iDestY - iStartY); //undefined if (iDX==0 && iDY==0) return NO_DIRECTION; //reconstruct the Z coordinate int iStartZ = -iStartXHex-iStartY; int iDestZ = -iDestXHex-iDestY; int iDZ = iDestZ - iStartZ; float maximum = 0; int maximumIndex = -1; for(int i=0; i<6; i++) { float dotProduct = iDX * hexspaceDirections[i][0] + iDY * hexspaceDirections[i][1] + iDZ * hexspaceDirections[i][2]; if(dotProduct > maximum) { maximum = dotProduct; maximumIndex = i; } } return (DirectionTypes)maximumIndex; }
int plotDistance(int iX1, int iY1, int iX2, int iY2) { int iX1H = xToHexspaceX(iX1,iY1); int iX2H = xToHexspaceX(iX2,iY2); //reconstruct the Z coordinate int iZ1H = -iX1H-iY1; int iZ2H = -iX2H-iY2; int iDX = dxWrap(iX2H - iX1H); int iDY = dyWrap(iY2 - iY1); int iDZ = dxWrap(iZ2H - iZ1H); //this is by design, dx and dz have the same range return (abs(iDX) + abs(iDY) + abs(iDZ)) / 2; }
int getRingIterationIndex(const CvPlot* pCenter, const CvPlot* pPlot) { int iWrappedDX = dxWrap(pPlot->getX() - pCenter->getX()); int iWrappedDY = dyWrap(pPlot->getY() - pCenter->getY()); // convert to hex-space coordinates - the coordinate system axes are E and NE (not orthogonal) int iCenterHexX = xToHexspaceX(pCenter->getX(), pCenter->getY()); int iPlotHexX = xToHexspaceX(pCenter->getX() + iWrappedDX, pCenter->getY() + iWrappedDY); int iDX = dxWrap(iPlotHexX - iCenterHexX); int iDY = iWrappedDY; // Regardless of the working radius, we need to offset into the array by the maximum radius return GC.getRingIterationIndexHex((iDX + MAX_CITY_RADIUS), (iDY + MAX_CITY_RADIUS)); }
CvPlot* plotXY(int iX, int iY, int iDX, int iDY) { // convert the start coord to hex-space coordinates int iStartHexX = xToHexspaceX(iX, iY); int iPlotHexX = iStartHexX + iDX; int iPlotY = iY + iDY; // Y is the same in both coordinate systems // convert from hex-space coordinates to the storage array iPlotHexX = hexspaceXToX(iPlotHexX, iPlotY); return GC.getMap().plot(iPlotHexX , iPlotY); }
int plotCityXY(const CvCity* pCity, const CvPlot* pPlot) { int iDX; int iWrappedDX = dxWrap(pPlot->getX() - pCity->getX()); int iWrappedDY = dyWrap(pPlot->getY() - pCity->getY()); int iDY = iWrappedDY; // convert to hex-space coordinates - the coordinate system axes are E and NE (not orthogonal) int iCityHexX = xToHexspaceX(pCity->getX(), pCity->getY()); int iPlotHexX = xToHexspaceX(pCity->getX() + iWrappedDX, pCity->getY() + iWrappedDY); iDX = dxWrap(iPlotHexX - iCityHexX); if(hexDistance(iDX, iDY) > CITY_PLOTS_RADIUS) { return -1; } else { return GC.getXYCityPlot((iDX + CITY_PLOTS_RADIUS), (iDY + CITY_PLOTS_RADIUS)); } }
void CvDistanceMap::Dump(const char* filename) { ofstream out(filename); if (out) { out << "#x,y,hx,hz,water,distance,id,owner\n"; for (int i=0; i<GC.getMap().numPlots(); i++) { CvPlot* pPlot = GC.getMap().plotByIndexUnchecked(i); int xHex = xToHexspaceX(pPlot->getX(),pPlot->getY()); int zHex = -xHex-pPlot->getY(); out << pPlot->getX() << "," << pPlot->getY() << "," << xHex << "," << zHex << "," << (pPlot->isWater() ? 1 : 0) << "," << GetClosestFeatureDistance(*pPlot) << "," << GetClosestFeatureID(*pPlot) << "," << GetClosestFeatureOwner(*pPlot) << "\n"; } } out.close(); }
CvPlot* plotDirection(int iX, int iY, DirectionTypes eDirection) { #if defined(MOD_BALANCE_CORE) return GC.getMap().getNeighborUnchecked(iX,iY,eDirection); #else if(eDirection == NO_DIRECTION) { return GC.getMap().plot(iX, iY); } else { // convert to hex-space coordinates - the coordinate system axes are E and NE (not orthogonal) iX = xToHexspaceX(iX , iY); iX += GC.getPlotDirectionX()[eDirection]; iY += GC.getPlotDirectionY()[eDirection]; // convert from hex-space coordinates to the storage array iX = hexspaceXToX(iX, iY); return GC.getMap().plot(iX, iY); } #endif }
/// This function will return the CvPlot associated with the Index (0 to 36) of a City at iX,iY. The lower the Index the closer the Plot is to the City (roughly) CvPlot* iterateRingPlots(int iX, int iY, int iIndex) { int iDeltaHexX = 0; int iDeltaHexY = 0; if(iIndex < MAX_CITY_PLOTS) { iDeltaHexX = GC.getCityPlotX()[iIndex]; // getCityPlotX now uses hex-space coords iDeltaHexY = GC.getCityPlotY()[iIndex]; } else { // loop till we find the ring this is on int iThisRing = 0; int iHighestValueOnThisRing = 0; int iLowestValueOnThisRing = 0; while(iHighestValueOnThisRing < iIndex) { iThisRing++; iLowestValueOnThisRing = iHighestValueOnThisRing + 1; iHighestValueOnThisRing += iThisRing*6; } // determine what side of the hex we are on int iDiff = (iIndex - iLowestValueOnThisRing); int iSide = iDiff / iThisRing; int iOffset = iDiff % iThisRing; switch(iSide) { case 0: iDeltaHexX = 0 + iOffset; iDeltaHexY = iThisRing - iOffset; break; case 1: iDeltaHexX = iThisRing; iDeltaHexY = 0 - iOffset; break; case 2: iDeltaHexX = iThisRing - iOffset; iDeltaHexY = -iThisRing; break; case 3: iDeltaHexX = 0 - iOffset; iDeltaHexY = -iThisRing + iOffset; break; case 4: iDeltaHexX = -iThisRing; iDeltaHexY = 0 + iOffset; break; case 5: iDeltaHexX = -iThisRing + iOffset; iDeltaHexY = iThisRing; break; default: return 0; } } // convert the city coord to hex-space coordinates int iCityHexX = xToHexspaceX(iX, iY); int iPlotHexX = iCityHexX + iDeltaHexX; int iPlotY = iY + iDeltaHexY; // Y is the same in both coordinate systems // convert from hex-space coordinates to the storage array int iPlotX = hexspaceXToX(iPlotHexX, iPlotY); return GC.getMap().plot(iPlotX , iPlotY); }