Bazaar developer reference

CvMilitaryAI::FindBestAttackTarget(AIOperationTypes, PlayerTypes, int *)

Defined in
CvMilitaryAI.cpp, line 984
Class
CvMilitaryAI
Hook name
CivHooks::CvMilitaryAI_FindBestAttackTarget

Hooks

static bool BeforeCvMilitaryAI_FindBestAttackTarget(CvMilitaryAI* self, AIOperationTypes eAIOperationType, PlayerTypes eEnemy, int* piWinningScore, CvMilitaryTarget& result);static void AfterCvMilitaryAI_FindBestAttackTarget(CvMilitaryAI* self, AIOperationTypes eAIOperationType, PlayerTypes eEnemy, int* piWinningScore, CvMilitaryTarget& result);static CvMilitaryTarget ReplaceCvMilitaryAI_FindBestAttackTarget(CvMilitaryTarget (*original)(CvMilitaryAI*, AIOperationTypes, PlayerTypes, int*), CvMilitaryAI* self, AIOperationTypes eAIOperationType, PlayerTypes eEnemy, int* piWinningScore);// CivHooks.h gives this hook point no types, so nothing checks these hooks' parameters.host->RegisterHook(host->pluginIndex, CivHooks::CvMilitaryAI_FindBestAttackTarget::ID, CIV_HOOK_BEFORE, (void*)&BeforeCvMilitaryAI_FindBestAttackTarget);host->RegisterHook(host->pluginIndex, CivHooks::CvMilitaryAI_FindBestAttackTarget::ID, CIV_HOOK_AFTER, (void*)&AfterCvMilitaryAI_FindBestAttackTarget);host->RegisterHook(host->pluginIndex, CivHooks::CvMilitaryAI_FindBestAttackTarget::ID, CIV_HOOK_REPLACE, (void*)&ReplaceCvMilitaryAI_FindBestAttackTarget);

Code

