/// How many units of this type are in army? int CvArmyAI::GetUnitsOfType(MultiunitPositionTypes ePosition) const { int iRtnValue = 0; for(unsigned int iI = 0; iI < m_FormationEntries.size(); iI++) { if(m_FormationEntries[iI].m_iUnitID > ARMYSLOT_NO_UNIT) { CvUnit* pUnit = GET_PLAYER(m_eOwner).getUnit(m_FormationEntries[iI].m_iUnitID); if(pUnit->getMoves() > 0) { CvMultiUnitFormationInfo* thisFormation = GC.getMultiUnitFormationInfo(m_iFormationIndex); if(thisFormation) { const CvFormationSlotEntry& thisSlotEntry = thisFormation->getFormationSlotEntry(iI); if(thisSlotEntry.m_ePositionType == ePosition) { iRtnValue++; } } } } } return iRtnValue; }
/// Set index of the formation used by this army void CvArmyAI::SetFormationIndex(int iFormationIndex) { CvMultiUnitFormationInfo* thisFormation = GC.getMultiUnitFormationInfo(iFormationIndex); if(m_iFormationIndex != iFormationIndex && thisFormation) { ReleaseUnits(); m_iFormationIndex = iFormationIndex; m_FormationEntries = vector<CvArmyFormationSlot>(thisFormation->getNumFormationSlotEntries()); } }
/// How many units of this type are in army? int CvArmyAI::GetUnitsOfType(MultiunitPositionTypes ePosition) const { int iRtnValue = 0; for(unsigned int iI = 0; iI < m_FormationEntries.size(); iI++) { if (m_FormationEntries[iI].IsUsed()) { CvMultiUnitFormationInfo* thisFormation = GC.getMultiUnitFormationInfo(m_iFormationIndex); if(thisFormation) { const CvFormationSlotEntry& thisSlotEntry = thisFormation->getFormationSlotEntry(iI); if(thisSlotEntry.m_ePositionType == ePosition) { iRtnValue++; } } } } return iRtnValue; }
/// Set index of the formation used by this army void CvArmyAI::SetFormationIndex(int iFormationIndex) { CvArmyFormationSlot slot; if(m_iFormationIndex != iFormationIndex) { m_iFormationIndex = iFormationIndex; CvMultiUnitFormationInfo* thisFormation = GC.getMultiUnitFormationInfo(m_iFormationIndex); if(thisFormation) { int iNumSlots = thisFormation->getNumFormationSlotEntries(); // Build all the formation entries m_FormationEntries.clear(); for(int iI = 0; iI < iNumSlots; iI++) { slot.SetUnitID(ARMYSLOT_NO_UNIT); slot.SetTurnAtCheckpoint(ARMYSLOT_UNKNOWN_TURN_AT_CHECKPOINT); m_FormationEntries.push_back(slot); } } } }
/// Get center of mass of units in army (account for world wrap!) CvPlot* CvArmyAI::GetCenterOfMass(DomainTypes eDomainRequired) { CvPlot* pRtnValue = NULL; int iTotalX = 0; int iTotalY = 0; int iNumUnits = 0; UnitHandle pUnit; int iReferenceUnitX = -1; int iWorldWidth = GC.getMap().getGridWidth(); pUnit = GetFirstUnit(); if(pUnit) { iReferenceUnitX = pUnit->getX(); } while(pUnit) { int iUnitX = pUnit->getX(); bool bWorldWrapAdjust = false; int iDiff = iUnitX - iReferenceUnitX; if(abs(iDiff) > (iWorldWidth / 2)) { bWorldWrapAdjust = true; } if(bWorldWrapAdjust) { iTotalX += iUnitX + iWorldWidth; } else { iTotalX += iUnitX; } iTotalY += pUnit->getY(); iNumUnits++; pUnit = GetNextUnit(); } if(iNumUnits > 0) { int iAverageX = (iTotalX + (iNumUnits / 2)) / iNumUnits; if(iAverageX >= iWorldWidth) { iAverageX = iAverageX - iWorldWidth; } int iAverageY = (iTotalY + (iNumUnits / 2)) / iNumUnits; pRtnValue = GC.getMap().plot(iAverageX, iAverageY); } // Domain check if (eDomainRequired != NO_DOMAIN && pRtnValue) { if (pRtnValue->isWater() && eDomainRequired == DOMAIN_LAND || !pRtnValue->isWater() && eDomainRequired == DOMAIN_SEA) { // Find an adjacent plot that works for (int iI = 0; iI < NUM_DIRECTION_TYPES; iI++) { CvPlot *pLoopPlot = plotDirection(pRtnValue->getX(), pRtnValue->getY(), ((DirectionTypes)iI)); if (pLoopPlot != NULL) { if (pLoopPlot->isWater() && eDomainRequired == DOMAIN_SEA || !pLoopPlot->isWater() && eDomainRequired == DOMAIN_LAND) { return pLoopPlot; } } } // Try two plots out if really having problems #ifdef AUI_HEXSPACE_DX_LOOPS int iMaxDX, iDX; CvPlot* pLoopPlot; for (int iDY = -2; iDY <= 2; iDY++) { iMaxDX = 2 - MAX(0, iDY); for (iDX = -2 - MIN(0, iDY); iDX <= iMaxDX; iDX++) // MIN() and MAX() stuff is to reduce loops (hexspace!) { // No need for range check because loops are set up properly pLoopPlot = plotXY(pRtnValue->getX(), pRtnValue->getY(), iDX, iDY); if (pLoopPlot) { if (hexDistance(iDX, iDY) == 2) #else for (int iDX = -2; iDX <= 2; iDX++) { for (int iDY = -2; iDY <= 2; iDY++) { CvPlot *pLoopPlot = plotXYWithRangeCheck(pRtnValue->getX(), pRtnValue->getY(), iDX, iDY, 2); if (pLoopPlot) { #ifdef AUI_FIX_HEX_DISTANCE_INSTEAD_OF_PLOT_DISTANCE if (hexDistance(iDX, iDY) == 2) #else if (plotDistance(pRtnValue->getX(), pRtnValue->getY(), pLoopPlot->getX(), pLoopPlot->getY()) == 2) #endif #endif { if (pLoopPlot->isWater() && eDomainRequired == DOMAIN_SEA || !pLoopPlot->isWater() && eDomainRequired == DOMAIN_LAND) { return pLoopPlot; } } } } } // Give up - just use location of first unit pUnit = GetFirstUnit(); pRtnValue = pUnit->plot(); } } return pRtnValue; } /// Return distance from this plot of unit in army farthest away int CvArmyAI::GetFurthestUnitDistance(CvPlot* pPlot) { int iLargestDistance = 0; UnitHandle pUnit; int iNewDistance; pUnit = GetFirstUnit(); while(pUnit) { iNewDistance = plotDistance(pUnit->getX(), pUnit->getY(), pPlot->getX(), pPlot->getY()); if(iNewDistance > iLargestDistance) { iLargestDistance = iNewDistance; } pUnit = GetNextUnit(); } return iLargestDistance; } // FORMATION ACCESSORS /// Retrieve index of the formation used by this army int CvArmyAI::GetFormationIndex() const { return m_iFormationIndex; } /// Set index of the formation used by this army void CvArmyAI::SetFormationIndex(int iFormationIndex) { CvArmyFormationSlot slot; if(m_iFormationIndex != iFormationIndex) { m_iFormationIndex = iFormationIndex; CvMultiUnitFormationInfo* thisFormation = GC.getMultiUnitFormationInfo(m_iFormationIndex); if(thisFormation) { int iNumSlots = thisFormation->getNumFormationSlotEntries(); // Build all the formation entries m_FormationEntries.clear(); for(int iI = 0; iI < iNumSlots; iI++) { slot.SetUnitID(ARMY_NO_UNIT); slot.SetTurnAtCheckpoint(ARMYSLOT_UNKNOWN_TURN_AT_CHECKPOINT); m_FormationEntries.push_back(slot); } } } } /// How many slots are there in this formation if filled int CvArmyAI::GetNumFormationEntries() const { return m_FormationEntries.size(); } /// How many slots do we currently have filled? int CvArmyAI::GetNumSlotsFilled() const { int iRtnValue = 0; for(unsigned int iI = 0; iI < m_FormationEntries.size(); iI++) { if(m_FormationEntries[iI].m_iUnitID != ARMY_NO_UNIT) { iRtnValue++; } } return iRtnValue; }