MootPoint
Chieftain
Okay, I found a recursion. I *think* it's a barbarian unit trying to attack a city, and the mission to move into the city never sets the attack flag:
bFollow is a param that always defaults to false when one calls CvUnitAI::AI_cityAttack().
So, the barb goes through the motions of doing the attack, but is blocked from moving into the city square by this check in CvSelectionGroup::groupMove():
The code jumps into the else clause, pushes the same bloody Move mission right back into the queue, and it never gets resolved.
Is a barbarian unit supposed to be able to sack the city?
*edit* - okay, I found out what's causing the failure - the failure's in CvUnit.cpp:
So the canMoveInto() function fails because the elapsed game turn count check is less than the 30 * getGameSpeedInfo() check. If it was later in the game, this recursion wouldn't happen...
*edit 2*
Okay, proposed fix: the root of the problem is that when the AI city attack code tries to determine whether it can attack the plot, it calls generatePath(), which in turn calls canMoveOrAttackInto(), which calls canMoveInto() twice, with the attack flag off, then on. So the AI will always think that it can attack the city, but later when it tries to do the move, it's blocked. So I think it's actually a pretty simple fix - instead of:
Just get rid of the if(!bAttack) check & return false immediately.. Then you'll get consistency - if you're a barbarian unit, and you're at war with the plot's city, you can't attack before turn x, period.
(Tested against the save game, and it now works...)
Code:
getGroup()->pushMission(MISSION_MOVE_TO, pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), ((bFollow) ? MOVE_DIRECT_ATTACK : 0));
bFollow is a param that always defaults to false when one calls CvUnitAI::AI_cityAttack().
So, the barb goes through the motions of doing the attack, but is blocked from moving into the city square by this check in CvSelectionGroup::groupMove():
Code:
if ((pLoopUnit->canMove() && ((bCombat && (!(pLoopUnit->isNoCapture()) || !(pPlot->isEnemyCity(*pLoopUnit)))) ? pLoopUnit->canMoveOrAttackInto(pPlot) : pLoopUnit->canMoveInto(pPlot))) || (pLoopUnit == pCombatUnit))
{
pLoopUnit->move(pPlot, true);
}
/*************************************************************************************************/
/** Alertness END **/
/*************************************************************************************************/
else
{
pLoopUnit->joinGroup(NULL, true);
pLoopUnit->ExecuteMove(((float)(GC.getMissionInfo(MISSION_MOVE_TO).getTime() * gDLL->getMillisecsPerTurn())) / 1000.0f, false);
}
The code jumps into the else clause, pushes the same bloody Move mission right back into the queue, and it never gets resolved.
Is a barbarian unit supposed to be able to sack the city?
*edit* - okay, I found out what's causing the failure - the failure's in CvUnit.cpp:
Code:
if (isBarbarian() && GC.getGameINLINE().getElapsedGameTurns() < (30 * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent())/100)
{
if (pPlot->isCity() && atWar(pPlot->getTeam(), getTeam()))
{
if (!bAttack)
{
return false;
}
}
}
So the canMoveInto() function fails because the elapsed game turn count check is less than the 30 * getGameSpeedInfo() check. If it was later in the game, this recursion wouldn't happen...
*edit 2*
Okay, proposed fix: the root of the problem is that when the AI city attack code tries to determine whether it can attack the plot, it calls generatePath(), which in turn calls canMoveOrAttackInto(), which calls canMoveInto() twice, with the attack flag off, then on. So the AI will always think that it can attack the city, but later when it tries to do the move, it's blocked. So I think it's actually a pretty simple fix - instead of:
Code:
if (isBarbarian() && GC.getGameINLINE().getElapsedGameTurns() < (30 * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent())/100)
{
if (pPlot->isCity() && atWar(pPlot->getTeam(), getTeam()))
{
//if (!bAttack) <- delete this
{
return false;
}
}
}
Just get rid of the if(!bAttack) check & return false immediately.. Then you'll get consistency - if you're a barbarian unit, and you're at war with the plot's city, you can't attack before turn x, period.
(Tested against the save game, and it now works...)