BUG? PlotXYWithRangeCheck: used by the game to check range

Barathor

Emperor
Joined
May 7, 2011
Messages
1,202
PlotXYWithRangeCheck

EDIT: The function can be found within CvGameCoreUtils.h within the Civ5 source files.

Am I missing something, or is this not working properly?

This is an often used function within the game which checks if a tile is within a certain range:

Code:
inline CvPlot* plotXYWithRangeCheck(int iX, int iY, int iDX, int iDY, int iRange)
{
	int hexRange;

	// I'm assuming iDX and iDY are in hex-space
	if((iDX >= 0) == (iDY >= 0))  // the signs match
	{
		int iAbsDX = iDX >= 0 ? iDX : -iDX;
		int iAbsDY = iDY >= 0 ? iDY : -iDY;
		hexRange = iAbsDX + iAbsDY;
	}
	else
	{
		int iAbsDX = iDX >= 0 ? iDX : -iDX;
		int iAbsDY = iDY >= 0 ? iDY : -iDY;
		hexRange = iAbsDX >= iAbsDY ? iAbsDX : iAbsDY;
	}

	if(hexRange > iRange)
	{
		return NULL;
	}

	return plotXY(iX, iY, iDX, iDY);
}

Basically, if the signs match, the absolute values of the adjustments get added together; if the signs are different you use the greater absolute value of the two. If it's larger than the range value, it returns a null ("not within range").

But, here's a diagram of this function using both a Y-value that is even and one that is odd (using iRange = 2; iDX and iDY = -2 to 2):



The grayed hex cells would be considered out of the 2 hex range of the center point. The white cells are considered within range. Grayed text for the plot adjustments just means they wouldn't even be considered in the function, but I displayed them in the diagram anyway.

Here is an example of the function being utilized:

Code:
-- Don't trigger near our lands
local centerX = plot:GetX();
local centerY = plot:GetY();
for shiftX = -HexRadius, HexRadius, 1 do
	for shiftY = -HexRadius, HexRadius, 1 do
		local miasmaPlot = Map.PlotXYWithRangeCheck(centerX, centerY, shiftX, shiftY, HexRadius);
		if (miasmaPlot ~= nil and miasmaPlot:GetOwner() == player:GetID()) then
			return false;
		end
	end
end

Also, there are inconsistencies of its use throughout the game files. Most have an iDX and iDY minimum and maximum equal to -iRange to iRange. But, one or two examples used a maximum of iRange-1. Another I saw, for goody huts (resource pods) uses -3 to 3 for iDX and iDY but an iRange of 4. :confused:

I stumbled across this while working on a BE map script and messing with resource pod placement.
 
The key is that both X and Y are in hexspace (as indicated by the comment that says the code assums both iDX and iDY are in hexspace), so your coordinate map is wrong. X increases from left to right, Y increases from northeast to southwest. So the coordinates of tiles around a specific tile would be
Code:
        -------------------------------
        |              |              |
        |    -1  1     |     0  1     |
        |              |              |
----------------------------------------------
|              |              |              |
|    -1  0     |     0  0     |     1  0     |
|              |              |              |
----------------------------------------------
        |              |              |
        |     0 -1     |     1 -1     |
        |              |              |
        -------------------------------
... instead of the system you described. The main reason behind the whole hexspace-squarespace dualism (the fact that Civ5 and BE use both hexspace and squarespace systems instead settling with one) is that hexspace calculations are a lot faster and more elegant, but there are a lot of unused coordinates, so their storage becomes a lot more bloated if rectangularly-shaped maps don't wrap in at least one coordinate.

Granted, there are issues with Civ5's and BE's use of this function, but they are more performance-related than anything else.
 
Thanks for taking the time to help me out! I knew I was missing something, since the game uses the function a lot of times.

At first, I still wasn't quite understanding what you meant, but I did some googling and found this awesome site about hexagonal grids:
http://www.redblobgames.com/grids/hexagons/#coordinates

So, I was assuming the function was using offset coordinates like most of the Lua, when it was actually using axial coordinates, which are more efficient for the function's purpose -- like you said. (Utilizing cube coordinates looks pretty interesting on that page too.)
 
Top Bottom