Consistent freeze around turn 550 in single player game.

YHWH

Chieftain
Joined
Jun 5, 2010
Messages
1
So I've been playing an incredible single player game as the Luchuirp, slowly amassing vassal states and cities. However, I have a consistent freezing problem that occurs around turn 550. I recently created the mercurial gate, but chose not to play as Basium. I'm not sure if that is at the root of the problem or not.

I've noticed that each turn leading up to it ends with a loud, overlapping "roar" effect, and the AI turns seem to take longer and longer. Eventually the game freezes on an AI turn, allowing my to look around the map, but never take my next turn.

I've attached my most recent save, 90% of the time it freezes right after you end the turn.

Thanks in advance for any help.
 
Sorry, this game will be very difficult to fix.

The bug is being caused by the main Lanun army in the city of Aylesbury. There are about 200 Lanun units in this city; it would take a long time at best to find which unit it is - or the bug may be caused by the AI getting into a loop with so many units together.

If you delete the city, the game goes on, but obviously it cripples the Lanun.

Best wishes,

Breunor
 
I'll need to do more digging - some other day - but it appears related to ACTIVITY_HOLD which some groups of Lanun units have. Don't know yet why they have it or why it would cause so much trouble.
 
I'll need to do more digging - some other day - but it appears related to ACTIVITY_HOLD which some groups of Lanun units have. Don't know yet why they have it or why it would cause so much trouble.

Is Activity_Hold some sort of AI script? What exactly is it?

Any help is appreciated!

Best wishes,

Breunor
 
ACTIVITY_HOLD is what units do when they're skipping a turn. There's also ACTIVITY_AWAKE (ready for action), ACTIVITY_INTERCEPT (intercepting enemy aircraft), ACTIVITY_SLEEP (fortified/sleeping) etc. It's not AI specific, human units work the same way. It appears the AI is trying to move these units, despite them skipping a turn, then because they're skipping a turn it end up not moving them... and so we have our loop.

Will see if I can figure it out now.
 
Solved. I was wrong about ACTIVITY_HOLD having anything to do with it.

The problem is this:

If a unit under AIcontrol is in a group of more than one (that is, with other units) make it leave the group.
Allow units that are under AIcontrol to group with eachother.

What's the problem? Well what happens is the AI is forced to leave the group, then return to try again. The next time they run the normal routine, find someone to group with and do so.
The next time now being two in a group the unit is forced to leave the group and return to try again... always grouping with the same unit, which is in the same plot, then being forced to split on the next try.

So it's caused by a unit deciding to join a group, then being forced to leave said group, then joining, leaving and so on forever.

I see two possible solutions
Easy but not very good solution:
In CvUnit::canJoinGroup once again make sure you can't group AIcontrolled units (the code is there, just commented out)

Better but not as easy solution: (there are many variations of this, this is just one of them)
Don't force units to leave groups with other AIcontrolled units. This code in CvUnitAI::AI_update() would need to be changed:
Code:
        if (getGroup()->getNumUnits()>1)
        {
            joinGroup(NULL);
            return true;
        }

Looping through each unit to see if they're ai controlled should work, like this:
Code:
        if (getGroup()->getNumUnits()>1)
        {
			CLLNode<IDInfo>* pUnitNode = getGroup()->headUnitNode();
			CvUnit* pLoopUnit;

			while (pUnitNode != NULL)
			{
				pLoopUnit = ::getUnit(pUnitNode->m_data);
				pUnitNode = getGroup()->nextUnitNode(pUnitNode);
				if (!pLoopUnit->isAIControl())
				{
					joinGroup(NULL);
					return true;
				}
			}
        }
Ironically while this solves the WoC it does not mean the turn can be continued - there's another unrelated WoC in another part of the code, causing the same split-and-join behavior :crazyeye:
(pretty sure I know the cause, just gotta add one if statement to fix it)


Another possible solution would be to see if the head unit is in the same AIControlled state as this and leave the group if not. (aicontrolled head, nonaicontrolled unit --> leave group; nonaicontrolled head, aicontrolled unit -> leave group). The problem I have with that is it can break up a big group, human or AI, simply because the head unit became AI controlled.
 
