//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
	}
}
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));
}
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 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));
	}
}
Example #7
0
///TKs Med
CvCity* CvMap::findCity(int iX, int iY, PlayerTypes eOwner, TeamTypes eTeam, bool bSameArea, bool bCoastalOnly, TeamTypes eTeamAtWarWith, DirectionTypes eDirection, CvCity* pSkipCity, bool bRandom)
{
	int iBestValue = MAX_INT;
	CvCity* pBestCity = NULL;
    std::vector<CvCity*> aCitys;
	for (int iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if ((eOwner == NO_PLAYER) || (iI == eOwner))
			{
				if ((eTeam == NO_TEAM) || (GET_PLAYER((PlayerTypes)iI).getTeam() == eTeam))
				{
					int iLoop;
					for (CvCity* pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
					{
						if (!bSameArea || (pLoopCity->area() == plotINLINE(iX, iY)->area()) || (bCoastalOnly && (pLoopCity->waterArea() == plotINLINE(iX, iY)->area())))
						{
							if (!bCoastalOnly || pLoopCity->isCoastal(GC.getMIN_WATER_SIZE_FOR_OCEAN()))
							{
								if ((eTeamAtWarWith == NO_TEAM) || atWar(GET_PLAYER((PlayerTypes)iI).getTeam(), eTeamAtWarWith))
								{
									if ((eDirection == NO_DIRECTION) || (estimateDirection(dxWrap(pLoopCity->getX_INLINE() - iX), dyWrap(pLoopCity->getY_INLINE() - iY)) == eDirection))
									{
										if ((pSkipCity == NULL) || (pLoopCity != pSkipCity))
										{
										    if (!bRandom)
										    {
                                                int iValue = plotDistance(iX, iY, pLoopCity->getX_INLINE(), pLoopCity->getY_INLINE());

                                                if (iValue < iBestValue)
                                                {
                                                    iBestValue = iValue;
                                                    pBestCity = pLoopCity;
                                                }
										    }
										    else
										    {
										        aCitys.push_back(pLoopCity);
										    }
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
    if (bRandom)
    {
        int iRandom = aCitys.size();

        if (iRandom >= 1)
        {
            iRandom = GC.getGameINLINE().getSorenRandNum(iRandom, "Random Find City");
            return aCitys[iRandom];
        }
        else
        {
            return NULL;
        }

    }

    return pBestCity;
}
int cyDxWrap(int iDX)
{
	return dxWrap(iDX);
}