OOS in multiplayer - List of OOS from RandomLogger and possible solutions?

Jun 7, 2008
Just wonder...
So, I'm currently having a MP game with RyoHazuki but our experience is not one of the best. We definitely had a better experience a couple of hundreds revisions ago, when we've been able to reach modern era. Right now we're slowly going on in Medieval/Renaissance but OOS are very frequent (every 4-5 turns lately, or worse). We've already disabled some BUG options that we already know are causing troubles (range bombardment, Dynamic XP, Defender Withdrawal and some other). We're playing with MegaCivPack and Revolutions but that hasn't caused any issue until now and the game is very enjoyable on that side.
We've discovered a problem probably with Great Generals when used as Field Commanders. We had an OOS that we couldn't avoid by reloading and we only solved it removing one of my Field Commanders (Morale III + Tactics I promoted). I'm not sure but it might be that this particular problem is caused by Tactics I which gives a higher withdrawal chance (since I know that Defender Withdrawal caused OOS problems, I suspect there's something in the code there).
Anyway, I've made a list of most of the OOS we've encountered using the RandomLogger.log. I'm not really sure how to look at it, but I had the idea that looking at the last identical entry in both players logs and then looking at the first different might help in finding where the code is causing troubles. I've got plenty of logs of both players, here's a list of what I've found in RandomLogger:

AI Target City Value
AI Diplo Demand Tribute
AI Diplo Declare War Trade
AI Diplo Open Borders
AI Diplo Alliance
AI Update Area Targets
First Strike
AI Upgrade
AI Barb
Event pick city / Event pick player
Feature Growth / Bonus Depletion

The last one is called in bool CvUnitAI::AI_Abombard() and bool CvUnitAI::AI_FEngage() so disabling Archer Bombard and Fighter Engagement temporarily solves the problem.
I'm investigating other logs but it's very hard. A possibly easy one should be First Strike

44282 207 Global First Strike 1 0
44283 207 Global First Strike 2 0

44282 207 Global First Strike 1 0
44283 207 Global First Strike 1 0

These are the logs of player 1 and 2. That particular difference points to

setCombatFirstStrikes((pCombatUnit->immuneToFirstStrikes()) ? 0 : (firstStrikes() + GC.getGameINLINE().getSorenRandNum(chanceFirstStrikes() + 1, "First Strike")));

which is found in CvUnit.cpp. The fact that this line is calling chanceFirstStrikes, points toward

int CvUnit::chanceFirstStrikes() const
	return std::max(0, (m_pUnitInfo->getChanceFirstStrikes() + getExtraChanceFirstStrikes()));

which in turns leads to

int CvUnit::getExtraChanceFirstStrikes() const
/* Afforess	                  Start		 03/1/10                       Coded By: KillMePlease   */
/*                                                                                              */
/* Great Commanders                                                                             */
	if (!isCommander()) //this is not a commander
		CvUnit* pCommander = getCommander();
		if (pCommander != NULL)
			return	m_iExtraChanceFirstStrikes + pCommander->getExtraChanceFirstStrikes();
/* Afforess	                     END                                                            */
	return m_iExtraChanceFirstStrikes;

which is again Field Commanders code. But from here I'm lost. I thought this should be a possibly easy one because from the logs First Strike random number is called twice in a row hopefully without any other random number being generated between the two calls, so there must be something in CvUnit::chanceFirstStrikes() because 1 and 2 are returned in two consecutive calls.
I hope some other dll expert like Afforess or Thunderbrd can provide some help. Anyway the most frequent OOS until now is always connected with diplomacy, usually AI Diplo Trade War or AI Diplo Declare War Trade.
Top Bottom