Ok, I'm wanting to raise the issue with forest preserves again.
Just a reminder that in PIG mod FPs are available with Monarchy and Lumbermills are available relatively early as well, at Guilds.
I've made sure not to make the mistake of leaving the option checked "workers leave forests" in all my recent tests using AI autoplay and I'm still seeing very poor decision making with respect to these two improvements. It's not uncommon to see the classic "oscillation" problem, that used to happen with cottages/workshops/ now happening with lumbermills (LMs) and forest preserves (FPs). I will watch a worker stand on a forest and not move off it, continuously building FP after LM after FP.
Obviously this is going to have a negative impact on the AI's performance.
I've tried looking at the code but am having difficulty making much sense of it. However, I was able to narrow my attention to this piece of code in CvCityAI.cpp:
Code:
int iHappiness = GC.getImprovementInfo(eFinalImprovement).getHappiness();
if ((iHappiness != 0) && !(GET_PLAYER(getOwnerINLINE()).getAdvancedStartPoints() >= 0))
{
int iHappyLevel = iHappyAdjust + (happyLevel() - unhappyLevel(0));
if (eImprovement == pPlot->getImprovementType())
{
iHappyLevel -= iHappiness;
}
int iHealthLevel = (goodHealth() - badHealth(false, 0));
int iHappyValue = 0;
if (iHappyLevel <= 0)
{
iHappyValue += 400;
}
bool bCanGrow = true;// (getYieldRate(YIELD_FOOD) > foodConsumption());
if (iHappyLevel <= iHealthLevel)
{
iHappyValue += 200 * std::max(0, (bCanGrow ? std::min(6, 2 + iHealthLevel - iHappyLevel) : 0) - iHappyLevel);
}
else
{
iHappyValue += 200 * std::max(0, (bCanGrow ? 1 : 0) - iHappyLevel);
}
if (!pPlot->isBeingWorked())
{
iHappyValue *= 4;
iHappyValue /= 3;
}
iHappyValue += std::max(0, (pPlot->getCityRadiusCount() - 1)) * ((iHappyValue > 0) ? iHappyLevel / 2 : [B]200[/B]);
iValue += iHappyValue * iHappiness;
}
My guess is that on that line:
Code:
iHappyValue += std::max(0, (pPlot->getCityRadiusCount() - 1)) * ((iHappyValue > 0) ? iHappyLevel / 2 : [B]200[/B]);
(pPlot->getCityRadiusCount() - 1)) is often 1, and the expression it is being multiplied by often equates to 200.
My fairly direct question I guess, is "Why is that last part of the multiplication returning 200 when the boolean test is negative?"
If 200 is arbitrary then it's almost certainly too high.
I see the number 200 a lot for the AI's valuation of FPs.
I would happily look into changing some of the logic here myself if someone can give me a brief desccription of the meaning of some of the functions/variables here. e.g.
iHappyAdjust, happyLevel(), unhappylevel(0)
I'm also suspicious of the logic on this:
Code:
bool bCanGrow = true;// (getYieldRate(YIELD_FOOD) > foodConsumption());
As in, why is the logic commented out?