Hooks
static bool BeforeCvEspionageAI_FindTargetSpyNumbers(CvEspionageAI* self, int* piTargetOffensiveSpies, int* piTargetDefensiveSpies, int* piTargetCityStateSpies, int* piTargetDiplomatSpies);static void AfterCvEspionageAI_FindTargetSpyNumbers(CvEspionageAI* self, int* piTargetOffensiveSpies, int* piTargetDefensiveSpies, int* piTargetCityStateSpies, int* piTargetDiplomatSpies);static void ReplaceCvEspionageAI_FindTargetSpyNumbers(void (*original)(CvEspionageAI*, int*, int*, int*, int*), CvEspionageAI* self, int* piTargetOffensiveSpies, int* piTargetDefensiveSpies, int* piTargetCityStateSpies, int* piTargetDiplomatSpies);CivRegisterBefore<CivHooks::CvEspionageAI_FindTargetSpyNumbers>(host, &BeforeCvEspionageAI_FindTargetSpyNumbers);CivRegisterAfter<CivHooks::CvEspionageAI_FindTargetSpyNumbers>(host, &AfterCvEspionageAI_FindTargetSpyNumbers);CivRegisterReplace<CivHooks::CvEspionageAI_FindTargetSpyNumbers>(host, &ReplaceCvEspionageAI_FindTargetSpyNumbers);
Code
5150// Figure out how the spies should be allocated5151void CvEspionageAI::FindTargetSpyNumbers(int* piTargetOffensiveSpies, int* piTargetDefensiveSpies, int* piTargetCityStateSpies, int* piTargetDiplomatSpies)5152{5153 CvDiplomacyAI* pDiploAI = m_pPlayer->GetDiplomacyAI();51545155 int iNumRemainingSpies = m_pPlayer->GetEspionage()->GetNumAliveSpies();5156 if(iNumRemainingSpies == 0)5157 {5158 *piTargetDefensiveSpies = 0;5159 *piTargetOffensiveSpies = 0;5160 *piTargetCityStateSpies = 0;5161 *piTargetDiplomatSpies = 0;5162 return;5163 }51645165 bool bAllocatedOffensiveSpies = false;5166 bool bAllocatedDefensiveSpies = false;5167 bool bAllocatedCityStateSpies = false;5168 bool bAllocatedDiplomatSpies = false;5169 float fTechPositionRatio = m_pPlayer->GetPlayerTechs()->GetTechAI()->GetTechRatio();51705171 // if going for diplo or conquest, evaluate the offensive spies before assigning CS spies5172 if (pDiploAI->IsGoingForDiploVictory())5173 {5174 // find out how many diplomats we need5175 float fNumDiplomats = 0.0f;5176 for (uint ui = 0; ui < MAX_MAJOR_CIVS; ui++)5177 {5178 PlayerTypes ePlayer = (PlayerTypes)ui;5179 // must not be me and must be alive5180 if (ePlayer == m_pPlayer->GetID() || !GET_PLAYER(ePlayer).isAlive())5181 {5182 continue;5183 }51845185 CvLeagueAI::DiplomatUsefulnessLevels eUsefulnessLevel = m_pPlayer->GetLeagueAI()->GetDiplomatUsefulnessAtCiv(ePlayer);5186 switch (eUsefulnessLevel)5187 {5188 case CvLeagueAI::DIPLOMAT_USEFULNESS_HIGH:5189 fNumDiplomats += 1.0f;5190 break;5191 case CvLeagueAI::DIPLOMAT_USEFULNESS_MEDIUM:5192 fNumDiplomats += 0.5f;5193 break;5194 case CvLeagueAI::DIPLOMAT_USEFULNESS_LOW:5195 fNumDiplomats += 0.25f;5196 break;5197 case CvLeagueAI::DIPLOMAT_USEFULNESS_NONE:5198 break;5199 }5200 }52015202 // assign spies to be diplomats5203 int iNumDiplomats = (int)floor(fNumDiplomats);5204 *piTargetDiplomatSpies = min(iNumRemainingSpies, iNumDiplomats);5205 bAllocatedDiplomatSpies = true;5206 iNumRemainingSpies -= *piTargetDiplomatSpies;52075208 // assign offensive spies according to tech position5209 *piTargetOffensiveSpies = (int)ceil(fTechPositionRatio * iNumRemainingSpies);5210 bAllocatedOffensiveSpies = true;5211 iNumRemainingSpies -= *piTargetOffensiveSpies;52125213 int iNumCityStates = 0;5214 for(uint ui = MAX_MAJOR_CIVS; ui < MAX_CIV_PLAYERS; ui++)5215 {5216 PlayerTypes ePlayer = (PlayerTypes)ui;5217 if (!GET_PLAYER(ePlayer).isAlive())5218 {5219 continue;5220 }52215222 if(!GET_TEAM(m_pPlayer->getTeam()).isHasMet(GET_PLAYER(ePlayer).getTeam()))5223 {5224 continue;5225 }52265227 // don't interact with city-states that are at war with us5228 if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAtWar(m_pPlayer->getTeam()))5229 {5230 continue;5231 }52325233 if (GET_PLAYER(ePlayer).isMinorCiv())5234 {5235 iNumCityStates++;5236 }5237 }52385239 *piTargetCityStateSpies = min(iNumRemainingSpies, iNumCityStates);5240 bAllocatedCityStateSpies = true;5241 }5242 else if (pDiploAI->IsGoingForWorldConquest())5243 {5244 // assign offensive spies according to tech position5245 *piTargetOffensiveSpies = (int)ceil(fTechPositionRatio * iNumRemainingSpies);5246 bAllocatedOffensiveSpies = true;5247 iNumRemainingSpies -= *piTargetOffensiveSpies;52485249 // Assign the rest to militaristic city-states5250 // for now, assign spies to the militaristic city states5251 int iNumMilitaristicCityStates = 0;5252 for(uint ui = MAX_MAJOR_CIVS; ui < MAX_CIV_PLAYERS; ui++)5253 {5254 PlayerTypes ePlayer = (PlayerTypes)ui;5255 if (!GET_PLAYER(ePlayer).isAlive())5256 {5257 continue;5258 }52595260 if(!GET_TEAM(m_pPlayer->getTeam()).isHasMet(GET_PLAYER(ePlayer).getTeam()))5261 {5262 continue;5263 }52645265 // don't interact with city-states that are at war with us5266 if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAtWar(m_pPlayer->getTeam()))5267 {5268 continue;5269 }52705271 if (GET_PLAYER(ePlayer).isMinorCiv() && GET_PLAYER(ePlayer).GetMinorCivAI()->GetTrait() == MINOR_CIV_TRAIT_MILITARISTIC)5272 {5273 iNumMilitaristicCityStates++;5274 }5275 }52765277 *piTargetCityStateSpies = min(iNumRemainingSpies, iNumMilitaristicCityStates);5278 bAllocatedCityStateSpies = true;5279 }5280 else if (pDiploAI->IsGoingForCultureVictory())5281 {5282 // assign two spies to be diplomats5283 int iNumDiplomats = min(iNumRemainingSpies, 2);5284 iNumDiplomats = min(iNumDiplomats, m_pPlayer->GetCulture()->GetMaxPropagandaDiplomatsWanted());5285 *piTargetDiplomatSpies = iNumDiplomats;52865287 if (iNumDiplomats > 0)5288 {5289 bAllocatedDiplomatSpies = true;5290 iNumRemainingSpies -= *piTargetDiplomatSpies;5291 }5292 }5293 else if (pDiploAI->IsGoingForSpaceshipVictory())5294 {5295 // assign none to CS5296 *piTargetCityStateSpies = 0;5297 bAllocatedCityStateSpies = true;5298 }5299 else5300 {5301 // assign 1/3rd to CS5302 *piTargetCityStateSpies = iNumRemainingSpies / 3;5303 bAllocatedCityStateSpies = true;5304 }53055306 iNumRemainingSpies -= *piTargetCityStateSpies;5307 if (!bAllocatedOffensiveSpies)5308 {5309 *piTargetOffensiveSpies = (int)ceil(fTechPositionRatio * iNumRemainingSpies);5310 bAllocatedOffensiveSpies = true;5311 iNumRemainingSpies -= *piTargetOffensiveSpies;5312 }53135314 *piTargetDefensiveSpies = iNumRemainingSpies;5315 bAllocatedDefensiveSpies = true;53165317 // rationalization5318 std::vector<CvCity*> apOtherCityList;5319 CvCity* pLoopCity = NULL;5320 int iLoop = 0;5321 for(uint ui = 0; ui < MAX_MAJOR_CIVS; ui++)5322 {5323 PlayerTypes eTargetPlayer = (PlayerTypes)ui;53245325 // don't count the player's own cities5326 if(eTargetPlayer == m_pPlayer->GetID())5327 {5328 continue;5329 }53305331 for(pLoopCity = GET_PLAYER(eTargetPlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(eTargetPlayer).nextCity(&iLoop))5332 {5333 CvPlot* pCityPlot = pLoopCity->plot();5334 CvAssertMsg(pCityPlot, "City plot is null!");5335 if(pCityPlot)5336 {5337 if(pCityPlot->isRevealed(m_pPlayer->getTeam()))5338 {5339 apOtherCityList.push_back(pLoopCity);5340 }5341 }5342 }5343 }53445345 while(*piTargetDefensiveSpies > m_pPlayer->getNumCities())5346 {5347 if(*piTargetOffensiveSpies < (int)apOtherCityList.size())5348 {5349 (*piTargetDefensiveSpies)--;5350 (*piTargetOffensiveSpies)++;5351 }5352 else5353 {5354 // spies will be unused5355 (*piTargetDefensiveSpies)--;5356 }5357 }53585359 while(*piTargetOffensiveSpies > (int)apOtherCityList.size())5360 {5361 if(*piTargetDefensiveSpies < m_pPlayer->getNumCities())5362 {5363 (*piTargetDefensiveSpies)++;5364 (*piTargetOffensiveSpies)--;5365 }5366 else5367 {5368 // spies will be unused5369 (*piTargetOffensiveSpies)--;5370 }5371 }5372}