// Returns ratio of strengths of stacks times 100 // (so 100 is even ratio, numbers over 100 mean this group is more powerful than the stack on a plot) int CvSelectionGroupAI::AI_compareStacks(const CvPlot* pPlot, bool bPotentialEnemy, bool bCheckCanAttack, bool bCheckCanMove) const { FAssert(pPlot != NULL); int compareRatio; DomainTypes eDomainType = getDomainType(); // if not aircraft, then choose based on the plot, not the head unit (mainly for transport carried units) if (eDomainType != DOMAIN_AIR) { if (pPlot->isWater()) eDomainType = DOMAIN_SEA; else eDomainType = DOMAIN_LAND; } compareRatio = AI_sumStrength(pPlot, eDomainType, bCheckCanAttack, bCheckCanMove); compareRatio *= 100; PlayerTypes eOwner = getOwnerINLINE(); if (eOwner == NO_PLAYER) { eOwner = getHeadOwner(); } FAssert(eOwner != NO_PLAYER); int defenderSum = pPlot->AI_sumStrength(NO_PLAYER, getOwnerINLINE(), eDomainType, true, !bPotentialEnemy, bPotentialEnemy); compareRatio /= std::max(1, defenderSum); return compareRatio; }
// Returns ratio of strengths of stacks times 100 // (so 100 is even ratio, numbers over 100 mean this group is more powerful than the stack on a plot) int CvSelectionGroupAI::AI_compareStacks(const CvPlot* pPlot, bool bCheckCanAttack) const { FAssert(pPlot != NULL); int compareRatio; DomainTypes eDomainType = getDomainType(); // if not aircraft, then choose based on the plot, not the head unit (mainly for transport carried units) if (eDomainType != DOMAIN_AIR) { if (pPlot->isWater()) eDomainType = DOMAIN_SEA; else eDomainType = DOMAIN_LAND; } compareRatio = AI_sumStrength(pPlot, eDomainType, bCheckCanAttack); compareRatio *= 100; PlayerTypes eOwner = getOwnerINLINE(); if (eOwner == NO_PLAYER) { eOwner = getHeadOwner(); } FAssert(eOwner != NO_PLAYER); // K-Mod. Note. This function currently does not support bPotentialEnemy == false. //FAssert(bPotentialEnemy); int defenderSum = pPlot->isVisible(getHeadTeam(), false) ? GET_PLAYER(eOwner).AI_localDefenceStrength(pPlot, NO_TEAM, eDomainType, 0) : GET_TEAM(getHeadTeam()).AI_getStrengthMemory(pPlot); // K-Mod end compareRatio /= std::max(1, defenderSum); // K-Mod. If there are more defenders than we have attacks, but yet the ratio is still greater than 100, // then inflate the ratio futher to account for the fact that we are going to do significantly more damage to them than they to us. // The purpose of this is to give the AI extra encouragement to attack when its units are better than the defender's units. /* if (compareRatio > 100) { FAssert(getHeadUnit() && getNumUnits() > 0); int iDefenders = pPlot->getNumVisibleEnemyDefenders(getHeadUnit()); if (iDefenders > getNumUnits()) { compareRatio += (compareRatio - 100) * (iDefenders - getNumUnits()) / getNumUnits(); } } */ // (currently disabled) // K-Mod end return compareRatio; }
// Returns ratio of strengths of stacks times 100 // (so 100 is even ratio, numbers over 100 mean this group is more powerful than the stack on a plot) int CvSelectionGroupAI::AI_compareStacks(const CvPlot* pPlot, bool bPotentialEnemy, bool bCheckCanAttack, bool bCheckCanMove) const { FAssert(pPlot != NULL); int compareRatio; DomainTypes eDomainType = getDomainType(); // if not aircraft, then choose based on the plot, not the head unit (mainly for transport carried units) if (eDomainType != DOMAIN_AIR) { if (pPlot->isWater()) eDomainType = DOMAIN_SEA; else eDomainType = DOMAIN_LAND; } compareRatio = AI_sumStrength(pPlot, eDomainType, bCheckCanAttack, bCheckCanMove); compareRatio *= 100; PlayerTypes eOwner = getOwnerINLINE(); if (eOwner == NO_PLAYER) { eOwner = getHeadOwner(); } FAssert(eOwner != NO_PLAYER); /************************************************************************************************/ /* UNOFFICIAL_PATCH 03/04/10 jdog5000 */ /* */ /* Bugfix */ /************************************************************************************************/ /* original bts code int defenderSum = pPlot->AI_sumStrength(NO_PLAYER, getOwnerINLINE(), eDomainType, true, !bPotentialEnemy, bPotentialEnemy); */ // Clearly meant to use eOwner here ... int defenderSum = pPlot->AI_sumStrength(NO_PLAYER, eOwner, eDomainType, true, !bPotentialEnemy, bPotentialEnemy); /************************************************************************************************/ /* UNOFFICIAL_PATCH END */ /************************************************************************************************/ compareRatio /= std::max(1, defenderSum); return compareRatio; }
// K-Mod. I've removed bCheckMove, and changed bCheckCanAttack to include checks for moves, and for hasAlreadyAttacked / blitz int CvSelectionGroupAI::AI_sumStrength(const CvPlot* pAttackedPlot, DomainTypes eDomainType, bool bCheckCanAttack) const { CLLNode<IDInfo>* pUnitNode; CvUnit* pLoopUnit; int strSum = 0; bool bDefenders = pAttackedPlot ? pAttackedPlot->isVisibleEnemyUnit(getHeadOwner()) : false; // K-Mod bool bCountCollateral = pAttackedPlot && pAttackedPlot != plot(); // K-Mod pUnitNode = headUnitNode(); int iBaseCollateral = bCountCollateral ? iBaseCollateral = estimateCollateralWeight(pAttackedPlot, pAttackedPlot->getTeam() == getTeam() ? NO_TEAM : pAttackedPlot->getTeam()) : 0; while (pUnitNode != NULL) { pLoopUnit = ::getUnit(pUnitNode->m_data); pUnitNode = nextUnitNode(pUnitNode); if (!pLoopUnit->isDead()) { // K-Mod. (original checks deleted.) if (bCheckCanAttack) { if (pLoopUnit->getDomainType() == DOMAIN_AIR) { if (!pLoopUnit->canAirAttack() || !pLoopUnit->canMove() || (pAttackedPlot && bDefenders && !pLoopUnit->canMoveInto(pAttackedPlot, true, true))) continue; // can't attack. } else { if (!pLoopUnit->canAttack() || !pLoopUnit->canMove() || (pAttackedPlot && bDefenders && !pLoopUnit->canMoveInto(pAttackedPlot, true, true)) || (!pLoopUnit->isBlitz() && pLoopUnit->isMadeAttack())) continue; // can't attack. } } // K-Mod end if (eDomainType == NO_DOMAIN || pLoopUnit->getDomainType() == eDomainType) { strSum += pLoopUnit->currEffectiveStr(pAttackedPlot, pLoopUnit); // K-Mod estimate the attack power of collateral units. (cf with calculation in AI_localAttackStrength) if (bCountCollateral && pLoopUnit->collateralDamage() > 0) { int iPossibleTargets = pLoopUnit->collateralDamageMaxUnits(); // If !bCheckCanAttack, then lets not assume pAttackPlot won't get more units on it. if (bCheckCanAttack && pAttackedPlot->isVisible(getTeam(), false)) iPossibleTargets = std::min(iPossibleTargets, pAttackedPlot->getNumVisibleEnemyDefenders(pLoopUnit) - 1); if (iPossibleTargets > 0) { // collateral damage is not trivial to calculate. This estimate is pretty rough. // (Note: collateralDamage() and iBaseCollateral both include factors of 100.) strSum += pLoopUnit->baseCombatStr() * iBaseCollateral * pLoopUnit->collateralDamage() * iPossibleTargets / 10000; } } // K-Mod end } } } return strSum; }