//------------------------------------------------------------------------------ bool CvDllGameContext::RandomNumberGeneratorSyncCheck(PlayerTypes ePlayer, ICvRandom1* pRandom, bool bIsHost) { // uh oh! Check the Random number generator! const CvRandom& localSimRandomNumberGenerator = GC.getGame().getJonRand(); CvRandom* pkRandom = GC.UnwrapRandomPointer(pRandom); if(localSimRandomNumberGenerator != *pkRandom) { FILogFile* logFile = LOGFILEMGR.GetLog("net_message_debug.log", 0); char formatBuf[128] = {"\0"}; std::string rngLogMessage = "Game Random Number Generators are out of sync : local.seed="; _i64toa_s(localSimRandomNumberGenerator.getSeed(), formatBuf, 127, 10); rngLogMessage += formatBuf; rngLogMessage += ", remote.seed="; _i64toa_s(pkRandom->getSeed(), formatBuf, 127, 10); rngLogMessage += formatBuf; rngLogMessage += "\n\tlocal.callCount="; _itoa_s(localSimRandomNumberGenerator.getCallCount(), formatBuf, 10); rngLogMessage += formatBuf; rngLogMessage += ", remote.callCount="; _itoa_s(pkRandom->getCallCount(), formatBuf, 10); rngLogMessage += formatBuf; rngLogMessage += "\n\tlocal.resetCount="; _itoa_s(localSimRandomNumberGenerator.getResetCount(), formatBuf, 10); rngLogMessage += formatBuf; rngLogMessage += ", remote.resetCount="; _itoa_s(pkRandom->getResetCount(), formatBuf, 10); rngLogMessage += formatBuf; rngLogMessage += "\n"; if(logFile) logFile->DebugMsg(rngLogMessage.c_str()); return false; } return true; }
//------------------------------------------------------------------------------ bool CvDllGameContext::RandomNumberGeneratorSyncCheck(PlayerTypes ePlayer, ICvRandom1* pRandom, bool bIsHost) { // uh oh! Check the Random number generator! const CvRandom& localSimRandomNumberGenerator = GC.getGame().getJonRand(); CvRandom* pkRandom = GC.UnwrapRandomPointer(pRandom); if(localSimRandomNumberGenerator != *pkRandom) { FILogFile* logFile = LOGFILEMGR.GetLog("net_message_debug.log", 0); char formatBuf[128] = {"\0"}; std::string rngLogMessage = "Game Random Number Generators are out of sync : local.seed="; rngLogMessage += _itoa_s(localSimRandomNumberGenerator.getSeed(), formatBuf, 10); rngLogMessage += ", remote.seed="; rngLogMessage += _itoa_s(pkRandom->getSeed(), formatBuf, 10); rngLogMessage += "\n\tlocal.callCount="; rngLogMessage += _itoa_s(localSimRandomNumberGenerator.getCallCount(), formatBuf, 10); rngLogMessage += ", remote.callCount="; rngLogMessage += _itoa_s(pkRandom->getCallCount(), formatBuf, 10); rngLogMessage += "\n\tlocal.resetCount="; rngLogMessage += _itoa_s(localSimRandomNumberGenerator.getResetCount(), formatBuf, 10); rngLogMessage += ", remote.resetCount="; rngLogMessage += _itoa_s(pkRandom->getResetCount(), formatBuf, 10); rngLogMessage += "\n"; if(localSimRandomNumberGenerator.callStackDebuggingEnabled() && pkRandom->callStackDebuggingEnabled()) { std::string localCallStack(""); std::string remoteCallStack(""); localSimRandomNumberGenerator.resolveCallStacks(); const std::vector<std::string>& localCallStacks = localSimRandomNumberGenerator.getResolvedCallStacks(); const std::vector<std::string>& remoteCallStacks = pkRandom->getResolvedCallStacks(); const std::vector<unsigned long>& localSeedHistory = localSimRandomNumberGenerator.getSeedHistory(); const std::vector<unsigned long>& remoteSeedHistory = pkRandom->getSeedHistory(); std::vector<unsigned long>::const_iterator localSeedIterator = localSeedHistory.begin(); std::vector<unsigned long>::const_iterator remoteSeedIterator = remoteSeedHistory.begin(); unsigned int callNumber = 0; for(localSeedIterator = localSeedHistory.begin(), remoteSeedIterator = remoteSeedHistory.begin(); localSeedIterator != localSeedHistory.end() && remoteSeedIterator != remoteSeedHistory.end(); ++localSeedIterator, ++remoteSeedIterator, ++callNumber) { if(*localSeedIterator != *remoteSeedIterator) { if(callNumber < localCallStacks.size() && callNumber < remoteCallStacks.size()) { rngLogMessage += "At Call #"; rngLogMessage += _itoa_s(callNumber, formatBuf, 10); rngLogMessage += " random number seeds are different.\n"; if(callNumber > 0) { rngLogMessage += "Call #"; rngLogMessage += _itoa_s(callNumber - 1, formatBuf, 10); rngLogMessage += "\nLocal:\n"; rngLogMessage += localCallStacks[callNumber - 1]; rngLogMessage += "\nRemote:\n"; rngLogMessage += remoteCallStacks[callNumber - 1]; } rngLogMessage += "Call #"; rngLogMessage += _itoa_s(callNumber, formatBuf, 10); rngLogMessage += "\nLocal:\n"; rngLogMessage += localCallStacks[callNumber]; rngLogMessage += "\nRemote:\n"; rngLogMessage += remoteCallStacks[callNumber]; break; } } } if(localSeedIterator != localSeedHistory.end() && remoteSeedIterator == remoteSeedHistory.end()) { rngLogMessage += "\nLocal random number generator called more than remote at call #"; rngLogMessage += _itoa_s(callNumber, formatBuf, 10); rngLogMessage += "\n"; if(callNumber < localSeedHistory.size()) { rngLogMessage += "Local CallStack:\n"; rngLogMessage += localCallStacks[callNumber]; } } else if(remoteSeedIterator != remoteSeedHistory.end() && localSeedIterator == localSeedHistory.end()) { rngLogMessage += "\nremote random number generator called more than local at call #"; rngLogMessage += _itoa_s(callNumber, formatBuf, 10); rngLogMessage += "\n"; if(callNumber < remoteSeedHistory.size()) { rngLogMessage += "remote CallStack:\n"; rngLogMessage += remoteCallStacks[callNumber]; } } // find first different call std::vector<std::string>::const_iterator localCallStackIterator; std::vector<std::string>::const_iterator remoteCallStackIterator; for(localCallStackIterator = localCallStacks.begin(), remoteCallStackIterator = remoteCallStacks.begin(), callNumber = 0; localCallStackIterator != localCallStacks.end() && remoteCallStackIterator != remoteCallStacks.end(); ++localCallStackIterator, ++remoteCallStackIterator, ++callNumber) { if(*localCallStackIterator != *remoteCallStackIterator) { rngLogMessage += "\nFirst different callstack at call #"; rngLogMessage += _itoa_s(callNumber, formatBuf, 10); rngLogMessage += "\n"; rngLogMessage += "Local :\n"; rngLogMessage += *localCallStackIterator; rngLogMessage += "Remote :\n"; rngLogMessage += *remoteCallStackIterator; break; } } if(logFile) { logFile->DebugMsg(rngLogMessage.c_str()); } CvAssertMsg(false, rngLogMessage.c_str()); if(logFile) { rngLogMessage = "\nDebug dump:\n"; // add full history rngLogMessage += "Seed History -\n"; localSeedIterator = localSeedHistory.begin(); remoteSeedIterator = remoteSeedHistory.begin(); callNumber = 0; while(localSeedIterator != localSeedHistory.end() || remoteSeedIterator != remoteSeedHistory.end()) { ++callNumber; rngLogMessage += "\t Call #"; rngLogMessage += _itoa_s(callNumber, formatBuf, 10); rngLogMessage += " LOCAL="; if(localSeedIterator != localSeedHistory.end()) { rngLogMessage += _itoa_s(*localSeedIterator, formatBuf, 10); ++localSeedIterator; } rngLogMessage += "\tREMOTE="; if(remoteSeedIterator != remoteSeedHistory.end()) { rngLogMessage += _itoa_s(*remoteSeedIterator, formatBuf, 10); ++remoteSeedIterator; } rngLogMessage += "\n"; } rngLogMessage += "\nLocal callstack history\n"; callNumber = 0; std::string lastCallStackLogged; unsigned int repeatCount = 0; std::vector<std::string>::const_iterator i; for(i = localCallStacks.begin(); i != localCallStacks.end(); ++i) { if(lastCallStackLogged != *i) { if(repeatCount > 0) { rngLogMessage += "Last message repeated "; rngLogMessage += _itoa_s(repeatCount, formatBuf, 10); rngLogMessage += " times\n"; } rngLogMessage += "Call #"; rngLogMessage += _itoa_s(callNumber, formatBuf, 10); rngLogMessage += "\n"; rngLogMessage += *i; lastCallStackLogged = *i; repeatCount = 0; } else { repeatCount++; } ++callNumber; } rngLogMessage += "\nRemote callstack history\n"; callNumber = 0; repeatCount = 0; for(i = remoteCallStacks.begin(); i != remoteCallStacks.end(); ++i) { if(lastCallStackLogged != *i) { if(repeatCount > 0) { rngLogMessage += "Last message repeated "; rngLogMessage += _itoa_s(repeatCount, formatBuf, 10); rngLogMessage += " times\n"; } rngLogMessage += "Call #"; rngLogMessage += _itoa_s(callNumber, formatBuf, 10); rngLogMessage += "\n"; rngLogMessage += *i; lastCallStackLogged = *i; repeatCount = 0; } else { repeatCount++; } ++callNumber; } logFile->DebugMsg(rngLogMessage.c_str()); } } else { if(logFile) { logFile->DebugMsg(rngLogMessage.c_str()); } CvAssertMsg(false, rngLogMessage.c_str()); } /* If this point has been reached, the OOS may be nearly unrecoverable // attempt to recover if(m_isHost) { CvRandom & rng = auto_ptr<ICvGame1> pGame = GameCore::GetGame();\n.getJonRand(); rng.reset(m_simRandomNumberGenerator.getSeed()); } // brute force approach // JAR : todo - this is the solution of last resort if // loadDelta() doesn't work out */ return false; } return true; }