Looked at it one more time ( last time I've looked at this many years ago... ).
So, this is from function assignStartingPlots(); :
Code:
iHumanSlot = range((((countCivPlayersAlive() - 1) * GC.getHandicapInfo(getHandicapType()).getStartingLocationPercent()) / 100), 0, (countCivPlayersAlive() - 1));
[block1]
for (iI = 0; iI < iHumanSlot; iI++)
{
if (GET_PLAYER((PlayerTypes)iI).isAlive())
{
if (!(GET_PLAYER((PlayerTypes)iI).isHuman()))
{
if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
{
GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
playerOrder.push_back(iI);
}
}
}
}
[block2]
for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
{
if (GET_PLAYER((PlayerTypes)iI).isAlive())
{
if (GET_PLAYER((PlayerTypes)iI).isHuman())
{
if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
{
GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
playerOrder.push_back(iI);
}
}
}
}
[block3]
for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
{
if (GET_PLAYER((PlayerTypes)iI).isAlive())
{
if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
{
GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
playerOrder.push_back(iI);
}
}
}
How do I understand it: first we find variable iHumanSlot. For example, if there are 18 CIVS, and we are playing at Deity it will be 17 * 0.9 = 15.3 rounded down = 15. For Settler it will be 17 * 0.1 = 1.7 or rounded 1.
This means that first we are finding starting locations for 15 AIs ( block1), then for human ( block2 ) and then for AI's left.
Next thing is - how works findStartingPlot?
I've had impression before that it just finds the best available plot on the map. And that's why who chooses first - gets advantage, who chooses last ( for example, human on Deity ) - gets poor starting point.
Let's look at this place in function findStartingPlot:
Code:
for(int iPass = 0; iPass < GC.getMapINLINE().maxPlotDistance(); iPass++)
{
CvPlot *pBestPlot = NULL;
int iBestValue = 0;
for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
{
pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
if ((iBestArea == -1) || (pLoopPlot->getArea() == iBestArea))
{
//the distance factor is now done inside foundValue
iValue = pLoopPlot->getFoundValue(getID());
if (bRandomize && iValue > 0)
{
iValue += GC.getGameINLINE().getSorenRandNum(10000, "Randomize Starting Location");
}
if (iValue > iBestValue)
{
bValid = true;
if (bValid)
{
iBestValue = iValue;
pBestPlot = pLoopPlot;
}
}
}
}
if (pBestPlot != NULL)
{
return pBestPlot;
}
So this looks like we check all plots on the map ( if area is not set, and in random maps it looks like it is not set ), and calculate for all of them getFoundValue , and take the best value.
But what I've forgot on this years that there is a randomization process in it: we add random number from 0 to 9999 to the calculated value for each plot.
For example if we found plot1 with value 5000, and plot2 with value 7500, but random adding in first case was 6234 and in second case - 1117, then game still choose plot1 as the best one.
And this actually leave probability even to the first chooser to get a poor place. But still probably who choose close to last places ( as for example, human player on deity ) will have too small chance to get the best possible starting plot, at least in game with many AI opponents. Even if randomization process spoil choose for one or two AI's, and they miss the 3-golds start, it could not spoil it for all of them!
Next is to look - what is getFoundValue, how it estimates specific plot?
This is really big and complicated function as it is used during the whole game to estimate value of the plot too, so it take into account everything, even culture and units... Even if we try to look only at parameters that taken into account when bStartLocation is true ( i.e. this called for estimate this plot as a starting location ) it is too complicated.
So, I can say, for example some insights like:
"You get 600 points if plot is coastal. And additionally 1000 if this the only plot on this area ( on this continent/island ).
You get 200 points if it is on the hill. 40 points if it connected to the river and additional 100 points for freshWater. "
I can say that it takes into account resources, water, that plots with 2 food definitely better than 1 food etc. It penalties for deserts or water plots. Or plots that impassable to reach as mountains or other continent plots. It takes into account not only the plots within radius 2, but also estimates with a smaller weight plots within radius 5 etc. etc.
Also it is, of course, prevents to set starting location too close to the existing ones - otherwise everybody would just start in the same, the richest area.
But other things are too hard too say without deep analysis: this function looks like a total mess.
I even can't say this additional 5000 ( in average ) scores for randomization - is it many? few? Does it makes choose of starting location totally random, or, counterwise, has very small effect?
Hard to say.