/// Is this a valid Promotion for the UnitCombatType? bool IsPromotionValidForUnitCombatType(PromotionTypes ePromotion, UnitTypes eUnit) { CvUnitEntry* unitInfo = GC.getUnitInfo(eUnit); CvPromotionEntry* promotionInfo = GC.getPromotionInfo(ePromotion); if(unitInfo == NULL || promotionInfo == NULL) return false; // No combat class (civilians) if(unitInfo->GetUnitCombatType() == NO_UNITCOMBAT) { return false; } // Combat class not valid for this Promotion #if defined(MOD_GLOBAL_PROMOTION_CLASSES) if(!(promotionInfo->GetUnitCombatClass(unitInfo->GetUnitPromotionType()))) #else if(!(promotionInfo->GetUnitCombatClass(unitInfo->GetUnitCombatType()))) #endif { return false; } return true; }
// --------------------------------------------------------------------------- bool CvGameQueries::AreUnitsSameType(UnitTypes eFirstUnitType, UnitTypes eSecondUnitType) { CvUnitEntry* pkFirstUnitInfo = GC.getUnitInfo(eFirstUnitType); CvUnitEntry* pkSecondUnitInfo = GC.getUnitInfo(eSecondUnitType); if(pkFirstUnitInfo == NULL || pkSecondUnitInfo == NULL) return false; int eFirstDomain = pkFirstUnitInfo->GetDomainType(); int eSecondDomain = pkSecondUnitInfo->GetDomainType(); // antonjs: Added for Smoky Skies scenario. // If unit is DOMAIN_HOVER, its effective domain is a wildcard, equal to the other unit's domain. This prevents HOVER units from disobeying 1UPT. if (eFirstDomain == DOMAIN_HOVER && eSecondDomain == DOMAIN_HOVER) { // Already a match } else if (eFirstDomain == DOMAIN_HOVER) { eFirstDomain = eSecondDomain; // Make it a match } else if (eSecondDomain == DOMAIN_HOVER) { eSecondDomain = eFirstDomain; // Make it a match } // Must be in the same domain if(eFirstDomain == eSecondDomain) { // Conversely air units can always stack if(eFirstDomain == DOMAIN_AIR) { return false; } bool bUnit1Combat = false; bool bUnit2Combat = false; // Unit 1 is a combat unit? if(pkFirstUnitInfo->GetCombat() > 0 || pkFirstUnitInfo->GetRange() > 0) { bUnit1Combat = true; } // Unit 2 is a combat unit? if(pkSecondUnitInfo->GetCombat() > 0 || pkSecondUnitInfo->GetRange() > 0) { bUnit2Combat = true; } // Looped unit matches combat or non-combat type? if(bUnit1Combat == bUnit2Combat) { // Unit is the same domain & combat type, so we have a match return true; } } return false; }
// --------------------------------------------------------------------------- bool CvGameQueries::AreUnitsSameType(UnitTypes eFirstUnitType, UnitTypes eSecondUnitType) { CvUnitEntry* pkFirstUnitInfo = GC.getUnitInfo(eFirstUnitType); CvUnitEntry* pkSecondUnitInfo = GC.getUnitInfo(eSecondUnitType); if(pkFirstUnitInfo == NULL || pkSecondUnitInfo == NULL) return false; int eFirstDomain = pkFirstUnitInfo->GetDomainType(); int eSecondDomain = pkSecondUnitInfo->GetDomainType(); // Must be in the same domain if (eFirstDomain == eSecondDomain) { // Only one sea unit per plot! if (eFirstDomain == DOMAIN_SEA) { return true; } // Conversely air units can always stack if (eFirstDomain == DOMAIN_AIR) { return false; } bool bUnit1Combat = false; bool bUnit2Combat = false; // Unit 1 is a combat unit? if (pkFirstUnitInfo->GetCombat() > 0 || pkFirstUnitInfo->GetRange() > 0) { bUnit1Combat = true; } // Unit 2 is a combat unit? if (pkSecondUnitInfo->GetCombat() > 0 || pkSecondUnitInfo->GetRange() > 0) { bUnit2Combat = true; } // Looped unit matches combat or non-combat type? if (bUnit1Combat == bUnit2Combat) { // Unit is the same domain & combat type, so we have a match return true; } } return false; }
/// Is this a valid Promotion for the UnitCombatType? bool IsPromotionValidForUnitCombatType(PromotionTypes ePromotion, UnitTypes eUnit) { CvUnitEntry* unitInfo = GC.getUnitInfo(eUnit); CvPromotionEntry* promotionInfo = GC.getPromotionInfo(ePromotion); if(unitInfo == NULL || promotionInfo == NULL) return false; // No combat class (civilians) if(unitInfo->GetUnitCombatType() == NO_UNITCOMBAT) { return false; } // Combat class not valid for this Promotion if(!(promotionInfo->GetUnitCombatClass(unitInfo->GetUnitCombatType()))) { return false; } return true; }
bool isTechRequiredForUnit(TechTypes eTech, UnitTypes eUnit) { CvUnitEntry* info = GC.getUnitInfo(eUnit); if(info == NULL) { return false; } if(info->GetPrereqAndTech() == eTech) { return true; } for(int iI = 0; iI < GC.getNUM_UNIT_AND_TECH_PREREQS(); iI++) { if(info->GetPrereqAndTechs(iI) == eTech) { return true; } } return false; }
TechTypes getDiscoveryTech(UnitTypes eUnit, PlayerTypes ePlayer) { TechTypes eBestTech = NO_TECH; CvPlayerAI& kPlayer = GET_PLAYER(ePlayer); CvUnitEntry* pkUnitInfo = GC.getUnitInfo(eUnit); if(pkUnitInfo) { int iBestValue = 0; for(int iI = 0; iI < GC.getNumTechInfos(); iI++) { const TechTypes eTech = static_cast<TechTypes>(iI); CvTechEntry* pkTechInfo = GC.getTechInfo(eTech); if(pkTechInfo) { if(kPlayer.GetPlayerTechs()->CanResearch(eTech)) { int iValue = 0; for(int iJ = 0; iJ < GC.getNumFlavorTypes(); iJ++) { iValue += (pkTechInfo->GetFlavorValue(iJ) * pkUnitInfo->GetFlavorValue(iJ)); } if(iValue > iBestValue) { iBestValue = iValue; eBestTech = eTech; } } } } } return eBestTech; }
// --------------------------------------------------------------------------- UnitClassTypes CvGameQueries::GetLeastAdvancedUnitClassNobodyHas(bool bUseRandom /* = false */) { CvWeightedVector<int, SAFE_ESTIMATE_NUM_UNITS, true> UnitClassesVector; int iWeight; bool bValid; for (int i = 0; i < GC.getNumUnitClassInfos(); i++) { const UnitClassTypes eUnitClass = static_cast<UnitClassTypes>(i); CvUnitClassInfo* pkUnitClassInfo = GC.getUnitClassInfo(eUnitClass); if(pkUnitClassInfo) { const UnitTypes eDefaultUnit = (UnitTypes) pkUnitClassInfo->getDefaultUnitIndex(); // If the UnitClass doesn't have a Default Unit available to everyone, skip it if (eDefaultUnit == NO_UNIT) { continue; } CvUnitEntry* pkUnitInfo = GC.getUnitInfo(eDefaultUnit); if(pkUnitInfo == NULL) { continue; } // Only look at Land Units if (pkUnitInfo->GetDomainType() != DOMAIN_LAND) { continue; } // Only look at Military Units if (pkUnitInfo->GetCombat() <= 0) { continue; } const TechTypes ePrereqTech = (TechTypes) pkUnitInfo->GetPrereqAndTech(); // Unit has to require a Tech, otherwise it's too easy! if (ePrereqTech == NO_TECH) { continue; } CvTechEntry* pkTechInfo = GC.getTechInfo(ePrereqTech); if(pkTechInfo == NULL) { continue; } bValid = true; bool bAllPlayersHaveTech = true; for (int iMajorLoop = 0; iMajorLoop < MAX_MAJOR_CIVS; iMajorLoop++) { if (GET_PLAYER((PlayerTypes) iMajorLoop).isAlive()) { // If a player already has one of this Unit, throw it out - we want something more advanced if (GET_PLAYER((PlayerTypes) iMajorLoop).getUnitClassCount(eUnitClass) > 0) { bValid = false; break; } // Even if no one has this Unit lying around, if all players already have the Tech which unlocks it, throw it out - too easy if (bAllPlayersHaveTech && !GET_TEAM((TeamTypes) GET_PLAYER((PlayerTypes) iMajorLoop).getTeam()).GetTeamTechs()->HasTech(ePrereqTech)) { bAllPlayersHaveTech = false; } } } if (!bValid || bAllPlayersHaveTech) { continue; } iWeight = pkUnitInfo->GetPower(); // Add a Tech factor, since we want something in the near future, not too far off iWeight += (pkTechInfo->GetResearchCost() / 8); // Add a random bit so that the same Unit isn't ALWAYS picked if (bUseRandom) { iWeight += GC.getGame().getJonRandNum(iWeight / 10, "Minor Civ Quest: Gift Unit - Adding random weight to Unit Chosen"); } UnitClassesVector.push_back(i, iWeight); } } UnitClassesVector.SortItems(); //int iValue; bValid = true; for (int i = UnitClassesVector.size() - 1; i >= 0; i--) { const UnitClassTypes eUnitClass = (UnitClassTypes) UnitClassesVector.GetElement(i); // First Unit we find in this sorted Vector is our guy if (bValid) { return eUnitClass; } } return NO_UNITCLASS; }
bool isPromotionValid(PromotionTypes ePromotion, UnitTypes eUnit, bool bLeader, bool bTestingPrereq) { CvUnitEntry* unitInfo = GC.getUnitInfo(eUnit); CvPromotionEntry* promotionInfo = GC.getPromotionInfo(ePromotion); if(unitInfo == NULL || promotionInfo == NULL) return false; // Can this Promotion not be chosen through normal leveling? if(!bTestingPrereq && promotionInfo->IsCannotBeChosen()) { return false; } // If a Unit gets a Promotion for free then hand it out, no questions asked if(unitInfo->GetFreePromotions(ePromotion)) { return true; } // If this isn't a combat Unit, no Promotion if(unitInfo->GetUnitCombatType() == NO_UNITCOMBAT) { return false; } // Is this a valid Promotion for the UnitCombatType? if(!::IsPromotionValidForUnitCombatType(ePromotion, eUnit)) { return false; } if(!bLeader && promotionInfo->IsLeader()) { return false; } // If the Unit only has one move then Blitz is not useful if(unitInfo->GetMoves() == 1) { if(promotionInfo->IsBlitz()) { return false; } } // Promotion Prereqs if(NO_PROMOTION != promotionInfo->GetPrereqPromotion()) { if(!isPromotionValid((PromotionTypes)promotionInfo->GetPrereqPromotion(), eUnit, bLeader, true)) { return false; } } PromotionTypes ePrereq1 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion1(); PromotionTypes ePrereq2 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion2(); PromotionTypes ePrereq3 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion3(); PromotionTypes ePrereq4 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion4(); PromotionTypes ePrereq5 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion5(); PromotionTypes ePrereq6 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion6(); PromotionTypes ePrereq7 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion7(); PromotionTypes ePrereq8 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion8(); PromotionTypes ePrereq9 = (PromotionTypes)promotionInfo->GetPrereqOrPromotion9(); if(ePrereq1 != NO_PROMOTION || ePrereq2 != NO_PROMOTION || ePrereq3 != NO_PROMOTION || ePrereq4 != NO_PROMOTION || ePrereq5 != NO_PROMOTION || ePrereq6 != NO_PROMOTION || ePrereq7 != NO_PROMOTION || ePrereq8 != NO_PROMOTION || ePrereq9 != NO_PROMOTION) { bool bValid = false; if(!bValid) { if(NO_PROMOTION != ePrereq1 && isPromotionValid(ePrereq1, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq2 && isPromotionValid(ePrereq2, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq3 && isPromotionValid(ePrereq3, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq4 && isPromotionValid(ePrereq4, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq5 && isPromotionValid(ePrereq5, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq6 && isPromotionValid(ePrereq6, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq7 && isPromotionValid(ePrereq7, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq8 && isPromotionValid(ePrereq8, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { if(NO_PROMOTION != ePrereq9 && isPromotionValid(ePrereq9, eUnit, bLeader, true)) { bValid = true; } } if(!bValid) { return false; } } return true; }
AdvisorTypes CvAdvisorRecommender::FindUnassignedAdvisorForBuildable (PlayerTypes /*ePlayer*/, CvCityBuildable& buildable) { int aiAdvisorValues[NUM_ADVISOR_TYPES]; for (uint ui = 0; ui < NUM_ADVISOR_TYPES; ui++) { aiAdvisorValues[ui] = 0; } CvBuildingEntry* pBuilding = NULL; CvUnitEntry* pUnit = NULL; CvProjectEntry* pProject = NULL; switch (buildable.m_eBuildableType) { case CITY_BUILDABLE_UNIT: pUnit = GC.getUnitInfo((UnitTypes)buildable.m_iIndex); break; case CITY_BUILDABLE_BUILDING: pBuilding = GC.getBuildingInfo((BuildingTypes)buildable.m_iIndex); break; case CITY_BUILDABLE_PROJECT: pProject = GC.getProjectInfo((ProjectTypes)buildable.m_iIndex); break; } for (int i = 0; i < GC.getNumFlavorTypes(); i++) { FlavorTypes eFlavor = (FlavorTypes)i; int iFlavorValue = 0; if (pBuilding) { iFlavorValue = pBuilding->GetFlavorValue(eFlavor); } else if (pUnit) { iFlavorValue = pUnit->GetFlavorValue(eFlavor); } else if (pProject) { iFlavorValue = pProject->GetFlavorValue(eFlavor); } if (iFlavorValue <= 0) { continue; } for (uint uiAdvisor = 0; uiAdvisor < NUM_ADVISOR_TYPES; uiAdvisor++) { AdvisorTypes eAdvisor = (AdvisorTypes)uiAdvisor; aiAdvisorValues[uiAdvisor] += iFlavorValue * AdvisorInterestInFlavor(eAdvisor, eFlavor); } } AdvisorTypes eWinningAdvisor = NO_ADVISOR_TYPE; int iHighestValue = 0; for (uint ui = 0; ui < NUM_ADVISOR_TYPES; ui++) { // skip this advisor if already assigned if (m_aRecommendedBuilds[ui].m_eBuildableType != NOT_A_CITY_BUILDABLE) { continue; } if (aiAdvisorValues[ui] > iHighestValue) { eWinningAdvisor = (AdvisorTypes)ui; iHighestValue = aiAdvisorValues[ui]; } } return eWinningAdvisor; }