/// Value of this site for a settler
int CvSiteEvaluatorForSettler::PlotFoundValue(CvPlot* pPlot, CvPlayer* pPlayer, YieldTypes eYield, bool bCoastOnly)
{
	CvAssert(pPlot);
	if(!pPlot) return 0;

	if(!CanFound(pPlot, pPlayer, true))
	{
		return 0;
	}

	// Is there any reason this site doesn't work for a settler?
	//
	// First must be on coast if settling a new continent
	bool bIsCoastal = pPlot->isCoastalLand(GC.getMIN_WATER_SIZE_FOR_OCEAN());
	CvArea* pArea = pPlot->area();
	CvAssert(pArea);
	if(!pArea) return 0;
	int iNumAreaCities = pArea->getCitiesPerPlayer(pPlayer->GetID());
	if(bCoastOnly && !bIsCoastal && iNumAreaCities == 0)
	{
		return 0;
	}

	// Seems okay for a settler, use base class to determine exact value
	else
	{
		return CvCitySiteEvaluator::PlotFoundValue(pPlot, pPlayer, eYield);
	}
}
/// Make some adjustments to flavors based on the map we're on
void CvFlavorManager::AdjustWeightsForMap()
{
    int iTotalLandTiles;
    int iNumPlayers;
    double iTilesPerPlayer;
    double fAdjust;
    int iAdjust;

    iTotalLandTiles = GC.getMap().getLandPlots();
    iNumPlayers = GC.getGame().countMajorCivsAlive();

    if(iNumPlayers > 0)
    {
        int iNumFlavorTypes = GC.getNumFlavorTypes();
        // Find tiles per player
        iTilesPerPlayer = (double)iTotalLandTiles / (double)iNumPlayers;

        // Compute +/- addition
        //
        // We want this to be logarithmic, since that is the curve between lots of players on a duel map
        // and a few player on a huge map.  "FLAVOR_STANDARD_LOG10_TILES_PER_PLAYER" is the typical log10 of
        // tiles per player.  We go up and down from this point (multiplying by a coefficient) from here
        fAdjust = log10(iTilesPerPlayer) - GC.getFLAVOR_STANDARD_LOG10_TILES_PER_PLAYER();
        fAdjust *= (double)GC.getFLAVOR_EXPANDGROW_COEFFICIENT();
        iAdjust = (int)fAdjust;

        int iFlavorMaxValue = /*20*/ GC.getPERSONALITY_FLAVOR_MAX_VALUE();
        int iFlavorMinValue = /*0*/ GC.getPERSONALITY_FLAVOR_MIN_VALUE();

        int iExpansionIndex = GC.getInfoTypeForString("FLAVOR_EXPANSION");
        int iGrowthIndex = GC.getInfoTypeForString("FLAVOR_GROWTH");

        // Boost expansion
        CvAssert(iExpansionIndex >= 0 && iExpansionIndex < iNumFlavorTypes);
        if (iExpansionIndex >= 0 && iExpansionIndex < iNumFlavorTypes)
        {
            m_piPersonalityFlavor[iExpansionIndex] += iAdjust;
            if(m_piPersonalityFlavor[iExpansionIndex] > iFlavorMaxValue)
            {
                m_piPersonalityFlavor[iExpansionIndex] = iFlavorMaxValue;
            }
        }

        // Reduce growth
        CvAssert(iGrowthIndex >= 0 && iGrowthIndex < iNumFlavorTypes);
        if (iGrowthIndex >= 0 && iGrowthIndex < iNumFlavorTypes)
        {
            m_piPersonalityFlavor[iGrowthIndex] -= iAdjust;
            if(m_piPersonalityFlavor[iGrowthIndex] < iFlavorMinValue)
            {
                m_piPersonalityFlavor[iGrowthIndex] = iFlavorMinValue;
            }
        }

        // Save these off as our core personality and broadcast updates
        ResetToBasePersonality();
    }
}
bool atWar(TeamTypes eTeamA, TeamTypes eTeamB)
{
	if((eTeamA == NO_TEAM) || (eTeamB == NO_TEAM))
	{
		return false;
	}

	CvAssert(GET_TEAM(eTeamA).isAtWar(eTeamB) == GET_TEAM(eTeamB).isAtWar(eTeamA));
	CvAssert((eTeamA != eTeamB) || !(GET_TEAM(eTeamA).isAtWar(eTeamB)));

	return GET_TEAM(eTeamA).isAtWar(eTeamB);
}
예제 #4
0
	void  CvLoggerCSV::DeleteCSV(const char* strLogName)
	{
		CvAssert(strLogName != NULL);

		FILogFile *pLog;

		pLog = LOGFILEMGR.GetLog(strLogName, FILogFile::kDontTimeStamp);

		CvAssert(pLog != NULL);

		LOGFILEMGR.DeleteLog(pLog);

	}
bool isBeforeUnitCycle(const CvUnit* pFirstUnit, const CvUnit* pSecondUnit)
{
	CvAssert(pFirstUnit != NULL);
	CvAssert(pSecondUnit != NULL);
	CvAssert(pFirstUnit != pSecondUnit);

	if(!pFirstUnit || !pSecondUnit)
		return false;

	if(pFirstUnit->getOwner() != pSecondUnit->getOwner())
	{
		return (pFirstUnit->getOwner() < pSecondUnit->getOwner());
	}

	if(pFirstUnit->getDomainType() != pSecondUnit->getDomainType())
	{
		return (pFirstUnit->getDomainType() < pSecondUnit->getDomainType());
	}

	if(pFirstUnit->GetBaseCombatStrength() != pSecondUnit->GetBaseCombatStrength())
	{
		return (pFirstUnit->GetBaseCombatStrength() > pSecondUnit->GetBaseCombatStrength());
	}

	if(pFirstUnit->getUnitType() != pSecondUnit->getUnitType())
	{
		return (pFirstUnit->getUnitType() > pSecondUnit->getUnitType());
	}

	if(pFirstUnit->getLevel() != pSecondUnit->getLevel())
	{
		return (pFirstUnit->getLevel() > pSecondUnit->getLevel());
	}

#if defined(MOD_UNITS_XP_TIMES_100)
	if (pFirstUnit->getExperienceTimes100() != pSecondUnit->getExperienceTimes100())
	{
		return (pFirstUnit->getExperienceTimes100() > pSecondUnit->getExperienceTimes100());
	}
#else
	if (pFirstUnit->getExperience() != pSecondUnit->getExperience())
	{
		return (pFirstUnit->getExperience() > pSecondUnit->getExperience());
	}
#endif

	return (pFirstUnit->GetID() < pSecondUnit->GetID());
}
예제 #6
0
/// Delete the army
void CvArmyAI::Kill()
{
	CvAssert(GetOwner() != NO_PLAYER);
	CvAssertMsg(GetID() != -1, "GetID() is not expected to be equal with -1");

	int iUnitID;
	iUnitID = GetFirstUnitID();

	while(iUnitID != ARMYSLOT_NO_UNIT)
	{
		UnitHandle pThisUnit = GET_PLAYER(GetOwner()).getUnit(iUnitID);
		if(pThisUnit)
		{
			pThisUnit->setArmyID(-1);
#if defined(MOD_BALANCE_CORE)
			pThisUnit->AI_setUnitAIType(pThisUnit->getUnitInfo().GetDefaultUnitAIType());
#endif
		}
		iUnitID = GetNextUnitID();
	}

	m_FormationEntries.clear();

	CvAIOperation* pOperation = GET_PLAYER(GetOwner()).getAIOperation(m_iOperationID);
	if (pOperation)
		pOperation->DeleteArmyAI(m_iID);

	GET_PLAYER(GetOwner()).deleteArmyAI(m_iID);
}
/// Value of plot for providing tradeable resources
int CvCitySiteEvaluator::ComputeTradeableResourceValue(CvPlot* pPlot, const CvPlayer* pPlayer)
{
	int rtnValue = 0;

	CvAssert(pPlot);
	if(!pPlot) return rtnValue;

	// If we already own this Tile then we already have access to the Strategic Resource
	if(pPlot->isOwned())
	{
		return rtnValue;
	}

	TeamTypes eTeam = NO_TEAM;
	if(pPlayer != NULL)
	{
		eTeam = pPlayer->getTeam();
	}

	ResourceTypes eResource;
	eResource = pPlot->getResourceType(eTeam);

	if(eResource != NO_RESOURCE)
	{
		ResourceUsageTypes eResourceUsage = GC.getResourceInfo(eResource)->getResourceUsage();

		// Multiply number of tradeable resources by flavor value
		if(eResourceUsage == RESOURCEUSAGE_LUXURY || eResourceUsage == RESOURCEUSAGE_STRATEGIC)
		{
			rtnValue += pPlot->getNumResource() * m_iFlavorMultiplier[SITE_EVALUATION_RESOURCES];

			if(pPlayer)
			{
				// If we don't have this resource yet, increase it's value
				if(pPlayer->getNumResourceTotal(eResource) == 0)
					rtnValue *= 3;
#if defined(MOD_BALANCE_CORE_RESOURCE_MONOPOLIES)
				if(MOD_BALANCE_CORE_RESOURCE_MONOPOLIES && (GC.getMap().getNumResources(eResource) > 0))
				{
					//Will this get us closer to a monopoly?
					if((((pPlot->getNumResource() + pPlayer->getNumResourceTotal(eResource, false) + pPlayer->getResourceExport(eResource)) * 100) / GC.getMap().getNumResources(eResource)) >= 30)
					{
						rtnValue *= 2;
					}
					else if((((pPlot->getNumResource() + pPlayer->getNumResourceTotal(eResource, false)) * 100) / GC.getMap().getNumResources(eResource)) >= 50)
					{
						rtnValue *= 10;
					}
				}
#endif
			}
		}
	}

	return rtnValue;
}
bool isBeforeUnitCycle(const CvUnit* pFirstUnit, const CvUnit* pSecondUnit)
{
	CvAssert(pFirstUnit != NULL);
	CvAssert(pSecondUnit != NULL);
	CvAssert(pFirstUnit != pSecondUnit);

	if(!pFirstUnit || !pSecondUnit)
		return false;

	if(pFirstUnit->getOwner() != pSecondUnit->getOwner())
	{
		return (pFirstUnit->getOwner() < pSecondUnit->getOwner());
	}

	if(pFirstUnit->getDomainType() != pSecondUnit->getDomainType())
	{
		return (pFirstUnit->getDomainType() < pSecondUnit->getDomainType());
	}

	if(pFirstUnit->GetBaseCombatStrength() != pSecondUnit->GetBaseCombatStrength())
	{
		return (pFirstUnit->GetBaseCombatStrength() > pSecondUnit->GetBaseCombatStrength());
	}

	if(pFirstUnit->getUnitType() != pSecondUnit->getUnitType())
	{
		return (pFirstUnit->getUnitType() > pSecondUnit->getUnitType());
	}

	if(pFirstUnit->getLevel() != pSecondUnit->getLevel())
	{
		return (pFirstUnit->getLevel() > pSecondUnit->getLevel());
	}

	if(pFirstUnit->getExperience() != pSecondUnit->getExperience())
	{
		return (pFirstUnit->getExperience() > pSecondUnit->getExperience());
	}

	return (pFirstUnit->GetID() < pSecondUnit->GetID());
}
예제 #9
0
/// Log all potential builds
void CvProjectProductionAI::LogPossibleBuilds()
{
	if(GC.getLogging() && GC.getAILogging())
	{
		CvString strOutBuf;
		CvString strBaseString;
		CvString strTemp;
		CvString playerName;
		CvString cityName;
		CvString strDesc;
		CvString strLogName;

		CvAssert(m_pCity);
		if(!m_pCity) return;

		// Find the name of this civ and city
		playerName = GET_PLAYER(m_pCity->getOwner()).getCivilizationShortDescription();
		cityName = m_pCity->getName();

		// Open the log file
		FILogFile* pLog;
		pLog = LOGFILEMGR.GetLog(m_pCity->GetCityStrategyAI()->GetLogFileName(playerName, cityName), FILogFile::kDontTimeStamp);
		CvAssert(pLog);
		if(!pLog) return;

		// Get the leading info for this line
		strBaseString.Format("%03d, ", GC.getGame().getElapsedGameTurns());
		strBaseString += playerName + ", " + cityName + ", ";

		// Dump out the weight of each buildable item
		for(int iI = 0; iI < m_Buildables.size(); iI++)
		{
			CvProjectEntry* pProjectEntry = GC.GetGameProjects()->GetEntry(m_Buildables.GetElement(iI));

			strDesc = (pProjectEntry != NULL)? pProjectEntry->GetDescription() : "Unknown";
			strTemp.Format("Project, %s, %d", strDesc.GetCString(), m_Buildables.GetWeight(iI));
			strOutBuf = strBaseString + strTemp;
			pLog->Msg(strOutBuf);
		}
	}
}
예제 #10
0
void  CvLoggerCSV::WriteCSVLog(const char* strLogName, const char* strHeader)
	{

		FILogFile *pLog;

		pLog = LOGFILEMGR.GetLog(strLogName, FILogFile::kDontTimeStamp);

		CvAssert(pLog != NULL);

		pLog->Msg(strHeader);

	}
