Bazaar developer reference

CvTacticalAI::ScoreFormationPlots(CvArmyAI *, CvPlot *, CvPlot *, int)

Defined in
CvTacticalAI.cpp, line 5495
Class
CvTacticalAI
Hook name
CivHooks::CvTacticalAI_ScoreFormationPlots

Hooks

static bool BeforeCvTacticalAI_ScoreFormationPlots(CvTacticalAI* self, CvArmyAI* pArmy, CvPlot* pForwardTarget, CvPlot * pCurrentCOM, int iNumUnits, bool& result);static void AfterCvTacticalAI_ScoreFormationPlots(CvTacticalAI* self, CvArmyAI* pArmy, CvPlot* pForwardTarget, CvPlot * pCurrentCOM, int iNumUnits, bool& result);static bool ReplaceCvTacticalAI_ScoreFormationPlots(bool (*original)(CvTacticalAI*, CvArmyAI*, CvPlot*, CvPlot *, int), CvTacticalAI* self, CvArmyAI* pArmy, CvPlot* pForwardTarget, CvPlot * pCurrentCOM, int iNumUnits);CivRegisterBefore<CivHooks::CvTacticalAI_ScoreFormationPlots>(host, &BeforeCvTacticalAI_ScoreFormationPlots);CivRegisterAfter<CivHooks::CvTacticalAI_ScoreFormationPlots>(host, &AfterCvTacticalAI_ScoreFormationPlots);CivRegisterReplace<CivHooks::CvTacticalAI_ScoreFormationPlots>(host, &ReplaceCvTacticalAI_ScoreFormationPlots);

Code

5494/// Pick best hexes for deploying our army (mostly based on keeping a tight formation that is moving toward the target). Returns false if insufficient free plots.5495bool CvTacticalAI::ScoreFormationPlots(CvArmyAI* pArmy, CvPlot* pForwardTarget, CvPlot *pCurrentCOM, int iNumUnits)5496{5497	int iDX, iDY;5498	int iScore;5499	CvPlot* pPlot;5500	CvTacticalAnalysisCell* pCell;5501	int iNumDeployPlotsFound = 0;5502	CvTacticalTarget target;5503	bool bForcedToUseWater;55045505	// We'll store the hexes we've found here5506	m_TempTargets.clear();55075508	int iRange = 3;5509	for(iDX = -(iRange); iDX <= iRange; iDX++)5510	{5511		for(iDY = -(iRange); iDY <= iRange; iDY++)5512		{5513			pPlot = plotXY(pForwardTarget->getX(), pForwardTarget->getY(), iDX, iDY);5514			if(pPlot != NULL)5515			{5516				bForcedToUseWater = false;55175518				int iPlotDistance = plotDistance(pPlot->getX(), pPlot->getY(), pForwardTarget->getX(), pForwardTarget->getY());5519				if(iPlotDistance <= iRange)5520				{5521					int iPlotIndex = GC.getMap().plotNum(pPlot->getX(), pPlot->getY());5522					pCell = m_pMap->GetCell(iPlotIndex);5523					CvAIOperation* pOperation = m_pPlayer->getAIOperation(pArmy->GetOperationID());55245525					bool bValid = false;5526					if(pOperation->IsMixedLandNavalOperation() && pCell->CanUseForOperationGatheringCheckWater(true /*bWater*/))5527					{5528						bValid = true;5529					}55305531					else if(pOperation->IsAllNavalOperation() && pCell->CanUseForOperationGatheringCheckWater(true /*bWater*/))5532					{5533						bValid = true;5534					}55355536					else if((!pOperation->IsAllNavalOperation() && !pOperation->IsMixedLandNavalOperation()) && (pCell->CanUseForOperationGatheringCheckWater(false /*bWater*/) || GC.getMap().GetAIMapHint() & 1))5537					{5538						bValid = true;5539						if (pCell->IsWater())5540						{5541							bForcedToUseWater = true;5542						}5543					}55445545					if(pOperation->IsMixedLandNavalOperation() || pOperation->IsAllNavalOperation())5546					{5547						if(!pArmy->IsAllOceanGoing() && pCell->IsOcean())5548						{5549							bValid = false;5550						}5551					}55525553					if(bValid)5554					{5555						// Skip this plot if friendly unit that isn't in this army5556						CvUnit* pFriendlyUnit;5557						pFriendlyUnit = pCell->GetFriendlyMilitaryUnit();5558						if(pFriendlyUnit != NULL)5559						{5560							if(pFriendlyUnit->getArmyID() != pArmy->GetID())5561							{5562								continue;5563							}5564						}55655566						iNumDeployPlotsFound++;55675568						// Score plots close to COM and turn target highest5569						int iPlotDistanceFromCOM;5570						if (pForwardTarget == pCurrentCOM)5571						{5572							iPlotDistanceFromCOM = iPlotDistance;5573						}5574						else5575						{5576							iPlotDistanceFromCOM = plotDistance(pPlot->getX(), pPlot->getY(), pCurrentCOM->getX(), pCurrentCOM->getY());5577						}55785579						iScore = 800 - (iPlotDistance * 100) - (iPlotDistanceFromCOM * 100);55805581						if(pPlot->isCity() && pPlot->getOwner() == m_pPlayer->GetID())5582						{5583							iScore += 100;5584						}5585						else5586						{5587							iScore += pCell->GetDefenseModifier() * 2;5588						}5589						if (bForcedToUseWater)5590						{5591							iScore = 10;5592						}55935594						// Safe if closer to rear, or if forward target and COM are the same5595						bool bSafeForDeployment = iPlotDistanceFromCOM < iPlotDistance || pForwardTarget == pCurrentCOM;5596						pCell->SetSafeForDeployment(bSafeForDeployment);55975598						// Reduce score if safe for ranged (so these don't get picked first)5599						if (bSafeForDeployment)5600						{5601							iScore -= 200;5602						}56035604						pCell->SetDeploymentScore(iScore);56055606						// Save this in our list of potential targets5607						target.SetTargetX(pPlot->getX());5608						target.SetTargetY(pPlot->getY());5609						target.SetAuxIntData(iScore);5610						// A bit of a hack -- use high priority targets to indicate safe plots for ranged units5611						if(bSafeForDeployment)5612						{5613							target.SetTargetType(AI_TACTICAL_TARGET_HIGH_PRIORITY_UNIT);5614						}5615						else5616						{5617							target.SetTargetType(AI_TACTICAL_TARGET_LOW_PRIORITY_UNIT);5618						}5619						m_TempTargets.push_back(target);5620					}5621				}5622			}5623		}5624	}56255626	// Make sure we found enough5627	if(iNumDeployPlotsFound < iNumUnits)5628	{5629		return false;5630	}56315632	return true;5633}

Calls

Called by