/// Establish weights for one flavor; can be called multiple times to layer strategies void CvPolicyAI::AddFlavorWeights(FlavorTypes eFlavor, int iWeight, int iPropagationPercent) { int iPolicy; CvPolicyEntry* entry; int* paiTempWeights; CvPolicyXMLEntries* pkPolicyEntries = m_pCurrentPolicies->GetPolicies(); // Create a temporary array of weights paiTempWeights = (int*)_alloca(sizeof(int*) * pkPolicyEntries->GetNumPolicies()); // Loop through all our policies for(iPolicy = 0; iPolicy < pkPolicyEntries->GetNumPolicies(); iPolicy++) { entry = pkPolicyEntries->GetPolicyEntry(iPolicy); // Set its weight by looking at policy's weight for this flavor and using iWeight multiplier passed in if(entry) paiTempWeights[iPolicy] = entry->GetFlavorValue(eFlavor) * iWeight; else paiTempWeights[iPolicy] = 0; } // Propagate these values left in the tree so prereqs get bought if(iPropagationPercent > 0) { WeightPrereqs(paiTempWeights, iPropagationPercent); } // Add these weights over previous ones for(iPolicy = 0; iPolicy < m_pCurrentPolicies->GetPolicies()->GetNumPolicies(); iPolicy++) { m_PolicyAIWeights.IncreaseWeight(iPolicy, paiTempWeights[iPolicy]); } }
/// Choose a player's next policy purchase (could be opening a branch) int CvPolicyAI::ChooseNextPolicy(CvPlayer* pPlayer) { RandomNumberDelegate fcn; fcn = MakeDelegate(&GC.getGame(), &CvGame::getJonRandNum); int iRtnValue = (int)NO_POLICY; int iPolicyLoop; vector<int> aLevel3Tenets; bool bMustChooseTenet = (pPlayer->GetNumFreeTenets() > 0); // Create a new vector holding only policies we can currently adopt m_AdoptablePolicies.clear(); // Loop through adding the adoptable policies for(iPolicyLoop = 0; iPolicyLoop < m_pCurrentPolicies->GetPolicies()->GetNumPolicies(); iPolicyLoop++) { if(m_pCurrentPolicies->CanAdoptPolicy((PolicyTypes) iPolicyLoop) && (!bMustChooseTenet || m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetLevel() > 0)) { int iWeight = 0; iWeight += m_PolicyAIWeights.GetWeight(iPolicyLoop); // Does this policy finish a branch for us? if(m_pCurrentPolicies->WillFinishBranchIfAdopted((PolicyTypes) iPolicyLoop)) { int iPolicyBranch = m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetPolicyBranchType(); if(iPolicyBranch != NO_POLICY_BRANCH_TYPE) { int iFinisherPolicy = m_pCurrentPolicies->GetPolicies()->GetPolicyBranchEntry(iPolicyBranch)->GetFreeFinishingPolicy(); if(iFinisherPolicy != NO_POLICY) { iWeight += m_PolicyAIWeights.GetWeight(iFinisherPolicy); } } } m_AdoptablePolicies.push_back(iPolicyLoop + GC.getNumPolicyBranchInfos(), iWeight); if (m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetLevel() == 3) { aLevel3Tenets.push_back(iPolicyLoop); } } } // Did we already start a branch in the set that is mutually exclusive? bool bStartedAMutuallyExclusiveBranch = false; for(int iBranchLoop = 0; iBranchLoop < GC.getNumPolicyBranchInfos(); iBranchLoop++) { const PolicyBranchTypes ePolicyBranch = static_cast<PolicyBranchTypes>(iBranchLoop); CvPolicyBranchEntry* pkPolicyBranchInfo = GC.getPolicyBranchInfo(ePolicyBranch); if(pkPolicyBranchInfo) { if(pPlayer->GetPlayerPolicies()->IsPolicyBranchUnlocked(ePolicyBranch)) { if(pkPolicyBranchInfo->IsMutuallyExclusive()) { bStartedAMutuallyExclusiveBranch = true; } } } } AIGrandStrategyTypes eCultureGrandStrategy = (AIGrandStrategyTypes) GC.getInfoTypeForString("AIGRANDSTRATEGY_CULTURE"); AIGrandStrategyTypes eCurrentGrandStrategy = pPlayer->GetGrandStrategyAI()->GetActiveGrandStrategy(); // Loop though the branches adding each as another possibility if (!bMustChooseTenet) { for(int iBranchLoop = 0; iBranchLoop < GC.getNumPolicyBranchInfos(); iBranchLoop++) { const PolicyBranchTypes ePolicyBranch = static_cast<PolicyBranchTypes>(iBranchLoop); CvPolicyBranchEntry* pkPolicyBranchInfo = GC.getPolicyBranchInfo(ePolicyBranch); if(pkPolicyBranchInfo) { if(bStartedAMutuallyExclusiveBranch && pkPolicyBranchInfo->IsMutuallyExclusive()) { continue; } #if defined (JRMOD_C23) // Don't open a branch disabling an already opened branch if (pPlayer->GetPlayerPolicies()->IsPolicyBranchBlocked(ePolicyBranch)) continue; #endif if(pPlayer->GetPlayerPolicies()->CanUnlockPolicyBranch(ePolicyBranch) && !pPlayer->GetPlayerPolicies()->IsPolicyBranchUnlocked(ePolicyBranch)) { int iBranchWeight = 0; // Does this branch actually help us, based on game options? if(IsBranchEffectiveInGame(ePolicyBranch)) { iBranchWeight += WeighBranch(ePolicyBranch); iBranchWeight *= (100 - m_iPolicyWeightPercentDropNewBranch); iBranchWeight /= 100; #if defined (JRMOD_C23) //Following condition no longer makes sense since Cultural victory has changed but i let it since it can help the AI to focus on a tree. #endif if(eCurrentGrandStrategy == eCultureGrandStrategy) { iBranchWeight /= 3; } } m_AdoptablePolicies.push_back(iBranchLoop, iBranchWeight); } } } } m_AdoptablePolicies.SortItems(); LogPossiblePolicies(); // If there were any Level 3 tenets found, consider going for the one that matches our victory strategy if (aLevel3Tenets.size() > 0) { vector<int>::const_iterator it; for (it = aLevel3Tenets.begin(); it != aLevel3Tenets.end(); it++) { CvPolicyEntry *pEntry; pEntry = m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(*it); if (pEntry) { AIGrandStrategyTypes eGrandStrategy = pPlayer->GetGrandStrategyAI()->GetActiveGrandStrategy(); if (eGrandStrategy == GC.getInfoTypeForString("AIGRANDSTRATEGY_CONQUEST")) { if (pEntry->GetFlavorValue((FlavorTypes)GC.getInfoTypeForString("FLAVOR_OFFENSE")) > 0) { LogPolicyChoice((PolicyTypes)*it); return (*it) + GC.getNumPolicyBranchInfos(); } } else if(eGrandStrategy == GC.getInfoTypeForString("AIGRANDSTRATEGY_SPACESHIP")) { if (pEntry->GetFlavorValue((FlavorTypes)GC.getInfoTypeForString("FLAVOR_SPACESHIP")) > 0) { LogPolicyChoice((PolicyTypes)*it); return (*it) + GC.getNumPolicyBranchInfos(); } } else if(eGrandStrategy == GC.getInfoTypeForString("AIGRANDSTRATEGY_UNITED_NATIONS")) { if (pEntry->GetFlavorValue((FlavorTypes)GC.getInfoTypeForString("FLAVOR_DIPLOMACY")) > 0) { LogPolicyChoice((PolicyTypes)*it); return (*it) + GC.getNumPolicyBranchInfos(); } } else if(eGrandStrategy == GC.getInfoTypeForString("AIGRANDSTRATEGY_CULTURE")) { if (pEntry->GetFlavorValue((FlavorTypes)GC.getInfoTypeForString("FLAVOR_CULTURE")) > 0) { LogPolicyChoice((PolicyTypes)*it); return (*it) + GC.getNumPolicyBranchInfos(); } } } } } CvAssertMsg(m_AdoptablePolicies.GetTotalWeight() >= 0, "Total weights of considered policies should not be negative! Please send Anton your save file and version."); // If total weight is above 0, choose one above a threshold if(m_AdoptablePolicies.GetTotalWeight() > 0) { int iNumChoices = GC.getGame().getHandicapInfo().GetPolicyNumOptions(); iRtnValue = m_AdoptablePolicies.ChooseFromTopChoices(iNumChoices, &fcn, "Choosing policy from Top Choices"); } // Total weight may be 0 if the only branches and policies left are ones that are ineffective in our game, but we gotta pick something else if(m_AdoptablePolicies.GetTotalWeight() == 0 && m_AdoptablePolicies.size() > 0) { iRtnValue = m_AdoptablePolicies.ChooseAtRandom(&fcn, "Choosing policy at random (no good choices)"); } // Log our choice if(iRtnValue != (int)NO_POLICY) { if(iRtnValue >= GC.getNumPolicyBranchInfos()) { LogPolicyChoice((PolicyTypes)(iRtnValue - GC.getNumPolicyBranchInfos())); } else { LogBranchChoice((PolicyBranchTypes)iRtnValue); } } return iRtnValue; }
/// Choose a player's next policy purchase (could be opening a branch) int CvPolicyAI::ChooseNextPolicy(CvPlayer* pPlayer) { RandomNumberDelegate fcn; fcn = MakeDelegate(&GC.getGame(), &CvGame::getJonRandNum); int iRtnValue = (int)NO_POLICY; int iPolicyLoop; vector<int> aLevel3Tenets; bool bMustChooseTenet = (pPlayer->GetNumFreeTenets() > 0); // Create a new vector holding only policies we can currently adopt m_AdoptablePolicies.clear(); // Loop through adding the adoptable policies for(iPolicyLoop = 0; iPolicyLoop < m_pCurrentPolicies->GetPolicies()->GetNumPolicies(); iPolicyLoop++) { if(m_pCurrentPolicies->CanAdoptPolicy((PolicyTypes) iPolicyLoop) && (!bMustChooseTenet || m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetLevel() > 0)) { int iWeight = 0; iWeight += m_PolicyAIWeights.GetWeight(iPolicyLoop); #if defined(MOD_BALANCE_CORE) //If this is an ideology policy, let's snap those up. if(m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetLevel() > 0) { iWeight *= (m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetLevel() + 1); } //Older branches should be slowly phased out. PolicyBranchTypes ePolicyBranch = (PolicyBranchTypes)m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetPolicyBranchType(); if(ePolicyBranch != NO_POLICY_BRANCH_TYPE) { CvPolicyBranchEntry* pkPolicyBranchInfo = GC.getPolicyBranchInfo(ePolicyBranch); if(pkPolicyBranchInfo) { //If we're already in this branch, let's get a bonus based on how many we have in it (this will push the AI to finish branches quickly. if(m_pCurrentPolicies->GetNumPoliciesOwnedInBranch(ePolicyBranch) > 0 || m_pCurrentPolicies->IsPolicyBranchUnlocked(ePolicyBranch)) { iWeight *= (m_pCurrentPolicies->GetNumPoliciesOwnedInBranch(ePolicyBranch) + 1); } else { int iPolicyEra = pkPolicyBranchInfo->GetEraPrereq(); int iPlayerEra = pPlayer->GetCurrentEra(); if(iPolicyEra < iPlayerEra) { iWeight /= max(1, (iPlayerEra - iPolicyEra)); } } } if(ePolicyBranch == (PolicyBranchTypes)GC.getInfoTypeForString("POLICY_BRANCH_PIETY", true)) { EconomicAIStrategyTypes eStrategyBuildingReligion = (EconomicAIStrategyTypes) GC.getInfoTypeForString("ECONOMICAISTRATEGY_DEVELOPING_RELIGION", true); bool bBuildingReligion = false; if (eStrategyBuildingReligion != NO_ECONOMICAISTRATEGY) { bBuildingReligion = pPlayer->GetEconomicAI()->IsUsingStrategy(eStrategyBuildingReligion); } if(!bBuildingReligion) { iWeight = 0; } else { iWeight *= 5; } } } #endif // Does this policy finish a branch for us? if(m_pCurrentPolicies->WillFinishBranchIfAdopted((PolicyTypes) iPolicyLoop)) { int iPolicyBranch = m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetPolicyBranchType(); if(iPolicyBranch != NO_POLICY_BRANCH_TYPE) { int iFinisherPolicy = m_pCurrentPolicies->GetPolicies()->GetPolicyBranchEntry(iPolicyBranch)->GetFreeFinishingPolicy(); if(iFinisherPolicy != NO_POLICY) { iWeight += m_PolicyAIWeights.GetWeight(iFinisherPolicy); } } } m_AdoptablePolicies.push_back(iPolicyLoop + GC.getNumPolicyBranchInfos(), iWeight); if (m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(iPolicyLoop)->GetLevel() == 3) { aLevel3Tenets.push_back(iPolicyLoop); } } } // Did we already start a branch in the set that is mutually exclusive? bool bStartedAMutuallyExclusiveBranch = false; for(int iBranchLoop = 0; iBranchLoop < GC.getNumPolicyBranchInfos(); iBranchLoop++) { const PolicyBranchTypes ePolicyBranch = static_cast<PolicyBranchTypes>(iBranchLoop); CvPolicyBranchEntry* pkPolicyBranchInfo = GC.getPolicyBranchInfo(ePolicyBranch); if(pkPolicyBranchInfo) { if(pPlayer->GetPlayerPolicies()->IsPolicyBranchUnlocked(ePolicyBranch)) { if(pkPolicyBranchInfo->IsMutuallyExclusive()) { bStartedAMutuallyExclusiveBranch = true; } } } } #if defined(MOD_BALANCE_CORE) //Leftover from Vanilla victory #else AIGrandStrategyTypes eCultureGrandStrategy = (AIGrandStrategyTypes) GC.getInfoTypeForString("AIGRANDSTRATEGY_CULTURE"); AIGrandStrategyTypes eCurrentGrandStrategy = pPlayer->GetGrandStrategyAI()->GetActiveGrandStrategy(); #endif // Loop though the branches adding each as another possibility if (!bMustChooseTenet) { for(int iBranchLoop = 0; iBranchLoop < GC.getNumPolicyBranchInfos(); iBranchLoop++) { const PolicyBranchTypes ePolicyBranch = static_cast<PolicyBranchTypes>(iBranchLoop); CvPolicyBranchEntry* pkPolicyBranchInfo = GC.getPolicyBranchInfo(ePolicyBranch); if(pkPolicyBranchInfo) { if(bStartedAMutuallyExclusiveBranch && pkPolicyBranchInfo->IsMutuallyExclusive()) { continue; } #if defined(MOD_BALANCE_CORE) bool bNeedToFinish = false; for(int iBranchLoop2 = 0; iBranchLoop2 < GC.getNumPolicyBranchInfos(); iBranchLoop2++) { const PolicyBranchTypes ePolicyBranch2 = static_cast<PolicyBranchTypes>(iBranchLoop2); CvPolicyBranchEntry* pkPolicyBranchInfo2 = GC.getPolicyBranchInfo(ePolicyBranch2); //Do we already have a different policy branch unlocked? if(pkPolicyBranchInfo2 && ePolicyBranch2 != ePolicyBranch && pPlayer->GetPlayerPolicies()->IsPolicyBranchUnlocked(ePolicyBranch2)) { //Have we not finished it yet? If so, let's not open a new one. if(!pPlayer->GetPlayerPolicies()->HasPolicy((PolicyTypes)pkPolicyBranchInfo2->GetFreeFinishingPolicy())) { bNeedToFinish = true; break; } } } if(bNeedToFinish) { continue; } #endif if(pPlayer->GetPlayerPolicies()->CanUnlockPolicyBranch(ePolicyBranch) && !pPlayer->GetPlayerPolicies()->IsPolicyBranchUnlocked(ePolicyBranch)) { int iBranchWeight = 0; // Does this branch actually help us, based on game options? if(IsBranchEffectiveInGame(ePolicyBranch)) { iBranchWeight += WeighBranch(ePolicyBranch); iBranchWeight *= (100 - m_iPolicyWeightPercentDropNewBranch); iBranchWeight /= 100; #if defined(MOD_BALANCE_CORE) //Leftover from Vanilla victory #else if(eCurrentGrandStrategy == eCultureGrandStrategy) { iBranchWeight /= 3; } #endif } m_AdoptablePolicies.push_back(iBranchLoop, iBranchWeight); } } } } m_AdoptablePolicies.SortItems(); LogPossiblePolicies(); #if defined(MOD_BALANCE_CORE) #else // If there were any Level 3 tenets found, consider going for the one that matches our victory strategy if (aLevel3Tenets.size() > 0) { vector<int>::const_iterator it; for (it = aLevel3Tenets.begin(); it != aLevel3Tenets.end(); it++) { CvPolicyEntry *pEntry; pEntry = m_pCurrentPolicies->GetPolicies()->GetPolicyEntry(*it); if (pEntry) { AIGrandStrategyTypes eGrandStrategy = pPlayer->GetGrandStrategyAI()->GetActiveGrandStrategy(); if (eGrandStrategy == GC.getInfoTypeForString("AIGRANDSTRATEGY_CONQUEST")) { if (pEntry->GetFlavorValue((FlavorTypes)GC.getInfoTypeForString("FLAVOR_OFFENSE")) > 0) { LogPolicyChoice((PolicyTypes)*it); return (*it) + GC.getNumPolicyBranchInfos(); } } else if(eGrandStrategy == GC.getInfoTypeForString("AIGRANDSTRATEGY_SPACESHIP")) { if (pEntry->GetFlavorValue((FlavorTypes)GC.getInfoTypeForString("FLAVOR_SPACESHIP")) > 0) { LogPolicyChoice((PolicyTypes)*it); return (*it) + GC.getNumPolicyBranchInfos(); } } else if(eGrandStrategy == GC.getInfoTypeForString("AIGRANDSTRATEGY_UNITED_NATIONS")) { if (pEntry->GetFlavorValue((FlavorTypes)GC.getInfoTypeForString("FLAVOR_DIPLOMACY")) > 0) { LogPolicyChoice((PolicyTypes)*it); return (*it) + GC.getNumPolicyBranchInfos(); } } else if(eGrandStrategy == GC.getInfoTypeForString("AIGRANDSTRATEGY_CULTURE")) { if (pEntry->GetFlavorValue((FlavorTypes)GC.getInfoTypeForString("FLAVOR_CULTURE")) > 0) { LogPolicyChoice((PolicyTypes)*it); return (*it) + GC.getNumPolicyBranchInfos(); } } } } } #endif CvAssertMsg(m_AdoptablePolicies.GetTotalWeight() >= 0, "Total weights of considered policies should not be negative! Please send Anton your save file and version."); // If total weight is above 0, choose one above a threshold if(m_AdoptablePolicies.GetTotalWeight() > 0) { int iNumChoices = GC.getGame().getHandicapInfo().GetPolicyNumOptions(); iRtnValue = m_AdoptablePolicies.ChooseFromTopChoices(iNumChoices, &fcn, "Choosing policy from Top Choices"); } // Total weight may be 0 if the only branches and policies left are ones that are ineffective in our game, but we gotta pick something else if(m_AdoptablePolicies.GetTotalWeight() == 0 && m_AdoptablePolicies.size() > 0) { iRtnValue = m_AdoptablePolicies.ChooseAtRandom(&fcn, "Choosing policy at random (no good choices)"); } // Log our choice if(iRtnValue != (int)NO_POLICY) { if(iRtnValue >= GC.getNumPolicyBranchInfos()) { LogPolicyChoice((PolicyTypes)(iRtnValue - GC.getNumPolicyBranchInfos())); } else { LogBranchChoice((PolicyBranchTypes)iRtnValue); } } return iRtnValue; }