/// Value of this site for a settler
int CvSiteEvaluatorForSettler::PlotFoundValue(CvPlot* pPlot, CvPlayer* pPlayer, YieldTypes eYield, bool bCoastOnly)
{
	CvAssert(pPlot);
	if(!pPlot) return 0;

	if(!CanFound(pPlot, pPlayer, true))
	{
		return 0;
	}

	// Is there any reason this site doesn't work for a settler?
	//
	// First must be on coast if settling a new continent
	bool bIsCoastal = pPlot->isCoastalLand(GC.getMIN_WATER_SIZE_FOR_OCEAN());
	CvArea* pArea = pPlot->area();
	CvAssert(pArea);
	if(!pArea) return 0;
	int iNumAreaCities = pArea->getCitiesPerPlayer(pPlayer->GetID());
	if(bCoastOnly && !bIsCoastal && iNumAreaCities == 0)
	{
		return 0;
	}

	// Seems okay for a settler, use base class to determine exact value
	else
	{
		// if the civ gets a benefit from settling on a new continent (ie: Indonesia)
		// double the fertility of that plot
		int iLuxuryModifier = 0;
		if (pPlayer->GetPlayerTraits()->WillGetUniqueLuxury(pArea))
		{
			iLuxuryModifier = CvCitySiteEvaluator::PlotFoundValue(pPlot, pPlayer, eYield) * 2;
			return iLuxuryModifier;
		}
		else
		{
			return CvCitySiteEvaluator::PlotFoundValue(pPlot, pPlayer, eYield);
		}
	}
}
예제 #12
0
void CvPlayerAI::ProcessGreatPeople(void)
{
	SpecialUnitTypes eSpecialUnitGreatPerson = (SpecialUnitTypes) GC.getInfoTypeForString("SPECIALUNIT_PEOPLE");

	CvAssert(isAlive());

	if(!isAlive())
		return;

	int iLoop;
	for(CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit; pLoopUnit = nextUnit(&iLoop))
	{
		if(pLoopUnit->getSpecialUnitType() != eSpecialUnitGreatPerson)
		{
			continue;
		}

		GreatPeopleDirectiveTypes eDirective = NO_GREAT_PEOPLE_DIRECTIVE_TYPE;
		switch(pLoopUnit->AI_getUnitAIType())
		{
		case UNITAI_WRITER:
			eDirective = GetDirectiveWriter(pLoopUnit);
			break;
		case UNITAI_ARTIST:
			eDirective = GetDirectiveArtist(pLoopUnit);
			break;
		case UNITAI_MUSICIAN:
			eDirective = GetDirectiveMusician(pLoopUnit);
			break;
		case UNITAI_ENGINEER:
			eDirective = GetDirectiveEngineer(pLoopUnit);
			break;
		case UNITAI_MERCHANT:
			eDirective = GetDirectiveMerchant(pLoopUnit);
			break;
		case UNITAI_SCIENTIST:
			eDirective = GetDirectiveScientist(pLoopUnit);
			break;
		case UNITAI_GENERAL:
			eDirective = GetDirectiveGeneral(pLoopUnit);
			break;
		case UNITAI_PROPHET:
			eDirective = GetDirectiveProphet(pLoopUnit);
			break;
		case UNITAI_ADMIRAL:
			eDirective = GetDirectiveAdmiral(pLoopUnit);
			break;
		}

		pLoopUnit->SetGreatPeopleDirective(eDirective);
	}
}
예제 #13
0
/// Delete the army
void CvArmyAI::Kill()
{
	CvAssert(GetOwner() != NO_PLAYER);
	CvAssertMsg(GetID() != -1, "GetID() is not expected to be equal with -1");

	ReleaseUnits();

	CvAIOperation* pOperation = GET_PLAYER(GetOwner()).getAIOperation(m_iOperationID);
	if (pOperation)
		pOperation->DeleteArmyAI(m_iID);

	GET_PLAYER(GetOwner()).deleteArmyAI(m_iID);
}
/// Value of plot for providing strategic value
int CvCitySiteEvaluator::ComputeStrategicValue(CvPlot* pPlot, const CvPlayer*, int iPlotsFromCity)
{
	int rtnValue = 0;

	CvAssert(pPlot);
	if(!pPlot) return rtnValue;

#if defined(MOD_BALANCE_CORE_SETTLER)
	if (MOD_BALANCE_CORE_SETTLER) 
	{
		//Some features and terrain types are useful strategically. (Or really bad)
		if(pPlot->getOwner() == NO_PLAYER)
		{
			if(iPlotsFromCity <= 3 && (pPlot->getFeatureType() == FEATURE_ICE))
			{
				rtnValue += /*-10*/ GC.getBALANCE_BAD_TILES_STRATEGIC_VALUE();
			}
			if(iPlotsFromCity <= 3 && pPlot->isFreshWater_cached())
			{
				rtnValue += /*2*/ GC.getBALANCE_FRESH_WATER_STRATEGIC_VALUE();
			}
			if(iPlotsFromCity <= 3 && pPlot->isCoastalLand())
			{
				rtnValue += /*2*/ GC.getBALANCE_COAST_STRATEGIC_VALUE();
			}
		}
	}
#endif

	// Hills in first ring are useful for defense and production
	if(iPlotsFromCity == 1 && pPlot->isHills())
	{
		rtnValue += /*3*/ GC.getHILL_STRATEGIC_VALUE();
	}

	// Some Features are less attractive to settle in, (e.g. Jungles, since it takes a while before you can clear them and they slow down movement)
	if(pPlot->getFeatureType() != NO_FEATURE)
	{
		int iWeight = GC.getFeatureInfo(pPlot->getFeatureType())->getStartingLocationWeight();
		if(iWeight != 0 && iPlotsFromCity == 1)
		{
			rtnValue += iWeight;
		}
	}

	rtnValue *= m_iFlavorMultiplier[SITE_EVALUATION_STRATEGIC];

	return rtnValue;
}
예제 #15
0
/// Compute unit supply for the turn (returns component info)
int CvTreasury::CalculateUnitSupply(int& iPaidUnits, int& iBaseSupplyCost)
{
	int iSupply;

	iPaidUnits = std::max(0, (m_pPlayer->getNumOutsideUnits() - /*3*/ GC.getINITIAL_FREE_OUTSIDE_UNITS()));

	// JON: This is set to 0 right now, which pretty much means it's disabled
	iBaseSupplyCost = iPaidUnits* /*0*/ GC.getINITIAL_OUTSIDE_UNIT_GOLD_PERCENT();
	iBaseSupplyCost /= 100;

	iSupply = iBaseSupplyCost;

	CvHandicapInfo& playerHandicap = m_pPlayer->getHandicapInfo();
	iSupply *= playerHandicap.getUnitCostPercent();
	iSupply /= 100;

	if(!m_pPlayer->isHuman() && !m_pPlayer->IsAITeammateOfHuman() && !m_pPlayer->isBarbarian())
	{
		//iSupply *= gameHandicap->getAIUnitSupplyPercent();	// This is no longer valid
		//iSupply /= 100;

		iSupply *= std::max(0, ((GC.getGame().getHandicapInfo().getAIPerEraModifier() * m_pPlayer->GetCurrentEra()) + 100));
		iSupply /= 100;
	}

	// Game progress factor ranges from 0.0 to 1.0 based on how far into the game we are
	double fGameProgressFactor = float(GC.getGame().getElapsedGameTurns()) / GC.getGame().getEstimateEndTurn();

	// Multiplicative increase - helps scale costs as game goes on - the HIGHER this number the more is paid
	double fMultiplyFactor = 1.0 + (fGameProgressFactor* /*8*/ GC.getUNIT_MAINTENANCE_GAME_MULTIPLIER());
	// Exponential increase - this one really punishes those with a HUGE military - the LOWER this number the more is paid
	double fExponentialFactor = 1.0 + (fGameProgressFactor / /*7*/ GC.getUNIT_MAINTENANCE_GAME_EXPONENT_DIVISOR());

	double fTempCost = fMultiplyFactor * iSupply;
	int iFinalCost = (int) pow(fTempCost, fExponentialFactor);

	// A mod at the player level? (Policies, etc.)
	if(m_pPlayer->GetUnitSupplyMod() != 0)
	{
		iFinalCost *= (100 + m_pPlayer->GetUnitSupplyMod());
		iFinalCost /= 100;
	}

	CvAssert(iFinalCost >= 0);

	return iFinalCost;
}
/// Value of plot for providing strategic value
int CvCitySiteEvaluator::ComputeStrategicValue(CvPlot* pPlot, CvPlayer* pPlayer, int iPlotsFromCity)
{
	int rtnValue = 0;

	CvAssert(pPlot);
	if(!pPlot) return rtnValue;

	// Possible chokepoint if impassable terrain and exactly 2 plots from city
	if(iPlotsFromCity == 2 && (pPlot->isImpassable() || pPlot->isMountain()))
	{
		rtnValue += /*5*/ GC.getCHOKEPOINT_STRATEGIC_VALUE();
	}

	// Hills in first ring are useful for defense and production
	if(iPlotsFromCity == 1 && pPlot->isHills())
	{
		rtnValue += /*3*/ GC.getHILL_STRATEGIC_VALUE();
	}

	// Some Features are less attractive to settle in, (e.g. Jungles, since it takes a while before you can clear them and they slow down movement)
	if(pPlot->getFeatureType() != NO_FEATURE)
	{
		int iWeight = GC.getFeatureInfo(pPlot->getFeatureType())->getStartingLocationWeight();
		if(iWeight != 0 && iPlotsFromCity == 1)
		{
			rtnValue += iWeight;
		}
	}

	// Nearby City
	if(pPlayer != NULL && pPlot->isCity())
	{
//		if (pPlot->getOwner() == pPlayer->getID())
		{
			rtnValue += /*-1000*/ GC.getALREADY_OWNED_STRATEGIC_VALUE();
		}
	}

	// POSSIBLE FUTURE: Is there any way for us to know to grab land between us and another major civ?

	rtnValue *= m_iFlavorMultiplier[SITE_EVALUATION_STRATEGIC];

	return rtnValue;
}
/// Value of plot for providing tradeable resources
int CvCitySiteEvaluator::ComputeTradeableResourceValue(CvPlot* pPlot, CvPlayer* pPlayer)
{
	int rtnValue = 0;

	CvAssert(pPlot);
	if(!pPlot) return rtnValue;

	// If we already own this Tile then we already have access to the Strategic Resource
	if(pPlot->isOwned())
	{
		return rtnValue;
	}

	TeamTypes eTeam = NO_TEAM;
	if(pPlayer != NULL)
	{
		eTeam = pPlayer->getTeam();
	}

	ResourceTypes eResource;
	eResource = pPlot->getResourceType(eTeam);

	if(eResource != NO_RESOURCE)
	{
		ResourceUsageTypes eResourceUsage = GC.getResourceInfo(eResource)->getResourceUsage();

		// Multiply number of tradeable resources by flavor value
		if(eResourceUsage == RESOURCEUSAGE_LUXURY || eResourceUsage == RESOURCEUSAGE_STRATEGIC)
		{
			rtnValue += pPlot->getNumResource() * m_iFlavorMultiplier[SITE_EVALUATION_RESOURCES];

			if(pPlayer)
			{
				// If we don't have this resource yet, increase it's value
				if(pPlayer->getNumResourceTotal(eResource) == 0)
					rtnValue *= 3;
			}
		}
	}

	return rtnValue;
}
예제 #18
0
/// Compute inflation for this part of the game
int CvTreasury::CalculateInflationRate()
{
	CvGame& kGame = GC.getGame();

	CvHandicapInfo& playerHandicap = m_pPlayer->getHandicapInfo();
	CvHandicapInfo& gameHandicap = kGame.getHandicapInfo();
	CvGameSpeedInfo& gameSpeedInfo = kGame.getGameSpeedInfo();

	int iTurns = ((kGame.getGameTurn() + kGame.getElapsedGameTurns()) / 2);
	iTurns += gameSpeedInfo.getInflationOffset();

	if(iTurns <= 0)
	{
		return 0;
	}

	int iInflationPerTurnTimes10000 = gameSpeedInfo.getInflationPercent();
	iInflationPerTurnTimes10000 *= playerHandicap.getInflationPercent();
	iInflationPerTurnTimes10000 /= 100;

	int iModifier = 0;

	if(!m_pPlayer->isHuman() && !m_pPlayer->isBarbarian())
	{
		int iAIModifier = gameHandicap.getAIInflationPercent();
		iAIModifier *= std::max(0, ((gameHandicap.getAIPerEraModifier() * m_pPlayer->GetCurrentEra()) + 100));
		iAIModifier /= 100;

		iModifier += iAIModifier - 100;
	}

	iInflationPerTurnTimes10000 *= std::max(0, 100 + iModifier);
	iInflationPerTurnTimes10000 /= 100;

	// Keep up to second order terms in binomial series
	int iRatePercent = (iTurns * iInflationPerTurnTimes10000) / 100;
	iRatePercent += (iTurns * (iTurns - 1) * iInflationPerTurnTimes10000 * iInflationPerTurnTimes10000) / 2000000;

	CvAssert(iRatePercent >= 0);

	return iRatePercent;
}
/// Delete the army
void CvArmyAI::Kill()
{
	CvAssert(GetOwner() != NO_PLAYER);
	CvAssertMsg(GetID() != FFreeList::INVALID_INDEX, "GetID() is not expected to be equal with FFreeList::INVALID_INDEX");

	int iUnitID;
	iUnitID = GetFirstUnitID();

	while(iUnitID != ARMY_NO_UNIT)
	{
		UnitHandle pThisUnit = GET_PLAYER(GetOwner()).getUnit(iUnitID);
		if(pThisUnit)
		{
			pThisUnit->setArmyID(FFreeList::INVALID_INDEX);
		}
		iUnitID = GetNextUnitID();
	}

	m_FormationEntries.clear();
}
예제 #20
0
bool CvPlayerAI::AI_captureUnit(UnitTypes, CvPlot* pPlot)
{
	CvCity* pNearestCity;

	CvAssert(!isHuman());

	// Barbs always capture
	if (isBarbarian())
		return true;

	// we own it
	if (pPlot->getTeam() == getTeam())
		return true;

	// no man's land - may as well
	if (pPlot->getTeam() == NO_TEAM)
		return true;

	// friendly, sure (okay, this is pretty much just means open borders)
	if (pPlot->IsFriendlyTerritory(GetID()))
		return true;

	// not friendly, but "near" us
	pNearestCity = GC.getMap().findCity(pPlot->getX(), pPlot->getY(), NO_PLAYER, getTeam());
	if (pNearestCity != NULL)
	{
		if (plotDistance(pPlot->getX(), pPlot->getY(), pNearestCity->getX(), pNearestCity->getY()) <= 7)
			return true;
	}

	// very near someone we aren't friends with (and far from our nearest city)
	pNearestCity = GC.getMap().findCity(pPlot->getX(), pPlot->getY());
	if (pNearestCity != NULL)
	{
		if (plotDistance(pPlot->getX(), pPlot->getY(), pNearestCity->getX(), pNearestCity->getY()) <= 4)
			return false;
	}

	// I'd rather we grab it and run than destroy it
	return true;
}
예제 #21
0
/// Recommend highest-weighted Project
ProjectTypes CvProjectProductionAI::RecommendProject()
{
	CvAssert(m_pCity);
	if(!m_pCity)
		return NO_PROJECT;

	int iProjectLoop;
	int iWeight;
	int iTurnsLeft;

	// Reset list of all the possible projects
	m_Buildables.clear();

	// Loop through adding the available projects
	for(iProjectLoop = 0; iProjectLoop < GC.GetGameProjects()->GetNumProjects(); iProjectLoop++)
	{
		// Make sure this project can be built now
		if(m_pCity->canCreate((ProjectTypes)iProjectLoop))
		{
			// Update weight based on turns to construct
			iTurnsLeft = m_pCity->getProductionTurnsLeft((ProjectTypes) iProjectLoop, 0);
			iWeight = CityStrategyAIHelpers::ReweightByTurnsLeft(m_ProjectAIWeights.GetWeight((ProjectTypes)iProjectLoop), iTurnsLeft);
			m_Buildables.push_back(iProjectLoop, iWeight);
		}
	}

	// Sort items and grab the first one
	if(m_Buildables.size() > 0)
	{
		m_Buildables.SortItems();
		LogPossibleBuilds();
		return (ProjectTypes)m_Buildables.GetElement(0);
	}

	// Unless we didn't find any
	else
	{
		return NO_PROJECT;
	}
}
/// Vale of plot for providing faith
int CvCitySiteEvaluator::ComputeFaithValue(CvPlot* pPlot, CvPlayer* pPlayer)
{
	int rtnValue = 0;

	CvAssert(pPlot);
	if(!pPlot) return rtnValue;

	// From tile yield
	if(pPlayer == NULL)
	{
		rtnValue += pPlot->calculateNatureYield(YIELD_FAITH, NO_TEAM);
	}
	else
	{
		rtnValue += pPlot->calculateNatureYield(YIELD_FAITH, pPlayer->getTeam());
	}

	// From resource
	TeamTypes eTeam = NO_TEAM;
	if(pPlayer != NULL)
	{
		eTeam = pPlayer->getTeam();
	}

	ResourceTypes eResource;
	eResource = pPlot->getResourceType(eTeam);
	if(eResource != NO_RESOURCE)
	{
		rtnValue += GC.getResourceInfo(eResource)->getYieldChange(YIELD_FAITH);

		CvImprovementEntry* pImprovement = GC.GetGameImprovements()->GetImprovementForResource(eResource);
		if(pImprovement)
		{
			rtnValue += pImprovement->GetImprovementResourceYield(eResource, YIELD_FAITH);
		}
	}

	return rtnValue * m_iFlavorMultiplier[YIELD_FAITH];
}
/// Vale of plot for providing faith
int CvCitySiteEvaluator::ComputeFaithValue(CvPlot* pPlot, const CvPlayer* pPlayer)
{
	int rtnValue = 0;

	CvAssert(pPlot);
	if(!pPlot) return rtnValue;

	// From tile yield
	if(pPlayer == NULL)
	{
		rtnValue += pPlot->calculateNatureYield(YIELD_FAITH, NO_PLAYER);
	}
	else
	{
		rtnValue += pPlot->calculateNatureYield(YIELD_FAITH, pPlayer->GetID());
	}

	// From resource
	TeamTypes eTeam = NO_TEAM;
	if(pPlayer != NULL)
	{
		eTeam = pPlayer->getTeam();
	}

	ResourceTypes eResource;
	eResource = pPlot->getResourceType(eTeam);
	if(eResource != NO_RESOURCE)
	{
		//can we build an improvement on this resource? assume we will do it (natural yield is already considered)

		CvImprovementEntry* pImprovement = GC.GetGameImprovements()->GetImprovementForResource(eResource);
		if(pImprovement)
		{
			rtnValue += pImprovement->GetImprovementResourceYield(eResource, YIELD_FAITH);
		}
	}

	return rtnValue * m_iFlavorMultiplier[YIELD_FAITH];
}
예제 #24
0
bool CvPlayerAI::AI_captureUnit(UnitTypes, CvPlot* pPlot)
{
	CvCity* pNearestCity;

	CvAssert(!isHuman());

	// Barbs always capture
	if (isBarbarian())
		return true;

	if (pPlot->getTeam() == getTeam())
		return true;

	pNearestCity = GC.getMap().findCity(pPlot->getX(), pPlot->getY(), NO_PLAYER, getTeam());

	if (pNearestCity != NULL)
	{
		if (plotDistance(pPlot->getX(), pPlot->getY(), pNearestCity->getX(), pNearestCity->getY()) <= 4)
			return true;
	}

	return false;
}
예제 #25
0
//	---------------------------------------------------------------------------
bool CvUnitMovement::CostsOnlyOne(const CvUnit* pUnit, const CvPlot* pFromPlot, const CvPlot* pToPlot)
{
	if(!pToPlot->isValidDomainForAction(*pUnit))
	{
		// If we are a land unit that can embark, then do further tests.
		if(pUnit->getDomainType() != DOMAIN_LAND || pUnit->IsHoveringUnit() || pUnit->canMoveAllTerrain() || !pUnit->CanEverEmbark())
			return true;
	}

	CvAssert(!pUnit->IsImmobile());

	if(pUnit->flatMovementCost() || pUnit->getDomainType() == DOMAIN_AIR)
	{
		return true;
	}

	// Is the unit from a civ that can disembark for just 1 MP?
	if(!pToPlot->isWater() && pFromPlot->isWater() && pUnit->isEmbarked() && GET_PLAYER(pUnit->getOwner()).GetPlayerTraits()->IsEmbarkedToLandFlatCost())
	{
		return true;
	}

	return false;
}
int CvProcessProductionAI::CheckProcessBuildSanity(ProcessTypes eProcess, int iTempWeight, int iNumBuildables, int iGPT)
{
	CvProcessInfo* pProcess = GC.getProcessInfo(eProcess);
	if(!pProcess)
	{
		return 0;
	}

	if(iTempWeight == 0)
		return 0;

	if(iNumBuildables > 0)
	{
		if(iTempWeight > 300)
		{
			iTempWeight = 300;
		}
	}
	else
	{
		if(iTempWeight > 400)
		{
			iTempWeight = 400;
		}
	}

	CvPlayerAI& kPlayer = GET_PLAYER(m_pCity->getOwner());

	int iModifier = 0;

	//Bonus % additive. All values below will be added to this and combined with real value at end.
	int iBonus = 0;

	//////
	//WAR
	///////
	//Fewer processes while at war.
	int iNumWar = kPlayer.GetMilitaryAI()->GetNumberCivsAtWarWith(false);
	if(iNumWar > 0)
	{
		iBonus -= (iNumWar * 50);
		if(kPlayer.getNumCities() > 1 && m_pCity->GetThreatCriteria() != -1)
		{
			//More cities = more threat.
			int iThreat = (kPlayer.getNumCities() - m_pCity->GetThreatCriteria()) * 25;
			if(iThreat > 0)
			{
				iBonus -= iThreat;
			}
		}
		if(m_pCity->IsBastion())
		{
			iBonus -= 100;
		}
		if(m_pCity->IsBlockaded(true))
		{
			iBonus -= 100;
		}
		if(m_pCity->IsBlockadedWaterAndLand())
		{
			iBonus -= 100;
		}
	}
	//Tiny army? Eek!
	if(kPlayer.getNumMilitaryUnits() <= (kPlayer.getNumCities() * 2))
	{
		iBonus -= 100;
	}

	MilitaryAIStrategyTypes eBuildCriticalDefenses = (MilitaryAIStrategyTypes) GC.getInfoTypeForString("MILITARYAISTRATEGY_LOSING_WARS");
	// scale based on flavor and world size
	if(eBuildCriticalDefenses != NO_MILITARYAISTRATEGY && kPlayer.GetMilitaryAI()->IsUsingStrategy(eBuildCriticalDefenses))
	{
		iModifier -= 50;
	}
	EconomicAIStrategyTypes eStrategyLosingMoney = (EconomicAIStrategyTypes) GC.getInfoTypeForString("ECONOMICAISTRATEGY_LOSING_MONEY");
	EconomicAIStrategyTypes eStrategyCultureGS = (EconomicAIStrategyTypes) GC.getInfoTypeForString("ECONOMICAISTRATEGY_GS_CULTURE");
	AICityStrategyTypes eNeedFood = (AICityStrategyTypes) GC.getInfoTypeForString("AICITYSTRATEGY_NEED_IMPROVEMENT_FOOD");
	AICityStrategyTypes eNeedFoodNaval = (AICityStrategyTypes) GC.getInfoTypeForString("AICITYSTRATEGY_NEED_NAVAL_GROWTH");
	EconomicAIStrategyTypes eGrowCrazy = (EconomicAIStrategyTypes) GC.getInfoTypeForString("ECONOMICAISTRATEGY_GROW_LIKE_CRAZY");
	AICityStrategyTypes eScienceCap = (AICityStrategyTypes) GC.getInfoTypeForString("AICITYSTRATEGY_KEY_SCIENCE_CITY");

	//Yield value.
	
	//Base value of production.
	iModifier += (m_pCity->getYieldRate(YIELD_PRODUCTION, false) / 5);
	for(int iYield = 0; iYield < NUM_YIELD_TYPES; iYield++)
	{
		YieldTypes eYield = (YieldTypes)iYield;
		if(eYield == NO_YIELD)
			continue;

		if(m_pCity->GetCityStrategyAI()->GetMostDeficientYield() == eYield)
		{
			iModifier += 50;
		}
		if(pProcess->getProductionToYieldModifier(eYield) > 0)
		{
			switch(eYield)
			{
				case YIELD_GOLD:
				{
					if(MOD_BALANCE_CORE_HAPPINESS)
					{
						if(m_pCity->getUnhappinessFromGold() > 0)
						{
							iModifier += (m_pCity->getUnhappinessFromGold() * 2);
						}
					}
					if(eStrategyLosingMoney != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eStrategyLosingMoney))
					{
						iModifier += 25;
					}
				}
				break;
				case YIELD_CULTURE:
				{
					if(MOD_BALANCE_CORE_HAPPINESS)
					{
						if(m_pCity->getUnhappinessFromCulture() > 0)
						{
							iModifier += (m_pCity->getUnhappinessFromCulture() * 2);
						}
					}
					if(eStrategyCultureGS != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eStrategyCultureGS))
					{
						iModifier += 25;
					}
				}
				break;
				case YIELD_SCIENCE:
				{
					if(MOD_BALANCE_CORE_HAPPINESS)
					{
						if(m_pCity->getUnhappinessFromScience() > 0)
						{
							iModifier += (m_pCity->getUnhappinessFromScience() * 2);
						}
					}
					if(eScienceCap != NO_AICITYSTRATEGY && m_pCity->GetCityStrategyAI()->IsUsingCityStrategy(eScienceCap))
					{
						iModifier += 25;
					}
				}
				break;
				case YIELD_FOOD:
				{
					if(m_pCity->GetCityCitizens()->IsForcedAvoidGrowth())
						return 0;

					int iExcessFoodTimes100 = m_pCity->getYieldRateTimes100(YIELD_FOOD, false) - (m_pCity->foodConsumption() * 100);
					if (iExcessFoodTimes100 < 0)
					{
						iModifier += 25;
					}
					if(MOD_BALANCE_CORE_HAPPINESS)
					{
						if(m_pCity->getUnhappinessFromStarving() > 0)
						{
							iModifier += (m_pCity->getUnhappinessFromStarving() * 5);
						}
					}
					if(eGrowCrazy != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eGrowCrazy))
					{
						iModifier += 15;
					}
					if(eNeedFood != NO_AICITYSTRATEGY && m_pCity->GetCityStrategyAI()->IsUsingCityStrategy(eNeedFood))
					{
						iModifier += 15;
					}
					if(eNeedFoodNaval != NO_AICITYSTRATEGY && m_pCity->GetCityStrategyAI()->IsUsingCityStrategy(eNeedFoodNaval))
					{
						iModifier += 10;
					}
				}
				break;
			}
		}
	}
	for(int iI = 0; iI < GC.getNumLeagueProjectInfos(); iI++)
	{
		LeagueProjectTypes eLeagueProject = (LeagueProjectTypes) iI;
		CvLeagueProjectEntry* pInfo = GC.getLeagueProjectInfo(eLeagueProject);
		if (pInfo && pInfo->GetProcess() == eProcess)
		{
			if (GC.getGame().GetGameLeagues()->CanContributeToLeagueProject(m_pCity->getOwner(), eLeagueProject))
			{
				FStaticVector<LeagueProjectRewardTypes, 4, true, c_eCiv5GameplayDLL> veRewards;
				veRewards.push_back(pInfo->GetRewardTier3());
				veRewards.push_back(pInfo->GetRewardTier2());
				veRewards.push_back(pInfo->GetRewardTier1());
			
				for (uint i = 0; i < veRewards.size(); i++)
				{
					CvLeagueProjectRewardEntry* pRewardInfo = GC.getLeagueProjectRewardInfo(veRewards[i]);
					CvAssert(pRewardInfo);
					if (!pRewardInfo) continue;

					// Free Building in Capital
					if (pRewardInfo->GetBuilding() != NO_BUILDING)
					{
						CvBuildingEntry* pBuildingInfo = GC.getBuildingInfo(pRewardInfo->GetBuilding());
						if(pBuildingInfo)
						{
							int iValue = 1000;
							if(kPlayer.getCapitalCity() != NULL)
							{
								iValue = kPlayer.getCapitalCity()->GetCityStrategyAI()->GetBuildingProductionAI()->CheckBuildingBuildSanity(pRewardInfo->GetBuilding(), iValue, 5, 5, 1);
								iModifier += iValue;
							}
							else
							{
								iModifier += m_pCity->GetCityStrategyAI()->GetBuildingProductionAI()->GetWeight(pRewardInfo->GetBuilding());
							}
						}
					}

					// Happiness
					if (pRewardInfo->GetHappiness() != 0)
					{
						iModifier += pRewardInfo->GetHappiness() * (50 - kPlayer.GetHappiness());
					}

					// Free Social Policy
					if (pRewardInfo->GetFreeSocialPolicies() > 0)
					{
						iModifier += (kPlayer.GetPlayerPolicies()->GetNumPoliciesOwned() * 20);
					}

					EconomicAIStrategyTypes eStrategyCultureGS = (EconomicAIStrategyTypes) GC.getInfoTypeForString("ECONOMICAISTRATEGY_GS_CULTURE");
					// Temporary Culture Modifier
					if (pRewardInfo->GetCultureBonusTurns() > 0)
					{			
						if(eStrategyCultureGS != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eStrategyCultureGS))
						{
							iModifier += 250;
						}
					}

					// Temporary Tourism Modifier
					if (pRewardInfo->GetTourismBonusTurns() > 0)
					{
						if(eStrategyCultureGS != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eStrategyCultureGS))
						{
							iModifier += 250;
						}
					}

					// Golden Age Points
					if (pRewardInfo->GetGoldenAgePoints() > 0)
					{
						if(kPlayer.GetPlayerTraits()->GetGoldenAgeDurationModifier() > 0)
						{
							iModifier += (pRewardInfo->GetGoldenAgePoints() + kPlayer.GetPlayerTraits()->GetGoldenAgeDurationModifier()) * 5;
						}
						else
						{
							iModifier += (pRewardInfo->GetGoldenAgePoints() + kPlayer.getGoldenAgeModifier()) * 5;
						}
					}

					// City-State Influence Boost
					//antonjs: todo: ordering, to prevent ally / no longer ally notif spam
					EconomicAIStrategyTypes eStrategyUNGS = (EconomicAIStrategyTypes) GC.getInfoTypeForString("ECONOMICAISTRATEGY_GS_DIPLOMACY");
					if (pRewardInfo->GetCityStateInfluenceBoost() > 0)
					{		
						if(eStrategyUNGS != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eStrategyUNGS))
						{
							iModifier += 250;
						}
					}
					EconomicAIStrategyTypes eStrategySpaceShip = (EconomicAIStrategyTypes) GC.getInfoTypeForString("ECONOMICAISTRATEGY_GS_SPACESHIP");
					// Beaker boost based on previous turns
					if (pRewardInfo->GetBaseBeakersTurnsToCount() > 0)
					{
						if(eStrategySpaceShip != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eStrategySpaceShip))
						{
							iModifier += 250;
						}
					}
					
					// Free unit class
					if (pRewardInfo->GetFreeUnitClass() != NO_UNITCLASS)
					{
						UnitTypes eUnit = (UnitTypes) kPlayer.getCivilizationInfo().getCivilizationUnits(pRewardInfo->GetFreeUnitClass());
						if (eUnit != NO_UNIT)
						{
							CvUnitEntry* pkUnitInfo = GC.getUnitInfo(eUnit);
							if(pkUnitInfo)
							{
								int iValue = 500;
								if(kPlayer.getCapitalCity() != NULL)
								{
									iValue = kPlayer.getCapitalCity()->GetCityStrategyAI()->GetUnitProductionAI()->CheckUnitBuildSanity(eUnit, false, NULL, iValue, 1);
								}
								iModifier += iValue;
							}
						}
					}
					EconomicAIStrategyTypes eStrategyConquest = (EconomicAIStrategyTypes) GC.getInfoTypeForString("ECONOMICAISTRATEGY_GS_CONQUEST");
		
