Code
635/// Assign specializations to cities636void CvCitySpecializationAI::AssignSpecializations()637{638 int iI;639 CitySpecializationTypes eSpecialization;640 CitySpecializationData cityData;641 list<CitySpecializationData> citiesWithoutSpecialization;642 list<CitySpecializationTypes>::iterator it;643 list<CitySpecializationTypes>::iterator iterEnd;644 list<CitySpecializationData>::iterator cityIter;645 list<CitySpecializationData>::iterator cityIterEnd;646 list<CitySpecializationData>::iterator bestCity;647648 m_eNextSpecializationDesired = NO_CITY_SPECIALIZATION;649 citiesWithoutSpecialization.clear();650651 CitySpecializationTypes eWonderSpecialiation = GetWonderSpecialization();652653 // Find specializations needed (including for the next city we build)654 SelectSpecializations();655656 // OBVIOUS ASSIGNMENTS: Loop through our cities making obvious assignments657 CvCity* pLoopCity;658 int iLoop;659 for(pLoopCity = m_pPlayer->firstCity(&iLoop); pLoopCity != NULL; pLoopCity = m_pPlayer->nextCity(&iLoop))660 {661 if(pLoopCity->IsPuppet())662 {663 pLoopCity->GetCityStrategyAI()->SetSpecialization(GetEconomicDefaultSpecialization());664 LogSpecializationAssignment(pLoopCity, GetEconomicDefaultSpecialization(), true);665 continue;666 }667668 // If this is the city to build our current wonder in, mark all that669 if(m_bWonderChosen && pLoopCity->GetID() == m_iWonderCityID)670 {671 it = find(m_SpecializationsNeeded.begin(), m_SpecializationsNeeded.end(), eWonderSpecialiation);672 if(it != m_SpecializationsNeeded.end())673 {674 m_SpecializationsNeeded.erase(it);675 pLoopCity->GetCityStrategyAI()->SetSpecialization(eWonderSpecialiation);676 LogSpecializationAssignment(pLoopCity, eWonderSpecialiation, true);677 continue;678 }679 }680681 // If city default is equal to a needed type, go with that682 eSpecialization = pLoopCity->GetCityStrategyAI()->GetDefaultSpecialization();683 it = find(m_SpecializationsNeeded.begin(), m_SpecializationsNeeded.end(), eSpecialization);684 if(it != m_SpecializationsNeeded.end())685 {686 m_SpecializationsNeeded.erase(it);687 pLoopCity->GetCityStrategyAI()->SetSpecialization(eSpecialization);688 LogSpecializationAssignment(pLoopCity, eSpecialization);689 }690 else691 {692 // If cities' current specialization is needed, stick with that693 eSpecialization = pLoopCity->GetCityStrategyAI()->GetSpecialization();694 it = find(m_SpecializationsNeeded.begin(), m_SpecializationsNeeded.end(), eSpecialization);695 if(it != m_SpecializationsNeeded.end())696 {697 m_SpecializationsNeeded.erase(it);698 pLoopCity->GetCityStrategyAI()->SetSpecialization(eSpecialization);699 LogSpecializationAssignment(pLoopCity, eSpecialization);700 }701702 // Save this city off (with detailed data about what it is good at) to assign later703 else704 {705 cityData.m_eID = pLoopCity->GetID();706 for(iI = 0; iI <= YIELD_SCIENCE; iI++)707 {708 if(iI == YIELD_SCIENCE)709 {710 cityData.m_iWeight[iI] = PlotValueForScience(pLoopCity->plot()); // -- BKW, looks like PlotValueForScience is making some assumptions that are no longer true711 }712 else713 {714 cityData.m_iWeight[iI] = PlotValueForSpecificYield(pLoopCity->plot(), (YieldTypes)iI);715 }716 cityData.m_iWeight[iI] = AdjustValueBasedOnBuildings(pLoopCity, (YieldTypes)iI, cityData.m_iWeight[iI]);717 if(cityData.m_iWeight[iI] < 0)718 {719 cityData.m_iWeight[iI] = 0;720 }721 }722 citiesWithoutSpecialization.push_back(cityData);723724 LogCity(pLoopCity, cityData);725726 }727 }728 }729730 FAssert(citiesWithoutSpecialization.size() + 1 == m_SpecializationsNeeded.size());731732 // NEXT SPECIALIZATION NEEDED: Now figure out what we want to assign as our "next specialization needed"733734 // If only one specialization left, it's easy735 if(citiesWithoutSpecialization.empty())736 {737 it = m_SpecializationsNeeded.begin();738 m_eNextSpecializationDesired = *it;739 LogNextSpecialization(m_eNextSpecializationDesired);740 return;741 }742743 // If all specializations left are "general economic", set that as next needed744 bool bAllGeneral = true;745 it = m_SpecializationsNeeded.begin();746 iterEnd = m_SpecializationsNeeded.end();747 for(; it != iterEnd; ++it)748 {749 CitySpecializationTypes eType = *it;750 if(eType != GetEconomicDefaultSpecialization())751 {752 bAllGeneral = false;753 }754 }755756 if(bAllGeneral)757 {758 m_eNextSpecializationDesired = GetEconomicDefaultSpecialization();759 LogNextSpecialization(m_eNextSpecializationDesired);760 m_SpecializationsNeeded.erase(m_SpecializationsNeeded.begin());761 }762763 else764 {765 // Find best possible sites for each of the yield types766 FindBestSites();767768 // Compute the yield which we can improve the most with a new city769 int iCurrentDelta;770 int iBestDelta[YIELD_SCIENCE + 1];771 for(iI = 0; iI <= YIELD_SCIENCE; iI++)772 {773 iBestDelta[iI] = MIN_INT;774 }775 cityIter = citiesWithoutSpecialization.begin();776 cityIterEnd = citiesWithoutSpecialization.end();777 for(; cityIter != cityIterEnd; ++cityIter)778 {779 cityData = *cityIter;780 for(iI = 0; iI <= YIELD_SCIENCE; iI++)781 {782 iCurrentDelta = cityData.m_iWeight[iI] - m_iBestValue[iI];783 if(iCurrentDelta > iBestDelta[iI])784 {785 iBestDelta[iI] = iCurrentDelta;786 }787 }788 }789790 // Save yield improvements in a vector we can sort791 CvWeightedVector<int, YIELD_SCIENCE+1, true> yieldImprovements;792 for(iI = 0; iI <= YIELD_SCIENCE; iI++)793 {794 int iImprovementWithNewCity;795 if(iBestDelta[iI] > 0)796 {797 iImprovementWithNewCity = 0;798 }799 else800 {801 iImprovementWithNewCity = -iBestDelta[iI];802 }803 yieldImprovements.push_back(iI, iImprovementWithNewCity);804 }805 yieldImprovements.SortItems();806807 // Take them out in order and see if we need this specialization808 bool bFoundIt = false;809 for(iI = 0; iI < yieldImprovements.size(); iI++)810 {811 YieldTypes eMostImprovedYield = (YieldTypes)yieldImprovements.GetElement(iI);812813 // Loop through needed specializations until we find one that matches814 it = m_SpecializationsNeeded.begin();815 iterEnd = m_SpecializationsNeeded.end();816 for(; it != iterEnd; ++it)817 {818 CitySpecializationTypes eType = *it;819 YieldTypes eYield = GC.getCitySpecializationInfo(eType)->GetYieldType();820 if(eYield == eMostImprovedYield)821 {822 m_eNextSpecializationDesired = eType;823 LogNextSpecialization(m_eNextSpecializationDesired);824 m_SpecializationsNeeded.erase(it);825 bFoundIt = true;826 break;827 }828 }829 if(bFoundIt)830 {831 break;832 }833 }834 }835836 FAssert(citiesWithoutSpecialization.size() == m_SpecializationsNeeded.size());837838 // REMAINING ASSIGNMENTS: Make the rest of the assignments839 it = m_SpecializationsNeeded.begin();840 iterEnd = m_SpecializationsNeeded.end();841 for(; it != iterEnd; ++it)842 {843 const CitySpecializationTypes eType = *it;844 CvCitySpecializationXMLEntry* pkCitySpecializationEntry = GC.getCitySpecializationInfo(eType);845 if(pkCitySpecializationEntry == NULL)846 continue;847848 YieldTypes eYield = pkCitySpecializationEntry->GetYieldType();849 bool bCoastal = pkCitySpecializationEntry->IsMustBeCoastal();850 bestCity = citiesWithoutSpecialization.end();851852 // Pick best existing city based on a better computation of existing city's value for a yield type853 int iBestValue = -1;854 cityIter = citiesWithoutSpecialization.begin();855 cityIterEnd = citiesWithoutSpecialization.end();856 for(; cityIter != cityIterEnd; ++cityIter)857 {858 cityData = *cityIter;859860 if(bCoastal && !m_pPlayer->getCity(cityData.m_eID)->isCoastal(100))861 {862 continue;863 }864865 if(eYield == NO_YIELD)866 {867 // General economic is all yields added together868 int iCityValue = 0;869 for(iI = 0; iI <= YIELD_SCIENCE; iI++)870 {871 iCityValue += cityData.m_iWeight[iI];872 }873 if(iCityValue > iBestValue)874 {875 iBestValue = iCityValue;876 bestCity = cityIter;877 }878 }879 else880 {881 if(cityData.m_iWeight[(int)eYield] > iBestValue)882 {883 iBestValue = cityData.m_iWeight[(int)eYield];884 bestCity = cityIter;885 }886 }887 }888889 // Found a city to set890 if(bestCity != citiesWithoutSpecialization.end())891 {892 CvCity* pCity = m_pPlayer->getCity(bestCity->m_eID);893 pCity->GetCityStrategyAI()->SetSpecialization(eType);894 LogSpecializationAssignment(pCity, eType);895 citiesWithoutSpecialization.erase(bestCity);896 }897898 // No (coastal) city found, use default specialization as last resort899 else900 {901 CvCity* pCity = m_pPlayer->getCity(citiesWithoutSpecialization.begin()->m_eID);902 pCity->GetCityStrategyAI()->SetSpecialization(GetEconomicDefaultSpecialization());903 LogSpecializationAssignment(pCity, GetEconomicDefaultSpecialization());904 citiesWithoutSpecialization.erase(citiesWithoutSpecialization.begin());905 }906 }907908 return;909}