/// Value of this site for a civ starting location int CvSiteEvaluatorForStart::PlotFoundValue(CvPlot* pPlot, CvPlayer* pPlayer, YieldTypes, bool) { int rtnValue = 0; int iI; CvPlot* pLoopPlot(NULL); int iCelticForestCount = 0; CvAssert(pPlot); if(!pPlot) return rtnValue; if(!CanFound(pPlot, pPlayer, false)) { return rtnValue; } // Is there any reason this site doesn't work for a start location? // // Not on top of a goody hut if(pPlot->isGoody()) { return 0; } // We have our own special method of scoring, so don't call the base class for that (like settler version does) #if defined(MOD_GLOBAL_CITY_WORKING) int iLimit = (pPlayer != NULL) ? pPlayer->GetNumWorkablePlots() : AVG_CITY_PLOTS; for(iI = 0; iI < iLimit; iI++) #else for(iI = 0; iI < NUM_CITY_PLOTS; iI++) #endif { pLoopPlot = plotCity(pPlot->getX(), pPlot->getY(), iI); // Too close to map edge? if(pLoopPlot == NULL) { return 0; } else { int iDistance = plotDistance(pPlot->getX(), pPlot->getY(), pLoopPlot->getX(), pLoopPlot->getY()); #if defined(MOD_GLOBAL_CITY_WORKING) if (pPlayer != NULL) { CvAssert(iDistance <= pPlayer->getWorkPlotDistance()); if(iDistance > pPlayer->getWorkPlotDistance()) continue; } else { CvAssert(iDistance <= AVG_CITY_RADIUS); if(iDistance > AVG_CITY_RADIUS) continue; } #else CvAssert(iDistance <= NUM_CITY_RINGS); if(iDistance > NUM_CITY_RINGS) continue; #endif int iRingModifier = m_iRingModifier[iDistance]; // Skip the city plot itself for now if(iDistance != 0) { rtnValue += iRingModifier * ComputeFoodValue(pLoopPlot, pPlayer) * /*6*/ GC.getSTART_AREA_FOOD_MULTIPLIER(); rtnValue += iRingModifier * ComputeHappinessValue(pLoopPlot, pPlayer) * /*12*/ GC.getSTART_AREA_HAPPINESS_MULTIPLIER(); rtnValue += iRingModifier * ComputeProductionValue(pLoopPlot, pPlayer) * /*8*/ GC.getSTART_AREA_PRODUCTION_MULTIPLIER(); rtnValue += iRingModifier * ComputeGoldValue(pLoopPlot, pPlayer) * /*2*/ GC.getSTART_AREA_GOLD_MULTIPLIER(); rtnValue += iRingModifier * ComputeScienceValue(pLoopPlot, pPlayer) * /*1*/ GC.getSTART_AREA_SCIENCE_MULTIPLIER(); rtnValue += iRingModifier * ComputeFaithValue(pLoopPlot, pPlayer) * /*1*/ GC.getSTART_AREA_FAITH_MULTIPLIER(); rtnValue += iRingModifier * ComputeTradeableResourceValue(pLoopPlot, pPlayer) * /*1*/ GC.getSTART_AREA_RESOURCE_MULTIPLIER(); rtnValue += iRingModifier * ComputeStrategicValue(pLoopPlot, pPlayer, iDistance) * /*1*/ GC.getSTART_AREA_STRATEGIC_MULTIPLIER(); } if (pPlayer) { if (iDistance == 1 && pLoopPlot->getFeatureType() == FEATURE_FOREST) { if (pLoopPlot->getImprovementType() == NO_IMPROVEMENT && pPlayer->GetPlayerTraits()->IsFaithFromUnimprovedForest()) { iCelticForestCount += 1; } } } } } if (iCelticForestCount >= 3) { rtnValue += 2 * 1000 * m_iFlavorMultiplier[YIELD_FAITH]; } else if (iCelticForestCount >= 1) { rtnValue += 1 * 1000 * m_iFlavorMultiplier[YIELD_FAITH]; } if(rtnValue < 0) rtnValue = 0; // Finally, look at the city plot itself and use it as an overall multiplier if(pPlot->getResourceType() != NO_RESOURCE) { rtnValue += rtnValue * GC.getBUILD_ON_RESOURCE_PERCENT() / 100; } if(pPlot->isRiver()) { rtnValue += rtnValue * GC.getBUILD_ON_RIVER_PERCENT() / 100; } if(pPlot->isCoastalLand()) { rtnValue += rtnValue * GC.getSTART_AREA_BUILD_ON_COAST_PERCENT() / 100; } return rtnValue; }
/// Is it valid for this player to found a city here? bool CvCitySiteEvaluator::CanFound(CvPlot* pPlot, const CvPlayer* pPlayer, bool bTestVisible) const { CvAssert(pPlot); if(!pPlot) return false; CvPlot* pLoopPlot(NULL); bool bValid(false); int iRange(0), iDX(0), iDY(0); // Used to have a Python hook: CANNOT_FOUND_CITY_CALLBACK if(GC.getGame().isFinalInitialized()) { if(GC.getGame().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && pPlayer && pPlayer->isHuman()) { if(pPlayer->getNumCities() > 0) { return false; } } } if(pPlot->isImpassable() || pPlot->isMountain()) { return false; } if(pPlot->getFeatureType() != NO_FEATURE) { if(GC.getFeatureInfo(pPlot->getFeatureType())->isNoCity()) { return false; } } if(pPlayer) { if(pPlot->isOwned() && (pPlot->getOwner() != pPlayer->GetID())) { return false; } } CvTerrainInfo* pTerrainInfo = GC.getTerrainInfo(pPlot->getTerrainType()); if(!bValid) { if(pTerrainInfo->isFound()) { bValid = true; } } if(!bValid) { if(pTerrainInfo->isFoundCoast()) { if(pPlot->isCoastalLand()) { bValid = true; } } } if(!bValid) { if(pTerrainInfo->isFoundFreshWater()) { if(pPlot->isFreshWater()) { bValid = true; } } } // Used to have a Python hook: CAN_FOUND_CITIES_ON_WATER_CALLBACK if(pPlot->isWater()) { return false; } if(!bValid) { return false; } if(!bTestVisible) { // look at same land mass iRange = GC.getMIN_CITY_RANGE(); for(iDX = -(iRange); iDX <= iRange; iDX++) { for(iDY = -(iRange); iDY <= iRange; iDY++) { pLoopPlot = plotXYWithRangeCheck(pPlot->getX(), pPlot->getY(), iDX, iDY, iRange); if(pLoopPlot != NULL) { if(pLoopPlot->isCity()) { if(pLoopPlot->getLandmass() == pPlot->getLandmass()) { return false; } else if(hexDistance(iDX, iDY) < iRange) // one less for off shore { return false; } } } } } } return true; }
bool CvCitySiteEvaluator::CanFound(const CvPlot* pPlot, const CvPlayer* pPlayer, bool bIgnoreDistanceToExistingCities, const CvUnit* pUnit) const #else bool CvCitySiteEvaluator::CanFound(CvPlot* pPlot, const CvPlayer* pPlayer, bool bIgnoreDistanceToExistingCities) const #endif { CvAssert(pPlot); if(!pPlot) return false; CvPlot* pLoopPlot(NULL); bool bValid(false); // Used to have a Python hook: CANNOT_FOUND_CITY_CALLBACK if(GC.getGame().isFinalInitialized()) { if(GC.getGame().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && pPlayer && pPlayer->isHuman()) { if(pPlayer->getNumCities() > 0) { return false; } } } if (pUnit) { if(!pUnit->canEnterTerrain(*pPlot)) { return false; } } else if(!pPlot->isValidMovePlot(pPlayer ? pPlayer->GetID() : NO_PLAYER )) { return false; } if(pPlot->IsNaturalWonder()) return false; if(pPlot->getFeatureType() != NO_FEATURE) { if(GC.getFeatureInfo(pPlot->getFeatureType())->isNoCity()) { return false; } } if(pPlayer) { if(pPlot->isOwned() && (pPlot->getOwner() != pPlayer->GetID())) { return false; } } CvTerrainInfo* pTerrainInfo = GC.getTerrainInfo(pPlot->getTerrainType()); if(!bValid) { if(pTerrainInfo->isFound()) { bValid = true; } } if(!bValid) { if(pTerrainInfo->isFoundCoast()) { if(pPlot->isCoastalLand()) { bValid = true; } } } if(!bValid) { if(pTerrainInfo->isFoundFreshWater()) { if(pPlot->isFreshWater_cached()) { bValid = true; } } } // Used to have a Python hook: CAN_FOUND_CITIES_ON_WATER_CALLBACK if(pPlot->isWater()) { return false; } if(!bValid) { return false; } #if defined(MOD_BALANCE_CORE) if(pPlayer && pPlot->IsAdjacentOwnedByOtherTeam(pPlayer->getTeam())) { return false; } if(!bIgnoreDistanceToExistingCities) { int iMinDist(0), iDX(0), iDY(0); // look at same land mass iMinDist = /*3*/ GC.getMIN_CITY_RANGE(); if(pPlayer && pPlayer->isMinorCiv()) { if(GC.getMap().getWorldInfo().getMinDistanceCityStates() > 0) { iMinDist = GC.getMap().getWorldInfo().getMinDistanceCityStates(); } } else if(GC.getMap().getWorldInfo().getMinDistanceCities() > 0) { iMinDist = GC.getMap().getWorldInfo().getMinDistanceCities(); } for(iDX = -(iMinDist); iDX <= iMinDist; iDX++) { for(iDY = -(iMinDist); iDY <= iMinDist; iDY++) { pLoopPlot = plotXYWithRangeCheck(pPlot->getX(), pPlot->getY(), iDX, iDY, iMinDist); if(pLoopPlot != NULL) { if(pLoopPlot->isCity()) { if(pLoopPlot->getLandmass() == pPlot->getLandmass()) { return false; //we know that distance <= iMinDist here } else if(hexDistance(iDX, iDY) < iMinDist) // one less for off shore { return false; } } } } } } #endif return true; }