#if defined(MOD_DIPLOMACY_CITYSTATES_RESOLUTIONS)
					if (MOD_DIPLOMACY_CITYSTATES_RESOLUTIONS) 
					{
						//CSD Project Rewards
						if (pRewardInfo->GetAttackBonusTurns() > 0)
						{
							if(eStrategyConquest != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eStrategyConquest))
							{
								iModifier += 150;
							}
						}
						if (pRewardInfo->GetBaseFreeUnits() > 0)
						{
							if(eStrategyConquest != NO_ECONOMICAISTRATEGY && kPlayer.GetEconomicAI()->IsUsingStrategy(eStrategyConquest))
							{
								iModifier += 150;
							}
						}
						// Temporary Culture Modifier
						if (pRewardInfo->GetNumFreeGreatPeople() > 0)
						{
							iModifier += 250;
						}
					}
#endif
				}
			}
		}
	}
	if(iGPT <= 0)
	{
		iModifier += (iGPT *= -2);
	}

	if(m_pCity->IsPuppet())
	{
		iTempWeight *= (60 + iModifier);
		iTempWeight /= 100;
	}
	else
	{
		iTempWeight *= (100 + iModifier);
		iTempWeight /= 100;
	}

	return iTempWeight;
}
/// 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;
}
/// Retrieve the relative value of this plot (including plots that would be in city radius)
int CvCitySiteEvaluator::PlotFoundValue(CvPlot* pPlot, CvPlayer* pPlayer, YieldTypes eYield, bool)
{
	CvAssert(pPlot);
	if(!pPlot)
		return 0;

	// Make sure this player can even build a city here
	if(!CanFound(pPlot, pPlayer, false))
	{
		return 0;
	}

	int rtnValue = 0;

	int iFoodValue = 0;
	int iHappinessValue = 0;
	int iProductionValue = 0;
	int iGoldValue = 0;
	int iScienceValue = 0;
	int iFaithValue = 0;
	int iResourceValue = 0;
	int iStrategicValue = 0;

	int iCelticForestCount = 0;
	int iIroquoisForestCount = 0;
	int iBrazilJungleCount = 0;
	int iNaturalWonderCount = 0;
	int iDesertCount = 0;
	int iWetlandsCount = 0;
#if defined(MOD_BALANCE_CORE_SETTLER)
	int iWaterPlot = 0;
	int iBadPlot = 0;
	int iLoopPlots = 0;
#endif

	int iTotalFoodValue = 0;
	int iTotalHappinessValue = 0;
	int iTotalProductionValue = 0;
	int iTotalGoldValue = 0;
	int iTotalScienceValue = 0;
	int iTotalFaithValue = 0;
	int iTotalResourceValue = 0;
	int iTotalStrategicValue = 0;

	int iClosestCityOfMine = 999;
	int iClosestEnemyCity = 999;

	int iCapitalArea = NULL;

	bool bIsInca = false;
	int iAdjacentMountains = 0;

	if ( pPlayer->getCapitalCity() )
		iCapitalArea = pPlayer->getCapitalCity()->getArea();

	// Custom code for Inca ideal terrace farm locations
	ImprovementTypes eIncaImprovement = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_TERRACE_FARM", true);  
	if(eIncaImprovement != NO_IMPROVEMENT)
	{
		CvImprovementEntry* pkEntry = GC.getImprovementInfo(eIncaImprovement);
		if(pkEntry != NULL && pkEntry->IsSpecificCivRequired())
		{
			CivilizationTypes eCiv = pkEntry->GetRequiredCivilization();
			if(eCiv == pPlayer->getCivilizationType())
			{
				bIsInca = true;
			}
		}
	}

	for (int iDX = -7; iDX <= 7; iDX++)
	{
		for (int iDY = -7; iDY <= 7; iDY++)
		{
			CvPlot* pLoopPlot = plotXY(pPlot->getX(), pPlot->getY(), iDX, iDY);

			if (pLoopPlot != NULL)
			{
				int iDistance = plotDistance(pPlot->getX(), pPlot->getY(), pLoopPlot->getX(), pLoopPlot->getY());
				if (iDistance <= 7)
				{
					if ((pLoopPlot->getOwner() == NO_PLAYER) || (pLoopPlot->getOwner() == pPlayer->GetID()))
					{
						// See if there are other cities nearby
						if (iClosestCityOfMine > iDistance)
						{
							if (pLoopPlot->isCity())
							{
								iClosestCityOfMine = iDistance;
							}
						}

						// Skip the city plot itself for now
						if (iDistance <= 5)
						{
							int iRingModifier = m_iRingModifier[iDistance];

							iFoodValue = 0;
							iProductionValue = 0;
							iGoldValue = 0;
							iScienceValue = 0;
							iHappinessValue = 0;
							iResourceValue = 0;
							iStrategicValue = 0;

#if defined(MOD_GLOBAL_CITY_WORKING)
							if (iDistance > 0 && iDistance <= pPlayer->getWorkPlotDistance())
#else	
							if (iDistance > 0 && iDistance <= NUM_CITY_RINGS)
#endif
							{
								if (eYield == NO_YIELD || eYield == YIELD_FOOD)
								{
									iFoodValue = iRingModifier * ComputeFoodValue(pLoopPlot, pPlayer) * /*15*/ GC.getSETTLER_FOOD_MULTIPLIER();
								}
								if (eYield == NO_YIELD || eYield == YIELD_PRODUCTION)
								{
									iProductionValue = iRingModifier * ComputeProductionValue(pLoopPlot, pPlayer) * /*3*/ GC.getSETTLER_PRODUCTION_MULTIPLIER();
								}
								if (eYield == NO_YIELD || eYield == YIELD_GOLD)
								{
									iGoldValue = iRingModifier * ComputeGoldValue(pLoopPlot, pPlayer) * /*2*/ GC.getSETTLER_GOLD_MULTIPLIER();
								}
								if (eYield == NO_YIELD || eYield == YIELD_SCIENCE)
								{
									iScienceValue = iRingModifier * ComputeScienceValue(pLoopPlot, pPlayer) * /*1*/ GC.getSETTLER_SCIENCE_MULTIPLIER();
								}
								if (eYield == NO_YIELD || eYield == YIELD_FAITH)
								{
									iFaithValue = iRingModifier * ComputeFaithValue(pLoopPlot, pPlayer) * /*1*/ GC.getSETTLER_FAITH_MULTIPLIER();
								}
							}

							// whether or not we are working these we get the benefit as long as culture can grow to take them
							if (iDistance <= 5 && pLoopPlot->getOwner() == NO_PLAYER) // there is no benefit if we already own these tiles
							{
								iHappinessValue = iRingModifier * ComputeHappinessValue(pLoopPlot, pPlayer) * /*6*/ GC.getSETTLER_HAPPINESS_MULTIPLIER();
								iResourceValue = iRingModifier * ComputeTradeableResourceValue(pLoopPlot, pPlayer) * /*1*/ GC.getSETTLER_RESOURCE_MULTIPLIER();
								if (iDistance)
									iStrategicValue = ComputeStrategicValue(pLoopPlot, pPlayer, iDistance) * /*1*/ GC.getSETTLER_STRATEGIC_MULTIPLIER();  // the ring is included in the computation
							}

							iTotalFoodValue += iFoodValue;
							iTotalHappinessValue += iHappinessValue;
							iTotalProductionValue += iProductionValue;
							iTotalGoldValue += iGoldValue;
							iTotalScienceValue += iScienceValue;
							iTotalFaithValue += iFaithValue;
							iTotalResourceValue += iResourceValue;
							iTotalStrategicValue += iStrategicValue;

							int iPlotValue = iFoodValue + iHappinessValue + iProductionValue + iGoldValue + iScienceValue + iFaithValue + iResourceValue;
							
							if (iPlotValue == 0)
							{
								// this tile is so bad it gets negatives
								iPlotValue -= iRingModifier * GC.getSETTLER_FOOD_MULTIPLIER() * 2;
							}
							iPlotValue += iStrategicValue;

							// if this tile is a NW boost the value just so that we force the AI to claim them (if we can work it)
#if defined(MOD_GLOBAL_CITY_WORKING)
							if (pLoopPlot->IsNaturalWonder() && iDistance > 0 && iDistance <= pPlayer->getWorkPlotDistance())
#else	
							if (pLoopPlot->IsNaturalWonder() && iDistance > 0 && iDistance <= NUM_CITY_RINGS)
#endif
							{
								//iPlotValue += iPlotValue * 2 + 10;
								iPlotValue += iPlotValue * 2 + 500;
							}

							// lower value a lot if we already own this tile
							if (iPlotValue > 0 && pLoopPlot->getOwner() == pPlayer->GetID())
							{
#if defined(MOD_BALANCE_CORE_SETTLER)
								if (MOD_BALANCE_CORE_SETTLER) 
								{
									iPlotValue *= 2;
									iPlotValue /= 3;
								}
#else
								iPlotValue /= 4;
#endif
							}

							// add this plot into the total
							rtnValue += iPlotValue;

							FeatureTypes ePlotFeature = pLoopPlot->getFeatureType();
							ImprovementTypes ePlotImprovement = pLoopPlot->getImprovementType();
							ResourceTypes ePlotResource = pLoopPlot->getResourceType();

							if (ePlotFeature == FEATURE_FOREST)
							{
								if (iDistance <= 5)
								{
									++iIroquoisForestCount;
									if (iDistance == 1)
									{
										if (ePlotImprovement == NO_IMPROVEMENT)
										{
											++iCelticForestCount;
										}
									}
								}
							}
							else if (ePlotFeature == FEATURE_JUNGLE)
							{
#if defined(MOD_GLOBAL_CITY_WORKING)
								if (iDistance <= pPlayer->getWorkPlotDistance())
#else	
								if (iDistance <= NUM_CITY_RINGS)
#endif
								{
									++iBrazilJungleCount;
								}
							}
							else if (ePlotFeature == FEATURE_MARSH || ePlotFeature == FEATURE_FLOOD_PLAINS)
							{
#if defined(MOD_GLOBAL_CITY_WORKING)
								if (iDistance <= pPlayer->getWorkPlotDistance())
#else	
								if (iDistance <= NUM_CITY_RINGS)
#endif
								{
									++iWetlandsCount;
								}
							}

							if (pLoopPlot->IsNaturalWonder())
							{
								if (iDistance <= 1)
								{
									++iNaturalWonderCount;
								}
							}

							if (pLoopPlot->getTerrainType() == TERRAIN_DESERT)
							{
#if defined(MOD_GLOBAL_CITY_WORKING)
								if (iDistance <= pPlayer->getWorkPlotDistance())
#else	
								if (iDistance <= NUM_CITY_RINGS)
#endif
								{
									if (ePlotResource == NO_RESOURCE)
									{
										++iDesertCount;
									}
								}
							}

							if (bIsInca)
							{
								if (pLoopPlot->isHills())
								{
#if defined(MOD_GLOBAL_CITY_WORKING)
								if (iDistance <= pPlayer->getWorkPlotDistance())
#else	
								if (iDistance <= NUM_CITY_RINGS)
#endif
									{
										iAdjacentMountains = pLoopPlot->GetNumAdjacentMountains();
										if (iAdjacentMountains > 0 && iAdjacentMountains < 6)
										{
											//give the bonus if it's hills, with additional if bordered by mountains
											rtnValue += m_iIncaMultiplier + (iAdjacentMountains * m_iIncaMultiplier);
										}
									}
									
								}
							}
#if defined(MOD_BALANCE_CORE_SETTLER)
							if (MOD_BALANCE_CORE_SETTLER) 
							{
								if(pLoopPlot->isWater() && pLoopPlot->HasResource(NO_RESOURCE))
								{
									iWaterPlot++;
								}
								if(pLoopPlot == NULL || pLoopPlot->isImpassable() || pLoopPlot->getTerrainType() == TERRAIN_SNOW || pLoopPlot->getFeatureType() == FEATURE_ICE)
								{
									iBadPlot++;
								}
							}
#endif	
						}
					}
					else // this tile is owned by someone else
					{
						// See if there are other cities nearby (only count major civs)
						if (iClosestEnemyCity > iDistance)
						{
							if (pLoopPlot->isCity() && (pLoopPlot->getOwner() < MAX_MAJOR_CIVS))
							{
								iClosestEnemyCity = iDistance;
							}
						}
					}
				}
			}
#if defined(MOD_BALANCE_CORE_SETTLER)
			if (MOD_BALANCE_CORE_SETTLER) 
			{
				iLoopPlots++;
			}
#endif
		}
	}

	if (pPlayer->GetPlayerTraits()->IsFaithFromUnimprovedForest())
	{
		if (iCelticForestCount >= 3)
		{
			rtnValue += 2 * 1000 * m_iFlavorMultiplier[YIELD_FAITH];
		}
		else if (iCelticForestCount >= 1)
		{
			rtnValue += 1 * 1000 * m_iFlavorMultiplier[YIELD_FAITH];
		}
	}
	else if (pPlayer->GetPlayerTraits()->IsMoveFriendlyWoodsAsRoad())
	{
		rtnValue += iIroquoisForestCount * 10;	
	}
	else if (pPlayer->GetPlayerTraits()->GetNaturalWonderYieldModifier() > 0)	//ie: Spain
	{
		rtnValue += iNaturalWonderCount * m_iSpainMultiplier;	
	}

	// Custom code for Brazil
	ImprovementTypes eBrazilImprovement = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_BRAZILWOOD_CAMP", true);  
	if(eBrazilImprovement != NO_IMPROVEMENT)
	{
		CvImprovementEntry* pkEntry = GC.getImprovementInfo(eBrazilImprovement);
		if(pkEntry != NULL && pkEntry->IsSpecificCivRequired())
		{
			CivilizationTypes eCiv = pkEntry->GetRequiredCivilization();
			if(eCiv == pPlayer->getCivilizationType())
			{
				rtnValue += iBrazilJungleCount * m_iBrazilMultiplier;
			}
		}
	}

	// Custom code for Morocco
	ImprovementTypes eMoroccoImprovement = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_KASBAH", true);  
	if(eMoroccoImprovement != NO_IMPROVEMENT)
	{
		CvImprovementEntry* pkEntry = GC.getImprovementInfo(eMoroccoImprovement);
		if(pkEntry != NULL && pkEntry->IsSpecificCivRequired())
		{
			CivilizationTypes eCiv = pkEntry->GetRequiredCivilization();
			if(eCiv == pPlayer->getCivilizationType())
			{
				rtnValue += iDesertCount * m_iMorrocoMultiplier;
			}
		}
	}

	//Custom code for Netherlands
	ImprovementTypes ePolderImprovement = (ImprovementTypes)GC.getInfoTypeForString("IMPROVEMENT_POLDER", true);  
	if(ePolderImprovement != NO_IMPROVEMENT)
	{
		CvImprovementEntry* pkEntry = GC.getImprovementInfo(ePolderImprovement);
		if(pkEntry != NULL && pkEntry->IsSpecificCivRequired())
		{
			CivilizationTypes eCiv = pkEntry->GetRequiredCivilization();
			if(eCiv == pPlayer->getCivilizationType())
			{
				rtnValue += iWetlandsCount * m_iNetherlandsMultiplier;
			}
		}
	}

	if (rtnValue < 0) rtnValue = 0;

	// Finally, look at the city plot itself and use it as an overall multiplier
	if (pPlot->getResourceType(pPlayer->getTeam()) != NO_RESOURCE)
	{
		rtnValue += (int)rtnValue * /*-50*/ GC.getBUILD_ON_RESOURCE_PERCENT() / 100;
	}

	if (pPlot->isRiver())
	{
		rtnValue += (int)rtnValue * /*15*/ GC.getBUILD_ON_RIVER_PERCENT() / 100;
	}

	if (pPlot->isCoastalLand(GC.getMIN_WATER_SIZE_FOR_OCEAN()))
	{
		// okay, coast used to have lots of gold so players settled there "naturally", it doesn't any more, so I am going to give it a nudge in that direction
		// slewis - removed Brian(?)'s rtnValue adjustment and raised the BUILD_ON_COAST_PERCENT to 40 from 25
		//rtnValue += rtnValue > 0 ? 10 : 0;
		rtnValue += (int)rtnValue * /*40*/ GC.getSETTLER_BUILD_ON_COAST_PERCENT() / 100;
		int iNavalFlavor = pPlayer->GetGrandStrategyAI()->GetPersonalityAndGrandStrategy((FlavorTypes)m_iNavalIndex);
		if (iNavalFlavor > 7)
		{
			rtnValue += (int)rtnValue * /*40*/ GC.getSETTLER_BUILD_ON_COAST_PERCENT() / 100;
		}
		if (pPlayer->getCivilizationInfo().isCoastalCiv()) // we really like the coast (England, Norway, Polynesia, Carthage, etc.)
		{
			rtnValue += rtnValue > 0 ? 25 : 0;
			rtnValue *= 2;
		}
	}
#if defined(MOD_BALANCE_CORE_SETTLER)
	if (MOD_BALANCE_CORE_SETTLER) 
	{
		//Is this a water chokepoint? (More than four would make this a peninsula, which is not what we are looking for.)
		if(pPlot->IsChokePoint(true, false, 0))
		{
			rtnValue += (int)rtnValue * /*100*/ GC.getBALANCE_CHOKEPOINT_STRATEGIC_VALUE() / 100;
		}
		//Looking for mountains for chokepoints.
		//If the adjacent plot is not touching another mountain, and there is more than one mountain around pPlot, we've found a potential chokepoint.
		else if(pPlot->IsChokePoint(false, true, 1))
		{
			//Awesome, we found a mountain chokepoint within 1. Emphasize!
			rtnValue += (int)rtnValue * /*100*/ GC.getBALANCE_CHOKEPOINT_STRATEGIC_VALUE() / 75;
		}
		else if(pPlot->IsChokePoint(false, true, 2))
		{
			//Awesome, we found a mountain chokepoint within 2. Emphasize!
			rtnValue += (int)rtnValue * /*100*/ GC.getBALANCE_CHOKEPOINT_STRATEGIC_VALUE() / 100;
		}
		else if(pPlot->IsChokePoint(false, true, 3))
		{
			//Awesome, we found a mountain chokepoint within 3. Emphasize!
			rtnValue += (int)rtnValue * /*100*/ GC.getBALANCE_CHOKEPOINT_STRATEGIC_VALUE() / 125;
		}
		//Too many bad plots?
		if(iBadPlot > (iLoopPlots / 4))
		{
			rtnValue /= 5;
		}
		//Too much empty water?
		if(iWaterPlot > (iLoopPlots / 2))
		{
			rtnValue *= 2;
			rtnValue /= 3;
		}
	}
	//Let's see what we can do. (Strategic site locator pulled from below - less loop cycles used this way, as all we care about is the city plot itself, not every plot in the city's loop.
	if(pPlayer != NULL)
	{
		for(int iMajorLoop = 0; iMajorLoop < MAX_MAJOR_CIVS; iMajorLoop++)
		{
			PlayerTypes eOtherPlayer = (PlayerTypes) iMajorLoop;
			PlayerProximityTypes eProximity = GET_PLAYER(eOtherPlayer).GetProximityToPlayer(pPlayer->GetID());
			if(eOtherPlayer != pPlayer->GetID() && eOtherPlayer != NO_PLAYER && GET_PLAYER(eOtherPlayer).isAlive() && !GET_PLAYER(eOtherPlayer).isMinorCiv() && !GET_PLAYER(eOtherPlayer).isBarbarian())
			{
				if(eProximity >= PLAYER_PROXIMITY_CLOSE)
				{
					CvCity* pLoopTheirCity;
					int iClosestDistance = 6;
					int iDistance = 0;
					int iLoop;
					for(pLoopTheirCity = GET_PLAYER(eOtherPlayer).firstCity(&iLoop); pLoopTheirCity != NULL; pLoopTheirCity = GET_PLAYER(eOtherPlayer).nextCity(&iLoop))
					{
						if(pLoopTheirCity != NULL)
						{
							if(pPlot->getArea() == pLoopTheirCity->getArea())
							{
								iDistance = plotDistance(pPlot->getX(), pPlot->getY(), pLoopTheirCity->getX(), pLoopTheirCity->getY());
								
								if(iDistance <= iClosestDistance)
								{
									//There's at least 6 hexes between these plots, which means we can theoretically settle here.
									int iNumPlots = 0;
									int iNumBadPlots = 0;

									for(int iDX = -iClosestDistance; iDX <= iClosestDistance; iDX++)
									{
										for(int iDY = -iClosestDistance; iDY <= iClosestDistance; iDY++)
										{
											CvPlot* pLoopPlot = plotXYWithRangeCheck(pPlot->getX(), pPlot->getY(), iDX, iDY, iClosestDistance);
											if(pLoopPlot)
											{
												//Let's look for good, empty land.
												if(pLoopPlot->isImpassable() || pLoopPlot->isWater() || pLoopPlot->getOwner() != NO_PLAYER) 
												{
													iNumBadPlots++;
												}
													iNumPlots++;
											}
										}
									}
									if(iNumBadPlots > 0)
									{
										iNumBadPlots = (iNumBadPlots * 130) / 100;
									}
									//Good space must be greater than bad plots by at least 30%
									if(iNumPlots > iNumBadPlots)
									{
										//If there is significant empty land, and it is within the theoretical hex separation of the nearest two cities of two different players, there's a good chance it is border land. GET IT!
										rtnValue += (int)rtnValue * /*50*/ GC.getBALANCE_EMPIRE_BORDERLAND_STRATEGIC_VALUE() / 100;
										break;
									}
								}
							}
						}
					}
				}
			}
		}
	}
#endif

	// Nearby Cities?

	// Human
	if (pPlayer != NULL && pPlayer->isHuman())
	{
		if (iClosestCityOfMine == 3)
		{
			rtnValue /= 2;
		}
	}
	// AI
	else
	{
		int iGrowthFlavor = pPlayer->GetGrandStrategyAI()->GetPersonalityAndGrandStrategy((FlavorTypes)m_iGrowthIndex);
		int iExpansionFlavor = pPlayer->GetGrandStrategyAI()->GetPersonalityAndGrandStrategy((FlavorTypes)m_iExpansionIndex);

		int iSweetSpot = 5;
		iSweetSpot += (iGrowthFlavor > 7) ?  1 : 0;
		iSweetSpot += (iExpansionFlavor > 7) ?  -1 : 0;
		iSweetSpot += (iGrowthFlavor < 4) ?  -1 : 0;
		iSweetSpot += (iExpansionFlavor < 4) ?  1 : 0;
		iSweetSpot = max(4,iSweetSpot);
		iSweetSpot = min(6,iSweetSpot);

		if (iClosestCityOfMine == iSweetSpot) 
		{
			// 1.5 was not enough 2.0 was too much, so lets split the difference
			rtnValue *= 175;
			rtnValue /= 100;
		}
		else if (iClosestCityOfMine < iSweetSpot)
		{
			rtnValue /= 2;
		}
		else if (iClosestCityOfMine > 7)
		{
			rtnValue *= 2;
			rtnValue /= 3;
		}

		// use boldness to decide if we want to push close to enemies
		int iBoldness = pPlayer->GetDiplomacyAI()->GetBoldness();
		if (iBoldness < 4)
		{
			if (iClosestEnemyCity <= 4)
			{
				rtnValue /= 4;
			}
			else if (iClosestEnemyCity == 5)
			{
				rtnValue /= 2;
			}
		}
		else if (iBoldness > 7)
		{
			if (iClosestEnemyCity <= 5 && iClosestCityOfMine < 8)
			{
				rtnValue *= 3;
				rtnValue /= 2;
			}
		}
		else
		{
			if (iClosestEnemyCity < 5)
			{
				rtnValue *= 2;
				rtnValue /= 3;
			}
		}

		// if we are offshore, pull cities in tighter
		if (iCapitalArea != pPlot->getArea())
		{
			if (iClosestCityOfMine < 7)
			{
				rtnValue *= 3;
				rtnValue /= 2;
			}
		}
#if defined(MOD_BALANCE_CORE_SETTLER)
	if (MOD_BALANCE_CORE_SETTLER) 
		{
			//Let's judge just how well we can defend this city if we push out. If our neighbors are stronger than us, let's turtle a bit.
			for(int iMajorLoop = 0; iMajorLoop < MAX_MAJOR_CIVS; iMajorLoop++)
			{
				PlayerTypes eOtherPlayer = (PlayerTypes) iMajorLoop;
				if(eOtherPlayer != NO_PLAYER && GET_PLAYER(eOtherPlayer).isAlive() && !GET_PLAYER(eOtherPlayer).isMinorCiv() && !GET_PLAYER(eOtherPlayer).isBarbarian())
				{
					PlayerProximityTypes eProximity = GET_PLAYER(eOtherPlayer).GetProximityToPlayer(pPlayer->GetID());
					if(eProximity == PLAYER_PROXIMITY_NEIGHBORS && (pPlayer->GetMilitaryMight() < GET_PLAYER(eOtherPlayer).GetMilitaryMight()))
					{
						//Is the plot we're looking at in the same area as our strong neighbor?
						if (iClosestEnemyCity <= 6)
						{
							rtnValue /= 2;
						}
					}
				}
			}
		}
#endif
	}

	rtnValue = (rtnValue > 0) ? rtnValue : 0;

	return rtnValue;
}
/// 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;
}
/// Value of plot for providing strategic value
int CvCitySiteEvaluator::ComputeStrategicValue(CvPlot* pPlot, CvPlayer* pPlayer, int iPlotsFromCity)
{
	int rtnValue = 0;

	CvAssert(pPlot);
	if(!pPlot) return rtnValue;

	// Possible chokepoint if impassable terrain and exactly 2 plots from city
	if(iPlotsFromCity == 2 && (pPlot->isImpassable() || pPlot->isMountain()))
	{
		rtnValue += /*5*/ GC.getCHOKEPOINT_STRATEGIC_VALUE();
	}
#if defined(MOD_BALANCE_CORE_SETTLER)
	if (MOD_BALANCE_CORE_SETTLER) 
	{
		//Some features and terrain types are useful strategically. (Or really bad)
		if((pPlot->getOwner() == NO_PLAYER) || (pPlot->getOwner() != pPlayer->GetID()))
		{
			if(iPlotsFromCity <= 3 && (pPlot->getFeatureType() == FEATURE_ICE) || (pPlot->getTerrainType() == TERRAIN_SNOW))
			{
				rtnValue += /*-10*/ GC.getBALANCE_BAD_TILES_STRATEGIC_VALUE();
			}
			if(iPlotsFromCity <= 3 && pPlot->isFreshWater())
			{
				rtnValue += /*2*/ GC.getBALANCE_FRESH_WATER_STRATEGIC_VALUE();
			}
			if(iPlotsFromCity <= 3 && pPlot->isCoastalLand())
			{
				rtnValue += /*2*/ GC.getBALANCE_COAST_STRATEGIC_VALUE();
			}
		}
	}
#endif

	// Hills in first ring are useful for defense and production
	if(iPlotsFromCity == 1 && pPlot->isHills())
	{
		rtnValue += /*3*/ GC.getHILL_STRATEGIC_VALUE();
	}

	// Some Features are less attractive to settle in, (e.g. Jungles, since it takes a while before you can clear them and they slow down movement)
	if(pPlot->getFeatureType() != NO_FEATURE)
	{
		int iWeight = GC.getFeatureInfo(pPlot->getFeatureType())->getStartingLocationWeight();
		if(iWeight != 0 && iPlotsFromCity == 1)
		{
			rtnValue += iWeight;
		}
	}

	// Nearby City
	if(pPlayer != NULL && pPlot->isCity())
	{
//		if (pPlot->getOwner() == pPlayer->getID())
		{
			rtnValue += /*-1000*/ GC.getALREADY_OWNED_STRATEGIC_VALUE();
		}
	}

	// POSSIBLE FUTURE: Is there any way for us to know to grab land between us and another major civ?

	rtnValue *= m_iFlavorMultiplier[SITE_EVALUATION_STRATEGIC];

	return rtnValue;
}