I have completed a slightly less-recursive version of the formula for determining if mountains connect to the southeast or northwest. It's still a bit long, so I've decided to simply post my code segment. It is in the Java language (version 1.5 or later, although earlier may work, with Log4J [otherwise take out all the logging statements]):
Code:
//Fragment from another method
//Base terrain 5 is hills, 6 is mountains
//Does the tile connect to the southeast?
boolean southeastConnection = southeastConnection(xpos, ypos);
//If the tile directly SE isn't a mountain, there is no SE connection regardless
if (getTile(xpos + 1, ypos + 1) == null)
;
else if(getTile(xpos + 1, ypos + 1).getBaseTerrain() != 6 && getTile(xpos + 1, ypos + 1).getBaseTerrain() != 5)
southeastConnection = false;
//Does the tile connect to the northwest? Assume yes, then figure out if it doesn't.
boolean northwestConnection = true;
if (getTile(xpos - 1, ypos - 1) == null)
;
else if(getTile(xpos - 1, ypos - 1).getBaseTerrain() != 6 && getTile(xpos - 1, ypos - 1).getBaseTerrain() != 5)
northwestConnection = false; //Northwest
//If the tile NW doesn't connect, this one won't either.
if (!(southeastConnection(xpos-1, ypos - 1)))
northwestConnection = false;
/**
* Returns true if and only if, in an infinitely extending NW-SE chain of
* mountains/hills, the mountain at (xpos, ypos) will visually
* connect to the mountain directly to its southeast.
*
* This is determined by figuring out if the mountain at (xpos, ypos)
* will *NOT* connect to the mountain directly to the southeast, as this
* is the rarer condition, and then returning the opposite of what that
* calculation determines.
*
* @param xpos - The x position of the mountain/hill in question.
* @param ypos - The y position of the mountain/hill in question.
* @return - Whether, in a chain of mountains, that mountain/hill will
* connect to the mountain/hill to its southeast.
*/
private boolean southeastConnection(int xpos, int ypos)
{
//check for top of map.
if (ypos < 0 || ypos >= wmap.height - 1)
return false;
//NW/SE
int numberOfFives = ypos/5; //(to nearest integer)
int baseX = xpos;
int baseY = ypos;
//But we need baseX to be >= baseY if this is going to work. So if it's less, add the width to it.
if (baseX < baseY)
baseX = baseX + this.wmap.width;
baseX = baseX - 5*numberOfFives;
baseY = baseY - 5*numberOfFives;
//(BaseX, BaseY) will be in the first 5 rows and will be 5z tiles NW of the one in question, z an integer
//Now, there are 5 key tiles - (0, 0), (4, 2), (8, 4), (7, 1), and (11, 3). These are the first tiles where
//a "No SE" block occurs
boolean noSE = false;
if (logger.isTraceEnabled())
logger.trace("baseX, baseY: " + baseX + ", " + baseY);
while (baseX >= 0)
{
if (baseX == 0 && baseY == 0)
noSE = true;
if (baseX == 4 && baseY == 2)
noSE = true;
if (baseX == 8 && baseY == 4)
noSE = true;
if (baseX == 7 && baseY == 1)
noSE = true;
if (baseX == 11 && baseY == 3)
noSE = true;
baseX-=5;
}
if (logger.isTraceEnabled())
logger.trace("X: " + xpos + ", Y: " + ypos + " connects SE? " + !noSE);
return !noSE;
}
/**
* Returns the TILE specified by its x and y positions. This involves
* converting the 2D location into a 1D location in the TILE array.
* @param xPos
* @param yPos
* @return
*/
public TILE getTile(int xPos, int yPos)
{
int index = 0;
//always add in a width-worth * yPos/2 (truncated)
index+=((yPos/2)*(wmap.width));
if (yPos % 2 == 1) //add in half a width worth of tiles
index+=((wmap.width)/2);
index+=xPos/2;
try{
return tile.get(index);
}
catch(java.lang.IndexOutOfBoundsException e){
return null;
}
}
wmap refers to the World Map section of the BIQ; I think otherwise the variable names are either intuitive or explained in the code. I can clarify them if need be.
My more recursive explanation, which I first came up with, follows:
Code:
If we start at (0, 0), the first "Most SE" graphic in a chain starting there is at the 1st position - (0, 0) = (0, 0) + (0, 0)
For each jump directly E (first to (2,0)), we add 2 to the index of the 1st "Most SE" graphic - it is the third graphic for the next NW-Se chain at (2, 0)
It is the fifth graphic for the chain starting at (4, 0)
And then the second graphic for the one starting at (6, 0), because we take a modulus five
The fourth for the chain starting at (8, 0)
And the first again for the chain starting at (10, 0)
And we can figure out whether a graphic further south is the "Most SE" one by figuring out if it is an offset of (5x, 5y) from a "Most SE" graphic in the top 5 rows. Thus, the chain starting at (4, 0) has "Most SE" graphics at (8, 4), (13, 9), etc.
That definition isn't as formulaic and thorough, but may be more understandable. Both may well be improveable, to either simplify them or speed them up, but most importantly, the Java method does work correctly.
For determining the graphic to use, you then follow the formula in Dianthus's post #43, using northwestConnection and southeastConnection to determine whether to add 1 and 8 for NW/SE respectively.
I unfortunately have not been able to figure out what the formula for NE-SW chains is. I'm simply always adding 2/4 for NE/SW, respectively, which doesn't always match up with Civ but does more than half the time. At this point I've decided to throw in the towel on figuring that out and go forward with other things in life. But I'm uploading my most recent spreadsheets and notes so that if someone else cares to look, they can have a base of information to start from.
Mountain Chain Search NE SW.zip
Bookmarks