Second WoC also fixed. It was missing a check if we can join the group we want to join. So it wanted to join a group, then couldn't so it rejoined the old group (since that was the best group it could join), then wanted to join the new group...

To be honest, I'm not sure what this code is for. It's splitting up a group for seemingly no reason when it could instead move the entire group. But I've limited my changes to fixing the WoC.

Function CvUnitAI::ConquestMove()
Original code
Spoiler :
Code:
            bool splitup=false;
            for(pLoopSelectionGroup = GET_PLAYER(getOwnerINLINE()).firstSelectionGroup(&iLoop); pLoopSelectionGroup != NULL; pLoopSelectionGroup = GET_PLAYER(getOwnerINLINE()).nextSelectionGroup(&iLoop))
            {
                if (pLoopSelectionGroup->getHeadUnit() != NULL)
                {
                    if (pLoopSelectionGroup->getHeadUnit()->AI_getGroupflag()==GROUPFLAG_CONQUEST)
                    {
                        if (pLoopSelectionGroup!=getGroup())
                        {
                            CvPlot* pPlot = pLoopSelectionGroup->getHeadUnit()->plot();
                            if (AI_plotValid(pPlot))
                            {
                                if (!isEnemy(pPlot->getTeam()))
                                {
                                    if (!(pPlot->isVisibleEnemyUnit(this)))
                                    {
                                        if (generatePath(pPlot, 0, true, &iPathTurns))
                                        {
                                            if (pLoopSelectionGroup->getNumUnits() >= getGroup()->getNumUnits())
                                            {
                                                splitup=true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

New code (the weird spacing is caused by a mix of tabs and spaces)
Spoiler :
Code:
            bool splitup=false;
            for(pLoopSelectionGroup = GET_PLAYER(getOwnerINLINE()).firstSelectionGroup(&iLoop); pLoopSelectionGroup != NULL; pLoopSelectionGroup = GET_PLAYER(getOwnerINLINE()).nextSelectionGroup(&iLoop))
            {
                if (pLoopSelectionGroup->getHeadUnit() != NULL)
                {
                    if (pLoopSelectionGroup->getHeadUnit()->AI_getGroupflag()==GROUPFLAG_CONQUEST)
                    {
                        if (pLoopSelectionGroup!=getGroup())
                        {
                            CvPlot* pPlot = pLoopSelectionGroup->getHeadUnit()->plot();
                            if (AI_plotValid(pPlot))
                            {
                                if (!isEnemy(pPlot->getTeam()))
                                {
                                    if (!(pPlot->isVisibleEnemyUnit(this)))
                                    {
										if (AI_allowGroup(pLoopSelectionGroup->getHeadUnit(), UNITAI_UNKNOWN))
										{
											if (generatePath(pPlot, 0, true, &iPathTurns))
											{
												if (pLoopSelectionGroup->getNumUnits() >= getGroup()->getNumUnits())
												{
													splitup=true;
												}
											}
										}
                                    }
                                }
                            }
                        }
                    }
                }
            }


This fix, along with the first, allowed the turn to finish.
 
Snarko,

This is a HUGE find! I think this is probalby the single most important outstansing bug in that gaem that you may have squashed! I REALLY hope that his gets into patch o.

Best wishes,

Breunor
 
Snarko,

This is a HUGE find! I think this is probalby the single most important outstansing bug in that gaem that you may have squashed! I REALLY hope that his gets into patch o.

Best wishes,

Breunor

:agree: Very nicely done, Snarko!
 
I get the same problem after turn 400 (normal speed) in every game I play. Every one. How do I apply spacko's fixes? I'm not familiar with Civ4 modding/tweaking.
 
Wait for patch o.
 
Sorry, I misspelled your name snarko.

Will patch o even come? Generally when a mod developer goes standalone, the mod dies and never sees another patch.
 
I have no idea. I'm not on the team, I just solve bugs and post my conclusions/solutions :p
 
Would this fix the massive lag I get late game? (it hasn't crashed on me yet, but it can take all day to do ~50 turns).
 
No. This fixes infinite loops, where the game NEVER continue. It has no effect on normal turns.
 
Back
Top Bottom