983/// Best target by land OR sea984CvMilitaryTarget CvMilitaryAI::FindBestAttackTarget(AIOperationTypes eAIOperationType, PlayerTypes eEnemy, int* piWinningScore)985{986	int iFriendlyLoop;987	int iEnemyLoop;988	int iUnitLoop;989	CvCity* pFriendlyCity;990	CvCity* pEnemyCity;991	CvUnit* pLoopUnit;992	static CvWeightedVector<CvMilitaryTarget, SAFE_ESTIMATE_NUM_CITIES* 10, true> weightedTargetList;993	CvMilitaryTarget chosenTarget;994	CvPlayer &kEnemy = GET_PLAYER(eEnemy);995996	// Estimate the relative strength of units near our cities and near their cities (can't use TacticalAnalysisMap because we may not be at war - and that it isn't current if we are calling this from the DiploAI)997	for (pFriendlyCity = m_pPlayer->firstCity(&iFriendlyLoop); pFriendlyCity != NULL; pFriendlyCity = m_pPlayer->nextCity(&iFriendlyLoop))998	{999		CvPlot* pPlot = pFriendlyCity->plot();1000		int iX = pPlot->getX();1001		int iY = pPlot->getY();1002		bool bGeneralInTheVicinity = false;1003		int iPower = 0;1004		for (pLoopUnit = m_pPlayer->firstUnit(&iUnitLoop); pLoopUnit != NULL; pLoopUnit = m_pPlayer->nextUnit(&iUnitLoop))1005		{1006			if (pLoopUnit->IsCombatUnit())1007			{1008				int iDistance = plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), iX, iY);1009				if (iDistance <= 5)1010				{1011					iPower += pLoopUnit->GetPower();1012				}1013			}1014			if (!bGeneralInTheVicinity && pLoopUnit->IsGreatGeneral())1015			{1016				int iDistance = plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), iX, iY);1017				if (iDistance <= 5)1018				{1019					bGeneralInTheVicinity = true;1020				}1021			}1022		}1023		if (bGeneralInTheVicinity)1024		{1025			iPower *= 11;1026			iPower /= 10;1027		}1028		pFriendlyCity->iScratch = iPower;1029	}1030	for(pEnemyCity = kEnemy.firstCity(&iEnemyLoop); pEnemyCity != NULL; pEnemyCity = kEnemy.nextCity(&iEnemyLoop))1031	{1032		CvPlot* pPlot = pEnemyCity->plot();1033		if(pPlot->isRevealed(m_pPlayer->getTeam()))1034		{1035			int iX = pPlot->getX();1036			int iY = pPlot->getY();1037			bool bGeneralInTheVicinity = false;1038			int iPower = 0;1039			for (pLoopUnit = kEnemy.firstUnit(&iUnitLoop); pLoopUnit != NULL; pLoopUnit = kEnemy.nextUnit(&iUnitLoop))1040			{1041				if (pLoopUnit->IsCombatUnit())1042				{1043					int iDistance = plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), iX, iY);1044					if (iDistance <= 5)1045					{1046						iPower += pLoopUnit->GetPower();1047					}1048				}1049				if (!bGeneralInTheVicinity && pLoopUnit->IsGreatGeneral())1050				{1051					int iDistance = plotDistance(pLoopUnit->getX(), pLoopUnit->getY(), iX, iY);1052					if (iDistance <= 5)1053					{1054						bGeneralInTheVicinity = true;1055					}1056				}1057			}1058			if (bGeneralInTheVicinity)1059			{1060				iPower *= 11;1061				iPower /= 10;1062			}1063			pEnemyCity->iScratch = iPower;1064		}1065	}10661067	// Build a list of all the possible start city/target city pairs1068	static CvWeightedVector<CvMilitaryTarget, SAFE_ESTIMATE_NUM_CITIES* 10, true> prelimWeightedTargetList;1069	prelimWeightedTargetList.clear();1070	for(pFriendlyCity = m_pPlayer->firstCity(&iFriendlyLoop); pFriendlyCity != NULL; pFriendlyCity = m_pPlayer->nextCity(&iFriendlyLoop))1071	{1072		for(pEnemyCity = GET_PLAYER(eEnemy).firstCity(&iEnemyLoop); pEnemyCity != NULL; pEnemyCity = GET_PLAYER(eEnemy).nextCity(&iEnemyLoop))1073		{1074			if(pEnemyCity->plot()->isRevealed(m_pPlayer->getTeam()))1075			{1076				CvMilitaryTarget target;1077				int iWeight;1078				target.m_pMusterCity = pFriendlyCity;1079				target.m_pTargetCity = pEnemyCity;1080				target.iMusterNearbyUnitPower = pFriendlyCity->iScratch;1081				target.iTargetNearbyUnitPower = pEnemyCity->iScratch;10821083				if (eAIOperationType == AI_OPERATION_PURE_NAVAL_CITY_ATTACK)1084				{1085					target.m_bAttackBySea = true;1086					if (target.m_pMusterCity->isCoastal() && target.m_pTargetCity->isCoastal())1087					{1088						target.m_iPathLength = plotDistance(target.m_pMusterCity->getX(), target.m_pMusterCity->getY(), target.m_pTargetCity->getX(), target.m_pTargetCity->getY());1089					}1090				}10911092				else1093				{1094					ShouldAttackBySea(eEnemy, target);10951096					if (!pFriendlyCity->isCoastal() && target.m_bAttackBySea)1097					{1098						continue;1099					}1100				}11011102				if(target.m_iPathLength > 0)1103				{1104					iWeight = (10000 - target.m_iPathLength);   // Start by using the path length as the weight, shorter paths have higher weight1105					prelimWeightedTargetList.push_back(target, iWeight);1106				}1107			}1108		}1109	}11101111	// Let's score the 25 shortest paths ... anything more than that means there are too many interior cities from one (or both) sides being considered1112	prelimWeightedTargetList.SortItems();1113	weightedTargetList.clear();1114	int iTargetsConsidered = 0;1115	for (int iI = 0; iI < prelimWeightedTargetList.size() && iTargetsConsidered < 25; iI++)1116	{1117		CvMilitaryTarget target = prelimWeightedTargetList.GetElement(iI);1118		int iWeight;11191120		// If a sea target, we haven't checked the path yet.  Do that now1121		if (target.m_bAttackBySea)1122		{1123			if (!target.m_pMusterCity->isCoastal())1124			{1125				continue;1126			}1127			if (!target.m_pTargetCity->isCoastal())1128			{1129				continue;1130			}1131			CvPlot *pSeaPlotNearMuster = GetCoastalPlotAdjacentToTarget(target.m_pMusterCity->plot(), NULL);1132			CvPlot *pSeaPlotNearTarget = GetCoastalPlotAdjacentToTarget(target.m_pTargetCity->plot(), NULL);1133			if(!GC.getStepFinder().DoesPathExist(m_pPlayer->GetID(), eEnemy, pSeaPlotNearMuster, pSeaPlotNearTarget))1134			{1135				continue;1136			}1137		}11381139		iWeight = ScoreTarget(target, eAIOperationType);1140		weightedTargetList.push_back(target, iWeight);1141		iTargetsConsidered++;1142	}11431144	// Didn't find anything, abort1145	if(weightedTargetList.size() == 0)1146	{1147		chosenTarget.m_pTargetCity = NULL;   // Call off the attack1148		if (piWinningScore)1149		{1150			*piWinningScore = -1;1151		}1152		return chosenTarget;1153	}11541155	weightedTargetList.SortItems();1156	LogAttackTargets(eAIOperationType, eEnemy, weightedTargetList);11571158	if(weightedTargetList.GetTotalWeight() > 0)1159	{1160		RandomNumberDelegate fcn;1161		fcn = MakeDelegate(&GC.getGame(), &CvGame::getJonRandNum);1162		int iNumChoices = max (1, (weightedTargetList.size() * 25 / 100));1163		chosenTarget = weightedTargetList.ChooseFromTopChoices(iNumChoices, &fcn, "Choosing attack target from top 25%% of choices");1164		// if we need the winning score1165		if (piWinningScore)1166		{1167			*piWinningScore = ScoreTarget(chosenTarget, eAIOperationType);1168		}1169		LogChosenTarget(eAIOperationType, eEnemy, chosenTarget);1170	}1171	else1172	{1173		chosenTarget.m_pTargetCity = NULL;   // Call off the attack1174		if (piWinningScore)1175		{1176			*piWinningScore = -1;1177		}1178	}11791180	return chosenTarget;1181}

Calls

Called by