// 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; }
CvUnit* CvSelectionGroupAI::AI_getBestGroupAttacker(const CvPlot* pPlot, bool bPotentialEnemy, int& iUnitOdds, bool bForce, bool bNoBlitz) const { CLLNode<IDInfo>* pUnitNode; CvUnit* pLoopUnit; CvUnit* pBestUnit; int iPossibleTargets; int iValue; int iBestValue; int iOdds; int iBestOdds; iBestValue = 0; iBestOdds = 0; pBestUnit = NULL; pUnitNode = headUnitNode(); bool bIsHuman = (pUnitNode != NULL) ? GET_PLAYER(::getUnit(pUnitNode->m_data)->getOwnerINLINE()).isHuman() : true; while (pUnitNode != NULL) { pLoopUnit = ::getUnit(pUnitNode->m_data); pUnitNode = nextUnitNode(pUnitNode); if (!pLoopUnit->isDead()) { bool bCanAttack = false; if (pLoopUnit->getDomainType() == DOMAIN_AIR) { bCanAttack = pLoopUnit->canAirAttack(); } else { bCanAttack = pLoopUnit->canAttack(); if (bCanAttack && bNoBlitz && pLoopUnit->isBlitz() && pLoopUnit->isMadeAttack()) { bCanAttack = false; } } if (bCanAttack) { if (bForce || pLoopUnit->canMove()) { if (bForce || pLoopUnit->canMoveInto(pPlot, /*bAttack*/ true, /*bDeclareWar*/ bPotentialEnemy)) { iOdds = pLoopUnit->AI_attackOdds(pPlot, bPotentialEnemy); iValue = iOdds; FAssertMsg(iValue > 0, "iValue is expected to be greater than 0"); if (pLoopUnit->collateralDamage() > 0) { iPossibleTargets = std::min((pPlot->getNumVisibleEnemyDefenders(pLoopUnit) - 1), pLoopUnit->collateralDamageMaxUnits()); if (iPossibleTargets > 0) { iValue *= (100 + ((pLoopUnit->collateralDamage() * iPossibleTargets) / 5)); iValue /= 100; } } // if non-human, prefer the last unit that has the best value (so as to avoid splitting the group) if (iValue > iBestValue || (!bIsHuman && iValue > 0 && iValue == iBestValue)) { iBestValue = iValue; iBestOdds = iOdds; pBestUnit = pLoopUnit; } } } } } } iUnitOdds = iBestOdds; return pBestUnit; }
CvUnit* CvSelectionGroupAI::AI_getBestGroupAttacker(const CvPlot* pPlot, bool bPotentialEnemy, int& iUnitOdds, bool bForce, bool bNoBlitz) const { PROFILE_FUNC(); int iBestValue = 0; int iBestOdds = 0; CvUnit* pBestUnit = NULL; CLLNode<IDInfo>* pUnitNode = headUnitNode(); bool bIsHuman = (pUnitNode != NULL) ? GET_PLAYER(::getUnit(pUnitNode->m_data)->getOwnerINLINE()).isHuman() : true; while (pUnitNode != NULL) { CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data); pUnitNode = nextUnitNode(pUnitNode); if (!pLoopUnit->isDead()) { bool bCanAttack = false; if (pLoopUnit->getDomainType() == DOMAIN_AIR) { bCanAttack = pLoopUnit->canAirAttack(); } else { bCanAttack = pLoopUnit->canAttack(); if (bCanAttack && bNoBlitz && pLoopUnit->isBlitz() && pLoopUnit->isMadeAttack()) { bCanAttack = false; } } if (bCanAttack) { if (bForce || pLoopUnit->canMove()) { if (bForce || pLoopUnit->canMoveInto(pPlot, /*bAttack*/ true, /*bDeclareWar*/ bPotentialEnemy)) { /************************************************************************************************/ /* BETTER_BTS_AI_MOD 02/21/10 jdog5000 */ /* */ /* Lead From Behind */ /************************************************************************************************/ // From Lead From Behind by UncutDragon if (GC.getLFBEnable() && GC.getLFBUseCombatOdds()) { //pLoopUnit->LFBgetBetterAttacker(&pBestUnit, pPlot, bPotentialEnemy, iBestOdds, iValue); pLoopUnit->LFBgetBetterAttacker(&pBestUnit, pPlot, bPotentialEnemy, iBestOdds, iBestValue); // K-Mod. } else { int iOdds = pLoopUnit->AI_attackOdds(pPlot, bPotentialEnemy); int iValue = iOdds; FAssertMsg(iValue > 0, "iValue is expected to be greater than 0"); if (pLoopUnit->collateralDamage() > 0) { int iPossibleTargets = std::min((pPlot->getNumVisibleEnemyDefenders(pLoopUnit) - 1), pLoopUnit->collateralDamageMaxUnits()); if (iPossibleTargets > 0) { iValue *= (100 + ((pLoopUnit->collateralDamage() * iPossibleTargets) / 5)); iValue /= 100; } } // if non-human, prefer the last unit that has the best value (so as to avoid splitting the group) if (iValue > iBestValue || (!bIsHuman && iValue > 0 && iValue == iBestValue)) { iBestValue = iValue; iBestOdds = iOdds; pBestUnit = pLoopUnit; } } /************************************************************************************************/ /* BETTER_BTS_AI_MOD END */ /************************************************************************************************/ } } } } } iUnitOdds = iBestOdds; return pBestUnit; }