Menu

[r815]: / Trunk / Sources / CvPlayer.cpp  Maximize  Restore  History

Download this file

36902 lines (31328 with data), 1.2 MB

// player.cpp

#include "CvGameCoreDLL.h"
#include "CvGlobals.h"
#include "CvArea.h"
#include "CvGameAI.h"
#include "CvMap.h"
#include "CvViewport.h"
#include "CvPlot.h"
#include "CvRandom.h"
#include "CvTeamAI.h"
#include "CvGameCoreUtils.h"
#include "CvPlayerAI.h"
#include "CvPlayer.h"
#include "CvGameCoreUtils.h"
#include "CvArtFileMgr.h"
#include "CvDiploParameters.h"
#include "CvInitCore.h"
#include "CyArgsList.h"
#include "CvInfos.h"
#include "CvPopupInfo.h"
#include "CvDiploParameters.h"
#include "FProfiler.h"
#include "CvGameTextMgr.h"
#include "CyCity.h"
#include "CyPlot.h"
#include "CyUnit.h"
#include "CvEventReporter.h"
#include "CvTaggedSaveFormatWrapper.h"
#include "CvPipeline.h"

#include "CvDLLInterfaceIFaceBase.h"
#include "CvDLLEntityIFaceBase.h"
#include "CvDLLEngineIFaceBase.h"
#include "CvDLLFAStarIFaceBase.h"
#include "CvDLLPythonIFaceBase.h"
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      05/09/09                                jdog5000      */
/*                                                                                              */
/* General AI                                                                                   */
/************************************************************************************************/
#include "CvDLLFlagEntityIFaceBase.h"
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      10/02/09                                jdog5000      */
/*                                                                                              */
/* AI logging                                                                                   */
/************************************************************************************************/
#include "BetterBTSAI.h"
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
#include <math.h>
// BUG - Ignore Harmless Barbarians - start
#include "CvBugOptions.h"
// BUG - Ignore Harmless Barbarians - end
#include "FDataStreamBuffer.h"
#include<hash_map>

//	Koshling - save flag indicating this player has no data in the save as they have never
//	been alive
#define	PLAYER_UI_FLAG_OMITTED 2

//#define VALIDATION_FOR_PLOT_GROUPS

//	Helper class used to efficiently cache unit upgrade paths for this player
class CvUpgradeCache
{
	typedef struct upgradePair
	{
		UnitTypes		eFrom;
		UnitClassTypes	eTo;
	} upgradePair;

public:
	CvUpgradeCache(PlayerTypes eOwner)
	{
		m_validUpgrades = NULL;
		m_numUpgrades = 0;
		m_eOwner = eOwner;
	}
	virtual ~CvUpgradeCache()
	{
		SAFE_DELETE_ARRAY(m_validUpgrades);
	}

	bool upgradeAvailable(UnitTypes eFromUnit, UnitClassTypes eToUnitClass)
	{
		PROFILE_FUNC();

		upgradePair	key;

		key.eFrom = eFromUnit;
		key.eTo = eToUnitClass;

		if ( m_validUpgrades == NULL )
		{
			init();
		}

		return (bsearch((const void*)&key, (const void*)m_validUpgrades, m_numUpgrades, sizeof(upgradePair), upgradePairComparison) != NULL);
	}

private:
	void	init(void)
	{
		PROFILE_FUNC();

		std::list<upgradePair> directUpgrades;
		int iI, iJ;

		//	First populate the direct upgrades
		for(iI = 0; iI < GC.getNumUnitInfos(); iI++)
		{
			for(iJ = 0; iJ < GC.getNumUnitClassInfos(); iJ++)
			{
				if (GC.getUnitInfo((UnitTypes)iI).getUpgradeUnitClass((UnitClassTypes)iJ))
				{
					upgradePair newPair;

					newPair.eFrom = (UnitTypes)iI;
					newPair.eTo = (UnitClassTypes)iJ;

					directUpgrades.push_back(newPair);
				}
			}
		}

		std::list<upgradePair> upgrades;

		//	Now walk the direct upgrade links to fully populate the chains
		bool* bUnitUpgrades = new bool[GC.getNumUnitClassInfos()];

		for(iI = 0; iI < GC.getNumUnitInfos(); iI++)
		{
			memset(bUnitUpgrades,0,sizeof(bool)*GC.getNumUnitClassInfos());

			populateUpgradeChain((UnitTypes)iI, bUnitUpgrades, directUpgrades);

			for(iJ = 0; iJ < GC.getNumUnitClassInfos(); iJ++)
			{
				if ( bUnitUpgrades[iJ] )
				{
					upgradePair newPair;

					newPair.eFrom = (UnitTypes)iI;
					newPair.eTo = (UnitClassTypes)iJ;

					upgrades.push_back(newPair);
				}
			}
		}

		//	Now store them all and sort the array for easy searching
		m_numUpgrades = upgrades.size();
		m_validUpgrades = new upgradePair[m_numUpgrades];

		iI = 0;
		for(std::list<upgradePair>::const_iterator itr = upgrades.begin(); itr != upgrades.end(); ++itr)
		{
			m_validUpgrades[iI++] = (*itr);
		}

		qsort(m_validUpgrades, m_numUpgrades, sizeof(upgradePair), upgradePairComparison);
	}

	void populateUpgradeChain(UnitTypes eType, bool* abValid, const std::list<upgradePair>& directUpgrades)
	{
		for(std::list<upgradePair>::const_iterator itr = directUpgrades.begin(); itr != directUpgrades.end(); ++itr)
		{
			if ( (*itr).eFrom == eType )
			{
				abValid[(*itr).eTo] = true;
				populateUpgradeChain((UnitTypes)(GC.getCivilizationInfo(GET_PLAYER(m_eOwner).getCivilizationType()).getCivilizationUnits((*itr).eTo)), abValid, directUpgrades);
			}
		}
	}

#if 0
	bool upgradeAvailable(UnitTypes eFromUnit, UnitClassTypes eToUnitClass, int iCount)
	{
		UnitTypes eLoopUnit;
		int iI;
		int numUnitClassInfos = GC.getNumUnitClassInfos();

		if (iCount > numUnitClassInfos)
		{
			return false;
		}

		CvUnitInfo &fromUnitInfo = GC.getUnitInfo(eFromUnit);
		CvCivilizationInfo& civilizationInfo = GC.getCivilizationInfo(GET_PLAYER(m_eOwner).getCivilizationType());

		if (fromUnitInfo.getUpgradeUnitClass(eToUnitClass))
		{
			return true;
		}

		for (iI = 0; iI < numUnitClassInfos; iI++)
		{
			if (fromUnitInfo.getUpgradeUnitClass(iI))
			{
				eLoopUnit = ((UnitTypes)(civilizationInfo.getCivilizationUnits(iI)));

				if (eLoopUnit != NO_UNIT)
				{
					if (upgradeAvailable(eLoopUnit, eToUnitClass, (iCount + 1)))
					{
						return true;
					}
				}
			}
		}

		return false;
	}
#endif

	static int upgradePairComparison(const void* first, const void* second)
	{
		if ( ((upgradePair*)first)->eFrom == ((upgradePair*)second)->eFrom )
		{
			return (((upgradePair*)first)->eTo - ((upgradePair*)second)->eTo);
		}
		else
		{
			return (((upgradePair*)first)->eFrom - ((upgradePair*)second)->eFrom);
		}
	}

private:
	int					m_numUpgrades;
	upgradePair*		m_validUpgrades;
	PlayerTypes			m_eOwner;
};

CRITICAL_SECTION	CvPlayer::c_canConstructCacheSection;
CRITICAL_SECTION	CvPlayer::c_allCitiesPropertySection;
CRITICAL_SECTION	CvPlayer::c_buildingProcessingSection;
CRITICAL_SECTION	CvPlayer::c_GroupCycleSection;
bool				CvPlayer::m_staticsInitialized = false;

// Public Functions...

// Public Functions...

//Disable this passed in initialization list warning, as it is only stored in the constructor of CvBuildingList and not used
#pragma warning( disable : 4355 )

CvPlayer::CvPlayer()
: m_GameObject(this),
m_BuildingList(this, NULL),
m_UnitList(this, NULL),
m_Properties(this),
m_pBuildLists(NULL),
m_cachedBonusCount(NULL)
{
	if ( !m_staticsInitialized )
	{
		InitializeCriticalSectionAndSpinCount(&c_canConstructCacheSection, 4000);
		InitializeCriticalSection(&c_allCitiesPropertySection);
		InitializeCriticalSection(&c_buildingProcessingSection);
		InitializeCriticalSectionAndSpinCount(&c_GroupCycleSection, 4000);
		m_staticsInitialized = true;
	}

	m_aiSeaPlotYield = new int[NUM_YIELD_TYPES];
	m_aiYieldRateModifier = new int[NUM_YIELD_TYPES];
	m_aiCapitalYieldRateModifier = new int[NUM_YIELD_TYPES];
	m_aiExtraYieldThreshold = new int[NUM_YIELD_TYPES];
	m_aiTradeYieldModifier = new int[NUM_YIELD_TYPES];
	m_aiFreeCityCommerce = new int[NUM_COMMERCE_TYPES];
	m_aiCommercePercent = new int[NUM_COMMERCE_TYPES];
	m_aiCommerceRate = new int[NUM_COMMERCE_TYPES];
	m_abCommerceDirty = new bool[NUM_COMMERCE_TYPES];
	m_aiCommerceRateModifier = new int[NUM_COMMERCE_TYPES];
	m_aiCapitalCommerceRateModifier = new int[NUM_COMMERCE_TYPES];
	m_aiStateReligionBuildingCommerce = new int[NUM_COMMERCE_TYPES];
	m_aiSpecialistExtraCommerce = new int[NUM_COMMERCE_TYPES];
	m_aiSpecialistExtraYield = new int[NUM_YIELD_TYPES];
	m_aiCommerceFlexibleCount = new int[NUM_COMMERCE_TYPES];
	m_aiGoldPerTurnByPlayer = new int[MAX_PLAYERS];
	m_aiEspionageSpendingWeightAgainstTeam = new int[MAX_TEAMS];

	m_abFeatAccomplished = new bool[NUM_FEAT_TYPES];
	m_abOptions = new bool[NUM_PLAYEROPTION_TYPES];

	m_paiBonusExport = NULL;
	m_paiBonusImport = NULL;
	m_paiImprovementCount = NULL;
	m_paiFreeBuildingCount = NULL;
	m_paiExtraBuildingHappiness = NULL;
	m_paiExtraBuildingHealth = NULL;
	m_paiFeatureHappiness = NULL;
	m_paiUnitClassCount = NULL;
	m_paiUnitClassMaking = NULL;
	m_paiBuildingClassCount = NULL;
	m_paiBuildingClassMaking = NULL;
	m_paiHurryCount = NULL;
	m_paiSpecialBuildingNotRequiredCount = NULL;
	m_paiHasCivicOptionCount = NULL;
	m_paiNoCivicUpkeepCount = NULL;
	m_paiHasReligionCount = NULL;
	m_paiHasCorporationCount = NULL;
	m_paiUpkeepCount = NULL;
	m_paiSpecialistValidCount = NULL;
	m_aiPathLengthCache = NULL;
	m_aiCostPathLengthCache = NULL;
	m_bCanConstruct = NULL;
	m_bCanConstructCached = NULL;
	m_bCanConstructDefaultParam = NULL;
	m_bCanConstructCachedDefaultParam = NULL;
	m_upgradeCache = NULL;

	m_pabResearchingTech = NULL;
	m_pabLoyalMember = NULL;

	m_paeCivics = NULL;

	m_ppaaiSpecialistExtraYield = NULL;
	m_ppaaiImprovementYieldChange = NULL;

/************************************************************************************************/
/* Afforess	                  Start		 12/9/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	m_paiUnitCombatProductionModifier = NULL;
	m_paiBonusMintedPercent = NULL;
	m_pabAutomatedCanBuild = NULL;
	m_paiBuildingClassProductionModifier = NULL;
	m_paiUnitClassProductionModifier = NULL;
	m_ppaaiTerrainYieldChange = NULL;
	m_paiResourceConsumption = NULL;
	m_paiFreeSpecialistCount = NULL;
	m_ppiBuildingCommerceModifier = NULL;
	m_ppiBuildingClassCommerceChange = NULL;
	m_ppiSpecialistCommercePercentChanges = NULL;
	m_ppiSpecialistYieldPercentChanges = NULL;
	m_ppiBonusCommerceModifier = NULL;
	m_aiLandmarkYield = new int[NUM_YIELD_TYPES];
	m_aiModderOptions = new int[NUM_MODDEROPTION_TYPES];
	m_aiCeaseContactCounter = new int[MAX_PLAYERS];
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	m_paiImprovementUpgradeRateModifierSpecific = NULL;
	m_ppaaiSpecialistExtraCommerce = NULL;
/************************************************************************************************/
/* AI_AUTO_PLAY_MOD                        09/01/07                                MRGENIE      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	m_bDisableHuman = false;
/************************************************************************************************/
/* AI_AUTO_PLAY_MOD                        END                                                  */
/************************************************************************************************/
/************************************************************************************************/
/* REVOLUTION_MOD                         02/04/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	m_iFreeUnitCountdown = 0;

	m_iStabilityIndex = 500;
	m_iStabilityIndexAverage = 500;
	
	m_bRebel = false;
	m_iMotherPlayer = -1;

	// Used for DynamicCivNames
	CvWString m_szName;
	CvWString m_szCivDesc;
	CvWString m_szCivShort;
	CvWString m_szCivAdj;
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	// RevolutionDCM start - new diplomacy option
	setDoNotBotherStatus(NO_PLAYER);
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/

/************************************************************************************************/
/* UNOFFICIAL_PATCH                       12/07/09                             EmperorFool      */
/*                                                                                              */
/* Bugfix                                                                                       */
/************************************************************************************************/
	// Free Tech Popup Fix
	m_bChoosingFreeTech = false;
	m_bChoosingReligion = false;
/************************************************************************************************/
/* UNOFFICIAL_PATCH                        END                                                  */
/************************************************************************************************/

	m_zobristValue = GC.getGameINLINE().getSorenRand().getInt();

	m_iNumAnimalsSubdued = 0;
	m_iNumAnarchyTurns = 0;
	m_iNumCivicSwitches = 0;
	m_iNumCivicsSwitched = 0;

	reset(NO_PLAYER, true);

	InitializeCriticalSectionAndSpinCount(&m_cModifySection, 4000);
}


CvPlayer::~CvPlayer()
{
	uninit();

	SAFE_DELETE_ARRAY(m_aiSeaPlotYield);
	SAFE_DELETE_ARRAY(m_aiYieldRateModifier);
	SAFE_DELETE_ARRAY(m_aiCapitalYieldRateModifier);
	SAFE_DELETE_ARRAY(m_aiExtraYieldThreshold);
	SAFE_DELETE_ARRAY(m_aiTradeYieldModifier);
	SAFE_DELETE_ARRAY(m_aiFreeCityCommerce);
	SAFE_DELETE_ARRAY(m_aiCommercePercent);
	SAFE_DELETE_ARRAY(m_aiCommerceRate);
	SAFE_DELETE_ARRAY(m_abCommerceDirty);
	SAFE_DELETE_ARRAY(m_aiCommerceRateModifier);
	SAFE_DELETE_ARRAY(m_aiCapitalCommerceRateModifier);
	SAFE_DELETE_ARRAY(m_aiStateReligionBuildingCommerce);
	SAFE_DELETE_ARRAY(m_aiSpecialistExtraCommerce);
	SAFE_DELETE_ARRAY(m_aiSpecialistExtraYield);
	SAFE_DELETE_ARRAY(m_aiCommerceFlexibleCount);
	SAFE_DELETE_ARRAY(m_aiGoldPerTurnByPlayer);
	SAFE_DELETE_ARRAY(m_aiEspionageSpendingWeightAgainstTeam);
	SAFE_DELETE_ARRAY(m_abFeatAccomplished);
	SAFE_DELETE_ARRAY(m_abOptions);
/************************************************************************************************/
/* Afforess	                  Start		 02/02/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	SAFE_DELETE_ARRAY(m_aiLandmarkYield);
	SAFE_DELETE_ARRAY(m_aiModderOptions);
	SAFE_DELETE_ARRAY(m_aiCeaseContactCounter);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	SAFE_DELETE_ARRAY(m_cachedBonusCount);

	DeleteCriticalSection(&m_cModifySection);
}


void CvPlayer::init(PlayerTypes eID)
{
	LeaderHeadTypes eBestPersonality;
	int iValue;
	int iBestValue;
	int iI, iJ;

	//--------------------------------
	// Init saved data
	reset(eID);

	//--------------------------------
	// Init containers
	m_plotGroups.init();

	//m_cities.init();
	clearAllCities();

	//m_units.init();
	clearAllUnits();

	m_selectionGroups.init();

	m_eventsTriggered.init();

	//--------------------------------
	// Init non-saved data
	setupGraphical();

	//--------------------------------
	// Init other game data
	FAssert(getTeam() != NO_TEAM);
	GET_TEAM(getTeam()).changeNumMembers(1);

	if ((GC.getInitCore().getSlotStatus(getID()) == SS_TAKEN) || (GC.getInitCore().getSlotStatus(getID()) == SS_COMPUTER))
	{
		setAlive(true);

		if (GC.getGameINLINE().isOption(GAMEOPTION_RANDOM_PERSONALITIES))
		{
			if (!isBarbarian() && !isMinorCiv())
			{
				iBestValue = 0;
				eBestPersonality = NO_LEADER;

				for (iI = 0; iI < GC.getNumLeaderHeadInfos(); iI++)
				{
					if (iI != GC.getDefineINT("BARBARIAN_LEADER")) // XXX minor civ???
					{
						iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "Choosing Personality"));

						for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
						{
							if (GET_PLAYER((PlayerTypes)iJ).isAlive())
							{
								if (GET_PLAYER((PlayerTypes)iJ).getPersonalityType() == ((LeaderHeadTypes)iI))
								{
									iValue /= 2;
								}
							}
						}

						if (iValue > iBestValue)
						{
							iBestValue = iValue;
							eBestPersonality = ((LeaderHeadTypes)iI);
						}
					}
				}

				if (eBestPersonality != NO_LEADER)
				{
					setPersonalityType(eBestPersonality);
				}
			}
		}

		changeBaseFreeUnits(GC.getDefineINT("INITIAL_BASE_FREE_UNITS"));
		changeBaseFreeMilitaryUnits(GC.getDefineINT("INITIAL_BASE_FREE_MILITARY_UNITS"));
		changeFreeUnitsPopulationPercent(GC.getDefineINT("INITIAL_FREE_UNITS_POPULATION_PERCENT"));
		changeFreeMilitaryUnitsPopulationPercent(GC.getDefineINT("INITIAL_FREE_MILITARY_UNITS_POPULATION_PERCENT"));
		changeGoldPerUnit(GC.getDefineINT("INITIAL_GOLD_PER_UNIT"));
		changeTradeRoutes(GC.getDefineINT("INITIAL_TRADE_ROUTES"));
		changeStateReligionHappiness(GC.getDefineINT("INITIAL_STATE_RELIGION_HAPPINESS"));
		changeNonStateReligionHappiness(GC.getDefineINT("INITIAL_NON_STATE_RELIGION_HAPPINESS"));

		for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
		{
			changeTradeYieldModifier(((YieldTypes)iI), GC.getYieldInfo((YieldTypes)iI).getTradeModifier());
		}

		for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
		{
			setCommercePercent(((CommerceTypes)iI), GC.getCommerceInfo((CommerceTypes)iI).getInitialPercent());
		}

		FAssertMsg((GC.getNumTraitInfos() > 0), "GC.getNumTraitInfos() is less than or equal to zero but is expected to be larger than zero in CvPlayer::init");
		for (iI = 0; iI < GC.getNumTraitInfos(); iI++)
		{
			if (hasTrait((TraitTypes)iI))
			{
				processTrait((TraitTypes)iI, 1);
			}
		}

		updateMaxAnarchyTurns();

		for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
		{
			updateExtraYieldThreshold((YieldTypes)iI);
		}
/************************************************************************************************/
/* Afforess	                  Start		 04/06/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		GC.getInitCore().checkInitialCivics();
		
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

		for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
		{
			setCivics(((CivicOptionTypes)iI), ((CivicTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationInitialCivics(iI))));
		}

		for (iI = 0; iI < GC.getNumEventInfos(); iI++)
		{
			resetEventOccured((EventTypes)iI, false);
		}

		for (iI = 0; iI < GC.getNumEventTriggerInfos(); iI++)
		{
			resetTriggerFired((EventTriggerTypes)iI);
		}

		for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
		{
			UnitTypes eUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));

			if (NO_UNIT != eUnit)
			{
				if (GC.getUnitInfo(eUnit).isFound())
				{
					setUnitExtraCost((UnitClassTypes)iI, getNewCityProductionValue());
				}
			}
		}
	}


/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	// RevolutionDCM start - new diplomacy option
	setDoNotBotherStatus(NO_PLAYER);
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/

	AI_init();
/************************************************************************************************/
/* Afforess  Food Threshold Modifier   Start          08/16/09                   		         */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	setPopulationgrowthratepercentage(0);
	setReligionSpreadRate(0);
	setDistantUnitSupportCostModifier(0);
	setExtraCityDefense(0);
/************************************************************************************************/
/* Afforess  Food Threshold Modifier                        END                  		         */
/************************************************************************************************/

	m_contractBroker.init(eID);

	m_UnitList.init();
}

/************************************************************************************************/
/* REVOLUTION_MOD                         01/04/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// Copy of CvPlayer::init but with modifications for use in the middle of a game
//
void CvPlayer::initInGame(PlayerTypes eID, bool bSetAlive)
{
	LeaderHeadTypes eBestPersonality;
	int iValue;
	int iBestValue;
	int iI, iJ;

	//--------------------------------
	// Init saved data
	reset(eID);

	//--------------------------------
	// Init containers
	m_plotGroups.init();

	//m_cities.init();
	clearAllCities();

	//m_units.init();
	clearAllUnits();

	m_selectionGroups.init();

	m_eventsTriggered.init();

	m_contractBroker.init(eID);

	//--------------------------------
	// Init non-saved data
	setupGraphical();

	//--------------------------------
	// Init other game data
	FAssert(getTeam() != NO_TEAM);

	// Some effects on team necessary if this is the only member of the team
	int iOtherTeamMembers = 0;
	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
	{
		if( iI != getID() )
		{
			if( GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam() )
			{
				iOtherTeamMembers++;
			}
		}
	}

	bool bTeamInit = false;
	if( (iOtherTeamMembers == 0) || GET_TEAM(getTeam()).getNumMembers() == 0 )
	{
		bTeamInit = true;
		GET_TEAM(getTeam()).init(getTeam());
		GET_TEAM(getTeam()).resetPlotAndCityData();
	}

	if( bTeamInit || (GET_TEAM(getTeam()).getNumMembers() == iOtherTeamMembers) )
	{
		GET_TEAM(getTeam()).changeNumMembers(1);
	}

	if ((GC.getInitCore().getSlotStatus(getID()) == SS_TAKEN) || (GC.getInitCore().getSlotStatus(getID()) == SS_COMPUTER))
	{
		if( bSetAlive ) 
		{
			setAlive(true);
		}

		if (GC.getGameINLINE().isOption(GAMEOPTION_RANDOM_PERSONALITIES))
		{
			if (!isBarbarian() && !isMinorCiv())
			{
				iBestValue = 0;
				eBestPersonality = NO_LEADER;

				for (iI = 0; iI < GC.getNumLeaderHeadInfos(); iI++)
				{
					if (iI != GC.getDefineINT("BARBARIAN_LEADER")) // XXX minor civ???
					{
						iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "Choosing Personality"));

						for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
						{
							if (GET_PLAYER((PlayerTypes)iJ).isAlive())
							{
								if (GET_PLAYER((PlayerTypes)iJ).getPersonalityType() == ((LeaderHeadTypes)iI))
								{
									iValue /= 2;
								}
							}
						}

						if (iValue > iBestValue)
						{
							iBestValue = iValue;
							eBestPersonality = ((LeaderHeadTypes)iI);
						}
					}
				}

				if (eBestPersonality != NO_LEADER)
				{
					setPersonalityType(eBestPersonality);
				}
			}
		}

		changeBaseFreeUnits(GC.getDefineINT("INITIAL_BASE_FREE_UNITS"));
		changeBaseFreeMilitaryUnits(GC.getDefineINT("INITIAL_BASE_FREE_MILITARY_UNITS"));
		changeFreeUnitsPopulationPercent(GC.getDefineINT("INITIAL_FREE_UNITS_POPULATION_PERCENT"));
		changeFreeMilitaryUnitsPopulationPercent(GC.getDefineINT("INITIAL_FREE_MILITARY_UNITS_POPULATION_PERCENT"));
		changeGoldPerUnit(GC.getDefineINT("INITIAL_GOLD_PER_UNIT"));
		changeTradeRoutes(GC.getDefineINT("INITIAL_TRADE_ROUTES"));
		changeStateReligionHappiness(GC.getDefineINT("INITIAL_STATE_RELIGION_HAPPINESS"));
		changeNonStateReligionHappiness(GC.getDefineINT("INITIAL_NON_STATE_RELIGION_HAPPINESS"));

		for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
		{
			changeTradeYieldModifier(((YieldTypes)iI), GC.getYieldInfo((YieldTypes)iI).getTradeModifier());
		}

		for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
		{
			setCommercePercent(((CommerceTypes)iI), GC.getCommerceInfo((CommerceTypes)iI).getInitialPercent());
		}

		FAssertMsg((GC.getNumTraitInfos() > 0), "GC.getNumTraitInfos() is less than or equal to zero but is expected to be larger than zero in CvPlayer::init");
		for (iI = 0; iI < GC.getNumTraitInfos(); iI++)
		{
			if (hasTrait((TraitTypes)iI))
			{
				processTrait((TraitTypes)iI, 1);
			}
		}

		updateMaxAnarchyTurns();

		for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
		{
			updateExtraYieldThreshold((YieldTypes)iI);
		}

		for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
		{
			setCivics(((CivicOptionTypes)iI), ((CivicTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationInitialCivics(iI))));
		}

		// Reset all triggers at first, set those whose events have fired in next block
		for (iI = 0; iI < GC.getNumEventTriggerInfos(); iI++)
		{
			resetTriggerFired((EventTriggerTypes)iI);
		}

		for (iI = 0; iI < GC.getNumEventInfos(); iI++)
		{
/* original bts code
			resetEventOccured((EventTypes)iI, false);
*/
			// Has global trigger fired already?
				
			const EventTriggeredData* pEvent = NULL;
			for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
			{
				if( iJ != getID() )
				{
					pEvent = GET_PLAYER((PlayerTypes)iJ).getEventOccured((EventTypes)iI, true);
					if ( pEvent != NULL )
					{
						CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(pEvent->m_eTrigger);
						if( kTrigger.isGlobal() )
						{
							setTriggerFired( *pEvent, false, false );
							break;
						}
						else if( kTrigger.isTeam() && GET_PLAYER((PlayerTypes)iJ).getTeam() == getTeam() )
						{
							setTriggerFired( *pEvent, false, false );
							break;
						}
					}
				}
			}
			
			resetEventOccured((EventTypes)iI, false);
		}

		for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
		{
			UnitTypes eUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));

			if (NO_UNIT != eUnit)
			{
				if (GC.getUnitInfo(eUnit).isFound())
				{
					setUnitExtraCost((UnitClassTypes)iI, getNewCityProductionValue());
				}
			}
		}
	}

	resetPlotAndCityData();

/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	// RevolutionDCM start - new diplomacy option
	setDoNotBotherStatus(NO_PLAYER);
	// RevolutionDCM end
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/
	m_UnitList.init();

	AI_init();
}

//
// Reset all data for this player stored in plot and city objects
//
void CvPlayer::resetPlotAndCityData( )
{
	CvPlot* pLoopPlot;
	CvCity* pLoopCity;
	for (int iPlot = 0; iPlot < GC.getMapINLINE().numPlotsINLINE(); ++iPlot)
	{
		pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);

		pLoopPlot->setCulture(getID(), 0, false, false);
		pLoopPlot->setFoundValue(getID(), 0);

		pLoopCity = pLoopPlot->getPlotCity();
		if( pLoopCity != NULL )
		{
			pLoopCity->setCulture(getID(), 0, false, false);
			pLoopCity->changeNumRevolts(getID(), -pLoopCity->getNumRevolts(getID()));
			pLoopCity->setEverOwned(getID(), false);
			pLoopCity->setTradeRoute(getID(), false);
		}
	}
}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/


void CvPlayer::uninit()
{
	SAFE_DELETE_ARRAY(m_paiBonusExport);
	SAFE_DELETE_ARRAY(m_paiBonusImport);
	SAFE_DELETE_ARRAY(m_paiImprovementCount);
	SAFE_DELETE_ARRAY(m_paiFreeBuildingCount);
	SAFE_DELETE_ARRAY(m_paiExtraBuildingHappiness);
	SAFE_DELETE_ARRAY(m_paiExtraBuildingHealth);
	SAFE_DELETE_ARRAY(m_paiFeatureHappiness);
	SAFE_DELETE_ARRAY(m_paiUnitClassCount);
	SAFE_DELETE_ARRAY(m_paiUnitClassMaking);
	SAFE_DELETE_ARRAY(m_paiBuildingClassCount);
	SAFE_DELETE_ARRAY(m_paiBuildingClassMaking);
	SAFE_DELETE_ARRAY(m_paiHurryCount);
	SAFE_DELETE_ARRAY(m_paiSpecialBuildingNotRequiredCount);
	SAFE_DELETE_ARRAY(m_paiHasCivicOptionCount);
	SAFE_DELETE_ARRAY(m_paiNoCivicUpkeepCount);
	SAFE_DELETE_ARRAY(m_paiHasReligionCount);
	SAFE_DELETE_ARRAY(m_paiHasCorporationCount);
	SAFE_DELETE_ARRAY(m_paiUpkeepCount);
	SAFE_DELETE_ARRAY(m_paiSpecialistValidCount);

	SAFE_DELETE_ARRAY(m_pabResearchingTech);
	SAFE_DELETE_ARRAY(m_pabLoyalMember);

	SAFE_DELETE_ARRAY(m_paeCivics);
	SAFE_DELETE_ARRAY(m_aiPathLengthCache);
	SAFE_DELETE_ARRAY(m_aiCostPathLengthCache);

	SAFE_DELETE_ARRAY(m_bCanConstruct);
	SAFE_DELETE_ARRAY(m_bCanConstructCached);
	SAFE_DELETE_ARRAY(m_bCanConstructDefaultParam);
	SAFE_DELETE_ARRAY(m_bCanConstructCachedDefaultParam);

	SAFE_DELETE(m_upgradeCache);

	SAFE_DELETE(m_pBuildLists);

	m_triggersFired.clear();
	m_mapScoreHistory.clear();

	if (m_ppaaiSpecialistExtraYield != NULL)
	{
		for (int iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppaaiSpecialistExtraYield[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppaaiSpecialistExtraYield);
	}

	if (m_ppaaiImprovementYieldChange != NULL)
	{
		for (int iI = 0; iI < GC.getNumImprovementInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppaaiImprovementYieldChange[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppaaiImprovementYieldChange);
	}

/************************************************************************************************/
/* Afforess	                  Start		 12/9/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	SAFE_DELETE_ARRAY(m_paiUnitCombatProductionModifier);
	SAFE_DELETE_ARRAY(m_paiBonusMintedPercent);
	SAFE_DELETE_ARRAY(m_paiBuildingClassProductionModifier);
	SAFE_DELETE_ARRAY(m_paiUnitClassProductionModifier);
	SAFE_DELETE_ARRAY(m_pabAutomatedCanBuild);
	SAFE_DELETE_ARRAY(m_paiResourceConsumption);
	SAFE_DELETE_ARRAY(m_paiFreeSpecialistCount);
	SAFE_DELETE_ARRAY(m_paiImprovementUpgradeRateModifierSpecific);
	if (m_ppaaiSpecialistExtraCommerce != NULL)
	{
		for (int iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppaaiSpecialistExtraCommerce[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppaaiSpecialistExtraCommerce);
	}
	if (m_ppaaiTerrainYieldChange != NULL)
	{
		for (int iI = 0; iI < GC.getNumTerrainInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppaaiTerrainYieldChange[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppaaiTerrainYieldChange);
	}
	if (m_ppiBuildingCommerceModifier != NULL)
	{
		for (int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppiBuildingCommerceModifier[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppiBuildingCommerceModifier);
	}
	if (m_ppiBuildingClassCommerceChange != NULL)
	{
		for (int iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppiBuildingClassCommerceChange[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppiBuildingClassCommerceChange);
	}
	if (m_ppiBonusCommerceModifier != NULL)
	{
		for (int iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppiBonusCommerceModifier[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppiBonusCommerceModifier);
	}
	if (m_ppiSpecialistCommercePercentChanges != NULL)
	{
		for (int iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppiSpecialistCommercePercentChanges[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppiSpecialistCommercePercentChanges);
	}
	if (m_ppiSpecialistYieldPercentChanges != NULL)
	{
		for (int iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			SAFE_DELETE_ARRAY(m_ppiSpecialistYieldPercentChanges[iI]);
		}
		SAFE_DELETE_ARRAY(m_ppiSpecialistYieldPercentChanges);
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	m_groupCycle.clear();

	m_researchQueue.clear();

	m_cityNames.clear();

	m_contractBroker.reset();

	m_plotGroups.uninit();

	//m_cities.uninit();
	clearAllCities();

	//m_units.uninit();
	clearAllUnits();

	m_selectionGroups.uninit();

	m_eventsTriggered.uninit();

	clearMessages();

	clearPopups();

	clearDiplomacy();
}


// FUNCTION: reset()
// Initializes data members that are serialized.
void CvPlayer::reset(PlayerTypes eID, bool bConstructorCall)
{
	int iI, iJ;

	//--------------------------------
	// Uninit class
	uninit();

	// < M.A.D. Nukes Start >
	m_iMADDeterrent = 0;
	m_iMADIncoming = 0;
	m_iMADOutgoing = 0;
	m_iMADNukesCount = 0;
	for(iI = 0; iI < MAX_PLAYERS; iI++)
	{
		m_bMADTrigger[iI] = false;
	}
	// < M.A.D. Nukes End   >

	m_iStartingX = INVALID_PLOT_COORD;
	m_iStartingY = INVALID_PLOT_COORD;
	m_iTotalPopulation = 0;
	m_iTotalLand = 0;
	m_iTotalLandScored = 0;
	m_iGold = 0;
	m_iGoldPerTurn = 0;
	m_iAdvancedStartPoints = -1;
	m_iGoldenAgeTurns = 0;
	m_iNumUnitGoldenAges = 0;
	m_iStrikeTurns = 0;
	m_iAnarchyTurns = 0;
	m_iMaxAnarchyTurns = 0;
	m_iAnarchyModifier = 0;
	m_iGoldenAgeModifier = 0;
	m_iGlobalHurryModifier = 0;
	m_iGreatPeopleCreated = 0;
	m_iGreatGeneralsCreated = 0;
	m_iGreatPeopleThresholdModifier = 0;
	m_iGreatGeneralsThresholdModifier = 0;
	m_iGreatPeopleRateModifier = 0;
	m_iGreatGeneralRateModifier = 0;
	m_iDomesticGreatGeneralRateModifier = 0;
	m_iStateReligionGreatPeopleRateModifier = 0;
	m_iMaxGlobalBuildingProductionModifier = 0;
	m_iMaxTeamBuildingProductionModifier = 0;
	m_iMaxPlayerBuildingProductionModifier = 0;
	m_iFreeExperience = 0;
	m_iFeatureProductionModifier = 0;
	m_iWorkerSpeedModifier = 0;
	m_iImprovementUpgradeRateModifier = 0;
	m_iMilitaryProductionModifier = 0;
	m_iSpaceProductionModifier = 0;
	m_iCityDefenseModifier = 0;
/************************************************************************************************/
/* REVDCM                                 09/02/10                                phungus420    */
/*                                                                                              */
/* Player Functions                                                                             */
/************************************************************************************************/
	m_iNonStateReligionCommerceCount = 0;
	m_iUpgradeAnywhereCount = 0;
	m_iRevIdxLocal = 0;
	m_iRevIdxNational = 0;
	m_iRevIdxDistanceModifier = 0;
	m_iRevIdxHolyCityGood = 0;
	m_iRevIdxHolyCityBad = 0;
	m_fRevIdxNationalityMod = 0;
	m_fRevIdxBadReligionMod = 0;
	m_fRevIdxGoodReligionMod = 0;
	m_bInquisitionConditions = false;
	m_iUnitUpgradePriceModifier = 0;
	m_iCityLimit = 0;
	m_iCityOverLimitUnhappy = 0;
	m_iForeignUnhappyPercent = 0;
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/
	m_iNumNukeUnits = 0; 
	m_iNumOutsideUnits = 0; 
	m_iBaseFreeUnits = 0;
	m_iBaseFreeMilitaryUnits = 0;
	m_iFreeUnitsPopulationPercent = 0;
	m_iFreeMilitaryUnitsPopulationPercent = 0;
	m_iGoldPerUnit = 0;
	m_iGoldPerMilitaryUnit = 0;
	m_iExtraUnitCost = 0;
	m_iNumMilitaryUnits = 0;
	m_iHappyPerMilitaryUnit = 0;
	m_iMilitaryFoodProductionCount = 0;
	m_iConscriptCount = 0;
	m_iMaxConscript = 0;
	m_iHighestUnitLevel = 1;
	m_iOverflowResearch = 0;
	m_iNoUnhealthyPopulationCount = 0;
	m_iExpInBorderModifier = 0;
	m_iBuildingOnlyHealthyCount = 0;
	//DPII < Maintenance Modifier >
	m_iMaintenanceModifier = 0;
	m_iCoastalDistanceMaintenanceModifier = 0;
	m_iConnectedCityMaintenanceModifier = 0;
	//DPII < Maintenance Modifier >
	m_iDistanceMaintenanceModifier = 0;
	m_iNumCitiesMaintenanceModifier = 0;
	m_iCorporationMaintenanceModifier = 0;
	m_iTotalMaintenance = 0;
	m_iUpkeepModifier = 0;
	m_iLevelExperienceModifier = 0;
	m_iExtraHealth = 0;
	m_iBuildingGoodHealth = 0;
	m_iBuildingBadHealth = 0;
	m_iExtraHappiness = 0;
	m_iBuildingHappiness = 0;
	m_iLargestCityHappiness = 0;
	m_iWarWearinessPercentAnger = 0;
	m_iWarWearinessModifier = 0;
	m_iFreeSpecialist = 0;
	m_iNoForeignTradeCount = 0;
	m_iNoCorporationsCount = 0;
	m_iNoForeignCorporationsCount = 0;
	m_iCoastalTradeRoutes = 0;
	m_iTradeRoutes = 0;
	m_iRevolutionTimer = 0;
	m_iConversionTimer = 0;
	m_iStateReligionCount = 0;
	m_iNoNonStateReligionSpreadCount = 0;
	m_iStateReligionHappiness = 0;
	m_iNonStateReligionHappiness = 0;
	m_iStateReligionUnitProductionModifier = 0;
	m_iStateReligionBuildingProductionModifier = 0;
	m_iStateReligionFreeExperience = 0;
	m_iCapitalCityID = FFreeList::INVALID_INDEX;
	m_iCitiesLost = 0;
	m_iWinsVsBarbs = 0;
	m_iAssets = 0;
	m_iPower = 0;
	m_iTechPower = 0;
	m_iUnitPower = 0;
	m_iPopulationScore = 0;
	m_iLandScore = 0;
	m_iTechScore = 0;
	m_iWondersScore = 0;
	m_iCombatExperience = 0;
	m_iPopRushHurryCount = 0;
	m_iInflationModifier = 0;
	m_accruedCostRatioTimes10000 = 10000;	//	1:1 at the start
	m_uiStartTime = 0;

	m_bAlive = false;
	m_bEverAlive = false;
	m_bTurnActive = false;
	m_bAutoMoves = false;
	m_bEndTurn = false;
	m_bPbemNewTurn = false;
	m_bExtendedGame = false;
	m_bFoundedFirstCity = false;
	m_bStrike = false;
	//TB Nukefix
	m_bNukesValid = false;
	m_iNationalHurryAngerModifier = 0;
	m_iNationalEnemyWarWearinessModifier = 0;
	m_iFixedBordersCount = 0;
	m_iSeizedForeignConnectednessPercent = 0;
	m_iWarMongerIndex = 0;

	m_Properties.clear();
	m_canHaveBuilder.clear();

	setTurnHadUIInteraction(false);

	m_civicSwitchHistory.clear();

/************************************************************************************************/
/* UNOFFICIAL_PATCH                       12/07/09                             EmperorFool      */
/*                                                                                              */
/* Bugfix                                                                                       */
/************************************************************************************************/
	// Free Tech Popup Fix
	m_bChoosingFreeTech = false;
/************************************************************************************************/
/* UNOFFICIAL_PATCH                        END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* AI_AUTO_PLAY_MOD                        09/01/07                            MRGENIE          */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	m_bDisableHuman = false;
/************************************************************************************************/
/* AI_AUTO_PLAY_MOD                        END                                                  */
/************************************************************************************************/


/************************************************************************************************/
/* REVOLUTION_MOD                         02/04/09                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	m_iFreeUnitCountdown = 0;

	m_iStabilityIndex = 500;
	m_iStabilityIndexAverage = 500;

	m_bRebel = false;
	m_iMotherPlayer = -1;

	// Used for DynamicCivNames
	m_szName.clear();
	m_szCivDesc.clear();
	m_szCivShort.clear();
	m_szCivAdj.clear();
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
	m_eID = eID;
	updateTeamType();
	updateHuman();

	if (m_eID != NO_PLAYER)
	{
		m_ePersonalityType = GC.getInitCore().getLeader(m_eID); //??? Is this repeated data???
	}
	else
	{
		m_ePersonalityType = NO_LEADER;
	}
	m_eCurrentEra = ((EraTypes)0);  //??? Is this repeated data???
	m_eLastStateReligion = NO_RELIGION;
	m_eParent = NO_PLAYER;
/************************************************************************************************/
/* Afforess	                  Start		 12/9/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
    m_ePledgedVote = NO_PLAYER_VOTE;
	m_eSecretaryGeneralVote = NO_TEAM;
    m_iEnslavementChance = 0;
	m_iForeignTradeRouteModifier = 0;
	m_iTaxRateUnhappiness = 0;
	m_iCivicHappiness = 0;
	m_iFractionalXPEarnedInCity = 0;
	m_iUnitUpgradePriceModifier = 0;
	
	m_iWorldHappiness = 0;
	m_iProjectHappiness = 0;
	m_iWorldHealth = 0;
	m_iProjectHealth = 0;
	m_iForceAllTradeRoutes = 0;
	m_iWorldTradeRoutes = 0;
	m_iNoCapitalUnhappiness = 0;
	m_iTaxationAnger = 0;
	m_iLastTurnTaxRate = 0;
	m_iCivilizationHealth = 0;
	
	m_bShowLandmarks = true;

	m_iBuildingInflation = 0;
	m_iCivicInflation = 0;
	m_iProjectInflation = 0;
	m_iTechInflation = 0;
	
	m_iHurryCostModifier = 0;
	m_iHurryInflationModifier = 0;
	m_iHurryCount = 0;

	m_eBestRoute = NO_ROUTE;

	m_iNoLandmarkAngerCount = 0;
	m_iLandmarkHappiness = 0;
	m_eDemandWarAgainstTeam = NO_TEAM;
	
	m_iCorporationSpreadModifier = 0;
	m_iCorporateTaxIncome = 0;

	m_eCurrentAgeSegment = AGE_SEGMENT_DAWN;
	m_eCurrentCulturalAge = FIRST_CULTURAL_AGE;
	m_iCulture = 0;
	
	m_iFractionalCombatExperience = 0;

	m_bInhibitPlotGroupRecalc = false;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
	{
		m_aiSeaPlotYield[iI] = 0;
		m_aiYieldRateModifier[iI] = 0;
		m_aiCapitalYieldRateModifier[iI] = 0;
		m_aiExtraYieldThreshold[iI] = 0;
		m_aiTradeYieldModifier[iI] = 0;
/************************************************************************************************/
/* Afforess	                  Start		 04/15/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		m_aiLandmarkYield[iI] = 0;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/		
		m_aiSpecialistExtraYield[iI] = 0;
	}

	for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
	{
		m_aiFreeCityCommerce[iI] = 0;
		m_aiCommercePercent[iI] = 0;
		m_aiCommerceRate[iI] = 0;
		m_abCommerceDirty[iI] = false;
		m_aiCommerceRateModifier[iI] = 0;
		m_aiCapitalCommerceRateModifier[iI] = 0;
		m_aiStateReligionBuildingCommerce[iI] = 0;
		m_aiSpecialistExtraCommerce[iI] = 0;
		m_aiCommerceFlexibleCount[iI] = 0;
	}

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		m_aiGoldPerTurnByPlayer[iI] = 0;
		if (!bConstructorCall && getID() != NO_PLAYER)
		{
			GET_PLAYER((PlayerTypes) iI).m_aiGoldPerTurnByPlayer[getID()] = 0;
		}
	}

	for (iI = 0; iI < MAX_TEAMS; iI++)
	{
		m_aiEspionageSpendingWeightAgainstTeam[iI] = 0;

		if (!bConstructorCall && getTeam() != NO_TEAM)
		{
			for (iJ = 0; iJ < MAX_PLAYERS; iJ++)
			{
				if (GET_PLAYER((PlayerTypes) iJ).getTeam() == iI)
				{
					GET_PLAYER((PlayerTypes) iJ).setEspionageSpendingWeightAgainstTeam(getTeam(), 0);
				}
			}
		}
	}

	for (iI = 0; iI < NUM_FEAT_TYPES; iI++)
	{
		m_abFeatAccomplished[iI] = false;
	}

	for (iI = 0; iI < NUM_PLAYEROPTION_TYPES; iI++)
	{
		m_abOptions[iI] = false;
	}

	m_szScriptData = "";

	SAFE_DELETE_ARRAY(m_cachedBonusCount);
	m_cachedBonusCountGameTurn = -1;

	if (!bConstructorCall)
	{
		FAssertMsg(0 < GC.getNumBonusInfos(), "GC.getNumBonusInfos() is not greater than zero but it is used to allocate memory in CvPlayer::reset");
		FAssertMsg(m_paiBonusExport==NULL, "about to leak memory, CvPlayer::m_paiBonusExport");
		m_paiBonusExport = new int [GC.getNumBonusInfos()];
		FAssertMsg(m_paiBonusImport==NULL, "about to leak memory, CvPlayer::m_paiBonusImport");
		m_paiBonusImport = new int [GC.getNumBonusInfos()];
		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_paiBonusExport[iI] = 0;
			m_paiBonusImport[iI] = 0;
		}

		FAssertMsg(0 < GC.getNumImprovementInfos(), "GC.getNumImprovementInfos() is not greater than zero but it is used to allocate memory in CvPlayer::reset");
		FAssertMsg(m_paiImprovementCount==NULL, "about to leak memory, CvPlayer::m_paiImprovementCount");
		m_paiImprovementCount = new int [GC.getNumImprovementInfos()];
		for (iI = 0; iI < GC.getNumImprovementInfos(); iI++)
		{
			m_paiImprovementCount[iI] = 0;
		}

		FAssertMsg(m_paiFreeBuildingCount==NULL, "about to leak memory, CvPlayer::m_paiFreeBuildingCount");
		m_paiFreeBuildingCount = new int [GC.getNumBuildingInfos()];
		FAssertMsg(m_paiExtraBuildingHappiness==NULL, "about to leak memory, CvPlayer::m_paiExtraBuildingHappiness");
		m_paiExtraBuildingHappiness = new int [GC.getNumBuildingInfos()];
		FAssertMsg(m_paiExtraBuildingHealth==NULL, "about to leak memory, CvPlayer::m_paiExtraBuildingHealth");
		m_paiExtraBuildingHealth = new int [GC.getNumBuildingInfos()];
		for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
			m_paiFreeBuildingCount[iI] = 0;
			m_paiExtraBuildingHappiness[iI] = 0;
			m_paiExtraBuildingHealth[iI] = 0;
		}

		FAssertMsg(m_paiFeatureHappiness==NULL, "about to leak memory, CvPlayer::m_paiFeatureHappiness");
		m_paiFeatureHappiness = new int [GC.getNumFeatureInfos()];
		for (iI = 0; iI < GC.getNumFeatureInfos(); iI++)
		{
			m_paiFeatureHappiness[iI] = 0;
		}

		FAssertMsg(m_paiUnitClassCount==NULL, "about to leak memory, CvPlayer::m_paiUnitClassCount");
		m_paiUnitClassCount = new int [GC.getNumUnitClassInfos()];
		FAssertMsg(m_paiUnitClassMaking==NULL, "about to leak memory, CvPlayer::m_paiUnitClassMaking");
		m_paiUnitClassMaking = new int [GC.getNumUnitClassInfos()];
		for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
		{
			m_paiUnitClassCount[iI] = 0;
			m_paiUnitClassMaking[iI] = 0;
		}

		FAssertMsg(m_paiBuildingClassCount==NULL, "about to leak memory, CvPlayer::m_paiBuildingClassCount");
		m_paiBuildingClassCount = new int [GC.getNumBuildingClassInfos()];
		FAssertMsg(m_paiBuildingClassMaking==NULL, "about to leak memory, CvPlayer::m_paiBuildingClassMaking");
		m_paiBuildingClassMaking = new int [GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			m_paiBuildingClassCount[iI] = 0;
			m_paiBuildingClassMaking[iI] = 0;
		}

		FAssertMsg(m_paiHurryCount==NULL, "about to leak memory, CvPlayer::m_paiHurryCount");
		m_paiHurryCount = new int [GC.getNumHurryInfos()];
		for (iI = 0; iI < GC.getNumHurryInfos(); iI++)
		{
			m_paiHurryCount[iI] = 0;
		}

		FAssertMsg(m_paiSpecialBuildingNotRequiredCount==NULL, "about to leak memory, CvPlayer::m_paiSpecialBuildingNotRequiredCount");
		m_paiSpecialBuildingNotRequiredCount = new int [GC.getNumSpecialBuildingInfos()];
		for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); iI++)
		{
			m_paiSpecialBuildingNotRequiredCount[iI] = 0;
		}
	
		FAssertMsg(m_paiHasCivicOptionCount==NULL, "about to leak memory, CvPlayer::m_paiHasCivicOptionCount");
		m_paiHasCivicOptionCount = new int[GC.getNumCivicOptionInfos()];
		FAssertMsg(m_paiNoCivicUpkeepCount==NULL, "about to leak memory, CvPlayer::m_paiNoCivicUpkeepCount");
		m_paiNoCivicUpkeepCount = new int[GC.getNumCivicOptionInfos()];
		FAssertMsg(m_paeCivics==NULL, "about to leak memory, CvPlayer::m_paeCivics");
		m_paeCivics = new CivicTypes [GC.getNumCivicOptionInfos()];
		for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
		{
			m_paiHasCivicOptionCount[iI] = 0;
			m_paiNoCivicUpkeepCount[iI] = 0;
			m_paeCivics[iI] = NO_CIVIC;
		}

		FAssertMsg(m_bCanConstruct==NULL, "about to leak memory, CvPlayer::m_bCanConstruct");
		m_bCanConstruct = new bool[GC.getNumBuildingInfos()];

		FAssertMsg(m_bCanConstructCached==NULL, "about to leak memory, CvPlayer::m_bCanConstructCached");
		m_bCanConstructCached = new bool[GC.getNumBuildingInfos()];
		for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
			m_bCanConstructCached[iI] = false;
		}

		FAssertMsg(m_bCanConstructDefaultParam==NULL, "about to leak memory, CvPlayer::m_bCanConstructDefaultParam");
		m_bCanConstructDefaultParam = new bool[GC.getNumBuildingInfos()];

		FAssertMsg(m_bCanConstructCachedDefaultParam==NULL, "about to leak memory, CvPlayer::m_bCanConstructCachedDefaultParam");
		m_bCanConstructCachedDefaultParam = new bool[GC.getNumBuildingInfos()];
		for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
			m_bCanConstructCachedDefaultParam[iI] = false;
		}
		
		FAssertMsg(m_aiPathLengthCache==NULL, "about to leak memory, CvPlayer::m_aiPathLengthCache");
		m_aiPathLengthCache = new int[GC.getNumTechInfos()];
		for (iI = 0; iI < GC.getNumTechInfos(); iI++)
		{
			m_aiPathLengthCache[iI] = -1;
		}
		
		FAssertMsg(m_aiCostPathLengthCache==NULL, "about to leak memory, CvPlayer::m_aiCostPathLengthCache");
		m_aiCostPathLengthCache = new int[GC.getNumTechInfos()];
		for (iI = 0; iI < GC.getNumTechInfos(); iI++)
		{
			m_aiCostPathLengthCache[iI] = -1;
		}

		FAssertMsg(m_paiHasReligionCount==NULL, "about to leak memory, CvPlayer::m_paiHasReligionCount");
		m_paiHasReligionCount = new int[GC.getNumReligionInfos()];
		for (iI = 0;iI < GC.getNumReligionInfos();iI++)
		{
			m_paiHasReligionCount[iI] = 0;
		}
	
		FAssertMsg(m_paiHasCorporationCount==NULL, "about to leak memory, CvPlayer::m_paiHasCorporationCount");
		m_paiHasCorporationCount = new int[GC.getNumCorporationInfos()];
		for (iI = 0;iI < GC.getNumCorporationInfos();iI++)
		{
			m_paiHasCorporationCount[iI] = 0;
		}

		FAssertMsg(m_pabResearchingTech==NULL, "about to leak memory, CvPlayer::m_pabResearchingTech");
		m_pabResearchingTech = new bool[GC.getNumTechInfos()];
		for (iI = 0; iI < GC.getNumTechInfos(); iI++)
		{
			m_pabResearchingTech[iI] = false;
		}

		FAssertMsg(m_pabLoyalMember==NULL, "about to leak memory, CvPlayer::m_pabLoyalMember");
		m_pabLoyalMember = new bool[GC.getNumVoteSourceInfos()];
		for (iI = 0; iI < GC.getNumVoteSourceInfos(); iI++)
		{
			m_pabLoyalMember[iI] = true;
		}

		FAssertMsg(0 < GC.getNumUpkeepInfos(), "GC.getNumUpkeepInfos() is not greater than zero but it is used to allocate memory in CvPlayer::reset");
		FAssertMsg(m_paiUpkeepCount==NULL, "about to leak memory, CvPlayer::m_paiUpkeepCount");
		m_paiUpkeepCount = new int[GC.getNumUpkeepInfos()];
		for (iI = 0; iI < GC.getNumUpkeepInfos(); iI++)
		{
			m_paiUpkeepCount[iI] = 0;
		}

		FAssertMsg(0 < GC.getNumSpecialistInfos(), "GC.getNumSpecialistInfos() is not greater than zero but it is used to allocate memory in CvPlayer::reset");
		FAssertMsg(m_paiSpecialistValidCount==NULL, "about to leak memory, CvPlayer::m_paiSpecialistValidCount");
		m_paiSpecialistValidCount = new int[GC.getNumSpecialistInfos()];
		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			m_paiSpecialistValidCount[iI] = 0;
		}

		FAssertMsg(0 < GC.getNumSpecialistInfos(), "GC.getNumSpecialistInfos() is not greater than zero but it is used to allocate memory in CvPlayer::reset");
		FAssertMsg(m_ppaaiSpecialistExtraYield==NULL, "about to leak memory, CvPlayer::m_ppaaiSpecialistExtraYield");
		m_ppaaiSpecialistExtraYield = new int*[GC.getNumSpecialistInfos()];
/************************************************************************************************/
/* Afforess	                  Start		 03/27/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		m_paiFreeSpecialistCount = new int[GC.getNumSpecialistInfos()];
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			m_ppaaiSpecialistExtraYield[iI] = new int[NUM_YIELD_TYPES];
			for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
			{
				m_ppaaiSpecialistExtraYield[iI][iJ] = 0;
			}
/************************************************************************************************/
/* Afforess	                  Start		 03/27/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
			m_paiFreeSpecialistCount[iI] = 0;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		}
		//TB Traits begin		
		FAssertMsg(0 < GC.getNumSpecialistInfos(), "GC.getNumSpecialistInfos() is not greater than zero but it is used to allocate memory in CvPlayer::reset");
		FAssertMsg(m_ppaaiSpecialistExtraCommerce==NULL, "about to leak memory, CvPlayer::m_ppaaiSpecialistExtraCommerce");
		m_ppaaiSpecialistExtraCommerce = new int*[GC.getNumSpecialistInfos()];
		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			m_ppaaiSpecialistExtraCommerce[iI] = new int[NUM_COMMERCE_TYPES];
			for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
			{
				m_ppaaiSpecialistExtraCommerce[iI][iJ] = 0;
			}
		}

		//TB Traits end
		FAssertMsg(m_ppaaiImprovementYieldChange==NULL, "about to leak memory, CvPlayer::m_ppaaiImprovementYieldChange");
		m_ppaaiImprovementYieldChange = new int*[GC.getNumImprovementInfos()];
		//TB Traits begin
		FAssertMsg(m_paiImprovementUpgradeRateModifierSpecific==NULL, "about to leak memory, CvPlayer::m_paiImprovementUpgradeRateModifierSpecific");
		m_paiImprovementUpgradeRateModifierSpecific = new int [GC.getNumImprovementInfos()];
		//TB Traits end
		for (iI = 0; iI < GC.getNumImprovementInfos(); iI++)
		{
			m_ppaaiImprovementYieldChange[iI] = new int[NUM_YIELD_TYPES];
			for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
			{
				m_ppaaiImprovementYieldChange[iI][iJ] = 0;
			}
			//TB Traits begin
			m_paiImprovementUpgradeRateModifierSpecific[iI] = 0;
			//TB Traits end
		}

/************************************************************************************************/
/* Afforess	                  Start		 12/9/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		FAssertMsg(m_paiUnitCombatProductionModifier==NULL, "about to leak memory, CvPlayer::m_paiUnitCombatProductionModifier");
		m_paiUnitCombatProductionModifier = new int [GC.getNumUnitCombatInfos()];
		for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
		{
			m_paiUnitCombatProductionModifier[iI] = 0;
		}
		
		FAssertMsg(m_paiBonusMintedPercent==NULL, "about to leak memory, CvPlayer::m_paiBonusMintedPercent");
		m_paiBonusMintedPercent = new int [GC.getNumBonusInfos()];
		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_paiBonusMintedPercent[iI] = 0;
		}

		FAssertMsg(m_paiBuildingClassProductionModifier==NULL, "about to leak memory, CvPlayer::m_paiBuildingClassProductionModifier");
		m_paiBuildingClassProductionModifier = new int [GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			m_paiBuildingClassProductionModifier[iI] = 0;
		}
		
		FAssertMsg(m_paiUnitClassProductionModifier==NULL, "about to leak memory, CvPlayer::m_paiUnitClassProductionModifier");
		m_paiUnitClassProductionModifier = new int [GC.getNumUnitClassInfos()];
		for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
		{
			m_paiUnitClassProductionModifier[iI] = 0;
		}

		FAssertMsg(m_pabAutomatedCanBuild==NULL, "about to leak memory, CvPlayer::m_pabAutomatedCanBuild");
		m_pabAutomatedCanBuild = new bool [GC.getNumBuildInfos()];
		for (iI = 0; iI < GC.getNumBuildInfos(); iI++)
		{
			m_pabAutomatedCanBuild[iI] = true;
		}
		
		FAssertMsg(m_paiResourceConsumption==NULL, "about to leak memory, CvPlayer::m_paiResourceConsumption");
		m_paiResourceConsumption = new int [GC.getNumBonusInfos()];
		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_paiResourceConsumption[iI] = 0;
		}

		FAssertMsg(m_ppaaiTerrainYieldChange==NULL, "about to leak memory, CvPlayer::m_ppaaiTerrainYieldChange");
		m_ppaaiTerrainYieldChange = new int*[GC.getNumTerrainInfos()];
		for (iI = 0; iI < GC.getNumTerrainInfos(); iI++)
		{
			m_ppaaiTerrainYieldChange[iI] = new int[NUM_YIELD_TYPES];
			for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
			{
				m_ppaaiTerrainYieldChange[iI][iJ] = 0;
			}
		}
		FAssertMsg(m_ppiBuildingCommerceModifier==NULL, "about to leak memory, CvPlayer::m_ppiBuildingCommerceModifier");
		m_ppiBuildingCommerceModifier = new int*[GC.getNumBuildingInfos()];
		for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
			m_ppiBuildingCommerceModifier[iI] = new int[NUM_COMMERCE_TYPES];
			for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
			{
				m_ppiBuildingCommerceModifier[iI][iJ] = 0;
			}
		}
		FAssertMsg(m_ppiBuildingClassCommerceChange==NULL, "about to leak memory, CvPlayer::m_ppiBuildingClassCommerceChange");
		m_ppiBuildingClassCommerceChange = new int*[GC.getNumBuildingClassInfos()];
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			m_ppiBuildingClassCommerceChange[iI] = new int[NUM_COMMERCE_TYPES];
			for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
			{
				m_ppiBuildingClassCommerceChange[iI][iJ] = 0;
			}
		}

		FAssertMsg(m_ppiBonusCommerceModifier==NULL, "about to leak memory, CvPlayer::m_ppiBonusCommerceModifier");
		m_ppiBonusCommerceModifier = new int*[GC.getNumBonusInfos()];
		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_ppiBonusCommerceModifier[iI] = new int[NUM_COMMERCE_TYPES];
			for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
			{
				m_ppiBonusCommerceModifier[iI][iJ] = 0;
			}
		}
		
		FAssertMsg(m_ppiSpecialistCommercePercentChanges==NULL, "about to leak memory, CvPlayer::m_ppiSpecialistCommercePercentChanges");
		FAssertMsg(m_ppiSpecialistYieldPercentChanges==NULL, "about to leak memory, CvPlayer::m_ppiSpecialistYieldPercentChanges");
		m_ppiSpecialistCommercePercentChanges = new int*[GC.getNumSpecialistInfos()];
		m_ppiSpecialistYieldPercentChanges = new int*[GC.getNumSpecialistInfos()];
		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			m_ppiSpecialistCommercePercentChanges[iI] = new int[NUM_COMMERCE_TYPES];
			for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
			{
				m_ppiSpecialistCommercePercentChanges[iI][iJ] = 0;
			}
			m_ppiSpecialistYieldPercentChanges[iI] = new int[NUM_YIELD_TYPES];
			for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
			{
				m_ppiSpecialistYieldPercentChanges[iI][iJ] = 0;
			}
		}
		
		for (iI = 0; iI < NUM_MODDEROPTION_TYPES; iI++)
		{
			m_aiModderOptions[iI] = 0;
		}

		for (iI = 0; iI < MAX_PLAYERS; iI++)
		{
			m_aiCeaseContactCounter[iI] = 0;
		}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		m_mapEventsOccured.clear();
		m_mapEventCountdown.clear();
		m_aFreeUnitCombatPromotions.clear();
		m_aFreeUnitClassPromotions.clear();
		m_aVote.clear();
		m_aUnitExtraCosts.clear();
		m_triggersFired.clear();
	}

	m_plotGroups.removeAll();

	//m_cities.removeAll();
	clearAllCities();

	//m_units.removeAll();
	clearAllUnits();
	m_pTempUnit = NULL;

	m_selectionGroups.removeAll();

	m_eventsTriggered.removeAll();

	if (!bConstructorCall)
	{
		m_BuildingList.init();
		AI_reset(false);
	}

/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	// RevolutionDCM start - new diplomacy option
	setDoNotBotherStatus(NO_PLAYER);
	// RevolutionDCM end
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/
	m_UnitList.init();

	m_iNumAnimalsSubdued = 0;
	m_iNumAnarchyTurns = 0;
	m_iNumCivicSwitches = 0;
	m_iNumCivicsSwitched = 0;
	m_unitConstructionCounts.clear();

	m_bMaintenanceDirty = false;
	m_bUpdatesDeferred = false;
	Commanders.clear();
}

/************************************************************************************************/
/* CHANGE_PLAYER                          08/17/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// for logging
//
void CvPlayer::logMsg(char* format, ... )
{
	if (GC.isXMLLogging())
	{
		static char buf[2048];
		_vsnprintf( buf, 2048-4, format, (char*)(&format+1) );
		gDLL->logMsg("sdkDbg.log", buf);
	}
}

/************************************************************************************************/
/* CHANGE_PLAYER                           END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* CHANGE_PLAYER                          08/17/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// for stripping obsolete trait bonuses
// for complete reset, use in conjunction with addTraitBonuses
//
void CvPlayer::clearTraitBonuses( )
{
	int iI;

	FAssertMsg((GC.getNumTraitInfos() > 0), "GC.getNumTraitInfos() is less than or equal to zero but is expected to be larger than zero in CvPlayer::init");
	for (iI = 0; iI < GC.getNumTraitInfos(); iI++)
	{
		if (hasTrait((TraitTypes)iI))
		{
			processTrait((TraitTypes)iI, -1);
		}
	}
}

//
// for adding new trait bonuses
//
void CvPlayer::addTraitBonuses( )
{
	int iI;

	FAssertMsg((GC.getNumTraitInfos() > 0), "GC.getNumTraitInfos() is less than or equal to zero but is expected to be larger than zero in CvPlayer::init");
	for (iI = 0; iI < GC.getNumTraitInfos(); iI++)
	{
		if (hasTrait((TraitTypes)iI))
		{
			processTrait((TraitTypes)iI, 1);
		}
	}

	updateMaxAnarchyTurns();

	for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
	{
		updateExtraYieldThreshold((YieldTypes)iI);
	}
}
/************************************************************************************************/
/* CHANGE_PLAYER                           END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* CHANGE_PLAYER                          08/17/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// for changing the personality of the player
//
void CvPlayer::changePersonalityType( )
{
	LeaderHeadTypes eBestPersonality;
	int iValue;
	int iBestValue;
	int iI, iJ;

	if (GC.getGameINLINE().isOption(GAMEOPTION_RANDOM_PERSONALITIES))
	{
		if (!isBarbarian())
		{
			iBestValue = 0;
			eBestPersonality = NO_LEADER;

			for (iI = 0; iI < GC.getNumLeaderHeadInfos(); iI++)
			{
				if (iI != GC.getDefineINT("BARBARIAN_LEADER")) // XXX minor civ???
				{
					iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "Choosing Personality"));

					for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
					{
						if (GET_PLAYER((PlayerTypes)iJ).isAlive())
						{
							if (GET_PLAYER((PlayerTypes)iJ).getPersonalityType() == ((LeaderHeadTypes)iI))
							{
								iValue /= 2;
							}
						}
					}

					if (iValue > iBestValue)
					{
						iBestValue = iValue;
						eBestPersonality = ((LeaderHeadTypes)iI);
					}
				}
			}

			if (eBestPersonality != NO_LEADER)
			{
				setPersonalityType(eBestPersonality);
			}
		}
	}
	else
	{
		setPersonalityType( getLeaderType() );
	}
}
/************************************************************************************************/
/* CHANGE_PLAYER                           END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* CHANGE_PLAYER                          08/17/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// reset state of event logic, unit prices
//
void CvPlayer::resetCivTypeEffects( )
{
	int iI;

	if( !isAlive() ) 
	{
		for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
		{
			setCivics(((CivicOptionTypes)iI), ((CivicTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationInitialCivics(iI))));
		}

		for (iI = 0; iI < GC.getNumEventInfos(); iI++)
		{
			resetEventOccured((EventTypes)iI, false);
		}

		for (iI = 0; iI < GC.getNumEventTriggerInfos(); iI++)
		{
			if( (!GC.getEventTriggerInfo((EventTriggerTypes)iI).isGlobal()) && (!GC.getEventTriggerInfo((EventTriggerTypes)iI).isTeam() || GET_TEAM(getTeam()).getNumMembers() == 1) )
			{
				resetTriggerFired((EventTriggerTypes)iI);
			}
		}
	}

	for (iI = 0; iI < GC.getNumUnitClassInfos(); ++iI)
	{
		UnitTypes eUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));

		if (NO_UNIT != eUnit)
		{
			if (GC.getUnitInfo(eUnit).isFound())
			{
				setUnitExtraCost((UnitClassTypes)iI, getNewCityProductionValue());
			}
		}
	}
}
/************************************************************************************************/
/* CHANGE_PLAYER                           END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* CHANGE_PLAYER                          08/17/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// for switching the leaderhead of this player
//
void CvPlayer::changeLeader( LeaderHeadTypes eNewLeader )
{
	LeaderHeadTypes eOldLeader = getLeaderType();

	if( eOldLeader == eNewLeader )
		return;

	// Clear old traits
	clearTraitBonuses();

	GC.getInitCore().setLeader( getID(), eNewLeader );

	// Add new traits
	addTraitBonuses();

	// Set new personality
	changePersonalityType();

	if( isAlive() || isEverAlive() )
	{
		gDLL->getInterfaceIFace()->setDirty(HighlightPlot_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(UnitInfo_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(InfoPane_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Flag_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(MinimapSection_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Foreign_Screen_DIRTY_BIT, true);
	}

	AI_init();
}
/************************************************************************************************/
/* CHANGE_PLAYER                           END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* CHANGE_PLAYER                          05/09/09                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// for changing the civilization of this player
//
void CvPlayer::changeCiv( CivilizationTypes eNewCiv )
{
	CivilizationTypes eOldCiv = getCivilizationType();
	PlayerColorTypes eColor = (PlayerColorTypes)GC.getCivilizationInfo(eNewCiv).getDefaultPlayerColor();

	if( eOldCiv == eNewCiv )
		return;

	for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
	{
		if (eColor == NO_PLAYERCOLOR || (GET_PLAYER((PlayerTypes)iI).getPlayerColor() == eColor && iI != getID()) )
		{
			for (int iK = 0; iK < GC.getNumPlayerColorInfos(); iK++)
			{
				if (iK != GC.getCivilizationInfo((CivilizationTypes)GC.getDefineINT("BARBARIAN_CIVILIZATION")).getDefaultPlayerColor())
				{
					bool bValid = true;

					for (int iL = 0; iL < MAX_CIV_PLAYERS; iL++)
					{
						if (GET_PLAYER((PlayerTypes)iL).getPlayerColor() == iK)
						{
							bValid = false;
							break;
						}
					}

					if (bValid)
					{
						eColor = (PlayerColorTypes)iK;
						iI = MAX_CIV_PLAYERS;
						break;
					}
				}
			}
		}
	}

	GC.getInitCore().setCiv( getID(), eNewCiv );
	GC.getInitCore().setColor( getID(), eColor );

	resetCivTypeEffects();

	if( isAlive() )
	{
		// if the player is alive and showing on scoreboard, etc
		// change colors, graphics, flags, units
		GC.getInitCore().setFlagDecal( getID(), (CvWString)GC.getCivilizationInfo(eNewCiv).getFlagTexture() );
		GC.getInitCore().setArtStyle( getID(), (ArtStyleTypes)GC.getCivilizationInfo(eNewCiv).getArtStyleType() );

		// Forces update of units flags
		EraTypes eEra = getCurrentEra();
		bool bAuto = m_bDisableHuman;
		m_bDisableHuman = true;
		//setCurrentEra((EraTypes)((eEra + 1)%GC.getNumEraInfos()));
		setCurrentEra((EraTypes)0);
		setCurrentEra((EraTypes)(GC.getNumEraInfos() - 1));

		setCurrentEra(eEra);
		m_bDisableHuman = bAuto;
		gDLL->getInterfaceIFace()->makeInterfaceDirty();
		

		int iLoop;
		CvCity* pLoopCity;
		// dirty all of this player's cities...
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			if (pLoopCity->getOwnerINLINE() == getID())
			{
				pLoopCity->setLayoutDirty(true);
			}
		}

		//update unit eras
		CvUnit* pLoopUnit;
		CvPlot* pLoopPlot;
		for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			pLoopUnit->reloadEntity();
			pLoopPlot = pLoopUnit->plot();
/*
			if( pLoopPlot != NULL )
			{
				
				CvFlagEntity* pFlag = pLoopPlot->getFlagSymbol();

				if( pFlag != NULL )
				{

					if( gDLL->getFlagEntityIFace()->getPlayer(pFlag) == getID() )
					{
						gDLL->getFlagEntityIFace()->destroy(pFlag);
						CvFlagEntity* pNewFlag = gDLL->getFlagEntityIFace()->create(getID());
						if (pFlag != NULL)
						{
							gDLL->getFlagEntityIFace()->setPlot(pNewFlag, pLoopPlot, false);
						}

						gDLL->getFlagEntityIFace()->updateGraphicEra(pNewFlag);
					}

				}
				
				pLoopPlot->setFlagDirty(true);
				//pLoopPlot->updateGraphicEra();
			}
*/
		}

		//update flag eras
		gDLL->getInterfaceIFace()->setDirty(Flag_DIRTY_BIT, true);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(Soundtrack_DIRTY_BIT, true);
		}

		gDLL->getInterfaceIFace()->makeInterfaceDirty();

		// Need to force redraw
		gDLL->getEngineIFace()->SetDirty(CultureBorders_DIRTY_BIT, true);
		gDLL->getEngineIFace()->SetDirty(MinimapTexture_DIRTY_BIT, true);
		gDLL->getEngineIFace()->SetDirty(GlobeTexture_DIRTY_BIT, true);
		gDLL->getEngineIFace()->SetDirty(GlobePartialTexture_DIRTY_BIT, true);

		gDLL->getInterfaceIFace()->setDirty(ColoredPlots_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(HighlightPlot_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(UnitInfo_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(InfoPane_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(GlobeLayer_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(MinimapSection_DIRTY_BIT, true);
		gDLL->getEngineIFace()->SetDirty(MinimapTexture_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Foreign_Screen_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(SelectionSound_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(GlobeInfo_DIRTY_BIT, true);
	}
	else if( isEverAlive() )
	{
		// Not currently alive, but may show on some people's scoreboard
		// or graphs
		// change colors
		gDLL->getInterfaceIFace()->setDirty(InfoPane_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
	}

	setupGraphical();
}
/************************************************************************************************/
/* CHANGE_PLAYER                           END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* CHANGE_PLAYER                          08/17/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// for changing whether this player is human or not
//
void CvPlayer::setIsHuman( bool bNewValue )
{
	if( bNewValue == isHuman() )
		return;

	if( bNewValue )
		GC.getInitCore().setSlotStatus( getID(), SS_TAKEN );
	else
		GC.getInitCore().setSlotStatus( getID(), SS_COMPUTER ); // or SS_OPEN for multiplayer?

}
/************************************************************************************************/
/* CHANGE_PLAYER                          END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// for setting status of player to rebel, which affords some benefits
//
void CvPlayer::setIsRebel( bool bNewValue )
{
	if( bNewValue == isRebel() )
		return;
	else
		m_bRebel = bNewValue;
}

bool CvPlayer::isRebel() const
{
	return m_bRebel;
}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* REVOLUTION_MOD                         06/11/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
int CvPlayer::getStabilityIndex( ) const
{
	return m_iStabilityIndex;
}

void CvPlayer::setStabilityIndex( int iNewValue )
{
	m_iStabilityIndex = range(iNewValue,0,1000);
}

void CvPlayer::changeStabilityIndex( int iChange )
{
	setStabilityIndex( getStabilityIndex() + iChange );
}

int CvPlayer::getStabilityIndexAverage( ) const
{
	return m_iStabilityIndexAverage;
}

void CvPlayer::setStabilityIndexAverage( int iNewValue )
{
	m_iStabilityIndexAverage = range(iNewValue,0,1000);
}

void CvPlayer::updateStabilityIndexAverage( )
{
	setStabilityIndexAverage( (2*getStabilityIndexAverage() + getStabilityIndex())/3 );
}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

//////////////////////////////////////
// graphical only setup
//////////////////////////////////////
void CvPlayer::setupGraphical()
{
	if (!GC.IsGraphicsInitialized())
		return;

	CvCity* pLoopCity;
	CvUnit* pLoopUnit;

	// Setup m_cities
	int iLoop;
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->setupGraphical();
	}

	// Setup m_units
	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		//pLoopUnit->setupGraphical();
		pLoopUnit->reloadEntity();
	}
}


void CvPlayer::initFreeState()
{
	setGold(0);
	changeGold(GC.getHandicapInfo(getHandicapType()).getStartingGold());
	changeGold(GC.getEraInfo(GC.getGameINLINE().getStartEra()).getStartingGold());

	clearResearchQueue();
}


void CvPlayer::initFreeUnits()
{
	UnitTypes eLoopUnit;
	int iFreeCount;
	int iI, iJ;

	if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_START) && !isBarbarian())
	{
		int iPoints = GC.getGameINLINE().getNumAdvancedStartPoints();

		iPoints *= GC.getHandicapInfo(getHandicapType()).getAdvancedStartPointsMod();
		iPoints /= 100;

		if (!isHuman())
		{
			iPoints *= GC.getHandicapInfo(getHandicapType()).getAIAdvancedStartPercent();
			iPoints /= 100;
		}

		setAdvancedStartPoints(iPoints);

		// Starting visibility
		CvPlot* pStartingPlot = getStartingPlot();
		if (NULL != pStartingPlot)
		{
			for (int iPlotLoop = 0; iPlotLoop < GC.getMapINLINE().numPlots(); ++iPlotLoop)
			{
				CvPlot* pPlot = GC.getMapINLINE().plotByIndex(iPlotLoop);

				if (plotDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE()) <= GC.getDefineINT("ADVANCED_START_SIGHT_RANGE"))
				{
					pPlot->setRevealed(getTeam(), true, false, NO_TEAM, false);
				}
			}
		}
	}
	else
	{
		for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
		{
			eLoopUnit = (UnitTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI);

			if (eLoopUnit != NO_UNIT)
			{
				iFreeCount = GC.getCivilizationInfo(getCivilizationType()).getCivilizationFreeUnitsClass(iI);

				iFreeCount *= (GC.getEraInfo(GC.getGameINLINE().getStartEra()).getStartingUnitMultiplier() + ((!isHuman()) ? GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIStartingUnitMultiplier() : 0));

				for (iJ = 0; iJ < iFreeCount; iJ++)
				{
					addFreeUnit(eLoopUnit);
				}
			}
		}

		iFreeCount = GC.getEraInfo(GC.getGameINLINE().getStartEra()).getStartingDefenseUnits();
		iFreeCount += GC.getHandicapInfo(getHandicapType()).getStartingDefenseUnits();

		if (!isHuman())
		{
			iFreeCount += GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIStartingDefenseUnits();
		}

		if (iFreeCount > 0)
		{
			addFreeUnitAI(UNITAI_CITY_DEFENSE, iFreeCount);
		}

		iFreeCount = GC.getEraInfo(GC.getGameINLINE().getStartEra()).getStartingWorkerUnits();
		iFreeCount += GC.getHandicapInfo(getHandicapType()).getStartingWorkerUnits();

		if (!isHuman())
		{
			iFreeCount += GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIStartingWorkerUnits();
		}

		if (iFreeCount > 0)
		{
			addFreeUnitAI(UNITAI_WORKER, iFreeCount);
		}

		iFreeCount = GC.getEraInfo(GC.getGameINLINE().getStartEra()).getStartingExploreUnits();
		iFreeCount += GC.getHandicapInfo(getHandicapType()).getStartingExploreUnits();

		if (!isHuman())
		{
			iFreeCount += GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIStartingExploreUnits();
		}

		if (iFreeCount > 0)
		{
			addFreeUnitAI(UNITAI_EXPLORE, iFreeCount);
		}
	}
}


/************************************************************************************************/
/* LoR                                        11/03/10                          phungus420      */
/*                                                                                              */
/* Colonists                                                                                    */
/************************************************************************************************/
UnitTypes CvPlayer::getBestUnitType(UnitAITypes eUnitAI) const
{
	UnitTypes eLoopUnit;
	UnitTypes eBestUnit = NO_UNIT;
	bool bValid;
	int iValue;
	int iBestValue = 0;
	int iI, iJ;

	for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
	{
		eLoopUnit = (UnitTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI);

		if (eLoopUnit != NO_UNIT)
		{
			if (canTrain(eLoopUnit))
			{
				bValid = true;

				if (GC.getUnitInfo(eLoopUnit).getPrereqAndBonus() != NO_BONUS)
				{
					bValid = false;
				}

				for (iJ = 0; iJ < GC.getNUM_UNIT_PREREQ_OR_BONUSES(); iJ++)
				{
					if (GC.getUnitInfo(eLoopUnit).getPrereqOrBonuses(iJ) != NO_BONUS)
					{
						bValid = false;
					}
				}

				if (bValid)
				{
					iValue = AI_unitValue(eLoopUnit, eUnitAI, NULL);

					if (iValue > iBestValue)
					{
						eBestUnit = eLoopUnit;
						iBestValue = iValue;
					}
				}
			}
		}
	}

	return eBestUnit;
}
/************************************************************************************************/
/* LoR                            END                                                           */
/************************************************************************************************/


void CvPlayer::addFreeUnitAI(UnitAITypes eUnitAI, int iCount)
{
	UnitTypes eLoopUnit;
	UnitTypes eBestUnit;
	bool bValid;
	int iValue;
	int iBestValue;
	int iI, iJ;

	eBestUnit = NO_UNIT;
	iBestValue = 0;

	for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
	{
		eLoopUnit = (UnitTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI);

		if (eLoopUnit != NO_UNIT)
		{
			if (canTrain(eLoopUnit))
			{
				bValid = true;

				if (GC.getUnitInfo(eLoopUnit).getPrereqAndBonus() != NO_BONUS)
				{
					bValid = false;
				}

				for (iJ = 0; iJ < GC.getNUM_UNIT_PREREQ_OR_BONUSES(); iJ++)
				{
					if (GC.getUnitInfo(eLoopUnit).getPrereqOrBonuses(iJ) != NO_BONUS)
					{
						bValid = false;
					}
				}

				if (bValid)
				{
					iValue = AI_unitValue(eLoopUnit, eUnitAI, NULL);

					if (iValue > iBestValue)
					{
						eBestUnit = eLoopUnit;
						iBestValue = iValue;
					}
				}
			}
		}
	}

	if (eBestUnit != NO_UNIT)
	{
		for (iI = 0; iI < iCount; iI++)
		{
			addFreeUnit(eBestUnit, eUnitAI);
		}
	}
}


void CvPlayer::addFreeUnit(UnitTypes eUnit, UnitAITypes eUnitAI)
{
	CvPlot* pStartingPlot;
	CvPlot* pBestPlot;
	CvPlot* pLoopPlot;
	int iRandOffset;
	int iI;

	if (GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && isHuman())
	{
		if ((eUnitAI == UNITAI_SETTLE) || (GC.getUnitInfo(eUnit).getDefaultUnitAIType() == UNITAI_SETTLE))
		{
			if (AI_getNumAIUnits(UNITAI_SETTLE) >= 1)
			{
				return;
			}
		}
	}

	pStartingPlot = getStartingPlot();

	if (pStartingPlot != NULL)
	{
		pBestPlot = NULL;

		if (isHuman())
		{
			long lResult=0;
			PYTHON_CALL_FUNCTION4(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "startHumansOnSameTile", NULL, &lResult);
			if (lResult == 0)
			{
				if (!(GC.getUnitInfo(eUnit).isFound()))
				{
					iRandOffset = GC.getGameINLINE().getSorenRandNum(NUM_CITY_PLOTS, "Place Units (Player)");

					for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
					{
						pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), ((iI + iRandOffset) % NUM_CITY_PLOTS));

						if (pLoopPlot != NULL)
						{
							if (pLoopPlot->getArea() == pStartingPlot->getArea())
							{
							/************************************************************************************************/
							/* Afforess	Mountains Start		 09/18/09                                           		 */
							/*                                                                                              */
							/*                                                                                              */
							/************************************************************************************************/
								if (!(pLoopPlot->isImpassable(getTeam()))) // added getTeam()
							/************************************************************************************************/
							/* Afforess	Mountains End       END        		                                             */
							/************************************************************************************************/
								{
									if (!(pLoopPlot->isUnit()))
									{
										if (!(pLoopPlot->isGoody()))
										{
											pBestPlot = pLoopPlot;
											break;
										}
									}
								}
							}
						}
					}
				}
			}
		}

		if (pBestPlot == NULL)
		{
			pBestPlot = pStartingPlot;
		}

		initUnit(eUnit, pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), eUnitAI, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
	}
}


int CvPlayer::startingPlotRange() const
{
	int iRange;

	iRange = (GC.getMapINLINE().maxStepDistance() + 10);

	iRange *= GC.getDefineINT("STARTING_DISTANCE_PERCENT");
	iRange /= 100;

	iRange *= (GC.getMapINLINE().getLandPlots() / (GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getTargetNumCities() * GC.getGameINLINE().countCivPlayersAlive()));
	iRange /= NUM_CITY_PLOTS;

	iRange += std::min(((GC.getMapINLINE().getNumAreas() + 1) / 2), GC.getGameINLINE().countCivPlayersAlive());

	long lResult=0;
	if (PYTHON_CALL_FUNCTION4(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "minStartingDistanceModifier", NULL, &lResult))
	{
		iRange *= std::max<int>(0, (lResult + 100));
		iRange /= 100;
	}

	return std::max(iRange, GC.getDefineINT("MIN_CIV_STARTING_DISTANCE"));
}


bool CvPlayer::startingPlotWithinRange(CvPlot* pPlot, PlayerTypes ePlayer, int iRange, int iPass) const
{
	//PROFILE_FUNC();

	//XXX changes to AI_foundValue (which are far more flexible) make this function 
	//    redundant but it is still called from Python. 
	return false;
}

int CvPlayer::startingPlotDistanceFactor(CvPlot* pPlot, PlayerTypes ePlayer, int iRange) const
{
	PROFILE_FUNC();
	
	FAssert(ePlayer != getID());

	CvPlot* pStartingPlot;
	
	int iValue = 1000;

	pStartingPlot = getStartingPlot();

	if (pStartingPlot != NULL)
	{
		if (GC.getGameINLINE().isTeamGame())
		{
			if (GET_PLAYER(ePlayer).getTeam() == getTeam())
			{
				iRange *= GC.getDefineINT("OWN_TEAM_STARTING_MODIFIER");
				iRange /= 100;
			}
			else
			{
				iRange *= GC.getDefineINT("RIVAL_TEAM_STARTING_MODIFIER");
				iRange /= 100;
			}
		}

		int iDistance = stepDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE());
		if (pStartingPlot->getArea() != pPlot->getArea())
		{
			iDistance *= 4;            	
			iDistance /= 3;
		}

		iValue *= iDistance;
		iValue /= iRange ;

	}
    
	return std::max(1, iValue);

}


// Returns the id of the best area, or -1 if it doesn't matter:
int CvPlayer::findStartingArea() const
{
	PYTHON_ACCESS_LOCK_SCOPE
	PROFILE_FUNC();

	long result = -1;
	CyArgsList argsList;
	argsList.add(getID());		// pass in this players ID
	if (PYTHON_CALL_FUNCTION4(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "findStartingArea", argsList.makeFunctionArgs(), &result))
	{
		if (!gDLL->getPythonIFace()->pythonUsingDefaultImpl()) // Python override
		{
			if (result == -1 || GC.getMapINLINE().getArea(result) != NULL)
			{
				return result;
			}
			else
			{
				FAssertMsg(false, "python findStartingArea() must return -1 or the ID of a valid area");
			}
		}
	}

	int iBestValue = 0;
	int iBestArea = -1;
	int iValue;
	int iLoop = 0;

	CvArea *pLoopArea = NULL;

	// find best land area
	for(pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop))
	{
		if (!(pLoopArea->isWater()))
		{
			// iNumPlayersOnArea is the number of players starting on the area, plus this player
			int iNumPlayersOnArea = (pLoopArea->getNumStartingPlots() + 1);
			int iTileValue = ((pLoopArea->calculateTotalBestNatureYield() + (pLoopArea->countCoastalLand() * 2) + pLoopArea->getNumRiverEdges() + (pLoopArea->getNumTiles())) + 1);
			iValue = iTileValue / iNumPlayersOnArea;

			iValue *= std::min(NUM_CITY_PLOTS + 1, pLoopArea->getNumTiles() + 1);
			iValue /= (NUM_CITY_PLOTS + 1);

			if (iNumPlayersOnArea <= 2)
			{
				iValue *= 4;
				iValue /= 3;
			}

			if (iValue > iBestValue)
			{
				iBestValue = iValue;
				iBestArea = pLoopArea->getID();
			}
		}
	}

	return iBestArea;
}


CvPlot* CvPlayer::findStartingPlot(bool bRandomize)
{
	PROFILE_FUNC();

	{
		PYTHON_ACCESS_LOCK_SCOPE

		long result = -1;
		CyArgsList argsList;
		argsList.add(getID());		// pass in this players ID
		if (PYTHON_CALL_FUNCTION4(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "findStartingPlot", argsList.makeFunctionArgs(), &result))
		{
			if (!gDLL->getPythonIFace()->pythonUsingDefaultImpl()) // Python override
			{
				CvPlot *pPlot = GC.getMapINLINE().plotByIndexINLINE(result);
				if (pPlot != NULL)
				{
					return pPlot;
				}
				else
				{
					FAssertMsg(false, "python findStartingPlot() returned an invalid plot index!");
				}
			}
		}
	}

	CvPlot* pLoopPlot;
	bool bValid;
	int iBestArea = -1;
	int iValue;
	//int iRange;
	int iI;

	bool bNew = false;
	if (getStartingPlot() != NULL)
	{
		iBestArea = getStartingPlot()->getArea();
		setStartingPlot(NULL, true);
		bNew = true;
	}

	AI_updateFoundValues(true);
	
	if (!bNew)
	{
		iBestArea = findStartingArea();
	}

	//iRange = startingPlotRange();
	for(int iPass = 0; iPass < GC.getMapINLINE().maxPlotDistance(); iPass++)
	{
		CvPlot *pBestPlot = NULL;
		int iBestValue = 0;
		
		for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
		{
			pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

			if ((iBestArea == -1) || (pLoopPlot->getArea() == iBestArea))
			{
				//the distance factor is now done inside foundValue
				iValue = pLoopPlot->getFoundValue(getID());

				if (bRandomize && iValue > 0)
				{
					iValue += GC.getGameINLINE().getSorenRandNum(10000, "Randomize Starting Location");
				}

				if (iValue > iBestValue)
				{
					bValid = true;

					if (bValid)
					{
						iBestValue = iValue;
						pBestPlot = pLoopPlot;
					}
				}
			}
		}

		if (pBestPlot != NULL)
		{
			return pBestPlot;
		}

		FAssertMsg(iPass != 0, "CvPlayer::findStartingPlot - could not find starting plot in first pass.");
	}

	FAssertMsg(false, "Could not find starting plot.");
	return NULL;
}


CvPlotGroup* CvPlayer::initPlotGroup(CvPlot* pPlot, bool bRecalculateBonuses)
{
	CvPlotGroup* pPlotGroup;

	pPlotGroup = addPlotGroup();

	FAssertMsg(pPlotGroup != NULL, "PlotGroup is not assigned a valid value");

	pPlotGroup->init(pPlotGroup->getID(), getID(), pPlot, bRecalculateBonuses);

	return pPlotGroup;
}

CvCity* CvPlayer::initCity(int iX, int iY, bool bBumpUnits, bool bUpdatePlotGroups)
{
	PROFILE_FUNC();

	CvPlot*	pCityPlot = GC.getMapINLINE().plotINLINE(iX,iY);
	int iI, iJ;

	if ( bUpdatePlotGroups )
	{
		//	Take this group out of plot groups to remove any existing bonuses
		//	from it (it might have a resource)
		for (iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).isAlive())
			{
				CvPlotGroup* pOldPlotGroup = pCityPlot->getPlotGroup((PlayerTypes)iI);

				if ( pOldPlotGroup != NULL )
				{
					pOldPlotGroup->removePlot(pCityPlot);
				}
			}
		}
	}

	CvCity* pCity;

	pCity = addCity();

	FAssertMsg(pCity != NULL, "City is not assigned a valid value");
	FAssertMsg(!(GC.getMapINLINE().plotINLINE(iX, iY)->isCity()), "No city is expected at this plot when initializing new city");

	pCity->init(pCity->getID(), getID(), iX, iY, bBumpUnits, false);

	if ( bUpdatePlotGroups )
	{
		//	Set the city plots plot groups again
		for (iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).isAlive())
			{
				//	Need to check whether any cultural border chnages for this city
				//	have sliced anyone's trade networks
				bool tradeNetworkPotentiallyCut = false;

				if ( atWar(getTeam(), GET_PLAYER((PlayerTypes)iI).getTeam()) )
				{
					for (iJ = 0; iJ < pCity->getNumCityPlots(); iJ++)
					{
						CvPlot* pPlot = pCity->getCityIndexPlot(iJ);

						if (pPlot != NULL && pPlot->getOwnerINLINE() == getID())
						{
							if (pPlot->getPlotGroup((PlayerTypes)iI) != NULL )
							{
								//	Player who the city founder is at war with has
								//	a trade route intersecting the are newly controlled by
								//	the founded city
								tradeNetworkPotentiallyCut = true;
								break;
							}
						}
					}
				}

				if ( tradeNetworkPotentiallyCut )
				{
					//	Need to recalculate
					GET_PLAYER((PlayerTypes)iI).updatePlotGroups();
				}
				else
				{
					//	No meaningful changes - just add this city plot back in
					pCityPlot->updatePlotGroup((PlayerTypes)iI);
				}
			}
		}
	}

	return pCity;
}


void CvPlayer::acquireCity(CvCity* pOldCity, bool bConquest, bool bTrade, bool bUpdatePlotGroups)
{
	PROFILE_FUNC();

/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* Copy over city data                                                                          */
/************************************************************************************************/
	std::string scriptData;
	int iRevIdx;
	int iLocalRevIdx;
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

	CLLNode<IDInfo>* pUnitNode;
	CvCity* pNewCity;
	CvUnit* pLoopUnit;
	CvPlot* pCityPlot;
	CvPlot* pLoopPlot;
	bool* pabHasReligion;
	bool* pabHolyCity;
	bool* pabHasCorporation;
	bool* pabHeadquarters;
	int* paiNumRealBuilding;
	int* paiBuildingOriginalOwner;
	int* paiBuildingOriginalTime;
	CvWString szBuffer;
	CvWString szName;
	bool abEverOwned[MAX_PLAYERS];
	int aiCulture[MAX_PLAYERS];
	PlayerTypes eOldOwner;
	PlayerTypes eOriginalOwner;
	PlayerTypes eHighestCulturePlayer;
	BuildingTypes eBuilding;
	bool bRecapture;
	bool bRaze;
	bool bGift;
	int iRange;
	int iCaptureGold;
	int iGameTurnFounded;
	int iPopulation;
	int iHighestPopulation;
	int iHurryAngerTimer;
	int iConscriptAngerTimer;
	int iDefyResolutionAngerTimer;
	int iOccupationTimer;
	int iTeamCulturePercent;
	int iDamage;
	int iDX, iDY;
	int iI;
	CLinkList<IDInfo> oldUnits;
	std::vector<int> aeFreeSpecialists;
	CvPlotGroup* originalTradeNetworkConnectivity[MAX_PLAYERS];

/************************************************************************************************/
/* Afforess	                  Start		 02/15/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	int iOccupationRange = 0;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
/************************************************************************************************/
/* Afforess	                  Start		 06/14/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	int iOccupationTimeModifier = 100;
	for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		if (pOldCity->getNumRealBuilding((BuildingTypes)iI) > 0)
		{
			if (GC.getBuildingInfo((BuildingTypes)iI).getOccupationTimeModifier() != 0)
			{
				iOccupationTimeModifier += GC.getBuildingInfo((BuildingTypes)iI).getOccupationTimeModifier();
			}
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	pCityPlot = pOldCity->plot();
	eOldOwner = pOldCity->getOwnerINLINE();

	//	Whose trade networks was this city relevant to prior to ownership change
	if ( bUpdatePlotGroups )
	{
		for(int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			originalTradeNetworkConnectivity[iI] = GET_PLAYER((PlayerTypes)iI).isAlive() ? pCityPlot->getPlotGroup((PlayerTypes)iI) : NULL;
		}
	}
	
	pUnitNode = pCityPlot->headUnitNode();

	while (pUnitNode != NULL)
	{
		oldUnits.insertAtEnd(pUnitNode->m_data);
		pUnitNode = pCityPlot->nextUnitNode(pUnitNode);
	}

	pUnitNode = oldUnits.head();

	while (pUnitNode != NULL)
	{
		pLoopUnit = ::getUnit(pUnitNode->m_data);
		pUnitNode = oldUnits.next(pUnitNode);

		if (pLoopUnit && pLoopUnit->getTeam() != getTeam())
		{
			if (pLoopUnit->getDomainType() == DOMAIN_IMMOBILE)
			{
				pLoopUnit->kill(false, getID());
			}
		}
	}
/************************************************************************************************/
/* Afforess	                  Start		 07/21/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	iRange = pOldCity->getMaxCultureLevelAmongPlayers();

	iOccupationRange = iRange;

	if (hasFixedBorders())
	{
		pOldCity->clearCultureDistanceCache();
		for (iDX = -(iRange); iDX <= iRange; iDX++)
		{
			for (iDY = -(iRange); iDY <= iRange; iDY++)
			{
				if (pOldCity->cultureDistance(iDX, iDY) <= iRange)
				{
					pLoopPlot = plotXY(pOldCity->getX_INLINE(),pOldCity-> getY_INLINE(), iDX, iDY);

					if (pLoopPlot != NULL)
					{
						if (!pLoopPlot->isCity())	
						{
							if ((pLoopPlot->getOwnerINLINE() == pOldCity->getOwnerINLINE()) || (pLoopPlot->getOwnerINLINE() == NO_PLAYER))
							{
								bool bCultureLevelFound = false;
								bool bDoClaim = false;

								for (int iJ = 0; iJ < GC.getNumCultureLevelInfos(); ++iJ)
								{
									int iNumCitiesForRange = pLoopPlot->getCultureRangeCities(pOldCity->getOwnerINLINE(), iJ);
									
									// Occupy the tile if it is within the city's culture range, but not within any other city's range at the same or closer distance 
									if ((iNumCitiesForRange == 1) && ((pOldCity->getCultureLevel() >= iJ) && (pOldCity->cultureDistance(iDX, iDY) == iJ))) 
									{
										bDoClaim = true;
									}
									
									if (iNumCitiesForRange > 0) 
									{
										bCultureLevelFound = true;
										break;
									} 
								}

								// Occupy the tile if it is NOT within the city's culture range, but is within occupation range 
								if (!bCultureLevelFound)
								{
									if (pOldCity->cultureDistance(iDX, iDY) <= pOldCity->getOccupationCultureLevel())
									{
										bDoClaim = true;
									}
								}

								if (bDoClaim && pLoopPlot->isPotentialCityWorkForArea(pOldCity->area()))
								{							
									pLoopPlot->setClaimingOwner(getID());
									pLoopPlot->setForceUnownedTimer(1);
								}								
							}
						}
					}
				}
			}
		}
	}
	if (bConquest && !hasFixedBorders())
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	{
		iRange = pOldCity->getCultureLevel();

		for (iDX = -(iRange); iDX <= iRange; iDX++)
		{
			for (iDY = -(iRange); iDY <= iRange; iDY++)
			{
/************************************************************************************************/
/* Afforess	                  Start		 02/15/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
				if ((pOldCity->cultureDistance(iDX, iDY) <= iRange) && (pOldCity->cultureDistance(iDX, iDY) > 1))
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
				{
					pLoopPlot = plotXY(pOldCity->getX_INLINE(),pOldCity-> getY_INLINE(), iDX, iDY);

					if (pLoopPlot != NULL)
					{
						if (pLoopPlot->getOwnerINLINE() == pOldCity->getOwnerINLINE())	
						{
							if (pLoopPlot->getNumCultureRangeCities(pOldCity->getOwnerINLINE()) == 1)
							{
								bool bForceUnowned = false;

								for (iI = 0; iI < MAX_PLAYERS; iI++)
								{
									if (GET_PLAYER((PlayerTypes)iI).isAlive())
									{
										if ((GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam()) && (GET_PLAYER((PlayerTypes)iI).getTeam() != pOldCity->getTeam()))
										{
											if (pLoopPlot->getNumCultureRangeCities((PlayerTypes)iI) > 0)
											{
												bForceUnowned = true;
												break;
											}
										}
									}
								}

								if (bForceUnowned)
								{
									pLoopPlot->setForceUnownedTimer(GC.getDefineINT("FORCE_UNOWNED_CITY_TIMER"));
								}
							}
						}
					}
				}
			}
		}
	}

	if (pOldCity->getOriginalOwner() == pOldCity->getOwnerINLINE())
	{
		GET_PLAYER(pOldCity->getOriginalOwner()).changeCitiesLost(1);
	}
/************************************************************************************************/
/* REVOLUTION_MOD                         05/30/08                                jdog5000      */
/*                                                                                              */
/* For BarbarianCiv                                                                             */
/************************************************************************************************/
	// Added new BarbCiv specfic circumstance for counting a city as lost
	else if( !GC.getGame().isOption(GAMEOPTION_NO_BARBARIAN_CIV) && pOldCity->isCapital() && pOldCity->getOriginalOwner() == GC.getBARBARIAN_PLAYER() )
	{
		GET_PLAYER(pOldCity->getOwnerINLINE()).changeCitiesLost(1);
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
	else if (pOldCity->getOriginalOwner() == getID())
	{
		GET_PLAYER(pOldCity->getOriginalOwner()).changeCitiesLost(-1);
	}

	if (bConquest)
	{
		{
			MEMORY_TRACK_EXEMPT();

			szBuffer = gDLL->getText("TXT_KEY_MISC_CAPTURED_CITY", pOldCity->getNameKey()).GetCString();
			AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CITYCAPTURE", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_CITY_EDIT")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pOldCity->getX_INLINE(), pOldCity->getY_INLINE(), true, true);
		}
		szName.Format(L"%s (%s)", pOldCity->getName().GetCString(), GET_PLAYER(pOldCity->getOwnerINLINE()).getName());

		for (iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).isAlive())
			{
				if (iI != getID())
				{
					MEMORY_TRACK_EXEMPT();

					if (pOldCity->isRevealed(GET_PLAYER((PlayerTypes)iI).getTeam(), false))
					{
						szBuffer = gDLL->getText("TXT_KEY_MISC_CITY_CAPTURED_BY", szName.GetCString(), getCivilizationDescriptionKey());
						AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CITYCAPTURED", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_CITY_EDIT")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pOldCity->getX_INLINE(), pOldCity->getY_INLINE(), true, true);
					}
				/************************************************************************************************/
				/* Afforess	                  Start		 12/9/09                                                */
				/*                                                                                              */
				/*                                                                                              */
				/************************************************************************************************/
					else if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHasEmbassy(getTeam()))
					{
						szBuffer = gDLL->getText("TXT_KEY_MISC_CITY_CAPTURED_BY", szName.GetCString(), getCivilizationDescriptionKey());
						AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CITYCAPTURED", MESSAGE_TYPE_MAJOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_RED"));
					}
				/************************************************************************************************/
				/* Afforess	                     END                                                            */
				/************************************************************************************************/
				}
			}
		}

		szBuffer = gDLL->getText("TXT_KEY_MISC_CITY_WAS_CAPTURED_BY", szName.GetCString(), getCivilizationDescriptionKey());
		GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szBuffer, pOldCity->getX_INLINE(), pOldCity->getY_INLINE(), (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));
	}

	iCaptureGold = 0;

	if (bConquest)
	{
		PYTHON_ACCESS_LOCK_SCOPE

		long lCaptureGold;
		// Use python to determine city capture gold amounts...
		lCaptureGold = 0;

		CyCity* pyOldCity = new CyCity(pOldCity);

		CyArgsList argsList;
		argsList.add(gDLL->getPythonIFace()->makePythonObject(pyOldCity));	// pass in plot class
		
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "doCityCaptureGold", argsList.makeFunctionArgs(),&lCaptureGold);

		delete pyOldCity;	// python fxn must not hold on to this pointer 

		iCaptureGold = (int)lCaptureGold;
	}

	changeGold(iCaptureGold);

	pabHasReligion = new bool[GC.getNumReligionInfos()];
	pabHolyCity = new bool[GC.getNumReligionInfos()];
	pabHasCorporation = new bool[GC.getNumCorporationInfos()];
	pabHeadquarters = new bool[GC.getNumCorporationInfos()];
	paiNumRealBuilding = new int[GC.getNumBuildingInfos()];
	paiBuildingOriginalOwner = new int[GC.getNumBuildingInfos()];
	paiBuildingOriginalTime = new int[GC.getNumBuildingInfos()];

	for (iI = 0; iI < GC.getNumVoteSourceInfos(); ++iI)
	{
		pOldCity->processVoteSourceBonus((VoteSourceTypes)iI, false);
	}

	//	Koshling - need to remove bonuses due io old owner's trade network
	//	else it can feed into yield modifiers which are then incorrectly
	//	copied over to the new owner
	for (iI = 0; iI < GC.getNumBonusInfos(); ++iI)
	{
		if (pOldCity->hasBonus((BonusTypes)iI))
		{
			pOldCity->processBonus((BonusTypes)iI, -1);
		}
	}

	eOriginalOwner = pOldCity->getOriginalOwner();
	eHighestCulturePlayer = pOldCity->findHighestCulture();
	iGameTurnFounded = pOldCity->getGameTurnFounded();
	iPopulation = pOldCity->getPopulation();
	iHighestPopulation = pOldCity->getHighestPopulation();
	iHurryAngerTimer = pOldCity->getHurryAngerTimer();
	iConscriptAngerTimer = pOldCity->getConscriptAngerTimer();
	iDefyResolutionAngerTimer = pOldCity->getDefyResolutionAngerTimer();
	iOccupationTimer = pOldCity->getOccupationTimer();
	szName = pOldCity->getNameKey();
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	scriptData = pOldCity->getScriptData();
	iRevIdx = pOldCity->getRevolutionIndex();
	iLocalRevIdx = pOldCity->getLocalRevIndex();
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
	iDamage = pOldCity->getDefenseDamage();
	int iOldCityId = pOldCity->getID();

/************************************************************************************************/
/* Afforess	                  Start		 01/12/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	int iCiv = pOldCity->getCivilizationType();
	if (pOldCity->isBarbarian())
	{
	    iCiv = NO_CIVILIZATION;
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	
	for (iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
	{
		aeFreeSpecialists.push_back(pOldCity->getAddedFreeSpecialistCount((SpecialistTypes)iI));
	}

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		abEverOwned[iI] = pOldCity->isEverOwned((PlayerTypes)iI);
		aiCulture[iI] = pOldCity->getCultureTimes100((PlayerTypes)iI);
	}

	abEverOwned[getID()] = true;

	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		pabHasReligion[iI] = pOldCity->isHasReligion((ReligionTypes)iI);
		pabHolyCity[iI] = pOldCity->isHolyCity((ReligionTypes)iI);
	}

	for (iI = 0; iI < GC.getNumCorporationInfos(); iI++)
	{
		pabHasCorporation[iI] = pOldCity->isHasCorporation((CorporationTypes)iI);
		pabHeadquarters[iI] = pOldCity->isHeadquarters((CorporationTypes)iI);
	}

	for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		paiNumRealBuilding[iI] = pOldCity->getNumRealBuilding((BuildingTypes)iI);
		paiBuildingOriginalOwner[iI] = pOldCity->getBuildingOriginalOwner((BuildingTypes)iI);
		paiBuildingOriginalTime[iI] = pOldCity->getBuildingOriginalTime((BuildingTypes)iI);
	}

	std::vector<BuildingYieldChange> aBuildingYieldChange;
	std::vector<BuildingCommerceChange> aBuildingCommerceChange;
	BuildingChangeArray aBuildingHappyChange;
	BuildingChangeArray aBuildingHealthChange;
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); ++iI)
	{
		for (int iYield = 0; iYield < NUM_YIELD_TYPES; ++iYield)
		{
			BuildingYieldChange kChange;
			kChange.eBuildingClass = (BuildingClassTypes)iI;
			kChange.eYield = (YieldTypes)iYield;
			kChange.iChange = pOldCity->getBuildingYieldChange((BuildingClassTypes)iI, (YieldTypes)iYield);
			if (0 != kChange.iChange)
			{
				aBuildingYieldChange.push_back(kChange);
			}
		}

		for (int iCommerce = 0; iCommerce < NUM_COMMERCE_TYPES; ++iCommerce)
		{
			BuildingCommerceChange kChange;
			kChange.eBuildingClass = (BuildingClassTypes)iI;
			kChange.eCommerce = (CommerceTypes)iCommerce;
			kChange.iChange = pOldCity->getBuildingCommerceChange((BuildingClassTypes)iI, (CommerceTypes)iCommerce);
			if (0 != kChange.iChange)
			{
				aBuildingCommerceChange.push_back(kChange);
			}
		}

		int iChange = pOldCity->getBuildingHappyChange((BuildingClassTypes)iI);
		if (0 != iChange)
		{
			aBuildingHappyChange.push_back(std::make_pair((BuildingClassTypes)iI, iChange));
		}

		iChange = pOldCity->getBuildingHealthChange((BuildingClassTypes)iI);
		if (0 != iChange)
		{
			aBuildingHealthChange.push_back(std::make_pair((BuildingClassTypes)iI, iChange));
		}
	}

	bRecapture = ((eHighestCulturePlayer != NO_PLAYER) ? (GET_PLAYER(eHighestCulturePlayer).getTeam() == getTeam()) : false);

	pOldCity->kill(false, false);

	if (bTrade)
	{
		for (iDX = -1; iDX <= 1; iDX++)
		{
			for (iDY = -1; iDY <= 1; iDY++)
			{
				pLoopPlot	= plotXY(pCityPlot->getX_INLINE(), pCityPlot->getY_INLINE(), iDX, iDY);

				if (pLoopPlot != NULL)
				{
					pLoopPlot->setCulture(eOldOwner, 0, false, false);
				}
			}
		}
	}

	pNewCity = initCity(pCityPlot->getX_INLINE(), pCityPlot->getY_INLINE(), !bConquest, false);

	FAssertMsg(pNewCity != NULL, "NewCity is not assigned a valid value");

	pNewCity->setPreviousOwner(eOldOwner);
	pNewCity->setOriginalOwner(eOriginalOwner);
	pNewCity->setGameTurnFounded(iGameTurnFounded);
	pNewCity->setPopulation((bConquest && !bRecapture) ? std::max(1, (iPopulation - 1)) : iPopulation);
	pNewCity->setHighestPopulation(iHighestPopulation);
	pNewCity->setName(szName);
	pNewCity->setNeverLost(false);
	pNewCity->changeDefenseDamage(iDamage);
	
/************************************************************************************************/
/* Afforess	                  Start		 01/12/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (iCiv != NO_CIVILIZATION)
    {
        pNewCity->setCivilizationType(iCiv);
    }
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	pNewCity->setScriptData(scriptData);
	pNewCity->setRevolutionIndex( iRevIdx );
	pNewCity->setLocalRevIndex( iLocalRevIdx );
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		pNewCity->setEverOwned(((PlayerTypes)iI), abEverOwned[iI]);
		pNewCity->setCultureTimes100(((PlayerTypes)iI), aiCulture[iI], false, false);
	}

	for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		int iNum = 0;

		if (paiNumRealBuilding[iI] > 0)
		{
			BuildingClassTypes eBuildingClass = (BuildingClassTypes)GC.getBuildingInfo((BuildingTypes)iI).getBuildingClassType();
/************************************************************************************************/
/* Afforess	                  Start		 02/03/10                                              */
/*                                                                                              */
/*   Assimilation Bug Fix                                                                       */
/************************************************************************************************/
			if ((::isWorldWonderClass(eBuildingClass)) || (GC.getGameINLINE().isOption(GAMEOPTION_ASSIMILATION)))
			{
				eBuilding = (BuildingTypes)iI;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
			}
			else
			{			
				eBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(eBuildingClass);
			}

			if (eBuilding != NO_BUILDING)
			{
				if (bTrade || !(GC.getBuildingInfo((BuildingTypes)iI).isNeverCapture()))
				{
					if (!isProductionMaxedBuildingClass(((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())), true))
					{
						if (pNewCity->isValidBuildingLocation(eBuilding))
						{
							if (!bConquest || bRecapture || GC.getGameINLINE().getSorenRandNum(100, "Capture Probability") < GC.getBuildingInfo((BuildingTypes)iI).getConquestProbability())
							{
								iNum += paiNumRealBuilding[iI];
							}
						}
					}
				}

				pNewCity->setNumRealBuildingTimed(eBuilding, std::min(pNewCity->getNumRealBuilding(eBuilding) + iNum, GC.getCITY_MAX_NUM_BUILDINGS()), false, ((PlayerTypes)(paiBuildingOriginalOwner[iI])), paiBuildingOriginalTime[iI]);
			}
		}
	}

	for (std::vector<BuildingYieldChange>::iterator it = aBuildingYieldChange.begin(); it != aBuildingYieldChange.end(); ++it)
	{
		pNewCity->setBuildingYieldChange((*it).eBuildingClass, (*it).eYield, (*it).iChange);
	}

	for (std::vector<BuildingCommerceChange>::iterator it = aBuildingCommerceChange.begin(); it != aBuildingCommerceChange.end(); ++it)
	{
		pNewCity->setBuildingCommerceChange((*it).eBuildingClass, (*it).eCommerce, (*it).iChange);
	}

	for (BuildingChangeArray::iterator it = aBuildingHappyChange.begin(); it != aBuildingHappyChange.end(); ++it)
	{
		pNewCity->setBuildingHappyChange((*it).first, (*it).second);
	}

	for (BuildingChangeArray::iterator it = aBuildingHealthChange.begin(); it != aBuildingHealthChange.end(); ++it)
	{
		pNewCity->setBuildingHealthChange((*it).first, (*it).second);
	}

	for (iI = 0; iI < GC.getNumSpecialistInfos(); ++iI)
	{
		pNewCity->changeFreeSpecialistCount((SpecialistTypes)iI, aeFreeSpecialists[iI]);
	}

	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		if (pabHasReligion[iI])
		{
			pNewCity->setHasReligion(((ReligionTypes)iI), true, false, true);
		}

		if (pabHolyCity[iI])
		{
			GC.getGameINLINE().setHolyCity(((ReligionTypes)iI), pNewCity, false);
			// Sanguo Mod Performance start, added by poyuzhe 07.26.09
			for (int iJ = 0; iJ < GC.getMAX_PLAYERS(); iJ++)
			{
				if (GET_PLAYER((PlayerTypes)iJ).isAlive() && GET_PLAYER((PlayerTypes)iI).getStateReligion() == (ReligionTypes)iI)
				{
					GET_PLAYER(getID()).AI_invalidateAttitudeCache((PlayerTypes)iJ);
					GET_PLAYER((PlayerTypes)iJ).AI_invalidateAttitudeCache(getID());
				}
			}
			// Sanguo Mod Performance, end
		}
	}
/************************************************************************************************/
/* RevDCM	                  Start		 12/9/09                                                */
/*                                                                                              */
/* Inquisitions                                                                                 */
/************************************************************************************************/
	if(!(GET_PLAYER(eOldOwner).isHuman()))
	{
		GET_PLAYER(eOldOwner).AI_setHasInquisitionTarget();
	}
	if(!(GET_PLAYER(getID()).isHuman()))
	{
		GET_PLAYER(getID()).AI_setHasInquisitionTarget();
	}
/************************************************************************************************/
/* RevDCM	                     END                                                            */
/************************************************************************************************/
	for (iI = 0; iI < GC.getNumCorporationInfos(); iI++)
	{
		if (pabHasCorporation[iI])
		{
			pNewCity->setHasCorporation(((CorporationTypes)iI), true, false);
		}

		if (pabHeadquarters[iI])
		{
			GC.getGameINLINE().setHeadquarters(((CorporationTypes)iI), pNewCity, false);
		}
	}

	if (bTrade)
	{
		if (isHuman() || (getTeam() == GET_PLAYER(eOldOwner).getTeam()))
		{
			pNewCity->changeHurryAngerTimer(iHurryAngerTimer);
			pNewCity->changeConscriptAngerTimer(iConscriptAngerTimer);
			pNewCity->changeDefyResolutionAngerTimer(iDefyResolutionAngerTimer);
		}

		if (!bRecapture)
		{
			pNewCity->changeOccupationTimer(iOccupationTimer);
		}
	}

	if (bConquest)
	{
		iTeamCulturePercent = pNewCity->calculateTeamCulturePercent(getTeam());

		if (iTeamCulturePercent < GC.getDefineINT("OCCUPATION_CULTURE_PERCENT_THRESHOLD"))
		{
		
/************************************************************************************************/
/* Afforess	                  Start		 07/14/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
			pNewCity->changeOccupationTimer(((GC.getDefineINT("BASE_OCCUPATION_TURNS") + ((pNewCity->getPopulation() * GC.getDefineINT("OCCUPATION_TURNS_POPULATION_PERCENT")) / 100)) * (100 - iTeamCulturePercent)) / 100);
*/
			int iOccupationTime = GC.getDefineINT("BASE_OCCUPATION_TURNS");\
			//ls612: Remove the old define and replace it with something that scales with Gamespeeds
			iOccupationTime += pNewCity->getPopulation() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getOccupationTimePopulationPercent() / 100;
			iOccupationTime *= (100 - iTeamCulturePercent) / 100;
			
			iOccupationTime *= std::max(0,iOccupationTimeModifier);
			iOccupationTime /= 100;
			
			pNewCity->changeOccupationTimer(iOccupationTime);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

		}

		GC.getMapINLINE().verifyUnitValidPlot();
	}
/************************************************************************************************/
/* Afforess	                  Start		 02/15/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (iOccupationRange > 0)
	{
		pNewCity->setOccupationCultureLevel((CultureLevelTypes)iOccupationRange);
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	pNewCity->checkBuildings(true, true, true, true, true, false);

	pCityPlot->setRevealed(GET_PLAYER(eOldOwner).getTeam(), true, false, NO_TEAM, false);

	pNewCity->updateEspionageVisibility(false);

	pCityPlot->updateCulture(true, false);

	for (iI = 0; iI < NUM_DIRECTION_TYPES; iI++)
	{
		CvPlot* pAdjacentPlot = plotDirection(pCityPlot->getX_INLINE(), pCityPlot->getY_INLINE(), ((DirectionTypes)iI));

		if (pAdjacentPlot != NULL)
		{
			pAdjacentPlot->updateCulture(true, false);
		}
	}

	bool bConquestCanRaze = false;
	if (bConquest)
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyCity* pyCity = new CyCity(pNewCity);
		CyArgsList argsList;
		argsList.add(getID());	// Player ID
		argsList.add(gDLL->getPythonIFace()->makePythonObject(pyCity));	// pass in city class
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "canRazeCity", argsList.makeFunctionArgs(), &lResult);
		delete pyCity;	// python fxn must not hold on to this pointer 

		if (lResult == 1)
		{
			bConquestCanRaze = true;
		}
	}
	//	Don't bother with plot group caklculations if they are immediately to b superseded by
	//	an auto raze
	if ( bUpdatePlotGroups && (!bConquestCanRaze || !pNewCity->isAutoRaze()) )
	{
		PROFILE("CvPlayer::acquireCity.UpdatePlotGroups");

		for(int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if ( GET_PLAYER((PlayerTypes)iI).isAlive() )
			{
				if ( originalTradeNetworkConnectivity[iI] == NULL )
				{
					if ( pCityPlot->isTradeNetwork(GET_PLAYER((PlayerTypes)iI).getTeam()) )
					{
						GET_PLAYER((PlayerTypes)iI).updatePlotGroups(pCityPlot->area());
					}
				}
				else
				{
					originalTradeNetworkConnectivity[iI]->recalculatePlots();
				}
			}
		}
	}

	CvEventReporter::getInstance().cityAcquired(eOldOwner, getID(), pNewCity, bConquest, bTrade);

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      10/02/09                                jdog5000      */
/*                                                                                              */
/* AI logging                                                                                   */
/************************************************************************************************/
	if( gPlayerLogLevel >= 1 )
	{
		logBBAI("  Player %d (%S) acquires city %S bConq %d bTrade %d", getID(), getCivilizationDescription(0), pNewCity->getName(0).GetCString(), bConquest, bTrade );
	}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

	SAFE_DELETE_ARRAY(pabHasReligion);
	SAFE_DELETE_ARRAY(pabHolyCity);
	SAFE_DELETE_ARRAY(pabHasCorporation);
	SAFE_DELETE_ARRAY(pabHeadquarters);
	SAFE_DELETE_ARRAY(paiNumRealBuilding);
	SAFE_DELETE_ARRAY(paiBuildingOriginalOwner);
	SAFE_DELETE_ARRAY(paiBuildingOriginalTime);

	if ( bConquestCanRaze )
	{
		//auto raze based on game rules
		if (pNewCity->isAutoRaze())
		{
			if (iCaptureGold > 0)
			{
				MEMORY_TRACK_EXEMPT();

				szBuffer = gDLL->getText("TXT_KEY_MISC_PILLAGED_CITY", iCaptureGold, pNewCity->getNameKey());
				AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CITYRAZE", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_CITY_EDIT")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pNewCity->getX_INLINE(), pNewCity->getY_INLINE(), true, true);
			}

			pNewCity->doTask(TASK_RAZE);
		}
		else if (!isHuman())
		{
			AI_conquerCity(pNewCity); // could delete the pointer...
		}
		else
		{
			//popup raze option
			eHighestCulturePlayer = pNewCity->getLiberationPlayer(true);
			bRaze = canRaze(pNewCity);
			bGift = ((eHighestCulturePlayer != NO_PLAYER) 
					&& (eHighestCulturePlayer != getID()) 
					&& ((getTeam() == GET_PLAYER(eHighestCulturePlayer).getTeam()) 
						|| GET_TEAM(getTeam()).isOpenBorders(GET_PLAYER(eHighestCulturePlayer).getTeam()) 
						|| GET_TEAM(GET_PLAYER(eHighestCulturePlayer).getTeam()).isVassal(getTeam())));

			if (bRaze || bGift)
			{
				CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_RAZECITY);
				pInfo->setData1(pNewCity->getID());
				pInfo->setData2(eHighestCulturePlayer);
				pInfo->setData3(iCaptureGold);
				gDLL->getInterfaceIFace()->addPopup(pInfo, getID());
			}
			else
			{
				pNewCity->chooseProduction();
				CvEventReporter::getInstance().cityAcquiredAndKept(getID(), pNewCity);
			}
		}
	}
/************************************************************************************************/
/* REVOLUTION_MOD                         06/27/10                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/* original code
	else if (!bTrade)
*/
	// Silences double ask for accepting new city from Revolution mod
	else if (!bTrade && (GC.getGameINLINE().isOption(GAMEOPTION_NO_REVOLUTION)) )
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
	{
		if (isHuman())
		{
			CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_DISBANDCITY);
			pInfo->setData1(pNewCity->getID());
			gDLL->getInterfaceIFace()->addPopup(pInfo, getID());
		}
		else
		{
			CvEventReporter::getInstance().cityAcquiredAndKept(getID(), pNewCity);
		}
	}

	// Forcing events that deal with the old city not to expire just because we conquered that city
	for (CvEventMap::iterator it = m_mapEventsOccured.begin(); it != m_mapEventsOccured.end(); ++it)
	{
		EventTriggeredData &triggerData = it->second;
		if((triggerData.m_eOtherPlayer == eOldOwner) && (triggerData.m_iOtherPlayerCityId == iOldCityId))
		{
			triggerData.m_iOtherPlayerCityId = -1;
		}
	}
}


void CvPlayer::killCities()
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->kill(false);
	}

	GC.getGameINLINE().updatePlotGroups();
}


CvWString CvPlayer::getNewCityName() const
{
	CLLNode<CvWString>* pNode;
	CvWString szName;
	int iI;

	for (pNode = headCityNameNode(); (pNode != NULL); pNode = nextCityNameNode(pNode))
	{
		szName = gDLL->getText(pNode->m_data);
		if (isCityNameValid(szName, true))
		{
			szName = pNode->m_data;
			break;
		}
	}

	if (szName.empty())
	{
		getCivilizationCityName(szName, getCivilizationType());
	}

	if (szName.empty())
	{
		// Pick a name from another random civ
		int iRandOffset = GC.getGameINLINE().getSorenRandNum(GC.getNumCivilizationInfos(), "Place Units (Player)");
		for (iI = 0; iI < GC.getNumCivilizationInfos(); iI++)
		{
			int iLoopName = ((iI + iRandOffset) % GC.getNumCivilizationInfos());

			getCivilizationCityName(szName, ((CivilizationTypes)iLoopName));

			if (!szName.empty())
			{
				break;
			}
		}
	}

	if (szName.empty())
	{
		szName = "TXT_KEY_CITY";
	}

	return szName;
}


void CvPlayer::getCivilizationCityName(CvWString& szBuffer, CivilizationTypes eCivilization) const
{
	int iRandOffset;
	int iLoopName;
	int iI;

/************************************************************************************************/
/* REVOLUTION_MOD                         02/29/08                                jdog5000      */
/*                                                                                              */
/* Minor Civs                                                                                   */
/************************************************************************************************/
/* original code
	if (isBarbarian() || isMinorCiv())
	{
		iRandOffset = GC.getGameINLINE().getSorenRandNum(GC.getCivilizationInfo(eCivilization).getNumCityNames(), "Place Units (Player)");
	}
	else
	{
		iRandOffset = 0;
	}
*/
	iRandOffset = 0;

	if( !GC.getGameINLINE().isOption(GAMEOPTION_NO_REVOLUTION) || !GC.getGameINLINE().isOption(GAMEOPTION_NO_BARBARIAN_CIV) )
	{
		if( isBarbarian() )
		{
			iRandOffset = GC.getGameINLINE().getSorenRandNum(GC.getCivilizationInfo(eCivilization).getNumCityNames(), "Place Units (Player)");
		}
	}
	else 
	{
		if (isBarbarian() || isMinorCiv())
		{
			iRandOffset = GC.getGameINLINE().getSorenRandNum(GC.getCivilizationInfo(eCivilization).getNumCityNames(), "Place Units (Player)");
		}
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

	for (iI = 0; iI < GC.getCivilizationInfo(eCivilization).getNumCityNames(); iI++)
	{
		iLoopName = ((iI + iRandOffset) % GC.getCivilizationInfo(eCivilization).getNumCityNames());

		CvWString szName = gDLL->getText(GC.getCivilizationInfo(eCivilization).getCityNames(iLoopName));

		if (isCityNameValid(szName, true))
		{
			szBuffer = GC.getCivilizationInfo(eCivilization).getCityNames(iLoopName);
			break;
		}
	}
}


bool CvPlayer::isCityNameValid(CvWString& szName, bool bTestDestroyed) const
{
	CvCity* pLoopCity;
	int iLoop;

	if (bTestDestroyed)
	{
		if (GC.getGameINLINE().isDestroyedCityName(szName))
		{
			return false;
		}

		for (int iPlayer = 0; iPlayer < MAX_PLAYERS; ++iPlayer)
		{
			CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);
			for (pLoopCity = kLoopPlayer.firstCity(&iLoop); pLoopCity != NULL; pLoopCity = kLoopPlayer.nextCity(&iLoop))
			{
				if (pLoopCity->getName() == szName)
				{
					return false;
				}
			}
		}
	}
	else
	{
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			if (pLoopCity->getName() == szName)
			{
				return false;
			}
		}
	}

	return true;
}

CvUnit* CvPlayer::getTempUnit(UnitTypes eUnit, int iX, int iY)
{
	if ( m_pTempUnit == NULL )
	{
		m_pTempUnit = initUnit(eUnit, iX, iY, NO_UNITAI, NO_DIRECTION, UNIT_BIRTHMARK_TEMP_UNIT);
		((CvPlayerAI*)this)->AI_changeNumAIUnits(m_pTempUnit->AI_getUnitAIType(),-1);	//	This one doesn't count
		removeGroupCycle(m_pTempUnit->getGroup()->getID());
	}
	else
	{
		if ( m_pTempUnit->plot() != NULL )
		{
			m_pTempUnit->setXY(INVALID_PLOT_COORD,INVALID_PLOT_COORD,true,false);
		}

		m_pTempUnit->changeIdentity(eUnit);
		m_pTempUnit->setXY(iX, iY, true, false);
	}

	//	Set an arbitrary automation type - just need it to be flagged as automated
	m_pTempUnit->getGroup()->setAutomateType(AUTOMATE_BUILD);

	return m_pTempUnit;
}

void CvPlayer::releaseTempUnit()
{
	m_pTempUnit->setXY(INVALID_PLOT_COORD,INVALID_PLOT_COORD,true,false);
}

CvUnit* CvPlayer::initUnit(UnitTypes eUnit, int iX, int iY, UnitAITypes eUnitAI, DirectionTypes eFacingDirection, int iBirthmark)
{
	PROFILE_FUNC();

	FAssertMsg(eUnit != NO_UNIT, "Unit is not assigned a valid value");

	CvUnit* pUnit = addUnit();
	FAssertMsg(pUnit != NULL, "Unit is not assigned a valid value");
	if (NULL != pUnit)
	{
		pUnit->init(pUnit->getID(), eUnit, ((eUnitAI == NO_UNITAI) ? ((UnitAITypes)(GC.getUnitInfo(eUnit).getDefaultUnitAIType())) : eUnitAI), getID(), iX, iY, eFacingDirection, iBirthmark);
/************************************************************************************************/
/* Afforess	                  Start		 02/27/10                      Coded By: KillMePlease   */
/*                                                                                              */
/* Great Commanders                                                                             */
/************************************************************************************************/
		if (pUnit->isCommander())
		{
			Commanders.push_back(pUnit);
		}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	}

	return pUnit;
}


void CvPlayer::disbandUnit(bool bAnnounce)
{
	CvUnit* pLoopUnit;
	CvUnit* pBestUnit;
	wchar szBuffer[1024];
	int iValue;
	int iBestValue;
	int iLoop;

	iBestValue = MAX_INT;
	pBestUnit = NULL;

	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		if (!(pLoopUnit->hasCargo()))
		{
			if (!(pLoopUnit->isGoldenAge()))
			{
				if (pLoopUnit->getUnitInfo().getProductionCost() > 0)
				{
					if (!(pLoopUnit->isMilitaryHappiness()) || !(pLoopUnit->plot()->isCity()) || (pLoopUnit->plot()->plotCount(PUF_isMilitaryHappiness, -1, -1, getID()) > 1))
					{
						iValue = (10000 + GC.getGameINLINE().getSorenRandNum(1000, "Disband Unit"));

						iValue += (pLoopUnit->getUnitInfo().getProductionCost() * 5);

						iValue += (pLoopUnit->getExperience() * 20);
						iValue += (pLoopUnit->getLevel() * 100);

						if (pLoopUnit->canDefend() && pLoopUnit->plot()->isCity())
						{
							iValue *= 2;
						}

						if (pLoopUnit->plot()->getTeam() == pLoopUnit->getTeam())
						{
							iValue *= 3;
						}
/************************************************************************************************/
/* Afforess	                  Start		 02/12/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
						if (pLoopUnit->plot()->getOwnerINLINE() == pLoopUnit->getOwnerINLINE())
						{
							iValue /= 6;
						}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

						switch (pLoopUnit->AI_getUnitAIType())
						{
						case UNITAI_UNKNOWN:
						case UNITAI_ANIMAL:
							break;

						case UNITAI_SUBDUED_ANIMAL:
							iValue *= 3;
							break;

						case UNITAI_HUNTER:
							iValue *= 10;
							break;

						case UNITAI_SETTLE:
							iValue *= 20;
							break;

						case UNITAI_WORKER:
							iValue *= 10;
							break;

						case UNITAI_ATTACK:
						case UNITAI_ATTACK_CITY:
						case UNITAI_COLLATERAL:
						case UNITAI_PILLAGE:
						case UNITAI_RESERVE:
						case UNITAI_COUNTER:
						case UNITAI_PILLAGE_COUNTER:
							iValue *= 2;
							break;

						case UNITAI_CITY_DEFENSE:
						case UNITAI_CITY_COUNTER:
						case UNITAI_CITY_SPECIAL:
						case UNITAI_PARADROP:
							iValue *= 6;
							break;

						case UNITAI_EXPLORE:
							iValue *= 15;
							break;

						case UNITAI_MISSIONARY:
							iValue *= 8;
							break;

						case UNITAI_PROPHET:
						case UNITAI_ARTIST:
						case UNITAI_SCIENTIST:
						case UNITAI_GENERAL:
						case UNITAI_MERCHANT:
						case UNITAI_ENGINEER:
							break;

						case UNITAI_SPY:
							iValue *= 12;
							break;

						case UNITAI_ICBM:
							iValue *= 4;
							break;

						case UNITAI_WORKER_SEA:
							iValue *= 18;
							break;

						case UNITAI_ATTACK_SEA:
						case UNITAI_RESERVE_SEA:
						case UNITAI_ESCORT_SEA:
							break;

						case UNITAI_EXPLORE_SEA:
							iValue *= 25;
							break;

						case UNITAI_ASSAULT_SEA:
						case UNITAI_SETTLER_SEA:
						case UNITAI_MISSIONARY_SEA:
						case UNITAI_SPY_SEA:
						case UNITAI_CARRIER_SEA:
						case UNITAI_MISSILE_CARRIER_SEA:
							iValue *= 5;
							break;

						case UNITAI_PIRATE_SEA:
						case UNITAI_ATTACK_AIR:
							break;

						case UNITAI_DEFENSE_AIR:
						case UNITAI_CARRIER_AIR:
						case UNITAI_MISSILE_AIR:
							iValue *= 3;
							break;

						default:
							FAssert(false);
							break;
						}

						if (pLoopUnit->getUnitInfo().getExtraCost() > 0)
						{
							iValue /= (pLoopUnit->getUnitInfo().getExtraCost() + 1);
						}

						if (iValue < iBestValue)
						{
							iBestValue = iValue;
							pBestUnit = pLoopUnit;
						}
					}
				}
			}
		}
	}

	if (pBestUnit != NULL)
	{
		MEMORY_TRACK_EXEMPT();

		swprintf(szBuffer, gDLL->getText("TXT_KEY_MISC_UNIT_DISBANDED_NO_MONEY", pBestUnit->getNameKey()).GetCString());
		AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_UNITDISBANDED", MESSAGE_TYPE_MINOR_EVENT, pBestUnit->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pBestUnit->getX_INLINE(), pBestUnit->getY_INLINE(), true, true);

		FAssert(!(pBestUnit->isGoldenAge()));

		if( gPlayerLogLevel >= 2 )
		{
			CvWString szString;
			getUnitAIString(szString, pBestUnit->AI_getUnitAIType());

			logBBAI("    Player %d (%S) disbanding %S with UNITAI %S (forced)", getID(), getCivilizationDescription(0), pBestUnit->getName().GetCString(), szString.GetCString());
		}

		pBestUnit->kill(false);
	}
}


void CvPlayer::killUnits()
{
	CvUnit* pLoopUnit;
	int iLoop;

	for (pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		pLoopUnit->kill(false);
	}
}


// XXX should pUnit be a CvSelectionGroup???
// Returns the next unit in the cycle...
CvSelectionGroup* CvPlayer::cycleSelectionGroups(CvUnit* pUnit, bool bForward, bool bWorkers, bool* pbWrap, bool bAllowViewportSwitch)
{
	CLLNode<int>* pSelectionGroupNode;
	CLLNode<int>* pFirstSelectionGroupNode;
	CvSelectionGroup* pLoopSelectionGroup;
	CvViewport* pCurrentViewport = GC.getCurrentViewport();

	if (pbWrap != NULL)
	{
		*pbWrap = false;
	}

	pSelectionGroupNode = headGroupCycleNode();

	if (pUnit != NULL)
	{
		while (pSelectionGroupNode != NULL)
		{
			if (getSelectionGroup(pSelectionGroupNode->m_data) == pUnit->getGroup())
			{
				if (bForward)
				{
					pSelectionGroupNode = nextGroupCycleNode(pSelectionGroupNode);
				}
				else
				{
					pSelectionGroupNode = previousGroupCycleNode(pSelectionGroupNode);
				}
				break;
			}

			pSelectionGroupNode = nextGroupCycleNode(pSelectionGroupNode);
		}
	}

	if (pSelectionGroupNode == NULL)
	{
		if (bForward)
		{
			pSelectionGroupNode = headGroupCycleNode();
		}
		else
		{
			pSelectionGroupNode = tailGroupCycleNode();
		}

		if (pbWrap != NULL)
		{
			*pbWrap = true;
		}
	}

	if (pSelectionGroupNode != NULL)
	{
		CvSelectionGroup* pNonViewportOption = NULL;

		pFirstSelectionGroupNode = pSelectionGroupNode;

		while (true)
		{
			pLoopSelectionGroup = getSelectionGroup(pSelectionGroupNode->m_data);
			FAssertMsg(pLoopSelectionGroup != NULL, "LoopSelectionGroup is not assigned a valid value");

			if (pLoopSelectionGroup->readyToSelect())
			{
				if (!bWorkers || pLoopSelectionGroup->hasWorker())
				{
					if (pUnit && pLoopSelectionGroup == pUnit->getGroup())
					{
						if (pbWrap != NULL)
						{
							*pbWrap = true;
						}
					}

					if ( pCurrentViewport->isInViewport(pLoopSelectionGroup->getX(), pLoopSelectionGroup->getY(), GC.getViewportSelectionBorder()) )
					{
						return pLoopSelectionGroup;
					}
					else if ( pNonViewportOption == NULL )
					{
						pNonViewportOption = pLoopSelectionGroup;
					}
				}
			}

			if (bForward)
			{
				pSelectionGroupNode = nextGroupCycleNode(pSelectionGroupNode);

				if (pSelectionGroupNode == NULL)
				{
					pSelectionGroupNode = headGroupCycleNode();

					if (pbWrap != NULL)
					{
						*pbWrap = true;
					}
				}
			}
			else
			{
				pSelectionGroupNode = previousGroupCycleNode(pSelectionGroupNode);

				if (pSelectionGroupNode == NULL)
				{
					pSelectionGroupNode = tailGroupCycleNode();

					if (pbWrap != NULL)
					{
						*pbWrap = true;
					}
				}
			}

			if (pSelectionGroupNode == pFirstSelectionGroupNode)
			{
				break;
			}
		}

		if ( pNonViewportOption != NULL && bAllowViewportSwitch )
		{
			return pNonViewportOption;
		}
	}

	return NULL;
}


bool CvPlayer::hasTrait(TraitTypes eTrait) const
{
	FAssertMsg((getLeaderType() >= 0), "getLeaderType() is less than zero");
	FAssertMsg((eTrait >= 0), "eTrait is less than zero");
	return GC.getLeaderHeadInfo(getLeaderType()).hasTrait(eTrait);
}

/************************************************************************************************/
/* AI_AUTO_PLAY_MOD                           07/09/08                            jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
void CvPlayer::setHumanDisabled( bool newVal )
{
	m_bDisableHuman = newVal;
	updateHuman();
}
bool CvPlayer::isHumanDisabled() const
{
	return m_bDisableHuman;
}
/************************************************************************************************/
/* AI_AUTO_PLAY_MOD                            END                                              */
/************************************************************************************************/

bool CvPlayer::isHuman() const
{
	return m_bHuman;
}

void CvPlayer::updateHuman()
{
	if (getID() == NO_PLAYER)
	{
		m_bHuman = false;
	}
	else
	{
/************************************************************************************************/
/* AI_AUTO_PLAY_MOD                            09/01/07                        MRGENIE          */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
		m_bHuman = GC.getInitCore().getHuman(getID());
*/
		if( m_bDisableHuman )
		{
			m_bHuman = false;
		}
		else
		{
			m_bHuman = GC.getInitCore().getHuman(getID());
		}
/************************************************************************************************/
/* AI_AUTO_PLAY_MOD                            END                                              */
/************************************************************************************************/	
	}
}

bool CvPlayer::isBarbarian() const
{
	return (getID() == BARBARIAN_PLAYER);
}

static bool concealUnknownCivs() { return !gDLL->IsPitbossHost() && gDLL->getChtLvl() == 0 && !gDLL->GetWorldBuilderMode(); } // K-Mod

const wchar* CvPlayer::getName(uint uiForm) const
{
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
/* original code
	if (GC.getInitCore().getLeaderName(getID(), uiForm).empty() || (GC.getGameINLINE().isMPOption(MPOPTION_ANONYMOUS) && isAlive() && GC.getGameINLINE().getGameState() == GAMESTATE_ON))
	{
		return GC.getLeaderHeadInfo(getLeaderType()).getDescription(uiForm);
	}
	else
	{
		return GC.getInitCore().getLeaderName(getID(), uiForm);
	}
*/
	if( !(m_szName.empty()) )
	{
		return m_szName;
	}
	else if( GC.getInitCore().getLeaderName(getID(), uiForm).empty() || (GC.getGameINLINE().isMPOption(MPOPTION_ANONYMOUS) && isAlive() && GC.getGameINLINE().getGameState() == GAMESTATE_ON))
	{
		return GC.getLeaderHeadInfo(getLeaderType()).getDescription(uiForm);
	}
	else
	{
		return GC.getInitCore().getLeaderName(getID(), uiForm);
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
}

/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
// This sets the name of the player, ie Peter or Montezuma
void CvPlayer::setName(std::wstring szNewValue)
{
	if ( isCityNameValid(CvWString(szNewValue), false))
	{
		m_szName = szNewValue;
		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Foreign_Screen_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(InfoPane_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Flag_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(MinimapSection_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(UnitInfo_DIRTY_BIT, true);
	}
}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

const wchar* CvPlayer::getNameKey() const
{
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
/*
	if (GC.getInitCore().getLeaderNameKey(getID()).empty() || (GC.getGameINLINE().isMPOption(MPOPTION_ANONYMOUS) && isAlive()))
	{
		return GC.getLeaderHeadInfo(getLeaderType()).getTextKeyWide();
	}
	else
	{
		return GC.getInitCore().getLeaderNameKey(getID());
	}
*/
	if( !(m_szName.empty()) )
	{
		return m_szName;
	}
	else if (GC.getInitCore().getLeaderNameKey(getID()).empty() || (GC.getGameINLINE().isMPOption(MPOPTION_ANONYMOUS) && isAlive()))
	{
		return GC.getLeaderHeadInfo(getLeaderType()).getTextKeyWide();
	}
	else
	{
		return GC.getInitCore().getLeaderNameKey(getID());
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
}


const wchar* CvPlayer::getCivilizationDescription(uint uiForm) const
{
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
/*
	if (GC.getInitCore().getCivDescription(getID(), uiForm).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getDescription(uiForm);
	}
	else
	{
		return GC.getInitCore().getCivDescription(getID(), uiForm);
	}
*/
	if( !(m_szCivDesc.empty()) )
	{
		return m_szCivDesc;
	}
	
	else if (getCivilizationType() != NO_CIVILIZATION && GC.getInitCore().getCivDescription(getID(), uiForm).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getDescription(uiForm);
	}
	else
	{
		return GC.getInitCore().getCivDescription(getID(), uiForm);
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
}

/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
void CvPlayer::setCivName(std::wstring szNewDesc, std::wstring szNewShort, std::wstring szNewAdj)
{
	m_szCivDesc = szNewDesc;
	m_szCivShort = szNewShort;
	m_szCivAdj = szNewAdj;
	gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(Foreign_Screen_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(InfoPane_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(Flag_DIRTY_BIT, true);
	gDLL->getEngineIFace()->SetDirty(CultureBorders_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

// AIAndy: Extension to dynamic civ names using XML based names in CivNameInfos
CvWString CvPlayer::getNamePartFromList(std::vector<CivNameTypes>& aNames, std::vector<CivNameTypes>& aPrefix, std::vector<CivNameTypes>& aSuffix, bool& bCapitalUsed, bool& bCivUsed, bool& bLeaderUsed, bool& bFailed)
{
	if (bFailed)
		return CvWString();

	// filter out all that need more prefix or suffix than there is or want to use stuff that is already in the name
	int iNumPrefix = (int)aPrefix.size();
	int iNumSuffix = (int)aSuffix.size();
	for (int i=(int)aNames.size()-1; i>=0; i--)
	{
		CvCivNameInfo& kInfo = GC.getCivNameInfo((CivNameTypes)aNames[i]);
		if ((kInfo.getNumPrefix() > iNumPrefix) || (kInfo.getNumSuffix() > iNumSuffix) ||
			(kInfo.getUsesCapital() && bCapitalUsed) || (kInfo.getUsesCiv() && bCivUsed) || (kInfo.getUsesLeader() && bLeaderUsed))
		{
			aNames.erase(aNames.begin()+i);
		}
	}

	// return empty string if no possible name is found
	if (aNames.empty())
	{
		bFailed = true;
		return CvWString();
	}

	// select a name
	int iName = GC.getGameINLINE().getSorenRandNum((int)aNames.size(), "Civ Name Part");
	CivNameTypes eName = aNames[iName];
	
	CvWString aArgs[9];
	int iNumArgs = 0;
	CvCivNameInfo* pInfo = &(GC.getCivNameInfo(eName));

	// store some info for backtracking in case of failure
	bool bOldCapitalUsed = bCapitalUsed;
	bool bOldCivUsed = bCivUsed;
	bool bOldLeaderUsed = bLeaderUsed;

	if (pInfo->getUsesCapital())
	{
		aArgs[iNumArgs] = getCapitalCity()->getNameKey();
		iNumArgs++;
		bCapitalUsed = true;
	}

	if (pInfo->getUsesCiv())
	{
		aArgs[iNumArgs] = GC.getInitCore().getCivShortDescKey(getID());
		iNumArgs++;
		bCivUsed = true;
	}

	if (pInfo->getUsesLeader())
	{
		aArgs[iNumArgs] = GC.getInitCore().getLeaderNameKey(getID());
		iNumArgs++;
		bLeaderUsed = true;
	}

	iNumPrefix = pInfo->getNumPrefix();
	iNumSuffix = pInfo->getNumSuffix();

	// Limit in the number of arguments
	if (iNumArgs + iNumPrefix + iNumSuffix > 9)
	{
		bFailed = true;
	}

	if (!bFailed)
	{
		for (int i=0; i<iNumPrefix; i++)
		{
			aArgs[iNumArgs] = getNamePartFromList(aPrefix, aPrefix, aSuffix, bCapitalUsed, bCivUsed, bLeaderUsed, bFailed);
			if (bFailed)
				break;
			iNumArgs++;
		}
	}

	if (!bFailed)
	{
		for (int i=0; i<iNumSuffix; i++)
		{
			aArgs[iNumArgs] = getNamePartFromList(aSuffix, aPrefix, aSuffix, bCapitalUsed, bCivUsed, bLeaderUsed, bFailed);
			if (bFailed)
				break;
			iNumArgs++;
		}
	}

	// if it failed, fall back to using a name without prefix or suffix
	if (bFailed)
	{
		for (int i=(int)aNames.size()-1; i>=0; i--)
		{
			CvCivNameInfo& kInfo = GC.getCivNameInfo((CivNameTypes)aNames[i]);
			if ((kInfo.getNumPrefix() > 0) || (kInfo.getNumSuffix() > 0))
			{
				aNames.erase(aNames.begin()+i);
			}
		}

		// return empty string if no possible name is found
		if (aNames.empty())
		{
			return CvWString();
		}

		// select a name
		iName = GC.getGameINLINE().getSorenRandNum((int)aNames.size(), "Civ Name Part after Fail");
		eName = aNames[iName];
		
		iNumArgs = 0;
		pInfo = &(GC.getCivNameInfo(eName));

		// restore old used state
		bCapitalUsed = bOldCapitalUsed;
		bCivUsed = bOldCivUsed;
		bLeaderUsed = bOldLeaderUsed;

		if (pInfo->getUsesCapital())
		{
			aArgs[iNumArgs] = getCapitalCity()->getNameKey();
			iNumArgs++;
			bCapitalUsed = true;
		}

		if (pInfo->getUsesCiv())
		{
			aArgs[iNumArgs] = GC.getInitCore().getCivShortDescKey(getID());
			iNumArgs++;
			bCivUsed = true;
		}

		if (pInfo->getUsesLeader())
		{
			aArgs[iNumArgs] = GC.getInitCore().getLeaderNameKey(getID());
			iNumArgs++;
			bLeaderUsed = true;
		}
	}

	CvWString szName;

	switch (iNumArgs)
	{
		case 0:
			szName = gDLL->getText(pInfo->getNameKey());
			break;

		case 1:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str());
			break;

		case 2:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str(), aArgs[1].c_str());
			break;

		case 3:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str(), aArgs[1].c_str(), aArgs[2].c_str());
			break;

		case 4:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str(), aArgs[1].c_str(), aArgs[2].c_str(), aArgs[3].c_str());
			break;

		case 5:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str(), aArgs[1].c_str(), aArgs[2].c_str(), aArgs[3].c_str(), aArgs[4].c_str());
			break;

		case 6:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str(), aArgs[1].c_str(), aArgs[2].c_str(), aArgs[3].c_str(), aArgs[4].c_str(), aArgs[5].c_str());
			break;

		case 7:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str(), aArgs[1].c_str(), aArgs[2].c_str(), aArgs[3].c_str(), aArgs[4].c_str(), aArgs[5].c_str(), aArgs[6].c_str());
			break;

		case 8:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str(), aArgs[1].c_str(), aArgs[2].c_str(), aArgs[3].c_str(), aArgs[4].c_str(), aArgs[5].c_str(), aArgs[6].c_str(), aArgs[7].c_str());
			break;

		case 9:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0].c_str(), aArgs[1].c_str(), aArgs[2].c_str(), aArgs[3].c_str(), aArgs[4].c_str(), aArgs[5].c_str(), aArgs[6].c_str(), aArgs[7].c_str(), aArgs[8].c_str());
			break;
	}

	return szName;
}

const std::wstring CvPlayer::getNewCivName()
{
	std::vector<CivNameTypes> aPrefix;
	std::vector<CivNameTypes> aSuffix;
	std::vector<CivNameTypes> aNames;

	CvCity* pCapital = getCapitalCity();

	int iNumCivNames = GC.getNumCivNameInfos();
	for (int i=0; i<iNumCivNames; i++)
	{
		CvCivNameInfo& kInfo = GC.getCivNameInfo((CivNameTypes)i);
		if (kInfo.getCapitalCondition())
		{
			if (!pCapital)
				continue;

			if (!kInfo.getCapitalCondition()->evaluate(pCapital->getGameObject()))
			{
				continue;
			}
		}
		if (kInfo.getPlayerCondition())
		{
			if (!kInfo.getPlayerCondition()->evaluate(getGameObject()))
			{
				continue;
			}
		}
		if (kInfo.isPrefix())
		{
			aPrefix.push_back((CivNameTypes)i);
		}
		else if (kInfo.isSuffix())
		{
			aSuffix.push_back((CivNameTypes)i);
		}
		else
		{
			aNames.push_back((CivNameTypes)i);
		}
	}

	// filter out all that need more prefix or suffix than there is
	int iNumPrefix = (int)aPrefix.size();
	int iNumSuffix = (int)aSuffix.size();
	for (int i=(int)aNames.size()-1; i>=0; i--)
	{
		CvCivNameInfo& kInfo = GC.getCivNameInfo((CivNameTypes)aNames[i]);
		if ((kInfo.getNumPrefix() > iNumPrefix) || (kInfo.getNumSuffix() > iNumSuffix))
		{
			aNames.erase(aNames.begin()+i);
		}
	}

	// return empty string if no possible name is found
	if (aNames.empty())
	{
		return std::wstring();
	}

	// select a name
	int iName = GC.getGameINLINE().getSorenRandNum((int)aNames.size(), "Civ Name");
	CivNameTypes eName = aNames[iName];
	
	CvWString aArgs[9];
	int iNumArgs = 0;
	bool bCapitalUsed = pCapital == NULL;
	bool bCivUsed = false;
	bool bLeaderUsed = false;
	bool bFailed = false;
	CvCivNameInfo* pInfo = &(GC.getCivNameInfo(eName));

	if (pInfo->getUsesCapital())
	{
		aArgs[iNumArgs] = pCapital->getNameKey();
		iNumArgs++;
		bCapitalUsed = true;
	}

	if (pInfo->getUsesCiv())
	{
		aArgs[iNumArgs] = GC.getInitCore().getCivShortDescKey(getID());
		iNumArgs++;
		bCivUsed = true;
	}

	if (pInfo->getUsesLeader())
	{
		aArgs[iNumArgs] = GC.getInitCore().getLeaderNameKey(getID());
		iNumArgs++;
		bLeaderUsed = true;
	}

	iNumPrefix = pInfo->getNumPrefix();
	iNumSuffix = pInfo->getNumSuffix();

	// Limit in the number of arguments
	if (iNumArgs + iNumPrefix + iNumSuffix > 9)
	{
		bFailed = true;
	}

	if (!bFailed)
	{
		for (int i=0; i<iNumPrefix; i++)
		{
			aArgs[iNumArgs] = getNamePartFromList(aPrefix, aPrefix, aSuffix, bCapitalUsed, bCivUsed, bLeaderUsed, bFailed);
			if (bFailed)
				break;
			iNumArgs++;
		}
	}

	if (!bFailed)
	{
		for (int i=0; i<iNumSuffix; i++)
		{
			aArgs[iNumArgs] = getNamePartFromList(aSuffix, aPrefix, aSuffix, bCapitalUsed, bCivUsed, bLeaderUsed, bFailed);
			if (bFailed)
				break;
			iNumArgs++;
		}
	}

	// if it failed, fall back to using a name without prefix or suffix
	if (bFailed)
	{
		for (int i=(int)aNames.size()-1; i>=0; i--)
		{
			CvCivNameInfo& kInfo = GC.getCivNameInfo((CivNameTypes)aNames[i]);
			if ((kInfo.getNumPrefix() > 0) || (kInfo.getNumSuffix() > 0))
			{
				aNames.erase(aNames.begin()+i);
			}
		}

		// return empty string if no possible name is found
		if (aNames.empty())
		{
			return std::wstring();
		}

		// select a name
		iName = GC.getGameINLINE().getSorenRandNum((int)aNames.size(), "Civ Name after Fail");
		eName = aNames[iName];
		
		iNumArgs = 0;
		pInfo = &(GC.getCivNameInfo(eName));

		if (pInfo->getUsesCapital())
		{
			aArgs[iNumArgs] = pCapital->getNameKey();
			iNumArgs++;
		}

		if (pInfo->getUsesCiv())
		{
			aArgs[iNumArgs] = GC.getInitCore().getCivShortDescKey(getID());
			iNumArgs++;
		}

		if (pInfo->getUsesLeader())
		{
			aArgs[iNumArgs] = GC.getInitCore().getLeaderNameKey(getID());
			iNumArgs++;
		}
	}

	CvWString szName;

	switch (iNumArgs)
	{
		case 0:
			szName = gDLL->getText(pInfo->getNameKey());
			break;

		case 1:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0]);
			break;

		case 2:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0], aArgs[1]);
			break;

		case 3:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0], aArgs[1], aArgs[2]);
			break;

		case 4:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0], aArgs[1], aArgs[2], aArgs[3]);
			break;

		case 5:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0], aArgs[1], aArgs[2], aArgs[3], aArgs[4]);
			break;

		case 6:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0], aArgs[1], aArgs[2], aArgs[3], aArgs[4], aArgs[5]);
			break;

		case 7:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0], aArgs[1], aArgs[2], aArgs[3], aArgs[4], aArgs[5], aArgs[6]);
			break;

		case 8:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0], aArgs[1], aArgs[2], aArgs[3], aArgs[4], aArgs[5], aArgs[6], aArgs[7]);
			break;

		case 9:
			szName = gDLL->getText(pInfo->getNameKey(), aArgs[0], aArgs[1], aArgs[2], aArgs[3], aArgs[4], aArgs[5], aArgs[6], aArgs[7], aArgs[8]);
			break;
	}

	return szName;
}

const wchar* CvPlayer::getCivilizationDescriptionKey() const
{
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
/*
	if (GC.getInitCore().getCivDescriptionKey(getID()).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getTextKeyWide();
	}
	else
	{
		return GC.getInitCore().getCivDescriptionKey(getID());
	}
*/
	if( !(m_szCivDesc.empty()) )
	{
		return m_szCivDesc;
	}
	else if (GC.getInitCore().getCivDescriptionKey(getID()).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getTextKeyWide();
	}
	else
	{
		return GC.getInitCore().getCivDescriptionKey(getID());
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
}


const wchar* CvPlayer::getCivilizationShortDescription(uint uiForm) const
{
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
/*
	if (GC.getInitCore().getCivShortDesc(getID(), uiForm).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getShortDescription(uiForm);
	}
	else
	{
		return GC.getInitCore().getCivShortDesc(getID(), uiForm);
	}
*/
	// K-Mod. Conceal the civilization of unmet players.
/*	if (concealUnknownCivs() && !GET_TEAM(GC.getGameINLINE().getActiveTeam()).isHasSeen(getTeam()))
	{
		static CvWString string = gDLL->getText("TXT_KEY_UNKNOWN"); // hack to stop the string from going out of scope.
		return string;
	}*/
	// K-Mod end
	if( !(m_szCivShort.empty()) )
	{
		return m_szCivShort;
	}
	else if (GC.getInitCore().getCivShortDesc(getID(), uiForm).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getShortDescription(uiForm);
	}
	else
	{
		return GC.getInitCore().getCivShortDesc(getID(), uiForm);
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
}


const wchar* CvPlayer::getCivilizationShortDescriptionKey() const
{
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
/*
	if (GC.getInitCore().getCivShortDescKey(getID()).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getShortDescriptionKey();
	}
	else
	{
		return GC.getInitCore().getCivShortDescKey(getID());
	}
*/
	if( !(m_szCivShort.empty()) )
	{
		return m_szCivShort;
	}
	else if (GC.getInitCore().getCivShortDescKey(getID()).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getShortDescriptionKey();
	}
	else
	{
		return GC.getInitCore().getCivShortDescKey(getID());
	}

/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
}


const wchar* CvPlayer::getCivilizationAdjective(uint uiForm) const
{
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/* dynamic civ names                                                                            */
/************************************************************************************************/
/*
	if (GC.getInitCore().getCivAdjective(getID(), uiForm).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getAdjective(uiForm);
	}
	else
	{
		return GC.getInitCore().getCivAdjective(getID(), uiForm);
	}
*/
	if( !(m_szCivAdj.empty()) )
	{
		return m_szCivAdj;
	}
	else if (GC.getInitCore().getCivAdjective(getID(), uiForm).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getAdjective(uiForm);
	}
	else
	{
		return GC.getInitCore().getCivAdjective(getID(), uiForm);
	}

/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
}

const wchar* CvPlayer::getCivilizationAdjectiveKey() const
{
/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
	if (GC.getInitCore().getCivAdjectiveKey(getID()).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getAdjectiveKey();
	}
	else
	{
		return GC.getInitCore().getCivAdjectiveKey(getID());
	}
*/
	if( !(m_szCivAdj.empty()) )
	{
		return m_szCivAdj;
	}
	else if (GC.getInitCore().getCivAdjectiveKey(getID()).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getAdjectiveKey();
	}
	else
	{
		return GC.getInitCore().getCivAdjectiveKey(getID());
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
}


CvWString CvPlayer::getFlagDecal() const
{
	if (GC.getInitCore().getFlagDecal(getID()).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getFlagTexture();
	}
	else
	{
		return GC.getInitCore().getFlagDecal(getID());
	}
}

bool CvPlayer::isWhiteFlag() const
{
	if (GC.getInitCore().getFlagDecal(getID()).empty())
	{
		return GC.getCivilizationInfo(getCivilizationType()).getArtInfo()->isWhiteFlag();
	}
	else
	{
		return GC.getInitCore().getWhiteFlag(getID());
	}
}


const wchar* CvPlayer::getStateReligionName(uint uiForm) const
{
	if (getStateReligion() != NO_RELIGION)
	{
		return GC.getReligionInfo(getStateReligion()).getDescription(uiForm);
	}
	else
	{
		return gDLL->getText("TXT_KEY_MISC_NO_STATE_RELIGION");
	}
}

const wchar* CvPlayer::getStateReligionKey() const
{
	if (getStateReligion() != NO_RELIGION)
	{
		return GC.getReligionInfo(getStateReligion()).getTextKeyWide();
	}

	return L"TXT_KEY_MISC_NO_STATE_RELIGION";
}


const CvWString CvPlayer::getBestAttackUnitName(uint uiForm) const
{
	return gDLL->getObjectText((CvString)getBestAttackUnitKey(), uiForm, true);
}


const CvWString CvPlayer::getWorstEnemyName() const
{
	TeamTypes eWorstEnemy;

	eWorstEnemy = GET_TEAM(getTeam()).AI_getWorstEnemy();

	if (eWorstEnemy != NO_TEAM)
	{
		return GET_TEAM(eWorstEnemy).getName();
	}

	return "";
}

const wchar* CvPlayer::getBestAttackUnitKey() const
{
	CvCity* pCapitalCity;
	CvCity* pLoopCity;
	UnitTypes eBestUnit;
	int iLoop;
	int iDummyValue;

	eBestUnit = NO_UNIT;

	pCapitalCity = getCapitalCity();

	if (pCapitalCity != NULL)
	{
		eBestUnit = pCapitalCity->AI_bestUnitAI(UNITAI_ATTACK, iDummyValue, true);
	}

	if (eBestUnit == NO_UNIT)
	{
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			eBestUnit = pLoopCity->AI_bestUnitAI(UNITAI_ATTACK, iDummyValue, true);

			if (eBestUnit != NO_UNIT)
			{
				break;
			}
		}
	}

	if (eBestUnit != NO_UNIT)
	{
		return GC.getUnitInfo(eBestUnit).getTextKeyWide();
	}

	return L"TXT_KEY_MISC_NO_UNIT";
}


ArtStyleTypes CvPlayer::getArtStyleType() const
{
	if (GC.getInitCore().getArtStyle(getID()) == NO_ARTSTYLE)
	{
		return ((ArtStyleTypes)(GC.getCivilizationInfo(getCivilizationType()).getArtStyleType()));
	}
	else
	{
		return GC.getInitCore().getArtStyle(getID());
	}
}

const TCHAR* CvPlayer::getUnitButton(UnitTypes eUnit) const
{
	const CvArtInfoUnit * pUnitArtInfo = GC.getUnitInfo(eUnit).getArtInfo(0, getCurrentEra(), (UnitArtStyleTypes)GC.getCivilizationInfo(getCivilizationType()).getUnitArtStyleType());
	return pUnitArtInfo ? pUnitArtInfo->getButton() : NULL;
	//return GC.getUnitInfo(eUnit).getArtInfo(0, getCurrentEra(), (UnitArtStyleTypes) GC.getCivilizationInfo(getCivilizationType()).getUnitArtStyleType())->getButton();
}

void CvPlayer::recalculateUnitClassCounts(void)
{
	PROFILE_FUNC();

	CvUnit*	pLoopUnit;
	int		iLoop;

	for(int iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
	{
		m_paiUnitClassCount[iI] = 0;
	}

	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		m_paiUnitClassCount[pLoopUnit->getUnitClassType()]++;
	}
}

//	Helper classes to enact city turns in stages - currently split into 3 phases
class CvCityTurnBeginPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnBeginPipelineStage(const char* name) : CvPipelineStage(name, true)
	{
	}
	virtual ~CvCityTurnBeginPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doTurnBeginProcessing();
		cityItem->Complete(iKey);
	}
};

class CvCityTurnMiscAsyncPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnMiscAsyncPipelineStage(const char* name) : CvPipelineStage(name, false)
	{
	}
	virtual ~CvCityTurnMiscAsyncPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doTurnMiscAsync();
		cityItem->Complete(iKey);
	}
};

class CvCityTurnPreProductionPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnPreProductionPipelineStage(const char* name) : CvPipelineStage(name, true)
	{
	}
	virtual ~CvCityTurnPreProductionPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doTurnPreProduction();
		cityItem->Complete(iKey);
	}
};

class CvCityTurnEnactCurrentProductionPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnEnactCurrentProductionPipelineStage(const char* name) : CvPipelineStage(name, true)
	{
	}
	virtual ~CvCityTurnEnactCurrentProductionPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doTurnEnactCurrentProduction(cityItem);
		cityItem->Complete(iKey);
	}
};

class CvCityTurnChooseProductionPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnChooseProductionPipelineStage(const char* name) : CvPipelineStage(name, false)
	{
	}
	virtual ~CvCityTurnChooseProductionPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doTurnChooseProduction(cityItem);
		cityItem->Complete(iKey);
	}
};

class CvCityTurnEnactNewProductionPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnEnactNewProductionPipelineStage(const char* name) : CvPipelineStage(name, true)
	{
	}
	virtual ~CvCityTurnEnactNewProductionPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doTurnEnactNewProduction(cityItem);
		cityItem->Complete(iKey);
	}
};

class CvCityTurnPrepareCompleteProductionPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnPrepareCompleteProductionPipelineStage(const char* name) : CvPipelineStage(name, true)
	{
	}
	virtual ~CvCityTurnPrepareCompleteProductionPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doPrepareToCompleteProduction();
		cityItem->Complete(iKey);
	}
};

class CvCityTurnCompleteProductionPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnCompleteProductionPipelineStage(const char* name) : CvPipelineStage(name, false)
	{
	}
	virtual ~CvCityTurnCompleteProductionPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doTurnCompleteProduction();
		cityItem->Complete(iKey);
	}
};

class CvCityTurnPostProductionPipelineStage : public CvPipelineStage
{
public:
	CvCityTurnPostProductionPipelineStage(const char* name) : CvPipelineStage(name, true)
	{
	}
	virtual ~CvCityTurnPostProductionPipelineStage()
	{
	}

	virtual void	ProcessWorkItem(CvPipelineWorkItem*	item)
	{
		CvCityTurnPipelineWorkItem*	cityItem = (CvCityTurnPipelineWorkItem*)item;
		int	iKey = cityItem->GetKey();

		cityItem->getCity()->doTurnPostProduction();
		cityItem->Complete(iKey);
	}
};

CvPipeline*	CvPlayer::createCityTurnPipeline()
{
	SYSTEM_INFO sysinfo;
	GetSystemInfo(&sysinfo);
	DWORD numCPU = sysinfo.dwNumberOfProcessors;
	int iMaxThreads = std::max(1, ((int)numCPU / 2));
	int iThreads = (GC.getGameINLINE().isGameMultiPlayer() ? 1 : std::min(iMaxThreads, std::max(1, 1 + getNumCities() / 8)));

	CvPipeline*			pResult = new CvPipeline(iThreads);
	CvPipelineStage*	beginTurnStage = new CvCityTurnBeginPipelineStage("Begin");
	CvPipelineSyncPointStage* miscAsyncSyncPoint = new CvPipelineSyncPointStage("MiscAsyncSyncPoint");
	CvPipelineStage*	miscAsyncStage = new CvCityTurnMiscAsyncPipelineStage("MiscAsync");
	CvPipelineStage*	preProductionStage = new CvCityTurnPreProductionPipelineStage("PreProduction");
	CvPipelineStage*	productionEnactCurrentStage = new CvCityTurnEnactCurrentProductionPipelineStage("EnactCurrentProduction");
	CvPipelineStage*	prepareCurrentProductionCompletionStage = new CvCityTurnPrepareCompleteProductionPipelineStage("PrepareCurrentCompleteProdcution");
	CvPipelineStage*	currentProductionCompletionStage = new CvCityTurnCompleteProductionPipelineStage("CompleteCurrentProdcution");
	CvPipelineSyncPointStage* currentProductionSyncPoint = new CvPipelineSyncPointStage("CurrentProductionSyncPoint");
	CvPipelineStage*	productionChooseStage = new CvCityTurnChooseProductionPipelineStage("ChooseProduction");
	CvPipelineStage*	productionEnactNewStage = new CvCityTurnEnactNewProductionPipelineStage("EnactNewProduction");
	CvPipelineStage*	prepareProductionCompletionStage = new CvCityTurnPrepareCompleteProductionPipelineStage("PrepareCompleteProdcution");
	CvPipelineStage*	productionCompletionStage = new CvCityTurnCompleteProductionPipelineStage("CompleteProdcution");
	CvPipelineStage*	postProductionStage = new CvCityTurnPostProductionPipelineStage("PostProduction");

	pResult->AddStage(beginTurnStage);
	pResult->AddStage(miscAsyncSyncPoint);
	pResult->AddStage(miscAsyncStage);
	pResult->AddStage(preProductionStage);
	pResult->AddStage(productionEnactCurrentStage);
	pResult->AddStage(prepareCurrentProductionCompletionStage);
	pResult->AddStage(currentProductionCompletionStage);
	pResult->AddStage(currentProductionSyncPoint);
	pResult->AddStage(productionChooseStage);
	pResult->AddStage(productionEnactNewStage);
	pResult->AddStage(prepareProductionCompletionStage);
	pResult->AddStage(productionCompletionStage);
	pResult->AddStage(postProductionStage);

//	CvCityTurnPipelineWorkItem::m_bHasProcessedDeferalOfVoteSources = false;
//	CvCityTurnPipelineWorkItem::m_bHasProcessedUndeferalOfVoteSources = false;

	return pResult;
}

void CvPlayer::doTurn()
{
	PROFILE_FUNC();

	CvCity* pLoopCity;
	int iLoop;

#ifdef VALIDATION_FOR_PLOT_GROUPS
	for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

		if ( pLoopPlot->getPlotGroupId(getID()) != -1 && pLoopPlot->getPlotGroup(getID()) == NULL )
		{
			::MessageBox(NULL, "Invalid plot group id found!", "CvGameCoreDLL", MB_OK);
		}
	}
#endif

	//	Each turn flush the movement cost cache for each player to avoid it getting too large
	CvPlot::flushMovementCostCache();

#ifdef CAN_TRAIN_CACHING
	//	Clear training caches at the start of each turn
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->clearCanTrainCache(true);
	}
#endif

	m_canHaveBuilder.clear();

	FAssertMsg(isAlive(), "isAlive is expected to be true");
	FAssertMsg(!hasBusyUnit() || GC.getGameINLINE().isMPOption(MPOPTION_SIMULTANEOUS_TURNS)  || GC.getGameINLINE().isSimultaneousTeamTurns(), "End of turn with busy units in a sequential-turn game");

	CvEventReporter::getInstance().beginPlayerTurn( GC.getGameINLINE().getGameTurn(),  getID());
// < M.A.D. Nukes Start >
	if(isEnabledMAD())
	{
		for(int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if(getMADTrigger(iI))
			{
				if(!atWar(getTeam(), GET_PLAYER((PlayerTypes)iI).getTeam()))
				{
					setMADTrigger(iI, false);
				}
			}
		}
	}
	// < M.A.D. Nukes End   >

	setBuildingListInvalid();

	//	Reset cache of best route type to build
	m_eBestRoute = NO_ROUTE;

#ifdef CAN_BUILD_VALUE_CACHING
	CvPlot::ClearCanBuildCache();
#endif

	doUpdateCacheOnTurn();

	GC.getGameINLINE().verifyDeals();

	AI_doTurnPre();

	if (getRevolutionTimer() > 0)
	{
		changeRevolutionTimer(-1);
	}

	if (getConversionTimer() > 0)
	{
		changeConversionTimer(-1);
	}

	// Afforess: WarMongerer Index
	decayWarMongererIndex();

/************************************************************************************************/
/* REVOLUTION_MOD                         02/04/09                                jdog5000      */
/*                                                                                              */
/* For rebels and BarbarianCiv                                                                  */
/************************************************************************************************/
	if( getFreeUnitCountdown() > 0 )
	{
		setFreeUnitCountdown(getFreeUnitCountdown() - 1);
	}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

	CvUnit* pLoopUnit;

	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		pLoopUnit->clearCommanderCache();
	}

	setConscriptCount(0);

	AI_assignWorkingPlots();

	if (0 == GET_TEAM(getTeam()).getHasMetCivCount(true) || GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
	{
		setCommercePercent(COMMERCE_ESPIONAGE, 0);
	}

	// Afforess - Temp Fix for Outside Units Count - Unsure why this increases past the proper value...
	int iOutsideUnits = 0;
	for (pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		CvPlot* pPlot = pLoopUnit->plot();
		if (pPlot->getTeam() != getTeam() && (pPlot->getTeam() == NO_TEAM || !GET_TEAM(pPlot->getTeam()).isVassal(getTeam())))
		{
			iOutsideUnits++; 
		}
	}
	changeNumOutsideUnits(-getNumOutsideUnits() + iOutsideUnits);
	// Afforess End

	//	Recalculate city growth rates from scratch each turn
	recalculatePopulationgrowthratepercentage();

	verifyGoldCommercePercent();

	doGold();

	doResearch();

	doEspionagePoints();

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      05/08/09                                jdog5000      */
/*                                                                                              */
/* City AI                                                                                      */
/************************************************************************************************/
    // New function to handle wonder construction in a centralized manner
	GET_PLAYER(getID()).AI_doCentralizedProduction();
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* Afforess	                  Start		 6/27/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/

	doCheckForTaxationAnger();

	//Clear the cache each turn.
	recalculateAllResourceConsumption();

	doTaxes();
	
	doAdvancedEconomy();

	doInflation(false);

	//	Flush any outstanding UI activities before we start on city processing
	GC.getGameINLINE().doQueuedUIActivity();

	//Decrement cease contact counters
	for (int iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (m_aiCeaseContactCounter[iI] > 0)
		{
			m_aiCeaseContactCounter[iI] = m_aiCeaseContactCounter[iI] - 1;
		}
	}

/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	{
		PROFILE("CvPlayer::doTurn.DoCityTurn");

		//	Force calculation of city sites now if not already done, as we want this to occur
		//	on the main thread, once
		((CvPlayerAI*)this)->AI_getNumCitySites();

		CvPipeline*	pPipeline = createCityTurnPipeline();

		deferUpdates();

		//DWORD start = GetTickCount();

		pPipeline->Begin();

		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			pPipeline->EnqueueWorkItem(new CvCityTurnPipelineWorkItem(pLoopCity));
			//pLoopCity->doTurn();
		}

		pPipeline->End();

		//DWORD end = GetTickCount();

		//GC.getGameINLINE().logMsg("Player %d (num threads: %d) Elapsed pipeline: %d ms", getID(), GC.getNumPipelineThreads(), (end - start));

		resumeUpdates();

		delete pPipeline;
	}

/************************************************************************************************/
/* DCM                                     04/19/09                                Johny Smith  */
/************************************************************************************************/
	// Dale - SA: Opp Fire START
	if (GC.isDCM_OPP_FIRE())
	{
		for (pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			pLoopUnit->doOpportunityFire();
		}
	}
	// Dale - SA: Opp Fire END
	// Dale - SA: Active Defense START
	if (GC.isDCM_ACTIVE_DEFENSE())
	{
		for (pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			pLoopUnit->doActiveDefense();
		}
	}

	// Dale - SA: Active Defense END
/************************************************************************************************/
/* DCM                                     END                                                  */
/************************************************************************************************/
	if (getGoldenAgeTurns() > 0)
	{
		changeGoldenAgeTurns(-1);
	}

	if (getAnarchyTurns() > 0)
	{
		m_iNumAnarchyTurns++;	//	Increment stat counter for turns we have spent in anarchy
		changeAnarchyTurns(-1);
	}

	verifyCivics();

	updateTradeRoutes();

	updateWarWearinessPercentAnger();

	doEvents();

	updateEconomyHistory(GC.getGameINLINE().getGameTurn(), calculateTotalCommerce());
	updateIndustryHistory(GC.getGameINLINE().getGameTurn(), calculateTotalYield(YIELD_PRODUCTION));
	updateAgricultureHistory(GC.getGameINLINE().getGameTurn(), calculateTotalYield(YIELD_FOOD));
	updatePowerHistory(GC.getGameINLINE().getGameTurn(), getPower());
	updateCultureHistory(GC.getGameINLINE().getGameTurn(), processedNationalCulture());
	updateEspionageHistory(GC.getGameINLINE().getGameTurn(), GET_TEAM(getTeam()).getEspionagePointsEver());
	
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	//RevolutionDCM - revolution stability history
	updateRevolutionStabilityHistory(GC.getGameINLINE().getGameTurn(), getStabilityIndexAverage());
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/

	expireMessages();  // turn log

	gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);

	AI_doTurnPost();

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      07/08/09                                jdog5000      */
/*                                                                                              */
/* Debug                                                                                        */
/************************************************************************************************/
    if( GC.getGameINLINE().isDebugMode() )
	{
		GC.getGameINLINE().updateColoredPlots();
	}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

	if ( gPlayerLogLevel >= 1 )
	{
		dumpStats();
	}

	CvEventReporter::getInstance().endPlayerTurn( GC.getGameINLINE().getGameTurn(),  getID());
}

//	Dump stats to BBAI log
void CvPlayer::dumpStats() const
{
	int iLoop;
	CvCity* pLoopCity;
	CvUnit* pLoopUnit;

	logBBAI("%S stats for turn %d:", getCivilizationDescription(0), GC.getGameINLINE().getGameTurn());

	//	Economy stats
	int iUnitCosts = calculateUnitCost();
	int iUnitSupplyCosts = calculateUnitSupply();
	int iMaintenanceCosts = getTotalMaintenance();
	int iCivicUpkeepCosts = getCivicUpkeep();
	int iCorporateTaxIncome = getCorporateTaxIncome();
	int iTotalPreInflatedCosts = iUnitCosts + iUnitSupplyCosts + iMaintenanceCosts + iCivicUpkeepCosts - iCorporateTaxIncome;
	int iTotalCosts = iTotalPreInflatedCosts*std::max(0, (calculateInflationRate() + 100));

	iTotalCosts /= 100;

	//	Accrue some stats off cities
	int iTotalProduction = 0;
	int iTotalFood = 0;
	int	iCityCount = 0;
	int	iTotalPopulation = 0;

	for(pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iCityCount++;
		iTotalPopulation += pLoopCity->getPopulation();
		iTotalFood += pLoopCity->getYieldRate(YIELD_FOOD);
		iTotalProduction += pLoopCity->getYieldRate(YIELD_PRODUCTION);
	}

	logBBAI("    Gold rate: %d", getCommercePercent(COMMERCE_GOLD));
	logBBAI("    Science rate: %d", getCommercePercent(COMMERCE_RESEARCH));
	logBBAI("    Culture rate: %d", getCommercePercent(COMMERCE_CULTURE));
	logBBAI("    Espionage rate: %d", getCommercePercent(COMMERCE_ESPIONAGE));
	logBBAI("    Treasury: %d", getGold());
	logBBAI("    Total gold income from self: %d", getCommerceRate(COMMERCE_GOLD));
	logBBAI("    Total gold income from trade agreements: %d", getGoldPerTurn());
	logBBAI("    Unit cost (pre inflation): %d", iUnitCosts);
	logBBAI("    Unit supply cost (pre inflation): %d", iUnitSupplyCosts);
	logBBAI("    Maintenance cost (pre inflation): %d", iMaintenanceCosts);
	logBBAI("    Civic upkeep cost (pre inflation): %d", iCivicUpkeepCosts);
	logBBAI("    Corporate income (pre inflation): %d", iCorporateTaxIncome);
	logBBAI("    Inflation effect: %d", iTotalCosts - iTotalPreInflatedCosts);
	logBBAI("    Is in financial difficulties: %s", AI_isFinancialTrouble() ? "yes" : "no");
	logBBAI("    Total science output: %d", calculateResearchRate());
	logBBAI("    Total espionage output: %d", getCommerceRate(COMMERCE_ESPIONAGE));
	logBBAI("    Total cultural output: %d", getCommerceRate(COMMERCE_CULTURE));
	logBBAI("    Total population: %d", iTotalPopulation);
	logBBAI("    Total food output: %d", iTotalFood);
	logBBAI("    Total production output: %d", iTotalProduction);
	logBBAI("    Num cities: %d", iCityCount);
	logBBAI("    National rev index: %d", getRevIdxNational());
	logBBAI("    Number of barbarian units killed: %d", getWinsVsBarbs());
	logBBAI("    Number of animals subdued: %d", m_iNumAnimalsSubdued);
	logBBAI("    Civic switches: %d", m_iNumCivicSwitches);
	logBBAI("    Total num civics switched: %d", m_iNumCivicsSwitched);
	logBBAI("    Total turns in anarchy: %d (%d%%%%)", m_iNumAnarchyTurns, (100*m_iNumAnarchyTurns)/(std::max(1,GC.getGameINLINE().getGameTurn())));
	logBBAI("    Current civics:");

	for(int iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		CivicTypes	eCivic = getCivics((CivicOptionTypes)iI);

		if ( eCivic == NO_CIVIC )
		{
			logBBAI("        %S: NONE", GC.getCivicOptionInfo((CivicOptionTypes)iI).getDescription());
		}
		else
		{
			logBBAI("        %S: %S", GC.getCivicOptionInfo((CivicOptionTypes)iI).getDescription(), GC.getCivicInfo(eCivic).getDescription());
		}
	}

	logBBAI("    Civic switch history:");

	int iTurn = -1;
	for(int iI = 0; iI < (int)m_civicSwitchHistory.size(); iI++)
	{
		if ( m_civicSwitchHistory[iI].iTurn != iTurn )
		{
			iTurn = m_civicSwitchHistory[iI].iTurn;
			logBBAI("        Turn %d:", iTurn);
		}

		logBBAI("            %S -> %S%s",
				m_civicSwitchHistory[iI].eFromCivic == NO_CIVIC ? L"Unknown" : GC.getCivicInfo((CivicTypes)m_civicSwitchHistory[iI].eFromCivic).getDescription(),
				m_civicSwitchHistory[iI].eToCivic == NO_CIVIC ? L"Unknown" : GC.getCivicInfo((CivicTypes)m_civicSwitchHistory[iI].eToCivic).getDescription(),
				m_civicSwitchHistory[iI].bNoAnarchy ? " (no anarchy switch)" : "");
	}
	if ( iTurn == -1 )
	{
		logBBAI("        No switches made");
	}

	//	City stats
	for(pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		logBBAI("        City %S:", pLoopCity->getName().c_str());
		logBBAI("            Population: %d", pLoopCity->getPopulation());
		logBBAI("            Production: %d", pLoopCity->getYieldRate(YIELD_PRODUCTION));
		logBBAI("            Food surplus: %d", pLoopCity->foodDifference());
		logBBAI("            Local rev index: %d", pLoopCity->getLocalRevIndex());
		logBBAI("            Maintenance: %d", pLoopCity->getMaintenance());
		logBBAI("            Income: %d", pLoopCity->getCommerceRate(COMMERCE_GOLD));
		logBBAI("            Science: %d", pLoopCity->getCommerceRate(COMMERCE_RESEARCH));
		logBBAI("            Espionage: %d", pLoopCity->getCommerceRate(COMMERCE_ESPIONAGE));
		logBBAI("            Culture: %d", pLoopCity->getCommerceRate(COMMERCE_CULTURE));
		logBBAI("            Net happyness: %d", pLoopCity->happyLevel() - pLoopCity->unhappyLevel());
		logBBAI("            Net health: %d", pLoopCity->goodHealth() - pLoopCity->badHealth());
		logBBAI("            Food trade yield: %d", pLoopCity->getTradeYield(YIELD_FOOD));
		logBBAI("            Production trade yield: %d", pLoopCity->getTradeYield(YIELD_PRODUCTION));
		logBBAI("            Commerce trade yield: %d", pLoopCity->getTradeYield(YIELD_COMMERCE));
		logBBAI("            Property values:");

		CvProperties* pProperties = pLoopCity->getGameObject()->getProperties();

		for(int iJ = 0; iJ < pProperties->getNumProperties(); iJ++)
		{
			PropertyTypes	eProperty = (PropertyTypes)pProperties->getProperty(iJ);

			logBBAI("                %S: %d", GC.getPropertyInfo(eProperty).getDescription(), pProperties->getValue(iJ));
		}
	}

	//	Unit stats
	std::map<int, int> unitCounts;

	logBBAI("    Units:");
	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		UnitTypes eUnitType = pLoopUnit->getUnitType();
		UnitAITypes eAIType = pLoopUnit->AI_getUnitAIType();
		int		iMapKey = eAIType + (eUnitType << 16);

		std::map<int,int>::iterator itr = unitCounts.find(iMapKey);

		if ( itr == unitCounts.end() )
		{
			unitCounts.insert( std::make_pair(iMapKey, 1) );
		}
		else
		{
			(itr->second)++;
		}
	}

	for(std::map<int,int>::const_iterator itr = unitCounts.begin(); itr != unitCounts.end(); ++itr)
	{
		logBBAI("        %S (%s): %d", GC.getUnitInfo((UnitTypes)(itr->first >> 16)).getDescription(), GC.getUnitAIInfo((UnitAITypes)(itr->first & 0xFFFF)).getType(), itr->second);
	}

	logBBAI("    Buildings constructed by units:");
	for(std::map<BuildingTypes,int>::const_iterator itr = m_unitConstructionCounts.begin(); itr != m_unitConstructionCounts.end(); ++itr)
	{
		logBBAI("        %S: %d", GC.getBuildingInfo(itr->first).getDescription(), itr->second);
	}
}

void CvPlayer::NoteAnimalSubdued()
{
	m_iNumAnimalsSubdued++;
}

void CvPlayer::NoteUnitConstructed(BuildingTypes eBuilding)
{
	std::map<BuildingTypes,int>::iterator itr = m_unitConstructionCounts.find(eBuilding);

	if ( itr == m_unitConstructionCounts.end() )
	{
		m_unitConstructionCounts.insert( std::make_pair(eBuilding, 1) );
	}
	else
	{
		(itr->second)++;
	}
}

void CvPlayer::NoteCivicsSwitched(int iNumChanges)
{
	m_iNumCivicSwitches++;
	m_iNumCivicsSwitched += iNumChanges;
}

void CvPlayer::doTurnUnits()
{
	PROFILE_FUNC();

	CvSelectionGroup* pLoopSelectionGroup;
	int iLoop;

	AI_doTurnUnitsPre();

	m_guardableResourcePlots.clear();

	for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

		if (pLoopPlot->getOwnerINLINE() == getID())
		{
			BonusTypes eNonObsoleteBonus = pLoopPlot->getNonObsoleteBonusType(getTeam());

			if (eNonObsoleteBonus != NO_BONUS)
			{
				ImprovementTypes eImprovement = pLoopPlot->getImprovementType();

				if ((eImprovement != NO_IMPROVEMENT) && GC.getImprovementInfo(eImprovement).isImprovementBonusTrade(eNonObsoleteBonus))
				{
					m_guardableResourcePlots[iI] = eNonObsoleteBonus;
				}
			}
		}
	}

	for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup != NULL; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
	{
		pLoopSelectionGroup->doDelayedDeath();
	}

	for (int iPass = 0; iPass < 4; iPass++)
	{
		for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup != NULL; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
		{
			if ( pLoopSelectionGroup->plot() != NULL )
			{
				switch (pLoopSelectionGroup->getDomainType())
				{
				case DOMAIN_AIR:
					if (iPass == 1)
					{
						pLoopSelectionGroup->doTurn();
					}
					break;
				case DOMAIN_SEA:
					if (iPass == 2)
					{
						pLoopSelectionGroup->doTurn();
					}
					break;
				case DOMAIN_LAND:
					if (iPass == 3)
					{
						pLoopSelectionGroup->doTurn();
					}
					break;
				case DOMAIN_IMMOBILE:
					if (iPass == 0)
					{
						pLoopSelectionGroup->doTurn();
					}
					break;
				case NO_DOMAIN:
					FAssertMsg(NULL == pLoopSelectionGroup->getHeadUnit(), "Unit with no Domain");
				default:
					if (iPass == 3)
					{
						pLoopSelectionGroup->doTurn();
					}
					break;
				}
			}
		}
	}

	if (getID() == GC.getGameINLINE().getActivePlayer())
	{
		gDLL->getFAStarIFace()->ForceReset(&GC.getInterfacePathFinder());

		gDLL->getInterfaceIFace()->setDirty(Waypoints_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(SelectionButtons_DIRTY_BIT, true);
	}

	gDLL->getInterfaceIFace()->setDirty(UnitInfo_DIRTY_BIT, true);

	AI_doTurnUnitsPost();
}


void CvPlayer::verifyCivics()
{
	PROFILE_FUNC()

	int iI, iJ;

	if (!isAnarchy())
	{
		for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
		{
			if (!canDoCivics(getCivics((CivicOptionTypes)iI)))
			{
				for (iJ = 0; iJ < GC.getNumCivicInfos(); iJ++)
				{
					if (GC.getCivicInfo((CivicTypes)iJ).getCivicOptionType() == iI)
					{
						if (canDoCivics((CivicTypes)iJ))
						{
							setCivics(((CivicOptionTypes)iI), ((CivicTypes)iJ));
							break;
						}
					}
				}
			}
		}
	}
}

void CvPlayer::inhibitPlotGroupCalcsUntilFullRebuild(void)	//	Ignore updates until an update with reInitialize set
{
	m_bInhibitPlotGroupRecalc = true;
}

void CvPlayer::updatePlotGroups(CvArea* possibleNewInAreaOnly, bool reInitialize)
{
	PROFILE_FUNC();

	CvPlotGroup* pLoopPlotGroup;
	int iLoop;
	int iI;

	if (!(GC.getGameINLINE().isFinalInitialized()))
	{
		return;
	}

	if ( m_bInhibitPlotGroupRecalc && !reInitialize )
	{
		return;
	}

	m_bInhibitPlotGroupRecalc = false;

	CvCity* pLoopCity;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->startDeferredBonusProcessing();
	}

	if ( possibleNewInAreaOnly == NULL )
	{
		if ( reInitialize )
		{
			//	Throw away all existing plot groups
			for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
			{
				CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

				pLoopPlot->setPlotGroup(getID(), NULL, false);
			}

			m_plotGroups.removeAll();
		}
		else
		{
			for(pLoopPlotGroup = firstPlotGroup(&iLoop); pLoopPlotGroup != NULL; pLoopPlotGroup = nextPlotGroup(&iLoop))
			{
				pLoopPlotGroup->recalculatePlots();
			}
		}
	}

	for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
		
		if ( possibleNewInAreaOnly == NULL || pLoopPlot->area() == possibleNewInAreaOnly )
		{
			if ( pLoopPlot->getPlotGroup(getID()) == NULL )
			{
				CvPlotGroup::colorRegion(pLoopPlot, getID(), true);
			}
			//pLoopPlot->updatePlotGroup(getID(), false);
		}
	}

#ifdef VALIDATION_FOR_PLOT_GROUPS
	for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

		if ( pLoopPlot->getPlotGroupId(getID()) != -1 && pLoopPlot->getPlotGroup(getID()) == NULL )
		{
			::MessageBox(NULL, "Invalid plot group id found after recalc!", "CvGameCoreDLL", MB_OK);
		}
	}
#endif

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->endDeferredBonusProcessing();
	}

	updateTradeRoutes();
}

void CvPlayer::RecalculatePlotGroupHashes()
{
	PROFILE_FUNC();

	CvPlotGroup* pLoopPlotGroup;
	int iLoop;

	for(pLoopPlotGroup = firstPlotGroup(&iLoop); pLoopPlotGroup != NULL; pLoopPlotGroup = nextPlotGroup(&iLoop))
	{
		pLoopPlotGroup->RecalculateHashes();
	}
}

void CvPlayer::updateYield()
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateYield();
	}
}


void CvPlayer::updateMaintenance() const
{
	CvCity* pLoopCity;
	int iLoop;

	m_iTotalMaintenance = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateMaintenance();
		m_iTotalMaintenance += pLoopCity->getMaintenanceTimes100();
	}

	setMaintenanceDirty(false);

	FAssert(m_iTotalMaintenance >= 0);
}


void CvPlayer::updatePowerHealth()
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updatePowerHealth();
	}
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::updateExtraBuildingHappiness(bool bLimited)
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateExtraBuildingHappiness(bLimited);
	}
}


//Fuyu bLimited
void CvPlayer::updateExtraBuildingHealth(bool bLimited)
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateExtraBuildingHealth(bLimited);
	}
}


//Fuyu bLimited
void CvPlayer::updateFeatureHappiness(bool bLimited)
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateFeatureHappiness(bLimited);
	}
}


//Fuyu bLimited
void CvPlayer::updateReligionHappiness(bool bLimited)
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateReligionHappiness(bLimited);
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


void CvPlayer::updateExtraSpecialistYield()
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateExtraSpecialistYield();
	}
}


void CvPlayer::updateCommerce(CommerceTypes eCommerce, bool bForce) const
{
	CvCity* pLoopCity;
	int iLoop;

	if ( eCommerce == NO_COMMERCE )
	{
		for(int iI = 0; iI < NUM_COMMERCE_TYPES; iI++ )
		{
			updateCommerce((CommerceTypes)iI, bForce);
		}
	}
	else if (!m_bUpdatesDeferred)
	{
		if ( bForce || m_abCommerceDirty[eCommerce])
		{
			m_abCommerceDirty[eCommerce] = false;

			for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->updateCommerce(eCommerce, bForce);
			}
		}
	}
	else
	{
		m_abCommerceDirty[eCommerce] |= bForce;
	}
}

void CvPlayer::setCommerceDirty(CommerceTypes eIndex, bool bPlayerOnly)
{
	CvCity* pLoopCity;
	int iLoop;

	if ( eIndex == NO_COMMERCE )
	{
		for(int iI = 0; iI < NUM_COMMERCE_TYPES; iI++ )
		{
			setCommerceDirty((CommerceTypes)iI, bPlayerOnly);
		}
	}
	else
	{
		m_abCommerceDirty[eIndex] = true;

		if (!bPlayerOnly)
		{
			for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->setCommerceDirty(eIndex);
			}
		}
	}
}

void CvPlayer::updateBuildingCommerce()
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateBuildingCommerce();
	}
}


void CvPlayer::updateReligionCommerce()
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateReligionCommerce();
	}
}


void CvPlayer::updateCorporation()
{
	int iLoop;
	for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateCorporation();
	}
}


void CvPlayer::updateCityPlotYield()
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->plot()->updateYield();
	}
}


void CvPlayer::updateCitySight(bool bIncrement, bool bUpdatePlotGroups)
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->plot()->updateSight(bIncrement, bUpdatePlotGroups);
	}
}


void CvPlayer::updateTradeRoutes()
{
	PROFILE_FUNC()

	CLLNode<int>* pCityNode;
	CvCity* pLoopCity;
	CvCity* pListCity;
	CLinkList<int> cityList;
	int iTotalTradeModifier;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->clearTradeRoutes();
	}

	cityList.clear();

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iTotalTradeModifier = pLoopCity->totalTradeModifier();

		pCityNode = cityList.head();

		while (pCityNode != NULL)
		{
			pListCity = getCity(pCityNode->m_data);

			if (iTotalTradeModifier > pListCity->totalTradeModifier())
			{
				cityList.insertBefore(pLoopCity->getID(), pCityNode);
				break;
			}
			else
			{
				pCityNode = cityList.next(pCityNode);
			}
		}

		if (pCityNode == NULL)
		{
			cityList.insertAtEnd(pLoopCity->getID());
		}
	}

	pCityNode = cityList.head();

	while (pCityNode != NULL)
	{
		getCity(pCityNode->m_data)->updateTradeRoutes();
		pCityNode = cityList.next(pCityNode);
	}
}

void CvPlayer::updatePlunder(int iChange, bool bUpdatePlotGroups)
{
	int iLoop;
	for (CvUnit* pLoopUnit = firstUnit(&iLoop); NULL != pLoopUnit; pLoopUnit = nextUnit(&iLoop))
	{
		if (pLoopUnit->isBlockading())
		{
			pLoopUnit->updatePlunder(iChange, bUpdatePlotGroups);
		}
	}
}

void CvPlayer::updateTimers()
{
	CvSelectionGroup* pLoopSelectionGroup;
	int iLoop;

	for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
	{
		pLoopSelectionGroup->updateTimers(); // could destroy the selection group...
	}

	// if a unit was busy, perhaps it was not quite deleted yet, give it one more try
	if (getNumSelectionGroups() > getNumUnits())
	{
		for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
		{
			pLoopSelectionGroup->doDelayedDeath(); // could destroy the selection group...
		}
	}

	//Who cares?
	//FAssertMsg(getNumSelectionGroups() <= getNumUnits(), "The number of Units is expected not to exceed the number of Selection Groups");
}


bool CvPlayer::hasReadyUnautomatedUnit(bool bAny) const
{
	PROFILE_FUNC();

	CvSelectionGroup* pLoopSelectionGroup;
	int iLoop;

	for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
	{
		if (pLoopSelectionGroup->readyToMove(bAny, !isHuman()) && !pLoopSelectionGroup->isAutomated())
		{
			return true;
		}
	}

	return false;
}

bool CvPlayer::hasReadyUnit(bool bAny) const
{
	PROFILE_FUNC();

	CvSelectionGroup* pLoopSelectionGroup;
	int iLoop;

	for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
	{
		if (pLoopSelectionGroup->readyToMove(bAny, !isHuman()))
		{
			return true;
		}
	}

	return false;
}


bool CvPlayer::hasAutoUnit() const
{
	PROFILE_FUNC();

	CvSelectionGroup* pLoopSelectionGroup;
	int iLoop;

	for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
	{
		if (pLoopSelectionGroup->readyToAuto())
		{
			return true;
		}
	}

	return false;
}


bool CvPlayer::hasBusyUnit() const
{
	PROFILE_FUNC();

	CvSelectionGroup* pLoopSelectionGroup;
	int iLoop;

	for(pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
	{
		if (pLoopSelectionGroup->isBusy())
		{
		    if (pLoopSelectionGroup->getNumUnits() == 0)
		    {
		        pLoopSelectionGroup->kill();
		        return false;
		    }

			return true;
		}
	}

	return false;
}
/************************************************************************************************/
/* UNOFFICIAL_PATCH                       12/07/09                             EmperorFool      */
/*                                                                                              */
/* Bugfix                                                                                       */
/************************************************************************************************/
// Free Tech Popup Fix
bool CvPlayer::isChoosingFreeTech() const
{
	return m_bChoosingFreeTech;
}

void CvPlayer::setChoosingFreeTech(bool bValue)
{
	m_bChoosingFreeTech = bValue;
}
/************************************************************************************************/
/* UNOFFICIAL_PATCH                        END                                                  */
/************************************************************************************************/

void CvPlayer::chooseTech(int iDiscover, CvWString szText, bool bFront)
{
/************************************************************************************************/
/* UNOFFICIAL_PATCH                       12/07/09                             EmperorFool      */
/*                                                                                              */
/* Bugfix                                                                                       */
/************************************************************************************************/
	// Free Tech Popup Fix
	if (iDiscover > 0)
	{
		setChoosingFreeTech(true);
	}
/************************************************************************************************/
/* UNOFFICIAL_PATCH                        END                                                  */
/************************************************************************************************/

	CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_CHOOSETECH);
	if (NULL != pInfo)
	{
		pInfo->setData1(iDiscover);
		pInfo->setText(szText);
		gDLL->getInterfaceIFace()->addPopup(pInfo, getID(), false, bFront);
	}
}


int CvPlayer::calculateScore(bool bFinal, bool bVictory) const //Afforess: made const
{
	PROFILE_FUNC();

	if (!isAlive())
	{
		return 0;
	}

	if (GET_TEAM(getTeam()).getNumMembers() == 0)
	{
		return 0;
	}
/************************************************************************************************/
/* Afforess	                  Start		 06/25/10                                               */
/*                                                                                              */
/* Calculating the Score from python is time consuming                                          */
/************************************************************************************************/
/*
	long lScore = 0;

	CyArgsList argsList;
	argsList.add((int) getID());
	argsList.add(bFinal);
	argsList.add(bVictory);
	PYTHON_CALL_FUNCTION(__FUNCTION__, PYGameModule, "calculateScore", argsList.makeFunctionArgs(), &lScore);

	return ((int)lScore);
*/
	int iPopulationScore = getScoreComponent(getPopScore(), GC.getGameINLINE().getInitPopulation(), GC.getGameINLINE().getMaxPopulation(), GC.getSCORE_POPULATION_FACTOR(), true, bFinal, bVictory);
	
	int iLandScore = getScoreComponent(getLandScore(), GC.getGameINLINE().getInitLand(), GC.getGameINLINE().getMaxLand(), GC.getSCORE_LAND_FACTOR(), true, bFinal, bVictory);
	
	int iTechScore = getScoreComponent(getTechScore(), GC.getGameINLINE().getInitTech(), GC.getGameINLINE().getMaxTech(), GC.getSCORE_TECH_FACTOR(), true, bFinal, bVictory);
	
	int iWondersScore = getScoreComponent(getWondersScore(), GC.getGameINLINE().getInitWonders(), GC.getGameINLINE().getMaxWonders(), GC.getSCORE_WONDER_FACTOR(), false, bFinal, bVictory);
	
	return iPopulationScore + iLandScore + iTechScore + iWondersScore;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/	
}


int CvPlayer::findBestFoundValue() const
{
	CvArea* pLoopArea;
	int iValue;
	int iBestValue;
	int iLoop;

	iBestValue = 0;

	for(pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop))
	{
		iValue = pLoopArea->getBestFoundValue(getID());

		if (iValue > iBestValue)
		{
			iBestValue = iValue;
		}
	}

	return iBestValue;
}


int CvPlayer::upgradeAllPrice(UnitTypes eUpgradeUnit, UnitTypes eFromUnit)
{
	CvUnit* pLoopUnit;
	int iPrice;
	int iLoop;

	iPrice = 0;

	// Loop through units and determine the total power of this player's military
	for (pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		if (pLoopUnit->getUnitType() == eFromUnit)
		{
			if (pLoopUnit->canUpgrade(eUpgradeUnit, true))
			{
				iPrice += pLoopUnit->upgradePrice(eUpgradeUnit);
			}
		}
	}

	return iPrice;
}

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      11/14/09                                jdog5000      */
/*                                                                                              */
/* General AI                                                                                   */
/************************************************************************************************/
int CvPlayer::countReligionSpreadUnits(CvArea* pArea, ReligionTypes eReligion, bool bIncludeTraining) const
{
	PROFILE_FUNC();

	CvUnit* pLoopUnit;
	int iCount;
	int iLoop;

	iCount = 0;

	for (pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		if (pLoopUnit->getArea() == pArea->getID())
		{
			if (pLoopUnit->getUnitInfo().getReligionSpreads(eReligion) > 0)
			{
				iCount++;
			}
		}
	}

	if( bIncludeTraining )
	{
		CvCity* pLoopCity;
		for( pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop) )
		{
			UnitTypes eUnit = pLoopCity->getProductionUnit();

			if( eUnit != NO_UNIT )
			{
				if(GC.getUnitInfo(eUnit).getReligionSpreads(eReligion) > 0)
				{
					iCount++;
				}
			}
		}
	}

	return iCount;
}

int CvPlayer::countCorporationSpreadUnits(CvArea* pArea, CorporationTypes eCorporation, bool bIncludeTraining) const
{
	PROFILE_FUNC();

	int iCount = 0;
	int iLoop;
	for (CvUnit* pLoopUnit = firstUnit(&iLoop); NULL != pLoopUnit; pLoopUnit = nextUnit(&iLoop))
	{
		if (pLoopUnit->area() == pArea)
		{
			if (pLoopUnit->getUnitInfo().getCorporationSpreads(eCorporation) > 0)
			{
				++iCount;
			}
		}
	}

	if( bIncludeTraining )
	{
		CvCity* pLoopCity;
		for( pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop) )
		{
			UnitTypes eUnit = pLoopCity->getProductionUnit();

			if( eUnit != NO_UNIT )
			{
				if(GC.getUnitInfo(eUnit).getCorporationSpreads(eCorporation) > 0)
				{
					iCount++;
				}
			}
		}
	}

	return iCount;
}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

int CvPlayer::countNumCoastalCities() const
{
	CvCity* pLoopCity;
	int iCount;
	int iLoop;

	iCount = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->isCoastal(GC.getMIN_WATER_SIZE_FOR_OCEAN()))
		{
			iCount++;
		}
	}

	return iCount;
}


int CvPlayer::countNumCoastalCitiesByArea(CvArea* pArea) const
{
	CvCity* pLoopCity;
	int iCount;
	int iLoop;

	iCount = 0;

	int iAreaID = pArea->getID();
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->isCoastal(GC.getMIN_WATER_SIZE_FOR_OCEAN()))
		{
			if ((pLoopCity->getArea() == iAreaID) || pLoopCity->plot()->isAdjacentToArea(iAreaID))
			{
				iCount++;
			}
		}
	}

	return iCount;
}


unsigned long long CvPlayer::countTotalCulture() const
{
	CvCity* pLoopCity;
	unsigned long long iCount;
	int iLoop;

	iCount = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iCount += pLoopCity->getCultureTimes100(getID());
	}

	return iCount/100;
}


int CvPlayer::countOwnedBonuses(BonusTypes eBonus) const
{
	PROFILE("CvPlayer::countOwnedBonuses");
    CvCity* pLoopCity;
	CvPlot* pLoopPlot;
	int iI, iJ;
    int iLoop;
    
	FAssert(eBonus >= 0 && eBonus < GC.getNumBonusInfos());

	if ( eBonus < 0 && eBonus >= GC.getNumBonusInfos() )
	{
		return 0;
	}

	if ( m_cachedBonusCount == NULL )
	{
		m_cachedBonusCount = new int[GC.getNumBonusInfos()];
		m_cachedBonusCountGameTurn = -1;
	}

	//	We keep a per-turn cached result value for each bonus type
	//	Strictly this only gives approximately the right answer (since bonuses can
	//	change hands mid-turn, but the the purposes the evaluation is used for
	//	that's plenty good enough
	if ( GC.getGame().getGameTurn() != m_cachedBonusCountGameTurn )
	{
		for(iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			m_cachedBonusCount[iI] = 0;
		}

		bool bAdvancedStart = (getAdvancedStartPoints() >= 0) && (getCurrentEra() < 3);

		//count bonuses outside city radius
		for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
		{
			pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

			if ((pLoopPlot->getOwnerINLINE() == getID() && !pLoopPlot->isCityRadius()) ||
				(bAdvancedStart && pLoopPlot->isRevealed(getTeam(), false)))
			{
				BonusTypes ePlotBonus = pLoopPlot->getBonusType(getTeam());
				if ( NO_BONUS != ePlotBonus )
				{
					m_cachedBonusCount[ePlotBonus]++;
				}
			}
		}

		//count bonuses inside city radius or easily claimed
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			bool bCommerceCulture = (pLoopCity->getCommerceRate(COMMERCE_CULTURE) > 0);

			for(iJ = 0; iJ < GC.getNumBonusInfos(); iJ++)
			{
				m_cachedBonusCount[iJ] += pLoopCity->AI_countNumBonuses((BonusTypes)iJ, true, bCommerceCulture, -1);
			}
		}

		m_cachedBonusCountGameTurn = GC.getGame().getGameTurn();
	}

	return m_cachedBonusCount[eBonus];
}


int CvPlayer::countUnimprovedBonuses(CvArea* pArea, CvPlot* pFromPlot) const
{
	PROFILE_FUNC();

	CvPlot* pLoopPlot;
	ImprovementTypes eImprovement;
	BuildTypes eBuild;
	BonusTypes eNonObsoleteBonus;
	int iCount;
	int iI, iJ;

	if ( pFromPlot != NULL )
	{
		gDLL->getFAStarIFace()->ForceReset(&GC.getBorderFinder());
	}

	iCount = 0;

	for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

		if (pLoopPlot->area() == pArea)
		{
			if (pLoopPlot->getOwnerINLINE() == getID())
			{
				if (!(pLoopPlot->isCity()))
				{
					eNonObsoleteBonus = pLoopPlot->getNonObsoleteBonusType(getTeam());

					if (eNonObsoleteBonus != NO_BONUS)
					{
						eImprovement = pLoopPlot->getImprovementType();

						if ((eImprovement == NO_IMPROVEMENT) || !(GC.getImprovementInfo(eImprovement).isImprovementBonusTrade(eNonObsoleteBonus)))
						{
							if ((pFromPlot == NULL) || gDLL->getFAStarIFace()->GeneratePath(&GC.getBorderFinder(), pFromPlot->getX_INLINE(), pFromPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), false, getID(), true))
							{
								for (iJ = 0; iJ < GC.getNumBuildInfos(); iJ++)
								{
									eBuild = ((BuildTypes)iJ);

									if (GC.getBuildInfo(eBuild).getImprovement() != NO_IMPROVEMENT)
									{
										if (GC.getImprovementInfo((ImprovementTypes)(GC.getBuildInfo(eBuild).getImprovement())).isImprovementBonusTrade(eNonObsoleteBonus))
										{
											if (canBuild(pLoopPlot, eBuild))
											{
												iCount++;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}

	return iCount;
}


int CvPlayer::countCityFeatures(FeatureTypes eFeature) const
{
	PROFILE_FUNC();

	CvCity* pLoopCity;
	CvPlot* pLoopPlot;
	int iCount;
	int iLoop;
	int iI;

	iCount = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		for (iI = 0; iI < NUM_CITY_PLOTS; iI++)
		{
			pLoopPlot = plotCity(pLoopCity->getX_INLINE(), pLoopCity->getY_INLINE(), iI);

			if (pLoopPlot != NULL)
			{
				if (pLoopPlot->getFeatureType() == eFeature)
				{
					iCount++;
				}
			}
		}
	}

	return iCount;
}


int CvPlayer::countNumBuildings(BuildingTypes eBuilding) const
{
	PROFILE_FUNC();

	CvCity* pLoopCity;
	int iCount;
	int iLoop;

	iCount = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->getNumBuilding(eBuilding) > 0)
		{
			iCount += pLoopCity->getNumBuilding(eBuilding);
		}
	}

	return iCount;
}


int CvPlayer::countNumCitiesConnectedToCapital() const
{
	CvCity* pLoopCity;
	int iCount;
	int iLoop;

	iCount = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->isConnectedToCapital())
		{
			iCount++;
		}
	}

	return iCount;
}


int CvPlayer::countPotentialForeignTradeCities(CvArea* pIgnoreArea) const
{
	int iTempValue;
	int iCount;
	int iI;

	iCount = 0;

	for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
	{
		if (GET_TEAM((TeamTypes)iI).isAlive())
		{
			if (iI != getTeam())
			{
				if (GET_TEAM(getTeam()).isFreeTrade((TeamTypes)iI))
				{
					iTempValue = GET_TEAM((TeamTypes)iI).getNumCities();

					if (pIgnoreArea != NULL)
					{
						iTempValue -= GET_TEAM((TeamTypes)iI).countNumCitiesByArea(pIgnoreArea);
					}

					iCount += iTempValue;
				}
			}
		}
	}

	return iCount;
}


int CvPlayer::countPotentialForeignTradeCitiesConnected() const
{
	CvCity* pCapitalCity;
	CvCity* pLoopCity;
	int iCount;
	int iLoop;
	int iI;

	iCount = 0;

	pCapitalCity = getCapitalCity();

	if (pCapitalCity != NULL)
	{
		for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).isAlive())
			{
				if (GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam())
				{
					if (GET_TEAM(getTeam()).isFreeTrade(GET_PLAYER((PlayerTypes)iI).getTeam()))
					{
						for (pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
						{
							FAssert(pLoopCity->getOwnerINLINE() != getID());
							FAssert(pLoopCity->getTeam() != getTeam());

							if (pLoopCity->plotGroup(getID()) == pCapitalCity->plotGroup(getID()))
							{
								iCount++;
							}
						}
					}
				}
			}
		}
	}

	return iCount;
}



bool CvPlayer::canContact(PlayerTypes ePlayer) const
{
	if (ePlayer == getID())
	{
		return false;
	}

	if (!isAlive() || !(GET_PLAYER(ePlayer).isAlive()))
	{
		return false;
	}

	if (isBarbarian() || GET_PLAYER(ePlayer).isBarbarian())
	{
		return false;
	}

	if (isMinorCiv() || GET_PLAYER(ePlayer).isMinorCiv())
	{
		return false;
	}

	if (getTeam() != GET_PLAYER(ePlayer).getTeam())
	{
		if (!(GET_TEAM(getTeam()).isHasMet(GET_PLAYER(ePlayer).getTeam())))
		{
			return false;
		}

		if (atWar(getTeam(), GET_PLAYER(ePlayer).getTeam()))
		{
			if (!(GET_TEAM(getTeam()).canChangeWarPeace(GET_PLAYER(ePlayer).getTeam())))
			{
				return false;
			}
		}

		if (isHuman() || GET_PLAYER(ePlayer).isHuman())
		{
			if (GC.getGameINLINE().isOption(GAMEOPTION_ALWAYS_WAR))
			{
				return false;
			}
		}
	}

	return true;
}


void CvPlayer::contact(PlayerTypes ePlayer)
{
	CvDiploParameters* pDiplo;

	if (!canContact(ePlayer) || isTurnDone())
	{
		return;
	}

	if (GET_PLAYER(ePlayer).isHuman())
	{
		if (GC.getGameINLINE().isPbem() || GC.getGameINLINE().isHotSeat() || (GC.getGameINLINE().isPitboss() && !gDLL->isConnected(GET_PLAYER(ePlayer).getNetID())))
		{
			if (gDLL->isMPDiplomacy())
			{
				gDLL->beginMPDiplomacy(ePlayer, false, false);
			}
		}
		else
		{
			if (gDLL->getInterfaceIFace()->isFlashing(ePlayer))
			{
				if (!gDLL->getInterfaceIFace()->isDiplomacyLocked())
				{
					gDLL->getInterfaceIFace()->setDiplomacyLocked(true);
					gDLL->sendContactCiv(NETCONTACT_RESPONSE, ePlayer);
				}
			}
			else
			{
				gDLL->sendContactCiv(NETCONTACT_INITIAL, ePlayer);
			}
		}
	}
	else
	{
		pDiplo = new CvDiploParameters(ePlayer);
		FAssert(pDiplo != NULL);
		if (gDLL->ctrlKey())
		{
			pDiplo->setDiploComment((DiploCommentTypes)GC.getInfoTypeForString("AI_DIPLOCOMMENT_TRADING"));
		}
		gDLL->getInterfaceIFace()->setDiploQueue(pDiplo, GC.getGameINLINE().getActivePlayer());
	}
}


void CvPlayer::handleDiploEvent(DiploEventTypes eDiploEvent, PlayerTypes ePlayer, int iData1, int iData2)
{
	CivicTypes* paeNewCivics;
	CvCity* pCity;
	int iI;

	//OutputDebugString(CvString::format("UI interaction - diplo event for player %d (with player %d)\n", m_eID, ePlayer).c_str());
	setTurnHadUIInteraction(true);


/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	// RevolutionDCM start - new diplomacy option
	//FAssertMsg(ePlayer != getID(), "shouldn't call this function on ourselves");
	// RevolutionDCM end
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/


	switch (eDiploEvent)
	{
	case DIPLOEVENT_CONTACT:
		AI_setFirstContact(ePlayer, true);
		GET_PLAYER(ePlayer).AI_setFirstContact(getID(), true);
		break;

	case DIPLOEVENT_AI_CONTACT:
		break;

	case DIPLOEVENT_FAILED_CONTACT:
		AI_setFirstContact(ePlayer, true);
		GET_PLAYER(ePlayer).AI_setFirstContact(getID(), true);
		break;

	case DIPLOEVENT_GIVE_HELP:
		AI_changeMemoryCount(ePlayer, MEMORY_GIVE_HELP, 1);
		forcePeace(ePlayer);
		break;

	case DIPLOEVENT_REFUSED_HELP:
		AI_changeMemoryCount(ePlayer, MEMORY_REFUSED_HELP, 1);
		break;

	case DIPLOEVENT_ACCEPT_DEMAND:
		AI_changeMemoryCount(ePlayer, MEMORY_ACCEPT_DEMAND, 1);
		forcePeace(ePlayer);
		break;

	case DIPLOEVENT_REJECTED_DEMAND:
		FAssertMsg(GET_PLAYER(ePlayer).getTeam() != getTeam(), "shouldn't call this function on our own team");

		AI_changeMemoryCount(ePlayer, MEMORY_REJECTED_DEMAND, 1);

		if (AI_demandRebukedSneak(ePlayer))
		{
			GET_TEAM(getTeam()).AI_setWarPlan(GET_PLAYER(ePlayer).getTeam(), WARPLAN_PREPARING_LIMITED);
		}
		break;

	case DIPLOEVENT_DEMAND_WAR:
		FAssertMsg(GET_PLAYER(ePlayer).getTeam() != getTeam(), "shouldn't call this function on our own team");
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      10/02/09                                jdog5000      */
/*                                                                                              */
/* AI logging                                                                                   */
/************************************************************************************************/
		if( gTeamLogLevel >= 2 )
		{
			logBBAI("    Team %d (%S) declares war on team %d due to DIPLOEVENT", getTeam(), getCivilizationDescription(0), ePlayer );
		}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
		GET_TEAM(getTeam()).declareWar(GET_PLAYER(ePlayer).getTeam(), false, WARPLAN_LIMITED);
		break;

	case DIPLOEVENT_CONVERT:
		AI_changeMemoryCount(ePlayer, MEMORY_ACCEPTED_RELIGION, 1);
		GET_PLAYER(ePlayer).convert(getStateReligion());
		break;

	case DIPLOEVENT_NO_CONVERT:
		AI_changeMemoryCount(ePlayer, MEMORY_DENIED_RELIGION, 1);
		break;

	case DIPLOEVENT_REVOLUTION:
		AI_changeMemoryCount(ePlayer, MEMORY_ACCEPTED_CIVIC, 1);

		paeNewCivics = new CivicTypes[GC.getNumCivicOptionInfos()];

		for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
		{
			paeNewCivics[iI] = GET_PLAYER(ePlayer).getCivics((CivicOptionTypes)iI);
		}

		FAssertMsg(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic() != NO_CIVIC, "getFavoriteCivic() must be valid");

		paeNewCivics[GC.getCivicInfo((CivicTypes)(GC.getLeaderHeadInfo(getPersonalityType())).getFavoriteCivic()).getCivicOptionType()] = ((CivicTypes)(GC.getLeaderHeadInfo(getPersonalityType()).getFavoriteCivic()));

		GET_PLAYER(ePlayer).revolution(paeNewCivics, true);

		SAFE_DELETE_ARRAY(paeNewCivics);
		break;

	case DIPLOEVENT_NO_REVOLUTION:
		AI_changeMemoryCount(ePlayer, MEMORY_DENIED_CIVIC, 1);
		break;

	case DIPLOEVENT_JOIN_WAR:
		AI_changeMemoryCount(ePlayer, MEMORY_ACCEPTED_JOIN_WAR, 1);
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      10/02/09                                jdog5000      */
/*                                                                                              */
/* AI logging                                                                                   */
/************************************************************************************************/
		if( gTeamLogLevel >= 2 )
		{
			logBBAI("    Team %d (%S) declares war on team %d due to DIPLOEVENT", getTeam(), getCivilizationDescription(0), ePlayer );
		}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
		GET_TEAM(GET_PLAYER(ePlayer).getTeam()).declareWar(((TeamTypes)iData1), false, WARPLAN_DOGPILE);

		for (iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).isAlive())
			{
				if (GET_PLAYER((PlayerTypes)iI).getTeam() == ((TeamTypes)iData1))
				{
					GET_PLAYER((PlayerTypes)iI).AI_changeMemoryCount(getID(), MEMORY_HIRED_WAR_ALLY, 1);
				}
			}
		}
		// Afforess: update war monger index
		if (GET_TEAM(getTeam()).isAtWar((TeamTypes)iData1))
		{
			// If our team is at war with the person we hired the war ally for, we aren't much of a war monger, we just wanted an ally
			m_iWarMongerIndex += GC.getDefineINT("WARMONGER_INDEX_HIRED_WAR_ALLY", 200);
		}
		else
		{
			// If we incited  a war with a civ we aren't at war with, we are war mongerers
			m_iWarMongerIndex += GC.getDefineINT("WARMONGER_INDEX_HIRED_WAR_ALLY", 1000);
		}
		break;

	case DIPLOEVENT_NO_JOIN_WAR:
		AI_changeMemoryCount(ePlayer, MEMORY_DENIED_JOIN_WAR, 1);
/************************************************************************************************/
/* Afforess	                  Start		 05/24/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		if (m_eDemandWarAgainstTeam != NO_TEAM)
		{
			for (iI = 0; iI < MAX_PLAYERS; iI++)
			{
				if (GET_PLAYER((PlayerTypes)iI).isAlive())
				{
					if (GET_PLAYER((PlayerTypes)iI).getTeam() == m_eDemandWarAgainstTeam)
					{
						if (GET_PLAYER((PlayerTypes)iI).AI_getMemoryCount(ePlayer, MEMORY_EVENT_GOOD_TO_US) < 3)
						{
							GET_PLAYER((PlayerTypes)iI).AI_changeMemoryCount(ePlayer, MEMORY_EVENT_GOOD_TO_US, 1);
						}
					}
				}
			}
			m_eDemandWarAgainstTeam = NO_TEAM;
		}					
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		break;

	case DIPLOEVENT_STOP_TRADING:
		AI_changeMemoryCount(ePlayer, MEMORY_ACCEPTED_STOP_TRADING, 1);
		GET_PLAYER(ePlayer).stopTradingWithTeam((TeamTypes)iData1);

		for (iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).isAlive())
			{
				if (GET_PLAYER((PlayerTypes)iI).getTeam() == ((TeamTypes)iData1))
				{
					GET_PLAYER((PlayerTypes)iI).AI_changeMemoryCount(getID(), MEMORY_HIRED_TRADE_EMBARGO, 1);
				}
			}
		}
		break;

	case DIPLOEVENT_NO_STOP_TRADING:
		AI_changeMemoryCount(ePlayer, MEMORY_DENIED_STOP_TRADING, 1);
		break;

	case DIPLOEVENT_ASK_HELP:
		AI_changeMemoryCount(ePlayer, MEMORY_MADE_DEMAND_RECENT, 1);
		break;

	case DIPLOEVENT_MADE_DEMAND:
		if (AI_getMemoryCount(ePlayer, MEMORY_MADE_DEMAND) < 10)
		{
			AI_changeMemoryCount(ePlayer, MEMORY_MADE_DEMAND, 1);
		}
		AI_changeMemoryCount(ePlayer, MEMORY_MADE_DEMAND_RECENT, 1);
		break;

	case DIPLOEVENT_MADE_DEMAND_VASSAL:
		break;

	case DIPLOEVENT_RESEARCH_TECH:
		pushResearch(((TechTypes)iData1), true);
		break;

	case DIPLOEVENT_TARGET_CITY:
		pCity = GET_PLAYER((PlayerTypes)iData1).getCity(iData2);
		if (pCity != NULL)
		{
			pCity->area()->setTargetCity(getID(), pCity);
		}
		break;
/************************************************************************************************/
/* Afforess	                  Start		 08/01/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
   case DIPLOEVENT_MAKE_PEACE_WITH:
		if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAtWar((TeamTypes)iData1))
		{
			if (AI_getMemoryCount(ePlayer, MEMORY_EVENT_GOOD_TO_US) < 3)
			{
				AI_changeMemoryCount(ePlayer, MEMORY_EVENT_GOOD_TO_US, 1);
			}
			GET_TEAM(GET_PLAYER(ePlayer).getTeam()).makePeace((TeamTypes)iData1);
		}
        break;
    case DIPLOEVENT_NO_MAKE_PEACE_WITH:
		if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAtWar((TeamTypes)iData1))
		{
			if (AI_getMemoryCount(ePlayer, MEMORY_REFUSED_HELP) < 3)
			{
				AI_changeMemoryCount(ePlayer, MEMORY_REFUSED_HELP, 1);
			}
		}
        break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	// RevolutionDCM start - new diplomacy option
	case DIPLOEVENT_DO_NOT_BOTHER:
		if (!isHuman())	setDoNotBotherStatus((PlayerTypes)iData1);
		break;

	case DIPLOEVENT_RESUME_BOTHER:
		setDoNotBotherStatus(NO_PLAYER);
		break;
	// RevolutionDCM end
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/
	

	default:
		FAssert(false);
		break;
	}
}


bool CvPlayer::canTradeWith(PlayerTypes eWhoTo) const
{
	if (atWar(getTeam(), GET_PLAYER(eWhoTo).getTeam()))
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isTechTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isTechTrading())
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isGoldTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isGoldTrading())
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isMapTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isMapTrading())
	{
		return true;
	}

	if (canTradeNetworkWith(eWhoTo))
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isOpenBordersTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isOpenBordersTrading())
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isDefensivePactTrading() || GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isDefensivePactTrading())
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isPermanentAllianceTrading() || GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isPermanentAllianceTrading())
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isVassalStateTrading() || GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isVassalStateTrading())
	{
		return true;
	}

	return false;
}

bool CvPlayer::canReceiveTradeCity() const
{
	if (GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && isHuman())
	{
		return false;
	}

	return true;
}

bool CvPlayer::canTradeItem(PlayerTypes eWhoTo, TradeData item, bool bTestDenial) const
{
	CvCity *pOurCapitalCity;
/************************************************************************************************/
/* Afforess	                  Start		 07/29/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
    CvCity* pTheirCapitalCity;
    CvCity* pTradingCity;
    CvUnit* pUnitTraded;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	//	KOSHLING - do denial check at the end because it's expensive and 95% of the time we determine the trade is
	//	not possible before having to make the denial check that way
	bool bResult = false;

	switch (item.m_eItemType)
	{
	case TRADE_TECHNOLOGIES:
		if (!(GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_TRADING)))
		{
			if (GC.getTechInfo((TechTypes)(item.m_iData)).isTrade())
			{
				if (GET_TEAM(getTeam()).isHasTech((TechTypes)(item.m_iData)) && !(GET_TEAM(getTeam()).isNoTradeTech((TechTypes)(item.m_iData))))
				{
					if (!GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isHasTech((TechTypes)(item.m_iData)))
					{
						//if (GET_PLAYER(eWhoTo).isHuman() || (GET_PLAYER(eWhoTo).getCurrentResearch() != item.m_iData))
						{
							if (GET_TEAM(getTeam()).isTechTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isTechTrading())
							{
								FAssertMsg(item.m_iData >= 0, "item.m_iData is expected to be non-negative (invalid Index)");

								if (GET_PLAYER(eWhoTo).canResearch(((TechTypes)item.m_iData), true))
								{
									bResult = true;
								}
							}
						}
					}
				}
			}
		}
		break;

	case TRADE_RESOURCES:
		FAssertMsg(item.m_iData > -1, "iData is expected to be non-negative");

		if (canTradeNetworkWith(eWhoTo))
		{
			if (!GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isBonusObsolete((BonusTypes) item.m_iData) && !GET_TEAM(getTeam()).isBonusObsolete((BonusTypes) item.m_iData))
			{
				bool bCanTradeAll = (isHuman() || getTeam() == GET_PLAYER(eWhoTo).getTeam() || GET_TEAM(getTeam()).isVassal(GET_PLAYER(eWhoTo).getTeam()));
				if (getNumTradeableBonuses((BonusTypes) item.m_iData) > (bCanTradeAll ? 0 : 1))
				{
/************************************************************************************************/
/* Afforess	                  Start		 05/15/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
					if (GC.getDefineINT("CAN_TRADE_RESOURCES") > 0)
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
					// if (GET_PLAYER(eWhoTo).getNumAvailableBonuses(eBonus) == 0)
					{
						bResult = true;
					}
				}
			}
		}
		break;

	case TRADE_CITIES:
		{
			CvCity* pCityTraded = getCity(item.m_iData);

			if (NULL != pCityTraded && pCityTraded->getLiberationPlayer(false) == eWhoTo)
			{
				bResult = true;
			}
			else if (GET_PLAYER(eWhoTo).canReceiveTradeCity())
			{
				if (0 == GC.getGameINLINE().getMaxCityElimination())
				{
					if (!GET_TEAM(getTeam()).isAVassal() && !GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isVassal(getTeam()))
					{
						pOurCapitalCity = getCapitalCity();
						if (pOurCapitalCity != NULL)
						{
							if (pOurCapitalCity->getID() != item.m_iData)
							{
							/************************************************************************************************/
							/* Afforess	                  Start		 05/15/10                                                */
							/*                                                                                              */
							/*                                                                                              */
							/************************************************************************************************/
							if (GC.getDefineINT("CAN_TRADE_CITIES") > 0)
							/************************************************************************************************/
							/* Afforess	                     END                                                            */
							/************************************************************************************************/
								bResult = true;
							}
						}
					}
				}
			}
		}
		break;

/************************************************************************************************/
/* Afforess	                  Start		 07/29/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
    case TRADE_WORKER:
        {
            pUnitTraded = getUnit(item.m_iData);
            pTheirCapitalCity = GET_PLAYER(eWhoTo).getCapitalCity();
			if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY))
			{
				if (GC.getDefineINT("CAN_TRADE_WORKERS") > 0)
				{
					if (GET_TEAM(getTeam()).isHasEmbassy(GET_PLAYER(eWhoTo).getTeam()))
					{
						if (pUnitTraded != NULL)
						{
						//	pTradingCity = pUnitTraded->plot()->getPlotCity();
							if (GC.getUnitInfo(pUnitTraded->getUnitType()).isWorkerTrade() && pUnitTraded->canMove()/* && (pTradingCity != NULL) */&& (pTheirCapitalCity != NULL))
							{
							//	if (pTradingCity->getOwnerINLINE() == getID())
							//	{
								//	if (pTradingCity->isConnectedTo(pTheirCapitalCity))
								//	{
								//		if (pTradingCity->isRevealed(GET_PLAYER(eWhoTo).getTeam(), true))
								//		{
											if (!GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isUnitClassMaxedOut(pUnitTraded->getUnitClassType(), GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).getUnitClassMaking(pUnitTraded->getUnitClassType())))
											{
												if (!GET_PLAYER(eWhoTo).isUnitClassMaxedOut(pUnitTraded->getUnitClassType(), GET_PLAYER(eWhoTo).getUnitClassMaking(pUnitTraded->getUnitClassType())))
												{
													bResult = true;
												}
											}
									//	}
									//}
							//	}
							}
						}
					}
				}
			}
		}
        break;

    case TRADE_MILITARY_UNIT:
        {
            pUnitTraded = getUnit(item.m_iData);
            pTheirCapitalCity = GET_PLAYER(eWhoTo).getCapitalCity();
			
			if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY) && GC.getDefineINT("NO_MILITARY_UNIT_TRADING") == 0)
			{
				if (GET_TEAM(getTeam()).isHasEmbassy(GET_PLAYER(eWhoTo).getTeam()))
				{
					if (pUnitTraded != NULL)
					{
						UnitTypes eUnit = (UnitTypes)GC.getCivilizationInfo(GET_PLAYER(eWhoTo).getCivilizationType()).getCivilizationUnits(pUnitTraded->getUnitClassType());
						if ( NO_UNIT != eUnit )
				//		if (GET_PLAYER(eWhoTo).canTrain(eUnit))
						{
							pTradingCity = pUnitTraded->plot()->getPlotCity();
							if (GC.getUnitInfo(pUnitTraded->getUnitType()).isMilitaryTrade() && pUnitTraded->canMove() && (pTradingCity != NULL) && (pTheirCapitalCity != NULL))
							{
								if (pTradingCity->getOwnerINLINE() == getID())
								{
									if (pTradingCity->isConnectedTo(pTheirCapitalCity))
									{
										if (pTradingCity->isRevealed(GET_PLAYER(eWhoTo).getTeam(), true))
										{
											if (!GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isUnitClassMaxedOut(pUnitTraded->getUnitClassType(), GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).getUnitClassMaking(pUnitTraded->getUnitClassType())))
											{
												if (!GET_PLAYER(eWhoTo).isUnitClassMaxedOut(pUnitTraded->getUnitClassType(), GET_PLAYER(eWhoTo).getUnitClassMaking(pUnitTraded->getUnitClassType())))
												{
													bResult = true;
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
        break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	case TRADE_GOLD:
		if (GET_TEAM(getTeam()).isGoldTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isGoldTrading())
		{
			if (getGold() >= item.m_iData)
			{
			/************************************************************************************************/
			/* Afforess	                  Start		 05/15/10                                                */
			/*                                                                                              */
			/*                                                                                              */
			/************************************************************************************************/
			if (GC.getDefineINT("CAN_TRADE_GOLD") > 0)
			/************************************************************************************************/
			/* Afforess	                     END                                                            */
			/************************************************************************************************/
				bResult = true;
			}
		}
		break;

	case TRADE_GOLD_PER_TURN:
		if (GET_TEAM(getTeam()).isGoldTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isGoldTrading())
		{
			/************************************************************************************************/
			/* Afforess	                  Start		 05/15/10                                                */
			/*                                                                                              */
			/*                                                                                              */
			/************************************************************************************************/
			if (GC.getDefineINT("CAN_TRADE_GOLD_PER_TURN") > 0)
			/************************************************************************************************/
			/* Afforess	                     END                                                            */
			/************************************************************************************************/
			bResult = true;
		}
		break;

	case TRADE_MAPS:
		if (getTeam() != GET_PLAYER(eWhoTo).getTeam())
		{
			if (GET_TEAM(getTeam()).isMapTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isMapTrading())
			{
			/************************************************************************************************/
		/* Afforess	                  Start		 05/15/10                                                */
		/*                                                                                              */
		/*                                                                                              */
		/************************************************************************************************/
		if (GC.getDefineINT("CAN_TRADE_MAPS") > 0)
		/************************************************************************************************/
		/* Afforess	                     END                                                            */
		/************************************************************************************************/
				bResult = true;
			}
		}
		break;

	case TRADE_VASSAL:
	case TRADE_SURRENDER:
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      12/06/09                                jdog5000      */
/*                                                                                              */
/* Customization                                                                                */
/************************************************************************************************/
		if (!isHuman() || GET_PLAYER(eWhoTo).isHuman() || (GC.getDefineINT("BBAI_HUMAN_AS_VASSAL_OPTION") == 1))
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
		{
			CvTeam& kVassalTeam = GET_TEAM(getTeam());
			CvTeam& kMasterTeam = GET_TEAM(GET_PLAYER(eWhoTo).getTeam());
			if (kMasterTeam.isVassalStateTrading()) // the master must possess the tech
			{
				if (!kVassalTeam.isAVassal() && !kMasterTeam.isAVassal() && getTeam() != GET_PLAYER(eWhoTo).getTeam())
				{
					if ((kMasterTeam.isAtWar(getTeam()) || item.m_iData == 1) && item.m_eItemType == TRADE_SURRENDER)
					{
						bResult = true;
					}
					else if (!kMasterTeam.isAtWar(getTeam()) && item.m_eItemType == TRADE_VASSAL)
					{
						bResult = true;
					}
				}
			}
		}
		break;

/************************************************************************************************/
/* Afforess	                  Start		 07/29/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
    case TRADE_EMBASSY:
		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY) && GC.getDefineINT("CAN_TRADE_EMBASSIES") > 0)
		{
			if (getTeam() != GET_PLAYER(eWhoTo).getTeam())
			{
				if (!atWar(getTeam(), GET_PLAYER(eWhoTo).getTeam()))
				{
					if (!(GET_TEAM(getTeam()).isHasEmbassy(GET_PLAYER(eWhoTo).getTeam())))
					{
						if (GET_TEAM(getTeam()).isEmbassyTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isEmbassyTrading())
						{
							if (getCapitalCity() != NULL && GET_PLAYER(eWhoTo).getCapitalCity() != NULL)
							{
								bResult = true;
							}
						}
					}
				}
			}
		}
		break;

    case TRADE_CONTACT:
		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY) && GC.getDefineINT("CAN_TRADE_CONTACT") > 0)
		{
			if (!GET_TEAM((TeamTypes)item.m_iData).isMinorCiv())
			{
				if (!GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isHasMet((TeamTypes)(item.m_iData)) && GET_TEAM(getTeam()).isHasMet((TeamTypes)(item.m_iData)))
				{
					bResult = true;
				}
			}
		}
        break;

	case TRADE_WAR_REPARATIONS:
		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY) && GC.getDefineINT("CAN_TRADE_WAR_REPARATIONS", 1) > 0)
		{
			if (!GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isAtWar(getTeam()))
			{
				if (GET_PLAYER(eWhoTo).canTradeWarReparations((PlayerTypes)getID()))
				{
					bResult = true;
				}
			}
		}
        break;

	case TRADE_CEASE_RELATIONS:
		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY) && GC.getDefineINT("CAN_TRADE_CEASE_RELATIONS", 1) > 0)
		{
			if (canContact((PlayerTypes)item.m_iData) && AI_isWillingToTalk((PlayerTypes)item.m_iData) && !GET_TEAM(GET_PLAYER((PlayerTypes)item.m_iData).getTeam()).isAtWar(getTeam()))
			{
				bool bCivicPrevents = false;
				for (int iCivicOption = 0; iCivicOption < GC.getNumCivicOptionInfos(); iCivicOption++)
				{
					CivicTypes eCivic = GET_PLAYER((PlayerTypes)item.m_iData).getCivics((CivicOptionTypes)iCivicOption);
					if (eCivic != NO_CIVIC && GC.getCivicInfo(eCivic).isCanNotCeaseRelations())
					{
						bCivicPrevents = true;
						break;
					}
				}
				if (!bCivicPrevents)
				{
					bResult = true;
				}
			}
		}
        break;

    case TRADE_CORPORATION:
		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY) && GC.getDefineINT("CAN_TRADE_CORPORATIONS") > 0)
		{
			if (hasHeadquarters((CorporationTypes)(item.m_iData)))
			{
				if (GET_PLAYER(eWhoTo).getBestHQCity((CorporationTypes)(item.m_iData)) != NULL)
				{
					if (GET_PLAYER(eWhoTo).isActiveCorporation((CorporationTypes)(item.m_iData)))
					{
						bResult = true;
					}
				}
			}
		}
		break;

	case TRADE_SECRETARY_GENERAL_VOTE:
/* 		
		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY))
		{
			if (!(GET_TEAM(getTeam()).isHuman()))
			{
				if (GC.getGameINLINE().isDiploVote((VoteSourceTypes)item.m_iData))
				{
					if (GC.getGameINLINE().isTeamVoteEligible(GET_PLAYER(eWhoTo).getTeam(), ((VoteSourceTypes)item.m_iData)))
					{
						if (isVotingMember((VoteSourceTypes)item.m_iData) && (getPledgedSecretaryGeneralVote() == NO_TEAM))
						{
							return true;
						}
					}
				}
			}
		} */
		break;

    case TRADE_PLEDGE_VOTE:
/* 		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY))
		{
			iVoteID = GC.getGameINLINE().getCurrentVoteID();
			if (iVoteID > 0)
			{
				VoteTriggeredData* pVoteTriggered = GC.getGameINLINE().getVoteTriggered(iVoteID);
				if (pVoteTriggered != NULL)
				{
					if (GC.getGameINLINE().getSecretaryGeneral(pVoteTriggered->eVoteSource) != getTeam())
					{
						CvVoteInfo& kVote = GC.getVoteInfo(pVoteTriggered->kVoteOption.eVote);
						if (!GC.getGameINLINE().isTeamVote(pVoteTriggered->kVoteOption.eVote))
						{
							if (isVotingMember(pVoteTriggered->eVoteSource) && GET_PLAYER(eWhoTo).isVotingMember(pVoteTriggered->eVoteSource))
							{
								if (getPledgedVote() == NO_PLAYER_VOTE)
								{
									return true;
								}
							}
						}
					}
				}
			}
		} */
        break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	case TRADE_PEACE:
		if (!(GET_TEAM(getTeam()).isHuman())
/************************************************************************************************/
/* Afforess	                  Start		 05/15/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		&& GC.getDefineINT("CAN_TRADE_PEACE") > 0)
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		{
			if (!(GET_TEAM(getTeam()).isAVassal()))
			{
				if (GET_TEAM(getTeam()).isHasMet((TeamTypes)(item.m_iData)) && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isHasMet((TeamTypes)(item.m_iData)))
				{
					if (atWar(getTeam(), ((TeamTypes)(item.m_iData))))
					{
						bResult = true;
					}
				}
			}
		}
		break;

	case TRADE_WAR:
		if (!(GET_TEAM(getTeam()).isHuman())
/************************************************************************************************/
/* Afforess	                  Start		 05/15/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		&& GC.getDefineINT("CAN_TRADE_WAR") > 0)
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		{
			if (!(GET_TEAM(getTeam()).isAVassal()))
			{
				if (!GET_TEAM((TeamTypes)item.m_iData).isAVassal())
				{
					if (GET_TEAM(getTeam()).isHasMet((TeamTypes)(item.m_iData)) && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isHasMet((TeamTypes)(item.m_iData)))
					{
						if (GET_TEAM(getTeam()).canDeclareWar((TeamTypes)(item.m_iData)))
						{
							bResult = true;
						}
					}
				}
			}
		}
		break;

	case TRADE_EMBARGO:
		if (!(GET_TEAM(getTeam()).isHuman())
/************************************************************************************************/
/* Afforess	                  Start		 05/15/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		&& GC.getDefineINT("CAN_TRADE_EMBARGO") > 0)
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		{
			if (GET_TEAM(getTeam()).isHasMet((TeamTypes)(item.m_iData)) && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isHasMet((TeamTypes)(item.m_iData)))
			{
				if (canStopTradingWithTeam((TeamTypes)(item.m_iData)))
				{
					bResult = true;
				}
			}
		}
		break;

	case TRADE_CIVIC:
/************************************************************************************************/
/* UNOFFICIAL_PATCH                       10/22/09                          denev & jdog5000    */
/*                                                                                              */
/* Diplomacy                                                                                    */
/************************************************************************************************/
/* original bts code
		if (!(GET_TEAM(getTeam()).isHuman()))
*/
		if ((!(GET_TEAM(getTeam()).isHuman()) || (getTeam() == GET_PLAYER(eWhoTo).getTeam()))
/************************************************************************************************/
/* UNOFFICIAL_PATCH                        END                                                  */
/************************************************************************************************/
/************************************************************************************************/
/* Afforess	                  Start		 05/15/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		&& GC.getDefineINT("CAN_TRADE_CIVICS") > 0)
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		{
			if (GET_PLAYER(eWhoTo).isCivic((CivicTypes)(item.m_iData)))
			{
				if (canDoCivics((CivicTypes)(item.m_iData)) && !isCivic((CivicTypes)(item.m_iData)))
				{
					if (canRevolution(NULL))
					{
						bResult = true;
					}
				}
			}
		}
		break;

	case TRADE_RELIGION:
/************************************************************************************************/
/* UNOFFICIAL_PATCH                       10/22/09                          denev & jdog5000    */
/*                                                                                              */
/* Diplomacy                                                                                    */
/************************************************************************************************/
/* original bts code
		if (!(GET_TEAM(getTeam()).isHuman()))
*/
		if ((!(GET_TEAM(getTeam()).isHuman()) || (getTeam() == GET_PLAYER(eWhoTo).getTeam()))
/************************************************************************************************/
/* UNOFFICIAL_PATCH                        END                                                  */
/************************************************************************************************/
/************************************************************************************************/
/* Afforess	                  Start		 05/15/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		&& GC.getDefineINT("CAN_TRADE_RELIGIONS") > 0)
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		{
			if (GET_PLAYER(eWhoTo).getStateReligion() == ((ReligionTypes)(item.m_iData)))
			{
				if (canConvert((ReligionTypes)(item.m_iData)))
				{
					bResult = true;
				}
			}
		}
		break;

	case TRADE_OPEN_BORDERS:
		if ((getTeam() != GET_PLAYER(eWhoTo).getTeam())
/************************************************************************************************/
/* Afforess	                  Start		 05/15/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		&& GC.getDefineINT("CAN_TRADE_OPEN_BORDERS") > 0)
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		{
			if (!atWar(getTeam(), GET_PLAYER(eWhoTo).getTeam()))
			{
				if (!(GET_TEAM(getTeam()).isOpenBorders(GET_PLAYER(eWhoTo).getTeam())))
				{
					if (GET_TEAM(getTeam()).isOpenBordersTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isOpenBordersTrading())
					{
/************************************************************************************************/
/* Afforess	                  Start		 06/16/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
						if (GET_TEAM(getTeam()).canSignOpenBorders(GET_PLAYER(eWhoTo).getTeam()))
						{
							bResult = true;
						}
					}
				}
			}
		}
		break;
	
	case TRADE_RITE_OF_PASSAGE:
		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY))
		{
			if (getTeam() != GET_PLAYER(eWhoTo).getTeam())
			{
				if (!atWar(getTeam(), GET_PLAYER(eWhoTo).getTeam()))
				{
					if (!(GET_TEAM(getTeam()).isOpenBorders(GET_PLAYER(eWhoTo).getTeam())) && !(GET_TEAM(getTeam()).isLimitedBorders(GET_PLAYER(eWhoTo).getTeam())))
					{
						if (GET_TEAM(getTeam()).isOpenBordersTrading() && GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isOpenBordersTrading())
						{
							if (GC.getDefineINT("CAN_TRADE_LIMITED_BORDERS") > 0)
							{
								bResult = true;
							}
						}
					}
				}
			}
		}
		break;
	case TRADE_FREE_TRADE_ZONE:
		if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_DIPLOMACY))
		{
			if (getTeam() != GET_PLAYER(eWhoTo).getTeam())
			{
				if (!atWar(getTeam(), GET_PLAYER(eWhoTo).getTeam()))
				{
					if (GET_TEAM(getTeam()).canSignOpenBorders(GET_PLAYER(eWhoTo).getTeam()))
					{
						if (!GET_TEAM(getTeam()).isFreeTradeAgreement(GET_PLAYER(eWhoTo).getTeam()))
						{
							bResult = true;
						}
					}
				}
			}
		}
		break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	case TRADE_DEFENSIVE_PACT:
		if ((!(GET_TEAM(getTeam()).isAVassal()) && !(GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isAVassal()))
/************************************************************************************************/
/* Afforess	                  Start		 05/15/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		&& GC.getDefineINT("CAN_TRADE_DEFENSIVE_PACT") > 0)
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		{
			if (getTeam() != GET_PLAYER(eWhoTo).getTeam() && !GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isVassal(getTeam()))
			{
				if (!atWar(getTeam(), GET_PLAYER(eWhoTo).getTeam()))
				{
					if (!(GET_TEAM(getTeam()).isDefensivePact(GET_PLAYER(eWhoTo).getTeam())))
					{
						if (GET_TEAM(getTeam()).isDefensivePactTrading() || GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isDefensivePactTrading())
						{
							if ((GET_TEAM(getTeam()).getAtWarCount(true) == 0) && (GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).getAtWarCount(true) == 0))
							{
								if (GET_TEAM(getTeam()).canSignDefensivePact(GET_PLAYER(eWhoTo).getTeam()))
								{
									bResult = true;
								}
							}
						}
					}
				}
			}
		}
		break;

	case TRADE_PERMANENT_ALLIANCE:
		if (!(GET_TEAM(getTeam()).isAVassal()) && !(GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isAVassal()))
		{
			if (getTeam() != GET_PLAYER(eWhoTo).getTeam() && !GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isVassal(getTeam()))
			{
				if (!atWar(getTeam(), GET_PLAYER(eWhoTo).getTeam()))
				{
					if (GET_TEAM(getTeam()).isPermanentAllianceTrading() || GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).isPermanentAllianceTrading())
					{
						if ((GET_TEAM(getTeam()).getNumMembers() == 1) && (GET_TEAM(GET_PLAYER(eWhoTo).getTeam()).getNumMembers() == 1))
						{
							bResult = true;
						}
					}
				}
			}
		}
		break;

	case TRADE_PEACE_TREATY:
		bResult = true;
		break;
	}

	if (bTestDenial && bResult)
	{
		bResult &= (getTradeDenial(eWhoTo, item) == NO_DENIAL);
	}

	return bResult;
}


DenialTypes CvPlayer::getTradeDenial(PlayerTypes eWhoTo, TradeData item) const
{
	CvCity* pCity;

	switch (item.m_eItemType)
	{
	case TRADE_TECHNOLOGIES:
		return GET_TEAM(getTeam()).AI_techTrade(((TechTypes)(item.m_iData)), GET_PLAYER(eWhoTo).getTeam());
		break;

	case TRADE_RESOURCES:
		return AI_bonusTrade(((BonusTypes)(item.m_iData)), eWhoTo);
		break;

	case TRADE_CITIES:
		pCity = getCity(item.m_iData);
		if (pCity != NULL)
		{
			return AI_cityTrade(pCity, eWhoTo);
		}
		break;

	case TRADE_GOLD:
	case TRADE_GOLD_PER_TURN:
		break;

	case TRADE_MAPS:
		return GET_TEAM(getTeam()).AI_mapTrade(GET_PLAYER(eWhoTo).getTeam());
		break;

	case TRADE_SURRENDER:
		return GET_TEAM(getTeam()).AI_surrenderTrade(GET_PLAYER(eWhoTo).getTeam(), 140);
		break;

	case TRADE_VASSAL:
		return GET_TEAM(getTeam()).AI_vassalTrade(GET_PLAYER(eWhoTo).getTeam());
		break;

	case TRADE_PEACE:
		return GET_TEAM(getTeam()).AI_makePeaceTrade(((TeamTypes)(item.m_iData)), GET_PLAYER(eWhoTo).getTeam());
		break;

	case TRADE_WAR:
		return GET_TEAM(getTeam()).AI_declareWarTrade(((TeamTypes)(item.m_iData)), GET_PLAYER(eWhoTo).getTeam());
		break;

	case TRADE_EMBARGO:
		return AI_stopTradingTrade(((TeamTypes)(item.m_iData)), eWhoTo);
		break;

	case TRADE_CIVIC:
		return AI_civicTrade(((CivicTypes)(item.m_iData)), eWhoTo);
		break;

	case TRADE_RELIGION:
		return AI_religionTrade(((ReligionTypes)(item.m_iData)), eWhoTo);
		break;

	case TRADE_OPEN_BORDERS:
		return GET_TEAM(getTeam()).AI_openBordersTrade(GET_PLAYER(eWhoTo).getTeam());
		break;
		
	case TRADE_DEFENSIVE_PACT:
		return GET_TEAM(getTeam()).AI_defensivePactTrade(GET_PLAYER(eWhoTo).getTeam());
		break;

	case TRADE_PERMANENT_ALLIANCE:
		return GET_TEAM(getTeam()).AI_permanentAllianceTrade(GET_PLAYER(eWhoTo).getTeam());
		break;

	case TRADE_PEACE_TREATY:
		break;
/************************************************************************************************/
/* Afforess	                  Start		 06/16/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
	case TRADE_RITE_OF_PASSAGE:
		return GET_TEAM(getTeam()).AI_LimitedBordersTrade(GET_PLAYER(eWhoTo).getTeam());
		break;
	case TRADE_FREE_TRADE_ZONE:
		return GET_TEAM(getTeam()).AI_FreeTradeAgreement(GET_PLAYER(eWhoTo).getTeam());
		break;
	case TRADE_WORKER:
		{
			CvUnit* pUnit = getUnit(item.m_iData);
			if (pUnit != NULL)
			{
				return AI_workerTrade(pUnit, eWhoTo);
			}
		}
		break;
	case TRADE_MILITARY_UNIT:
		{
			CvUnit* pUnit = getUnit(item.m_iData);
			if (pUnit != NULL)
			{
				return AI_militaryUnitTrade(pUnit, eWhoTo);
			}
		}
		break;
	case TRADE_EMBASSY:
		return GET_TEAM(getTeam()).AI_embassyTrade(GET_PLAYER(eWhoTo).getTeam());
		break;

	case TRADE_CONTACT:
		return GET_TEAM(getTeam()).AI_contactTrade(((TeamTypes)item.m_iData), GET_PLAYER(eWhoTo).getTeam());
		break;
	case TRADE_WAR_REPARATIONS:
		return AI_tradeWarReparations((PlayerTypes)eWhoTo);
		break;
	case TRADE_CEASE_RELATIONS:
		return AI_tradeCeaseRelations((PlayerTypes)item.m_iData, eWhoTo);
		break;
	case TRADE_CORPORATION:
		return AI_corporationTrade(((CorporationTypes)(item.m_iData)), eWhoTo);
		break;
	case TRADE_PLEDGE_VOTE:
		break;
	case TRADE_SECRETARY_GENERAL_VOTE:
		return AI_secretaryGeneralTrade(((VoteSourceTypes)(item.m_iData)), eWhoTo);
		break;
/************************************************************************************************/
/* Afforess		                 END                                                            */
/************************************************************************************************/
	}

	return NO_DENIAL;
}


bool CvPlayer::canTradeNetworkWith(PlayerTypes ePlayer) const
{
	CvCity* pOurCapitalCity;

	pOurCapitalCity = getCapitalCity();

	if (pOurCapitalCity != NULL)
	{
		if (pOurCapitalCity->isConnectedToCapital(ePlayer))
		{
			return true;
		}
	}

	return false;
}


int CvPlayer::getNumAvailableBonuses(BonusTypes eBonus) const
{
	CvPlotGroup* pPlotGroup;

	pPlotGroup = ((getCapitalCity() != NULL) ? getCapitalCity()->plot()->getOwnerPlotGroup() : NULL);

	if (pPlotGroup != NULL)
	{
		return pPlotGroup->getNumBonuses(eBonus);
	}

	return 0;
}


int CvPlayer::getNumTradeableBonuses(BonusTypes eBonus) const
{
	return (getNumAvailableBonuses(eBonus) - getBonusImport(eBonus));
}

bool CvPlayer::hasBonus(BonusTypes eBonus) const
{
	int iLoop;
	for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->hasBonus(eBonus))
		{
			return true;
		}
	}

	return false;
}

int CvPlayer::getNumTradeBonusImports(PlayerTypes ePlayer) const
{
	CLLNode<TradeData>* pNode;
	CvDeal* pLoopDeal;
	int iCount;
	int iLoop;

	FAssert(ePlayer != getID());

	iCount = 0;

	for(pLoopDeal = GC.getGameINLINE().firstDeal(&iLoop); pLoopDeal != NULL; pLoopDeal = GC.getGameINLINE().nextDeal(&iLoop))
	{
		if ((pLoopDeal->getFirstPlayer() == getID()) && (pLoopDeal->getSecondPlayer() == ePlayer))
		{
			for (pNode = pLoopDeal->headSecondTradesNode(); (pNode != NULL); pNode = pLoopDeal->nextSecondTradesNode(pNode))
			{
				if (pNode->m_data.m_eItemType == TRADE_RESOURCES)
				{
					iCount++;
				}
			}
		}

		if ((pLoopDeal->getFirstPlayer() == ePlayer) && (pLoopDeal->getSecondPlayer() == getID()))
		{
			for (pNode = pLoopDeal->headFirstTradesNode(); (pNode != NULL); pNode = pLoopDeal->nextFirstTradesNode(pNode))
			{
				if (pNode->m_data.m_eItemType == TRADE_RESOURCES)
				{
					iCount++;
				}
			}
		}
	}

	return iCount;
}


bool CvPlayer::isTradingWithTeam(TeamTypes eTeam, bool bIncludeCancelable) const
{
	int iLoop;

	if (eTeam == getTeam())
	{
		return false;
	}

	for (CvDeal* pLoopDeal = GC.getGameINLINE().firstDeal(&iLoop); pLoopDeal != NULL; pLoopDeal = GC.getGameINLINE().nextDeal(&iLoop))
	{
		if (bIncludeCancelable || pLoopDeal->isCancelable(getID()))
		{
			if (!pLoopDeal->isPeaceDeal())
			{
				if ((pLoopDeal->getFirstPlayer() == getID()) && (GET_PLAYER(pLoopDeal->getSecondPlayer()).getTeam() == eTeam))
				{
					if (pLoopDeal->getLengthFirstTrades() > 0)
					{
						return true;
					}
				}

				if ((pLoopDeal->getSecondPlayer() == getID()) && (GET_PLAYER(pLoopDeal->getFirstPlayer()).getTeam() == eTeam))
				{
					if (pLoopDeal->getLengthSecondTrades() > 0)
					{
						return true;
					}
				}
			}
		}
	}

	return false;
}


bool CvPlayer::canStopTradingWithTeam(TeamTypes eTeam, bool bContinueNotTrading) const
{
	if (eTeam == getTeam())
	{
		return false;
	}

	if (GET_TEAM(getTeam()).isVassal(eTeam))
	{
		return false;
	}

	if (!isTradingWithTeam(eTeam, false))
	{
		if (bContinueNotTrading && !isTradingWithTeam(eTeam, true))
		{
			return true;
		}

		return false;
	}

	return true;
}


void CvPlayer::stopTradingWithTeam(TeamTypes eTeam)
{
	CvDeal* pLoopDeal;
	int iLoop;
	int iI;

	FAssert(eTeam != getTeam());

	for(pLoopDeal = GC.getGameINLINE().firstDeal(&iLoop); pLoopDeal != NULL; pLoopDeal = GC.getGameINLINE().nextDeal(&iLoop))
	{
		if (pLoopDeal->isCancelable(getID()) && !(pLoopDeal->isPeaceDeal()))
		{
			if (((pLoopDeal->getFirstPlayer() == getID()) && (GET_PLAYER(pLoopDeal->getSecondPlayer()).getTeam() == eTeam)) ||
				  ((pLoopDeal->getSecondPlayer() == getID()) && (GET_PLAYER(pLoopDeal->getFirstPlayer()).getTeam() == eTeam)))
			{
				pLoopDeal->kill();
			}
		}
	}

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() == eTeam)
			{
				GET_PLAYER((PlayerTypes)iI).AI_changeMemoryCount(getID(), MEMORY_STOPPED_TRADING, 1);
				GET_PLAYER((PlayerTypes)iI).AI_changeMemoryCount(getID(), MEMORY_STOPPED_TRADING_RECENT, 1);
			}
		}
	}
}


void CvPlayer::killAllDeals()
{
	CvDeal* pLoopDeal;
	int iLoop;

	for(pLoopDeal = GC.getGameINLINE().firstDeal(&iLoop); pLoopDeal != NULL; pLoopDeal = GC.getGameINLINE().nextDeal(&iLoop))
	{
		if ((pLoopDeal->getFirstPlayer() == getID()) || (pLoopDeal->getSecondPlayer() == getID()))
		{
			pLoopDeal->kill();
		}
	}
}


void CvPlayer::findNewCapital()
{
	CvCity* pOldCapital;
	CvCity* pLoopCity;
	CvCity* pBestCity;
	BuildingTypes eCapitalBuilding;
	int iValue;
	int iBestValue;
	int iLoop;

	eCapitalBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(GC.getDefineINT("CAPITAL_BUILDINGCLASS"))));

	if (eCapitalBuilding == NO_BUILDING)
	{
		return;
	}

	pOldCapital = getCapitalCity();

	iBestValue = 0;
	pBestCity = NULL;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity != pOldCapital)
		{
			if (0 == pLoopCity->getNumRealBuilding(eCapitalBuilding))
			{
				iValue = (pLoopCity->getPopulation() * 4);

				iValue += pLoopCity->getYieldRate(YIELD_FOOD);
				iValue += (pLoopCity->getYieldRate(YIELD_PRODUCTION) * 3);
				iValue += (pLoopCity->getYieldRate(YIELD_COMMERCE) * 2);
				iValue += pLoopCity->getCultureLevel();
				iValue += pLoopCity->getReligionCount();
				iValue += pLoopCity->getCorporationCount();
				iValue += (pLoopCity->getNumGreatPeople() * 2);

				iValue *= (pLoopCity->calculateCulturePercent(getID()) + 100);
				iValue /= 100;

				if (iValue > iBestValue)
				{
					iBestValue = iValue;
					pBestCity = pLoopCity;
				}
			}
		}
	}

	if (pBestCity != NULL)
	{
		if (pOldCapital != NULL)
		{
			pOldCapital->setNumRealBuilding(eCapitalBuilding, 0);
		}
		FAssertMsg(!(pBestCity->getNumRealBuilding(eCapitalBuilding)), "(pBestCity->getNumRealBuilding(eCapitalBuilding)) did not return false as expected");
		pBestCity->setNumRealBuilding(eCapitalBuilding, 1);
	}
}


int CvPlayer::getNumGovernmentCenters() const
{
	CvCity* pLoopCity;
	int iCount;
	int iLoop;

	iCount = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->isGovernmentCenter())
		{
			iCount++;
		}
	}

	return iCount;
}


bool CvPlayer::canRaze(CvCity* pCity) const
{
	if (!pCity->isAutoRaze())
	{
		if (GC.getGameINLINE().isOption(GAMEOPTION_NO_CITY_RAZING))
		{
			return false;
		}

		if (pCity->getOwnerINLINE() != getID())
		{
			return false;
		}
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/17/10                           jdog5000        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		// Change for IDW, so AI may raze cities it captures
		if( pCity->isEverOwned(getID()) || pCity->plot()->isCultureRangeCity(getID(), std::max(0,GC.getNumCultureLevelInfos() - 1)) )
		{
			if (pCity->calculateTeamCulturePercent(getTeam()) >= GC.getDefineINT("RAZING_CULTURAL_PERCENT_THRESHOLD"))
			{
				return false;
			}
		}
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/
	}

/************************************************************************************************/
/* Afforess	                  Start		 12/21/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if(GC.getUSE_CAN_RAZE_CITY_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyCity* pyCity = new CyCity(pCity);
		CyArgsList argsList;
		argsList.add(getID());	// Player ID
		argsList.add(gDLL->getPythonIFace()->makePythonObject(pyCity));	// pass in city class
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "canRazeCity", argsList.makeFunctionArgs(), &lResult);
		delete pyCity;	// python fxn must not hold on to this pointer 
		if (lResult == 0)
		{
			return (false);
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	return true;
}


void CvPlayer::raze(CvCity* pCity)
{
	wchar szBuffer[1024];
	PlayerTypes eHighestCulturePlayer;
	int iI, iJ;

	if (!canRaze(pCity))
	{
		return;
	}

	FAssert(pCity->getOwnerINLINE() == getID());

	eHighestCulturePlayer = pCity->findHighestCulture();

	if (eHighestCulturePlayer != NO_PLAYER)
	{
		if (GET_PLAYER(eHighestCulturePlayer).getTeam() != getTeam())
		{
			GET_PLAYER(eHighestCulturePlayer).AI_changeMemoryCount(getID(), MEMORY_RAZED_CITY, 1);
		}
	}

	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		if (pCity->isHolyCity((ReligionTypes)iI))
		{
			for (iJ = 0; iJ < MAX_PLAYERS; iJ++)
			{
				if (GET_PLAYER((PlayerTypes)iJ).isAlive())
				{
					if (iJ != getID())
					{
						if (GET_PLAYER((PlayerTypes)iJ).getStateReligion() == ((ReligionTypes)iI))
						{
							GET_PLAYER((PlayerTypes)iJ).AI_changeMemoryCount(getID(), MEMORY_RAZED_HOLY_CITY, 1);
						}
					}
				}
			}
		}
	}

	{
		MEMORY_TRACK_EXEMPT();

		swprintf(szBuffer, gDLL->getText("TXT_KEY_MISC_DESTROYED_CITY", pCity->getNameKey()).GetCString());
		AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CITYRAZE", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_CITY_EDIT")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), pCity->getX_INLINE(), pCity->getY_INLINE(), true, true);
	}

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if (iI != getID())
			{
				if (pCity->isRevealed(GET_PLAYER((PlayerTypes)iI).getTeam(), false))
				{
					MEMORY_TRACK_EXEMPT();

					swprintf(szBuffer, gDLL->getText("TXT_KEY_MISC_CITY_HAS_BEEN_RAZED_BY", pCity->getNameKey(), getCivilizationDescriptionKey()).GetCString());
					AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CITYRAZED", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("WORLDBUILDER_CITY_EDIT")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pCity->getX_INLINE(), pCity->getY_INLINE(), true, true);
				}
			}
		}
	}

	swprintf(szBuffer, gDLL->getText("TXT_KEY_MISC_CITY_RAZED_BY", pCity->getNameKey(), getCivilizationDescriptionKey()).GetCString());
	GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szBuffer, pCity->getX_INLINE(), pCity->getY_INLINE(), (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));

	// Report this event
	CvEventReporter::getInstance().cityRazed(pCity, getID());

	disband(pCity);
}


void CvPlayer::disband(CvCity* pCity)
{
	if (getNumCities() == 1)
	{
		setFoundedFirstCity(false);
	}

	GC.getGameINLINE().addDestroyedCityName(pCity->getName());

	pCity->kill(true);
}


bool CvPlayer::canReceiveGoody(CvPlot* pPlot, GoodyTypes eGoody, CvUnit* pUnit) const
{
	CvCity* pCity;
	UnitTypes eUnit;
	bool bTechFound;
	int iI;

	if (GC.getGoodyInfo(eGoody).getExperience() > 0)
	{
		if ((pUnit == NULL) || !(pUnit->canAcquirePromotionAny()) || (GC.getGameINLINE().getElapsedGameTurns() < 10))
		{
			return false;
		}
	}

	if (GC.getGoodyInfo(eGoody).getDamagePrereq() > 0)
	{
		if ((pUnit == NULL) || (pUnit->getDamage() < ((pUnit->maxHitPoints() * GC.getGoodyInfo(eGoody).getDamagePrereq()) / 100)))
		{
			return false;
		}
	}

	if (GC.getGoodyInfo(eGoody).isTech())
	{
		bTechFound = false;

		for (iI = 0; iI < GC.getNumTechInfos(); iI++)
		{
			if (GC.getTechInfo((TechTypes) iI).isGoodyTech())
			{
				if (canResearch((TechTypes)iI))
				{
					bTechFound = true;
					break;
				}
			}
		}

		if (!bTechFound)
		{
			return false;
		}
	}

	if (GC.getGoodyInfo(eGoody).isBad())
	{
		if ((pUnit == NULL) || pUnit->isNoBadGoodies())
		{
			return false;
		}
	}

	if (GC.getGoodyInfo(eGoody).getUnitClassType() != NO_UNITCLASS)
	{
		eUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(GC.getGoodyInfo(eGoody).getUnitClassType())));

		if (eUnit == NO_UNIT)
		{
			return false;
		}

/************************************************************************************************/
/* Afforess	                  Start		 6/11/11                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		int iCombat = (GC.getUnitInfo(eUnit).getCombat() + 
		GET_TEAM(getTeam()).getUnitClassStrengthChange((UnitClassTypes)GC.getUnitInfo(eUnit).getUnitClassType()));
		if ((iCombat > 0) && !(GC.getUnitInfo(eUnit).isOnlyDefensive()))
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		{
			if (GC.getGameINLINE().isGameMultiPlayer() || (GC.getGameINLINE().getElapsedGameTurns() < 20))
			{
				return false;
			}
		}

		if (GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && isHuman())
		{
			if (GC.getUnitInfo(eUnit).isFound())
			{
				return false;
			}
		}
	}

	if (GC.getGoodyInfo(eGoody).getBarbarianUnitClass() != NO_UNITCLASS)
	{
		if (GC.getGameINLINE().isOption(GAMEOPTION_NO_BARBARIANS))
		{
			return false;
		}

		if (getNumCities() == 0)
		{
			return false;
		}

		if (getNumCities() == 1)
		{
			pCity = GC.getMapINLINE().findCity(pPlot->getX_INLINE(), pPlot->getY_INLINE(), NO_PLAYER, getTeam());

			if (pCity != NULL)
			{
				if (plotDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pCity->getX_INLINE(), pCity->getY_INLINE()) <= (8 - getNumCities()))
				{
					return false;
				}
			}
		}
	}

	return true;
}


void CvPlayer::receiveGoody(CvPlot* pPlot, GoodyTypes eGoody, CvUnit* pUnit)
{
	CvPlot* pLoopPlot;
	CvPlot* pBestPlot = NULL;
	CvWString szBuffer;
	CvWString szTempBuffer;
	TechTypes eBestTech;
	UnitTypes eUnit;
	int iGold;
	int iOffset;
	int iRange;
	int iBarbCount;
	int iValue;
	int iBestValue;
	int iPass;
	int iDX, iDY;
	int iI;

	FAssertMsg(canReceiveGoody(pPlot, eGoody, pUnit), "Instance is expected to be able to recieve goody");

	szBuffer = GC.getGoodyInfo(eGoody).getDescription();

	iGold = GC.getGoodyInfo(eGoody).getGold() + GC.getGameINLINE().getSorenRandNum(GC.getGoodyInfo(eGoody).getGoldRand1(), "Goody Gold 1") + GC.getGameINLINE().getSorenRandNum(GC.getGoodyInfo(eGoody).getGoldRand2(), "Goody Gold 2");
	iGold  = (iGold * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent()) / 100;

	if (iGold != 0)
	{
		changeGold(iGold);

		szBuffer += gDLL->getText("TXT_KEY_MISC_RECEIVED_GOLD", iGold);
	}

	if (!szBuffer.empty() && getID() == GC.getGame().getActivePlayer())
	{
// BUG - Goody Hut Log - start
		// keep messages in event log forever
		MEMORY_TRACK_EXEMPT();

		AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, GC.getGoodyInfo(eGoody).getSound(), MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getImprovementArtInfo("ART_DEF_IMPROVEMENT_GOODY_HUT")->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), pPlot->getX_INLINE(), pPlot->getY_INLINE());
// BUG - Goody Hut Log - end
	}

	iRange = GC.getGoodyInfo(eGoody).getMapRange();

	if (iRange > 0)
	{
		iOffset = GC.getGoodyInfo(eGoody).getMapOffset();

		if (iOffset > 0)
		{
			iBestValue = 0;
			pBestPlot = NULL;

			for (iDX = -(iOffset); iDX <= iOffset; iDX++)
			{
				for (iDY = -(iOffset); iDY <= iOffset; iDY++)
				{
					pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);

					if (pLoopPlot != NULL)
					{
						if (!(pLoopPlot->isRevealed(getTeam(), false)))
						{
							iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "Goody Map"));

							iValue *= plotDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());

							if (iValue > iBestValue)
							{
								iBestValue = iValue;
								pBestPlot = pLoopPlot;
							}
						}
					}
				}
			}
		}

		if (pBestPlot == NULL)
		{
			pBestPlot = pPlot;
		}

		for (iDX = -(iRange); iDX <= iRange; iDX++)
		{
			for (iDY = -(iRange); iDY <= iRange; iDY++)
			{
				pLoopPlot = plotXY(pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), iDX, iDY);

				if (pLoopPlot != NULL)
				{
					if (plotDistance(pBestPlot->getX_INLINE(), pBestPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE()) <= iRange)
					{
						if (GC.getGameINLINE().getSorenRandNum(100, "Goody Map") < GC.getGoodyInfo(eGoody).getMapProb())
						{
							pLoopPlot->setRevealed(getTeam(), true, false, NO_TEAM, true);
						}
					}
				}
			}
		}
	}

	if (pUnit != NULL)
	{
		pUnit->changeExperience(GC.getGoodyInfo(eGoody).getExperience());
	}

	if (pUnit != NULL)
	{
		pUnit->changeDamage(-(GC.getGoodyInfo(eGoody).getHealing()));
	}

	if (GC.getGoodyInfo(eGoody).isTech())
	{
		iBestValue = 0;
		eBestTech = NO_TECH;

		for (iI = 0; iI < GC.getNumTechInfos(); iI++)
		{
			if (GC.getTechInfo((TechTypes) iI).isGoodyTech())
			{
				if (canResearch((TechTypes)iI))
				{
					iValue = (1 + GC.getGameINLINE().getSorenRandNum(10000, "Goody Tech"));

					if (iValue > iBestValue)
					{
						iBestValue = iValue;
						eBestTech = ((TechTypes)iI);
					}
				}
			}
		}

		FAssertMsg(eBestTech != NO_TECH, "BestTech is not assigned a valid value");

		GET_TEAM(getTeam()).setHasTech(eBestTech, true, getID(), true, true);
		GET_TEAM(getTeam()).setNoTradeTech(eBestTech, true);
	}

	if (GC.getGoodyInfo(eGoody).getUnitClassType() != NO_UNITCLASS)
	{
		eUnit = (UnitTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(GC.getGoodyInfo(eGoody).getUnitClassType());

		if (eUnit != NO_UNIT)
		{
			initUnit(eUnit, pPlot->getX_INLINE(), pPlot->getY_INLINE(), NO_UNITAI, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
		}
	}

	if (GC.getGoodyInfo(eGoody).getBarbarianUnitClass() != NO_UNITCLASS)
	{
		iBarbCount = 0;

		eUnit = (UnitTypes)GC.getCivilizationInfo(GET_PLAYER(BARBARIAN_PLAYER).getCivilizationType()).getCivilizationUnits(GC.getGoodyInfo(eGoody).getBarbarianUnitClass());

		if (eUnit != NO_UNIT)
		{
			for (iPass = 0; iPass < 2; iPass++)
			{
				if (iBarbCount < GC.getGoodyInfo(eGoody).getMinBarbarians())
				{
					for (iI = 0; iI < NUM_DIRECTION_TYPES; iI++)
					{
						pLoopPlot = plotDirection(pPlot->getX_INLINE(), pPlot->getY_INLINE(), ((DirectionTypes)iI));

						if (pLoopPlot != NULL)
						{
							if (pLoopPlot->getArea() == pPlot->getArea())
							{
							/************************************************************************************************/
							/* Afforess	Mountains Start		 09/18/09                                           		 */
							/*                                                                                              */
							/*                                                                                              */
							/************************************************************************************************/
								if (!(pLoopPlot->isImpassable(getTeam()))) // added getTeam()
							/************************************************************************************************/
							/* Afforess	Mountains End       END        		                                             */
							/************************************************************************************************/								{
									if (pLoopPlot->getNumUnits() == 0)
									{
										if ((iPass > 0) || (GC.getGameINLINE().getSorenRandNum(100, "Goody Barbs") < GC.getGoodyInfo(eGoody).getBarbarianUnitProb()))
										{
											GET_PLAYER(BARBARIAN_PLAYER).initUnit(eUnit, pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), ((pLoopPlot->isWater()) ? UNITAI_ATTACK_SEA : UNITAI_ATTACK), NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
											iBarbCount++;

											if ((iPass > 0) && (iBarbCount == GC.getGoodyInfo(eGoody).getMinBarbarians()))
											{
												break;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
}


void CvPlayer::doGoody(CvPlot* pPlot, CvUnit* pUnit)
{
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyPlot kGoodyPlot(pPlot);
		CyUnit kGoodyUnit(pUnit);
		CyArgsList argsList;
		argsList.add(getID());		// pass in this players ID
		argsList.add(gDLL->getPythonIFace()->makePythonObject(&kGoodyPlot));
		argsList.add(gDLL->getPythonIFace()->makePythonObject(&kGoodyUnit));

		long result=0;
		bool ok = PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "doGoody", argsList.makeFunctionArgs(), &result);
		if (ok && result)
		{
			return;
		}
	}

	FAssertMsg(pPlot->isGoody(), "pPlot->isGoody is expected to be true");

	pPlot->removeGoody();
	if (!isBarbarian())
	{
		for (int iI = 0; iI < GC.getDefineINT("NUM_DO_GOODY_ATTEMPTS"); iI++)
		{
			if (GC.getHandicapInfo(getHandicapType()).getNumGoodies() > 0)
			{
				GoodyTypes eGoody = (GoodyTypes)GC.getHandicapInfo(getHandicapType()).getGoodies(GC.getGameINLINE().getSorenRandNum(GC.getHandicapInfo(getHandicapType()).getNumGoodies(), "Goodies"));

				FAssert(eGoody >= 0);
				FAssert(eGoody < GC.getNumGoodyInfos());

				if (canReceiveGoody(pPlot, eGoody, pUnit))
				{
					receiveGoody(pPlot, eGoody, pUnit);

					// Python Event
					CvEventReporter::getInstance().goodyReceived(getID(), pPlot, pUnit, eGoody);
					break;
				}
			}
		}
	}
}


bool CvPlayer::canFound(int iX, int iY, bool bTestVisible) const
{
	CvPlot* pPlot;
	CvPlot* pLoopPlot;
	//bool bValid;
	int iRange;
	int iDX, iDY;

	pPlot = GC.getMapINLINE().plotINLINE(iX, iY);

	long lResult=0;
	if(GC.getUSE_CANNOT_FOUND_CITY_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		argsList.add((int)getID());
		argsList.add(iX);
		argsList.add(iY);
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "cannotFoundCity", argsList.makeFunctionArgs(), &lResult);

		if (lResult == 1)
		{
			return false;
		}
	}

	if (GC.getGameINLINE().isFinalInitialized())
	{
		if (GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && isHuman())
		{
			if (getNumCities() > 0)
			{
				return false;
			}
		}
	}

/************************************************************************************************/
/* Afforess	Mountains Start		 09/18/09                                           		 */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (pPlot->isImpassable(getTeam())) //added getTeam()
/************************************************************************************************/
/* Afforess	Mountains End       END        		                                             */
/************************************************************************************************/
	{
		return false;
	}

	//Afforess: most of logic moved into CvPlot::canFound
	if (!pPlot->canFound(getID(), false))
	{
		return false;
	}

	if (!isBarbarian() && !bTestVisible && getCityLimit() > 0 && getCityOverLimitUnhappy() == 0)
	{
		if (getNumCities() >= getCityLimit())
		{
			return false;
		}
	}

	if (!bTestVisible)
	{
		iRange = GC.getMIN_CITY_RANGE();

		for (iDX = -(iRange); iDX <= iRange; iDX++)
		{
			for (iDY = -(iRange); iDY <= iRange; iDY++)
			{
				pLoopPlot	= plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);

				if (pLoopPlot != NULL)
				{
					if (pLoopPlot->isCity())
					{
						if (pLoopPlot->area() == pPlot->area())
						{
							return false;
						}
					}
				}
			}
		}
	}

	return true;
}


void CvPlayer::found(int iX, int iY)
{
	CvCity* pCity;
	BuildingTypes eLoopBuilding;
	UnitTypes eDefenderUnit;
	int iI;

	//	This is checked by the caller on the main AI call path, but it is also usable (and used) form a few other paths, so best to leave it in
	if (!canFound(iX, iY))
	{
		return;
	}

	pCity = initCity(iX, iY, true, true);
	FAssertMsg(pCity != NULL, "City is not assigned a valid value");

	for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		if (GC.getBuildingInfo((BuildingTypes)iI).isNewCityFree(pCity->getGameObject()))
		{
			if (pCity->canConstruct((BuildingTypes)iI, false, false, false, false, true))
			{
				pCity->setNumRealBuilding((BuildingTypes)iI, 1);
			}
		}
	}
		

	if (isBarbarian())
	{
		int iDummyValue;
		eDefenderUnit = pCity->AI_bestUnitAI(UNITAI_CITY_DEFENSE, iDummyValue);

		if (eDefenderUnit == NO_UNIT)
		{
			eDefenderUnit = pCity->AI_bestUnitAI(UNITAI_ATTACK, iDummyValue);
		}

		if (eDefenderUnit != NO_UNIT)
		{
			for (iI = 0; iI < GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getBarbarianInitialDefenders(); iI++)
			{
				initUnit(eDefenderUnit, iX, iY, UNITAI_CITY_DEFENSE, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
			}
		}
	}

	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		eLoopBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI)));

		if (eLoopBuilding != NO_BUILDING)
		{
			if (GC.getBuildingInfo(eLoopBuilding).getFreeStartEra() != NO_ERA)
			{
				if (GC.getGameINLINE().getStartEra() >= GC.getBuildingInfo(eLoopBuilding).getFreeStartEra())
				{
					if (pCity->canConstruct(eLoopBuilding))
					{
						pCity->setNumRealBuilding(eLoopBuilding, 1);
					}
				}
			}
		}
	}
/************************************************************************************************/
/* Afforess	                  Start		 6/20/11                                                */
/*                                                                                              */
/*  Ensure free specialists from team/player (techs/civics) get placed                          */
/************************************************************************************************/
	for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
	{
		pCity->setFreeSpecialistCount(((SpecialistTypes)iI), 0);
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	if (getAdvancedStartPoints() >= 0)
	{
		// Free border expansion for Creative
		bool bCreative = false;
		for (iI = 0; iI < GC.getNumTraitInfos(); ++iI)
		{
			if (hasTrait((TraitTypes)iI))
			{
				if (GC.getTraitInfo((TraitTypes)iI).getCommerceChange(COMMERCE_CULTURE) > 0)
				{
					bCreative = true;
					break;
				}

			}
		}

		if (bCreative)
		{
			for (iI = 0; iI < GC.getNumCultureLevelInfos(); ++iI)
			{
				int iCulture = GC.getGameINLINE().getCultureThreshold((CultureLevelTypes)iI);
				if (iCulture > 0)
				{
					pCity->setCulture(getID(), iCulture, true, true);
					break;
				}
			}
		}
	}

	pCity->doAutobuild();
	if (isHuman() && getAdvancedStartPoints() < 0)
	{
		pCity->chooseProduction();
	}
	else
	{
		pCity->doFoundMessage();
	}

	CvEventReporter::getInstance().cityBuilt(pCity);

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      10/02/09                                jdog5000      */
/*                                                                                              */
/* AI logging                                                                                   */
/************************************************************************************************/
	if( gPlayerLogLevel >= 1 )
	{
		logBBAI("  Player %d (%S) founds new city %S at %d, %d", getID(), getCivilizationDescription(0), pCity->getName(0).GetCString(), iX, iY );
	}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
}


bool CvPlayer::canTrain(UnitTypes eUnit, bool bContinue, bool bTestVisible, bool bIgnoreCost) const
{
	PROFILE_FUNC();

/************************************************************************************************/
/* REVDCM                                 04/16/10                                phungus420    */
/*                                                                                              */
/* CanTrain Performance                                                                         */
/************************************************************************************************/
	if (eUnit == NO_UNIT) return false;
	CvUnitInfo& kUnit = GC.getUnitInfo(eUnit);
	UnitClassTypes eUnitClass = (UnitClassTypes)kUnit.getUnitClassType();
	int iI;

/************************************************************************************************/
/* Afforess	                  Start		 7/22/10                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/		
	/*
	FAssert(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(eUnitClass) == eUnit);
	if (GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(eUnitClass) != eUnit)
	{
		return false;
	}
	*/
	
	if (!GC.getGameINLINE().isOption(GAMEOPTION_ASSIMILATION))
	{
        if (GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(eUnitClass) != eUnit)
        {
            return false;
        }
	}
	
	if (!GC.getGameINLINE().canEverTrain(eUnit))
	{
		return false;
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	if (!bIgnoreCost)
	{
		if (kUnit.getProductionCost() == -1)
		{
			return false;
		}
	}

	if (GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && isHuman())
	{
		if (kUnit.isFound())
		{
			return false;
		}
	}

	if (GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
	{
		if (kUnit.isSpy() || kUnit.getEspionagePoints() > 0)
		{
			return false;
		}
	}

	if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)(kUnit.getPrereqAndTech()))))
	{
		return false;
	}
	
/************************************************************************************************/
/* REVDCM                                 02/16/10                                phungus420    */
/*                                                                                              */
/* CanTrain                                                                                     */
/************************************************************************************************/
	if (kUnit.getMaxStartEra() != NO_ERA)
	{
		if (GC.getGameINLINE().getStartEra() > kUnit.getMaxStartEra())
		{
			return false;
		}
	}

	if (kUnit.getForceObsoleteTech() != NO_TECH)
	{
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)(kUnit.getForceObsoleteTech())))
		{
			return false;
		}
	}
/* Moved to CvGame - Afforess 7/22/10
	if (kUnit.getPrereqGameOption() != NO_GAMEOPTION)
	{
		if (!(GC.getGameINLINE().isOption((GameOptionTypes)kUnit.getPrereqGameOption())))
		{
			return false;
		}
	}
	
	if (kUnit.getNotGameOption() != NO_GAMEOPTION)
	{
		if (GC.getGameINLINE().isOption((GameOptionTypes)kUnit.getNotGameOption()))
		{
			return false;
		}
	}
*/
	bool bNoReqCivic = true;
	bool bHasReqTech = false;
	for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
	{
		if (kUnit.isPrereqOrCivics(iI))
		{
			bNoReqCivic = false;
			if (GET_TEAM(getTeam()).isHasTech((TechTypes)(GC.getCivicInfo(CivicTypes(iI))).getTechPrereq()))
			{
				bHasReqTech = true;
			}
		}
	}
	if (!bNoReqCivic && !bHasReqTech)
	{
		return false;
	}
/************************************************************************************************/
/* REVDCM                                  END CanTrain                                         */
/************************************************************************************************/

	for (iI = 0; iI < GC.getNUM_UNIT_AND_TECH_PREREQS(); iI++)
	{
		if (kUnit.getPrereqAndTechs(iI) != NO_TECH)
		{
			if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)(kUnit.getPrereqAndTechs(iI)))))
			{
				return false;
			}
		}
	}

	if (kUnit.getStateReligion() != NO_RELIGION)
	{
		if (getStateReligion() != kUnit.getStateReligion())
		{
			return false;
		}
	}

	if (GC.getGameINLINE().isUnitClassMaxedOut(eUnitClass))
	{
		return false;
	}

	if (GET_TEAM(getTeam()).isUnitClassMaxedOut(eUnitClass))
	{
		return false;
	}

	if (isUnitClassMaxedOut(eUnitClass))
	{
		return false;
	}

	if (!bTestVisible)
	{
		if (GC.getGameINLINE().isUnitClassMaxedOut(eUnitClass, (GET_TEAM(getTeam()).getUnitClassMaking(eUnitClass) + ((bContinue) ? -1 : 0))))
		{
			return false;
		}

		if (GET_TEAM(getTeam()).isUnitClassMaxedOut(eUnitClass, (GET_TEAM(getTeam()).getUnitClassMaking(eUnitClass) + ((bContinue) ? -1 : 0))))
		{
			return false;
		}

		if (isUnitClassMaxedOut(eUnitClass, (getUnitClassMaking(eUnitClass) + ((bContinue) ? -1 : 0))))
		{
			return false;
		}

		if (GC.getGameINLINE().isNoNukes() || !(isNukesValid()))
		{
			if (kUnit.getNukeRange() != -1)
			{
				return false;
			}
		}

// Thomas SG - AC: Advanced Cargo START
		CvUnitInfo& kUnit = GC.getUnitInfo(eUnit);
		{
			if (kUnit.getNumSpecialUnitTypes() > 0 && !((kUnit.getTotalCargoSpace() - kUnit.getTotalSpecialCargoSpace()) > 0))
			{
				int notValid = 0;
				for (int iJ = 0; iJ < kUnit.getNumSpecialUnitTypes(); iJ++)
				{
					if (!(GC.getGameINLINE().isSpecialUnitValid((SpecialUnitTypes)(kUnit.getSpecialUnitType(iJ)))))
					{
						notValid++;
					}
				}
				if (notValid == kUnit.getNumSpecialUnitTypes())
				{
					return false;
				}
			}
		}
// Thomas SG - AC: Advanced Cargo END

/************************************************************************************************/
/* REVDCM                                 02/16/10                                phungus420    */
/*                                                                                              */
/* CanTrain                                                                                     */
/************************************************************************************************/
		bool bValid = false;
		bool bNoReqCivic = true;
		for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
		{
			if (kUnit.isPrereqOrCivics(iI))
			{
				bNoReqCivic = false;
				if (isCivic(CivicTypes(iI)))
				{
					bValid = true;
				}
			}
		}
		if (!bNoReqCivic && !bValid)
		{
			return false;
		}

		if (kUnit.isStateReligion())
		{
			if (getStateReligion() == NO_RELIGION)
			{
				return false;
			}
		}

		if(kUnit.isInquisitor())
		{
			if(!(isInquisitionConditions()))
			{
				return false;
			}
		}
/************************************************************************************************/
/* REVDCM                                  END CanTrain                                         */
/************************************************************************************************/
/************************************************************************************************/
/* REVDCM                              END Performance                                          */
/************************************************************************************************/
	}

	return true;
}


bool CvPlayer::canConstruct(BuildingTypes eBuilding, bool bContinue, bool bTestVisible, bool bIgnoreCost, TechTypes eIgnoreTechReq, int* probabilityEverConstructable) const
{
	bool bResult;
	bool bHaveCachedResult;

	PROFILE_FUNC();

	if (eBuilding == NO_BUILDING) return false;

	//	Cache the param variant with false, true, true as this is used VERY heavily and
	//	also the default param flavor
	if ( !bContinue && bTestVisible && bIgnoreCost && eIgnoreTechReq == NO_TECH && probabilityEverConstructable == NULL )
	{
		EnterCriticalSection(&c_canConstructCacheSection);

		if ( m_bCanConstructCached[eBuilding] )
		{
			bResult = m_bCanConstruct[eBuilding];
			bHaveCachedResult = true;
		}
		else
		{
			bHaveCachedResult = false;
		}

		LeaveCriticalSection(&c_canConstructCacheSection);

		if ( !bHaveCachedResult )
		{
			bResult = canConstructInternal(eBuilding, bContinue, bTestVisible, bIgnoreCost);

			EnterCriticalSection(&c_canConstructCacheSection);

			m_bCanConstruct[eBuilding] = bResult;
			m_bCanConstructCached[eBuilding] = true;

			LeaveCriticalSection(&c_canConstructCacheSection);
		}
	}
	else if ( !bContinue && !bTestVisible && !bIgnoreCost && eIgnoreTechReq == NO_TECH && probabilityEverConstructable == NULL )
	{
		EnterCriticalSection(&c_canConstructCacheSection);

		if ( m_bCanConstructCachedDefaultParam[eBuilding] )
		{
			bResult = m_bCanConstructDefaultParam[eBuilding];
			bHaveCachedResult = true;
		}
		else
		{
			bHaveCachedResult = false;
		}

		LeaveCriticalSection(&c_canConstructCacheSection);

		if ( !bHaveCachedResult )
		{
			bResult = canConstructInternal(eBuilding, bContinue, bTestVisible, bIgnoreCost);

			EnterCriticalSection(&c_canConstructCacheSection);

			m_bCanConstructDefaultParam[eBuilding] = bResult;
			m_bCanConstructCachedDefaultParam[eBuilding] = true;

			LeaveCriticalSection(&c_canConstructCacheSection);
		}
	}
	else
	{
		bResult = canConstructInternal(eBuilding, bContinue, bTestVisible, bIgnoreCost, eIgnoreTechReq, probabilityEverConstructable);
	}

	return bResult;
}

bool CvPlayer::canConstructInternal(BuildingTypes eBuilding, bool bContinue, bool bTestVisible, bool bIgnoreCost, TechTypes eIgnoreTechReq, int* probabilityEverConstructable) const
{
	PROFILE_FUNC();

	BuildingClassTypes eBuildingClass;
	int iI;
	CvTeamAI& currentTeam = GET_TEAM(getTeam());
/************************************************************************************************/
/* REVDCM                                 04/16/10                                phungus420    */
/*                                                                                              */
/* CanConstruct Performance                                                                     */
/************************************************************************************************/
	CvBuildingInfo& kBuilding = GC.getBuildingInfo(eBuilding);

	eBuildingClass = ((BuildingClassTypes)(kBuilding.getBuildingClassType()));
/************************************************************************************************/
/* Afforess	                  Start		5/28/10                                                 */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	/*
	FAssert(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(eBuildingClass) == eBuilding);
	if (GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(eBuildingClass) != eBuilding)
	{
		return false;
	}
	*/

	if ( probabilityEverConstructable != NULL )
	{
		*probabilityEverConstructable = 0;
	}

	if (eIgnoreTechReq != kBuilding.getPrereqAndTech() && !(currentTeam.isHasTech((TechTypes)(kBuilding.getPrereqAndTech()))))
	{
		return false;
	}

	for (iI = 0; iI < GC.getNUM_BUILDING_AND_TECH_PREREQS(); iI++)
	{
		if (kBuilding.getPrereqAndTechs(iI) != NO_TECH)
		{
			if (eIgnoreTechReq != kBuilding.getPrereqAndTechs(iI) && !(currentTeam.isHasTech((TechTypes)(kBuilding.getPrereqAndTechs(iI)))))
			{
				return false;
			}
		}
	}

	if (kBuilding.getSpecialBuildingType() != NO_SPECIALBUILDING)
	{
		TechTypes eRequiredTech = (TechTypes)(GC.getSpecialBuildingInfo((SpecialBuildingTypes) kBuilding.getSpecialBuildingType()).getTechPrereq());
		if (eIgnoreTechReq != eRequiredTech && !currentTeam.isHasTech(eRequiredTech))
		{
			return false;
		}
	}

	if (currentTeam.isObsoleteBuilding(eBuilding))
	{
		return false;
	}

	if (!GC.getGameINLINE().isOption(GAMEOPTION_ASSIMILATION))
	{
        if (GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(eBuildingClass) != eBuilding)
        {
            return false;
        }
	}

	if (GC.getGameINLINE().isBuildingClassMaxedOut(eBuildingClass))
	{
		return false;
	}

	if (currentTeam.isBuildingClassMaxedOut(eBuildingClass))
	{
		return false;
	}

	if (isBuildingClassMaxedOut(eBuildingClass))
	{
		return false;
	}

	if (!hasValidCivics(eBuilding))
	{
		if ( probabilityEverConstructable != NULL )
		{
			*probabilityEverConstructable = 20;
		}
		return false;
	}

	
	if (kBuilding.isPrereqWar())
	{
		if (currentTeam.getAtWarCount(true, false) == 0)
		{
			if ( probabilityEverConstructable != NULL )
			{
				*probabilityEverConstructable = 10;
			}
			return false;
		}
	}
	if (!GC.getGameINLINE().canEverConstruct(eBuilding))
	{
		return false;
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
/************************************************************************************************/
/* REVDCM                                 02/16/10                                phungus420    */
/*                                                                                              */
/* CanConstruct                                                                                 */
/************************************************************************************************/
/* Moved to CvGame - Afforess 7/22/10
	if (kBuilding.getPrereqGameOption() != NO_GAMEOPTION)
	{
		if (!(GC.getGameINLINE().isOption((GameOptionTypes)kBuilding.getPrereqGameOption())))
		{
			return false;
		}
	}

	if (kBuilding.getNotGameOption() != NO_GAMEOPTION)
	{
		if (GC.getGameINLINE().isOption((GameOptionTypes)kBuilding.getNotGameOption()))
		{
			return false;
		}
	}
/************************************************************************************************/
/* REVDCM                                  END CanContstruct                                    */
/************************************************************************************************/
	if (!bIgnoreCost)
	{
		if (kBuilding.getProductionCost() == -1)
		{
			return false;
		}
	}

	if (kBuilding.getStateReligion() != NO_RELIGION)
	{
		if (getStateReligion() != kBuilding.getStateReligion())
		{
			if ( probabilityEverConstructable != NULL )
			{
				//	Is this religion one we have in our civ?
				bool hasReligionSomewhere = false;
				int iLoop;
				CvCity* pLoopCity;

				for (pLoopCity = firstCity(&iLoop, true); pLoopCity != NULL; pLoopCity = nextCity(&iLoop, true))
				{
					if ( pLoopCity->isHasReligion((ReligionTypes)kBuilding.getStateReligion()) )
					{
						hasReligionSomewhere = true;
						break;
					}
				}

				*probabilityEverConstructable = (hasReligionSomewhere ? 20 : 5);
			}
			return false;
		}
	}

	if (GC.getGameINLINE().countCivTeamsEverAlive() < kBuilding.getNumTeamsPrereq())
	{
		return false;
	}

	if (kBuilding.getVictoryPrereq() != NO_VICTORY)
	{
		if (!(GC.getGameINLINE().isVictoryValid((VictoryTypes)(kBuilding.getVictoryPrereq()))))
		{
			return false;
		}

		if (isMinorCiv())
		{
			return false;
		}

		if (currentTeam.getVictoryCountdown((VictoryTypes)kBuilding.getVictoryPrereq()) >= 0)
		{
			return false;
		}
	}

	if (kBuilding.getMaxStartEra() != NO_ERA)
	{
		if (GC.getGameINLINE().getStartEra() > kBuilding.getMaxStartEra())
		{
			return false;
		}
	}

	CvCivilizationInfo &civilizationInfo = GC.getCivilizationInfo(getCivilizationType());
	int numBuildingClassInfos = GC.getNumBuildingClassInfos();

	if ( kBuilding.getPrereqNumOfBuildingClass(NO_BUILDINGCLASS) > 0 )
	{
		for (iI = 0; iI < numBuildingClassInfos; iI++)
		{
			BuildingTypes ePrereqBuilding = (BuildingTypes)civilizationInfo.getCivilizationBuildings(iI);

			if (NO_BUILDING != ePrereqBuilding && currentTeam.isObsoleteBuilding(ePrereqBuilding))
			{
				//Afforess count upgraded buildings for the prerequisite
				int iPrereqs = getBuildingClassPrereqBuilding(eBuilding, (BuildingClassTypes)iI, 0);
				if (iPrereqs > 0 && getBuildingClassCount((BuildingClassTypes)iI) < iPrereqs && getBuildingClassCountWithUpgrades((BuildingClassTypes)iI) < iPrereqs)
				{
					return false;
				}
			}
		}
	}

	if (!bTestVisible)
	{
		if (GC.getGameINLINE().isBuildingClassMaxedOut(eBuildingClass, (currentTeam.getBuildingClassMaking(eBuildingClass) + ((bContinue) ? -1 : 0))))
		{
			return false;
		}

		if (currentTeam.isBuildingClassMaxedOut(eBuildingClass, (currentTeam.getBuildingClassMaking(eBuildingClass) + ((bContinue) ? -1 : 0))))
		{
			return false;
		}

		if (isBuildingClassMaxedOut(eBuildingClass, (getBuildingClassMaking(eBuildingClass) + ((bContinue) ? -1 : 0))))
		{
			return false;
		}

		if (GC.getGameINLINE().isNoNukes())
		{
			if (kBuilding.isAllowsNukes())
			{
				for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
				{
					if (GC.getUnitInfo((UnitTypes)iI).getNukeRange() != -1)
					{
						return false;
					}
				}
			}
		}

		if (kBuilding.getSpecialBuildingType() != NO_SPECIALBUILDING)
		{
			if (!(GC.getGameINLINE().isSpecialBuildingValid((SpecialBuildingTypes)(kBuilding.getSpecialBuildingType()))))
			{
				return false;
			}
		}

//		if (getNumCities() < kBuilding.getNumCitiesPrereq())
		if (getNumCities() < (kBuilding.getNumCitiesPrereq()*(GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getBuildingClassPrereqModifier()+50)/100)) //45°, scaling <iCitiesPrereq> for map size using BuildingClassPrereqModifier
		{
			if ( probabilityEverConstructable != NULL )
			{
				*probabilityEverConstructable = 20;
			}
			return false;
		}

		if (getHighestUnitLevel() < kBuilding.getUnitLevelPrereq())
/************************************************************************************************/
/* REVDCM                                  END Performance                                      */
/************************************************************************************************/
		{
			if ( probabilityEverConstructable != NULL )
			{
				*probabilityEverConstructable = 20;
			}
			return false;
		}

		if ( kBuilding.getPrereqNumOfBuildingClass(NO_BUILDINGCLASS) > 0 )
		{
			for (iI = 0; iI < numBuildingClassInfos; iI++)
			{
				//Afforess count upgraded buildings for the prerequisite
				int iPrereqs = getBuildingClassPrereqBuilding(eBuilding, (BuildingClassTypes)iI, (bContinue ? 0 : getBuildingClassMaking(eBuildingClass)));
				if (iPrereqs > 0 && getBuildingClassCount((BuildingClassTypes)iI) < iPrereqs && getBuildingClassCountWithUpgrades((BuildingClassTypes)iI) < iPrereqs)
				{
					if ( probabilityEverConstructable != NULL )
					{
						*probabilityEverConstructable = 20;
					}
					return false;
				}
			}
		}

		if (!(*getPropertiesConst() <= *(kBuilding.getPrereqPlayerMaxProperties())))
			return false;

		if (!(*getPropertiesConst() >= *(kBuilding.getPrereqPlayerMinProperties())))
			return false;

	}

	return true;
}


bool CvPlayer::canCreate(ProjectTypes eProject, bool bContinue, bool bTestVisible) const
{
	int iI;

/************************************************************************************************/
/* REVDCM                                 04/16/10                                phungus420    */
/*                                                                                              */
/* CanCreate Performance                                                                        */
/************************************************************************************************/
	CvProjectInfo& kProject = GC.getProjectInfo(eProject);

	if (isBarbarian())
	{
		return false;
	}

	if (kProject.getProductionCost() == -1)
	{
		return false;
	}

	if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)(kProject.getTechPrereq()))))
	{
		return false;
	}

	if (kProject.getVictoryPrereq() != NO_VICTORY)
	{
		if (!(GC.getGameINLINE().isVictoryValid((VictoryTypes)(kProject.getVictoryPrereq()))))
		{
			return false;
		}

		if (isMinorCiv())
		{
			return false;
		}

		if (GET_TEAM(getTeam()).getVictoryCountdown((VictoryTypes)kProject.getVictoryPrereq()) >= 0)
		{
			return false;
		}
	}

	if (GC.getGameINLINE().isProjectMaxedOut(eProject))
	{
		return false;
	}

	if (GET_TEAM(getTeam()).isProjectMaxedOut(eProject))
	{
		return false;
	}

	if (!bTestVisible)
	{
		if (GC.getGameINLINE().isProjectMaxedOut(eProject, (GET_TEAM(getTeam()).getProjectMaking(eProject) + ((bContinue) ? -1 : 0))))
		{
			return false;
		}

		if (GET_TEAM(getTeam()).isProjectMaxedOut(eProject, (GET_TEAM(getTeam()).getProjectMaking(eProject) + ((bContinue) ? -1 : 0))))
		{
			return false;
		}

		if (GC.getGameINLINE().isNoNukes())
		{
			if (kProject.isAllowsNukes())
			{
				for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
				{
					if (GC.getUnitInfo((UnitTypes)iI).getNukeRange() != -1)
					{
						return false;
					}
				}
			}
		}

		if (kProject.getAnyoneProjectPrereq() != NO_PROJECT)
		{
			if (GC.getGameINLINE().getProjectCreatedCount((ProjectTypes)(kProject.getAnyoneProjectPrereq())) == 0)
			{
				return false;
			}
		}

		for (iI = 0; iI < GC.getNumProjectInfos(); iI++)
		{
			if (GET_TEAM(getTeam()).getProjectCount((ProjectTypes)iI) < kProject.getProjectsNeeded(iI))
/************************************************************************************************/
/* REVDCM                                  END Performance                                      */
/************************************************************************************************/
			{
				return false;
			}
		}
	}

	return true;
}


bool CvPlayer::canMaintain(ProcessTypes eProcess, bool bContinue) const
{
	if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)(GC.getProcessInfo(eProcess).getTechPrereq()))))
	{
		return false;
	}

	return true;
}


bool CvPlayer::isProductionMaxedUnitClass(UnitClassTypes eUnitClass) const
{
	if (eUnitClass == NO_UNITCLASS)
	{
		return false;
	}

	if (GC.getGameINLINE().isUnitClassMaxedOut(eUnitClass))
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isUnitClassMaxedOut(eUnitClass))
	{
		return true;
	}

	if (isUnitClassMaxedOut(eUnitClass))
	{
		return true;
	}

	return false;
}


bool CvPlayer::isProductionMaxedBuildingClass(BuildingClassTypes eBuildingClass, bool bAcquireCity) const
{
	if (eBuildingClass == NO_BUILDINGCLASS)
	{
		return false;
	}

	if (!bAcquireCity)
	{
		if (GC.getGameINLINE().isBuildingClassMaxedOut(eBuildingClass))
		{
			return true;
		}
	}

	if (GET_TEAM(getTeam()).isBuildingClassMaxedOut(eBuildingClass))
	{
		return true;
	}

	if (isBuildingClassMaxedOut(eBuildingClass, ((bAcquireCity) ? GC.getBuildingClassInfo(eBuildingClass).getExtraPlayerInstances() : 0)))
	{
		return true;
	}

	return false;
}


bool CvPlayer::isProductionMaxedProject(ProjectTypes eProject) const
{
	if (eProject == NO_PROJECT)
	{
		return false;
	}

	if (GC.getGameINLINE().isProjectMaxedOut(eProject))
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isProjectMaxedOut(eProject))
	{
		return true;
	}

	return false;
}


int CvPlayer::getProductionNeeded(UnitTypes eUnit) const
{
	UnitClassTypes eUnitClass = (UnitClassTypes)GC.getUnitInfo(eUnit).getUnitClassType();
	FAssert(NO_UNITCLASS != eUnitClass);

	int iProductionNeeded = GC.getUnitInfo(eUnit).getProductionCost();

	iProductionNeeded *= 100 + getUnitClassCount(eUnitClass) * GC.getUnitClassInfo(eUnitClass).getInstanceCostModifier();
	iProductionNeeded /= 100;

	iProductionNeeded *= GC.getDefineINT("UNIT_PRODUCTION_PERCENT");
	iProductionNeeded /= 100;

	iProductionNeeded *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
	iProductionNeeded /= 100;

	iProductionNeeded *= GC.getEraInfo(GC.getGameINLINE().getStartEra()).getTrainPercent();
	iProductionNeeded /= 100;

	if (!isHuman() && !isBarbarian())
	{
		if (isWorldUnitClass(eUnitClass))
		{
			iProductionNeeded *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIWorldTrainPercent();
			iProductionNeeded /= 100;
		}
		else
		{
			iProductionNeeded *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAITrainPercent();
			iProductionNeeded /= 100;
		}

		iProductionNeeded *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iProductionNeeded /= 100;
	}

	iProductionNeeded += getUnitExtraCost(eUnitClass);

	// Python cost modifier
	if(GC.getUSE_GET_UNIT_COST_MOD_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		argsList.add(getID());	// Player ID
		argsList.add((int)eUnit);
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "getUnitCostMod", argsList.makeFunctionArgs(), &lResult);

		if (lResult > 1)
		{
			iProductionNeeded *= lResult;
			iProductionNeeded /= 100;
		}
	}

	return std::max(1, iProductionNeeded);
}


int CvPlayer::getProductionNeeded(BuildingTypes eBuilding) const
{
	int iProductionNeeded;

	iProductionNeeded = GC.getBuildingInfo(eBuilding).getProductionCost();

	iProductionNeeded *= GC.getDefineINT("BUILDING_PRODUCTION_PERCENT");
	iProductionNeeded /= 100;

	iProductionNeeded *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getConstructPercent();
	iProductionNeeded /= 100;

	iProductionNeeded *= GC.getEraInfo(GC.getGameINLINE().getStartEra()).getConstructPercent();
	iProductionNeeded /= 100;

	if (!isHuman() && !isBarbarian())
	{
		if (isWorldWonderClass((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())))
		{
			iProductionNeeded *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIWorldConstructPercent();
			iProductionNeeded /= 100;
		}
		else
		{
			iProductionNeeded *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIConstructPercent();
			iProductionNeeded /= 100;
		}

		iProductionNeeded *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iProductionNeeded /= 100;
	}

	return std::max(1, iProductionNeeded);
}


int CvPlayer::getProductionNeeded(ProjectTypes eProject) const
{
	int iProductionNeeded;

	iProductionNeeded = GC.getProjectInfo(eProject).getProductionCost();

	iProductionNeeded *= GC.getDefineINT("PROJECT_PRODUCTION_PERCENT");
	iProductionNeeded /= 100;

	iProductionNeeded *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getCreatePercent();
	iProductionNeeded /= 100;

	iProductionNeeded *= GC.getEraInfo(GC.getGameINLINE().getStartEra()).getCreatePercent();
	iProductionNeeded /= 100;

	if (!isHuman() && !isBarbarian())
	{
		if (isWorldProject(eProject))
		{
			iProductionNeeded *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIWorldCreatePercent();
			iProductionNeeded /= 100;
		}
		else
		{
			iProductionNeeded *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAICreatePercent();
			iProductionNeeded /= 100;
		}

		iProductionNeeded *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iProductionNeeded /= 100;
	}

	return std::max(1, iProductionNeeded);
}

int CvPlayer::getProductionModifier(UnitTypes eUnit) const
{
	int iMultiplier = 0;

	if (GC.getUnitInfo(eUnit).isMilitaryProduction())
	{
		iMultiplier += getMilitaryProductionModifier();
	}

	for (int iI = 0; iI < GC.getNumTraitInfos(); iI++)
	{
		if (hasTrait((TraitTypes)iI))
		{
			iMultiplier += GC.getUnitInfo(eUnit).getProductionTraits(iI);

// Thomas SG - AC: Advanced Cargo START
			{
				if (GC.getUnitInfo(eUnit).getNumSpecialUnitTypes() > 0)
				{
					for (int iJ = 0; iJ < GC.getUnitInfo(eUnit).getNumSpecialUnitTypes(); iJ++)
					{
						iMultiplier += GC.getSpecialUnitInfo((SpecialUnitTypes) GC.getUnitInfo(eUnit).getSpecialUnitType(iJ)).getProductionTraits(iI);
					}
				}
			}
// Thomas SG - AC: Advanced Cargo END
		}
	}

	return iMultiplier;
}

int CvPlayer::getProductionModifier(BuildingTypes eBuilding) const
{
	int iMultiplier = 0;
	for (int iI = 0; iI < GC.getNumTraitInfos(); iI++)
	{	
		if (hasTrait((TraitTypes)iI))
		{
			iMultiplier += GC.getBuildingInfo(eBuilding).getProductionTraits(iI);

			if (GC.getBuildingInfo(eBuilding).getSpecialBuildingType() != NO_SPECIALBUILDING)
			{
				iMultiplier += GC.getSpecialBuildingInfo((SpecialBuildingTypes) GC.getBuildingInfo(eBuilding).getSpecialBuildingType()).getProductionTraits(iI);
			}
		}
	}

	if (::isWorldWonderClass((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())))
	{
		iMultiplier += getMaxGlobalBuildingProductionModifier();
	}

	if (::isTeamWonderClass((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())))
	{
		iMultiplier += getMaxTeamBuildingProductionModifier();
	}

	if (::isNationalWonderClass((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())))
	{
		iMultiplier += getMaxPlayerBuildingProductionModifier();
	}

	return iMultiplier;
}

int CvPlayer::getProductionModifier(ProjectTypes eProject) const
{
	int iMultiplier = 0;

	if (GC.getProjectInfo(eProject).isSpaceship())
	{
		iMultiplier += getSpaceProductionModifier();
	}

	return iMultiplier;
}

int CvPlayer::getBuildingClassPrereqBuilding(BuildingTypes eBuilding, BuildingClassTypes ePrereqBuildingClass, int iExtra) const
{
	CvBuildingInfo& kBuilding = GC.getBuildingInfo(eBuilding);

	int iPrereqs = kBuilding.getPrereqNumOfBuildingClass(ePrereqBuildingClass);
	
	// dont bother with the rest of the calcs if we have no prereqs
	if (iPrereqs < 1)
	{
		return 0;
	}
/************************************************************************************************/
/* Afforess	                  Start		 02/14/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (kBuilding.isForceNoPrereqScaling())
		return iPrereqs;
	if (isLimitedWonderClass(ePrereqBuildingClass))
		return iPrereqs;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	BuildingClassTypes eBuildingClass = (BuildingClassTypes)kBuilding.getBuildingClassType();

	iPrereqs *= std::max(0, (GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getBuildingClassPrereqModifier() + 100));
	iPrereqs /= 100;

	if (!isLimitedWonderClass(eBuildingClass))
	{
		iPrereqs *= (getBuildingClassCount((BuildingClassTypes)(GC.getBuildingInfo(eBuilding).getBuildingClassType())) + iExtra + 1);
	}

	if (GC.getGameINLINE().isOption(GAMEOPTION_ONE_CITY_CHALLENGE) && isHuman())
	{
		iPrereqs = std::min(1, iPrereqs);
	}

	return iPrereqs;
}


void CvPlayer::removeBuildingClass(BuildingClassTypes eBuildingClass)
{
	CvCity* pLoopCity;
	BuildingTypes eBuilding;
	int iLoop;

	eBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(eBuildingClass)));

	if (eBuilding != NO_BUILDING)
	{
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			if (pLoopCity->getNumRealBuilding(eBuilding) > 0)
			{
/************************************************************************************************/
/* UNOFFICIAL_PATCH                       02/16/10                          EmperorFool         */
/*                                                                                              */
/* Bugfix                                                                                       */
/************************************************************************************************/
/* original bts code
				pLoopCity->setNumRealBuilding(eBuilding, 0);
*/
				pLoopCity->setNumRealBuilding(eBuilding, pLoopCity->getNumRealBuilding(eBuilding) - 1);
/************************************************************************************************/
/* UNOFFICIAL_PATCH                        END                                                  */
/************************************************************************************************/
				break;
			}
		}
	}
}


// courtesy of the Gourd Bros...
void CvPlayer::processBuilding(BuildingTypes eBuilding, int iChange, CvArea* pArea)
{
	int iI, iJ;
	 //DPII < Maintenance Modifiers >
    CvArea* pLoopArea = NULL;
    int iLoop = 0;

	FAssert(iChange == 1 || iChange == -1);

    //DPII < Maintenance Modifiers >
	if (GC.getBuildingInfo(eBuilding).getFreeBuildingClass() != NO_BUILDINGCLASS)
	{
		BuildingTypes eFreeBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(GC.getBuildingInfo(eBuilding).getFreeBuildingClass());
		if (eFreeBuilding != NO_BUILDING)
		{
			changeFreeBuildingCount(eFreeBuilding, iChange);
		}
	}

	if (GC.getBuildingInfo(eBuilding).getFreeAreaBuildingClass() != NO_BUILDINGCLASS)
	{
		BuildingTypes eFreeBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(GC.getBuildingInfo(eBuilding).getFreeAreaBuildingClass());
		if (eFreeBuilding != NO_BUILDING)
		{
			changeFreeAreaBuildingCount(eFreeBuilding, pArea, iChange);
		}
	}

	if (GC.getBuildingInfo(eBuilding).getCivicOption() != NO_CIVICOPTION)
	{
		changeHasCivicOptionCount(((CivicOptionTypes)GC.getBuildingInfo(eBuilding).getCivicOption()), iChange);
	}
	//DPII < Maintenance Modifiers >
    changeMaintenanceModifier(GC.getBuildingInfo(eBuilding).getGlobalMaintenanceModifier() * iChange);
	changeDistanceMaintenanceModifier(GC.getBuildingInfo(eBuilding).getDistanceMaintenanceModifier() * iChange);
	changeNumCitiesMaintenanceModifier(GC.getBuildingInfo(eBuilding).getNumCitiesMaintenanceModifier() * iChange);
	changeCoastalDistanceMaintenanceModifier(GC.getBuildingInfo(eBuilding).getCoastalDistanceMaintenanceModifier() * iChange);
	changeConnectedCityMaintenanceModifier(GC.getBuildingInfo(eBuilding).getConnectedCityMaintenanceModifier() * iChange);
	//DPII < Maintenance Modifiers >
	changeGreatPeopleRateModifier(GC.getBuildingInfo(eBuilding).getGlobalGreatPeopleRateModifier() * iChange);
	changeGreatGeneralRateModifier(GC.getBuildingInfo(eBuilding).getGreatGeneralRateModifier() * iChange);
	changeDomesticGreatGeneralRateModifier(GC.getBuildingInfo(eBuilding).getDomesticGreatGeneralRateModifier() * iChange);
	changeAnarchyModifier(GC.getBuildingInfo(eBuilding).getAnarchyModifier() * iChange);
	changeGoldenAgeModifier(GC.getBuildingInfo(eBuilding).getGoldenAgeModifier() * iChange);
	changeHurryModifier(GC.getBuildingInfo(eBuilding).getGlobalHurryModifier() * iChange);
	changeFreeExperience(GC.getBuildingInfo(eBuilding).getGlobalFreeExperience() * iChange);
	changeWarWearinessModifier(GC.getBuildingInfo(eBuilding).getGlobalWarWearinessModifier() * iChange);
	pArea->changeFreeSpecialist(getID(), (GC.getBuildingInfo(eBuilding).getAreaFreeSpecialist() * iChange));
	changeFreeSpecialist(GC.getBuildingInfo(eBuilding).getGlobalFreeSpecialist() * iChange);
	changeCoastalTradeRoutes(GC.getBuildingInfo(eBuilding).getCoastalTradeRoutes() * iChange);
	changeTradeRoutes(GC.getBuildingInfo(eBuilding).getGlobalTradeRoutes() * iChange);
/************************************************************************************************/
/* Afforess  Food Threshold Modifier   Start          09/25/09                   		         */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	changePopulationgrowthratepercentage(GC.getBuildingInfo(eBuilding).getGlobalPopulationgrowthratepercentage(), (iChange==1));
	changeForceAllTradeRoutes(GC.getBuildingInfo(eBuilding).isForceAllTradeRoutes() * iChange);
	changeBuildingInflation(GC.getBuildingInfo(eBuilding).getInflationModifier() * iChange);

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		changeWorldTradeRoutes(GC.getBuildingInfo(eBuilding).getWorldTradeRoutes() * iChange);
	}
/************************************************************************************************/
/* Afforess  Food Threshold Modifier                        END                  		         */
/************************************************************************************************/
	if (GC.getBuildingInfo(eBuilding).getAreaHealth() > 0)
	{
		pArea->changeBuildingGoodHealth(getID(), (GC.getBuildingInfo(eBuilding).getAreaHealth() * iChange));
	}
	else
	{
		pArea->changeBuildingBadHealth(getID(), (GC.getBuildingInfo(eBuilding).getAreaHealth() * iChange));
	}
	if (GC.getBuildingInfo(eBuilding).getGlobalHealth() > 0)
	{
		changeBuildingGoodHealth(GC.getBuildingInfo(eBuilding).getGlobalHealth() * iChange);
	}
	else
	{
		changeBuildingBadHealth(GC.getBuildingInfo(eBuilding).getGlobalHealth() * iChange);
	}
	pArea->changeBuildingHappiness(getID(), (GC.getBuildingInfo(eBuilding).getAreaHappiness() * iChange));
	changeBuildingHappiness(GC.getBuildingInfo(eBuilding).getGlobalHappiness() * iChange);
	changeWorkerSpeedModifier(GC.getBuildingInfo(eBuilding).getWorkerSpeedModifier() * iChange);
	changeSpaceProductionModifier(GC.getBuildingInfo(eBuilding).getGlobalSpaceProductionModifier() * iChange);
	changeCityDefenseModifier(GC.getBuildingInfo(eBuilding).getAllCityDefenseModifier() * iChange);
/************************************************************************************************/
/* REVDCM                                 04/09/10                                phungus420    */
/*                                                                                              */
/* Building Effects                                                                             */
/************************************************************************************************/
	changeUnitUpgradePriceModifier(GC.getBuildingInfo(eBuilding).getUnitUpgradePriceModifier() * iChange);
	changeRevIdxNational(GC.getBuildingInfo(eBuilding).getRevIdxNational() * iChange);
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/
	pArea->changeCleanPowerCount(getTeam(), ((GC.getBuildingInfo(eBuilding).isAreaCleanPower()) ? iChange : 0));
	pArea->changeBorderObstacleCount(getTeam(), ((GC.getBuildingInfo(eBuilding).isAreaBorderObstacle()) ? iChange : 0));
	//DPII < Maintenance Modifiers >
    pArea->changeMaintenanceModifier(getID(), (GC.getBuildingInfo(eBuilding).getAreaMaintenanceModifier() * iChange));

    if (GC.getBuildingInfo(eBuilding).getOtherAreaMaintenanceModifier() != 0)
    {
        for (pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop))
        {
            if (!(pLoopArea == pArea))
            {
                pLoopArea->changeMaintenanceModifier(getID(), (GC.getBuildingInfo(eBuilding).getOtherAreaMaintenanceModifier()  * iChange));
            }
        }
    }
    //DPII < Maintenance Modifiers >
	for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
	{
		changeSeaPlotYield(((YieldTypes)iI), (GC.getBuildingInfo(eBuilding).getGlobalSeaPlotYieldChange(iI) * iChange));
		pArea->changeYieldRateModifier(getID(), ((YieldTypes)iI), (GC.getBuildingInfo(eBuilding).getAreaYieldModifier(iI) * iChange));
		changeYieldRateModifier(((YieldTypes)iI), (GC.getBuildingInfo(eBuilding).getGlobalYieldModifier(iI) * iChange));
	}

	for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
	{
		changeCommerceRateModifier(((CommerceTypes)iI), (GC.getBuildingInfo(eBuilding).getGlobalCommerceModifier(iI) * iChange));
		changeSpecialistExtraCommerce(((CommerceTypes)iI), (GC.getBuildingInfo(eBuilding).getSpecialistExtraCommerce(iI) * iChange));
		changeStateReligionBuildingCommerce(((CommerceTypes)iI), (GC.getBuildingInfo(eBuilding).getStateReligionCommerce(iI) * iChange));
		changeCommerceFlexibleCount(((CommerceTypes)iI), (GC.getBuildingInfo(eBuilding).isCommerceFlexible(iI)) ? iChange : 0);
	}

	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		BuildingTypes eOurBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI);
		if (NO_BUILDING != eOurBuilding)
		{
			changeExtraBuildingHappiness(eOurBuilding, (GC.getBuildingInfo(eBuilding).getBuildingHappinessChanges(iI) * iChange));
/************************************************************************************************/
/* Afforess	                  Start		 12/9/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
			changeBuildingClassProductionModifier(((BuildingClassTypes)iI), GC.getBuildingInfo(eBuilding).getGlobalBuildingClassProductionModifier(iI) * iChange);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		}
	}

	for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
	{
		for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
		{
			changeExtraSpecialistYield(((SpecialistTypes)iI), ((YieldTypes)iJ), (GC.getBuildingInfo(eBuilding).getSpecialistYieldChange(iI, iJ) * iChange));
		}
		//Afforess: SpecialistTypeCommerceChanges
		for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
		{
			changeSpecialistCommercePercentChanges((SpecialistTypes)iI, (CommerceTypes)iJ, GC.getBuildingInfo(eBuilding).getSpecialistCommercePercentChanges(iI, iJ) * iChange);
		}
	}
}


bool CvPlayer::canBuild(const CvPlot* pPlot, BuildTypes eBuild, bool bTestEra, bool bTestVisible, bool bIncludePythonOverrides) const
{
	PROFILE_FUNC();
/************************************************************************************************/
/* Afforess	                  Start		 09/25/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	CvBuildInfo& kBuild = GC.getBuildInfo(eBuild);
	
	if (pPlot != NULL)
	{
		if (!(pPlot->canBuild(eBuild, getID(), bTestVisible, bIncludePythonOverrides)))
		{
			return false;
		}
	}

	if (kBuild.getTechPrereq() != NO_TECH)
	{
		if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)kBuild.getTechPrereq())))
		{
			if ((!bTestEra && !bTestVisible) || ((getCurrentEra() + 1) < GC.getTechInfo((TechTypes) kBuild.getTechPrereq()).getEra()))
			{
				return false;
			}
		}
	}
	
	if (kBuild.getObsoleteTech() != NO_TECH)
	{
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)kBuild.getObsoleteTech()))
		{
			return false;
		}
	}

	if (pPlot != NULL)
	{
		if (pPlot->isDepletedMine())
		{
			if (kBuild.isMine())
			{
				return false;
			}
		}
	}

	if (kBuild.isDisabled())
	{
		return false;
	}
	
	if (kBuild.getImprovement() != NO_IMPROVEMENT)
	{
		if (GC.getImprovementInfo((ImprovementTypes)kBuild.getImprovement()).getPrereqTech() != NO_TECH)
		{
			if (!GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getImprovementInfo((ImprovementTypes)kBuild.getImprovement()).getPrereqTech()))
			{
				return false;
			}
		}
	}
	
	if (isModderOption(MODDEROPTION_HIDE_OBSOLETE_BUILDS))
	{
		if (kBuild.getRoute() != NO_ROUTE)
		{
			for (int iI = 0; iI < GC.getNumRouteInfos(); iI++)
			{
				if (GC.getRouteInfo((RouteTypes)iI).getMovementCost() < GC.getRouteInfo((RouteTypes)kBuild.getRoute()).getMovementCost())
				{
					for (int iJ = 0; iJ < GC.getNumBuildInfos(); iJ++)
					{
						if (GC.getBuildInfo((BuildTypes)iJ).getRoute() == iI)
						{
							if (canBuild(pPlot, (BuildTypes)iJ, false))
							{
								return false;
							}
						}
					}
				}
			}
		}
		if (kBuild.getImprovement() != NO_IMPROVEMENT)
		{
			for (int iI = 0; iI < GC.getNumImprovementInfos(); iI++)
			{
				if (GC.getImprovementInfo((ImprovementTypes)kBuild.getImprovement()).getImprovementUpgrade() == iI)
				{
					for (int iJ = 0; iJ < GC.getNumBuildInfos(); iJ++)
					{
						if (GC.getBuildInfo((BuildTypes)iJ).getImprovement() == iI)
						{
							if (canBuild(pPlot, (BuildTypes)iJ, false))
							{
								return false;
							}
						}
					}
				}
			}
		}
	}

	if (!bTestVisible)
	{
		if (pPlot != NULL)
		{
			if (pPlot->getFeatureType() != NO_FEATURE)
			{
				if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)kBuild.getFeatureTech(pPlot->getFeatureType()))))
				{
					if (!kBuild.isNoTechCanRemoveWithNoProductionGain(pPlot->getFeatureType()))
					{
						return false;
					}

				}
			}

			if (std::max(0, getGold()) < getBuildCost(pPlot, eBuild))
			{
				return false;
			}
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	return true;
}

// Returns the cost
int CvPlayer::getBuildCost(const CvPlot* pPlot, BuildTypes eBuild) const
{
	FAssert(eBuild >= 0 && eBuild < GC.getNumBuildInfos());

	if (pPlot->getBuildProgress(eBuild) > 0)
	{
		return 0;
	}
	
/************************************************************************************************/
/* Afforess	                  Start		 07/18/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
	return std::max(0, GC.getBuildInfo(eBuild).getCost() * (100 + calculateInflationRate())) / 100;
*/
	int iCost = GC.getBuildInfo(eBuild).getCost();
	iCost *= std::max(0, 100 + calculateInflationRate());
	iCost /= 100;
	if (GC.getBuildInfo(eBuild).getRoute() != NO_ROUTE)
	{
		if (pPlot->getRouteType() != NO_ROUTE)
		{
			if (GC.getDefineINT("ROUTES_UPGRADE"))
			{
				for (int iI = 0; iI < GC.getNumBuildInfos(); iI++)
				{
					if (GC.getBuildInfo((BuildTypes)iI).getRoute() == pPlot->getRouteType())
					{
						iCost = std::max(0, iCost - GC.getBuildInfo((BuildTypes)iI).getCost());
						break;
					}
				}
			}
		}
	}
	
	return iCost;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
}

bool CvPlayer::isRouteValid(RouteTypes eRoute, BuildTypes eRouteBuild, CvPlot* pPlot, CvUnit* pBuilder) const
{
	bool	bResult = false;

	if ((pPlot != NULL) ? ((pPlot->getRouteType() == eRoute) || canBuild(pPlot, eRouteBuild)) : GET_TEAM(getTeam()).isHasTech((TechTypes)(GC.getBuildInfo(eRouteBuild).getTechPrereq())))
	{
		bResult = (pBuilder == NULL || pBuilder->canBuild(pPlot,eRouteBuild));
	}

	return bResult;
}

/************************************************************************************************/
/* Afforess	                  Start		 5/29/11                                                */
/*                                                                                              */
/*  Do not blindly rely on XML value, check movement info and route cost                        */
/************************************************************************************************/
RouteTypes CvPlayer::getBestRoute(CvPlot* pPlot, bool bConnect, CvUnit* pBuilder) const
{
	PROFILE_FUNC();

	// Save best route type per player each turn, then just check that
	// one first and only check others if can't do best.
	if ( m_eBestRoute == NO_ROUTE )
	{
		//	Set cache to the best route ignoring the building unit (ie - best we can make for
		//	our tech level)
		m_eBestRoute = getBestRouteInternal(pPlot, bConnect, NULL, &m_eBestRouteBuild);
	}

	if ( m_eBestRoute != NO_ROUTE )
	{
		if ( isRouteValid(m_eBestRoute, m_eBestRouteBuild, pPlot, pBuilder) )
		{
			return m_eBestRoute;
		}
	}

	return getBestRouteInternal(pPlot, bConnect, pBuilder);
}

RouteTypes CvPlayer::getBestRouteInternal(CvPlot* pPlot, bool bConnect, CvUnit* pBuilder, BuildTypes* eBestRouteBuild) const
{
	RouteTypes eRoute;
	RouteTypes eBestRoute;
	int iValue;
	int iBestValue;
	int iI;

	iBestValue = 0;
	eBestRoute = NO_ROUTE;

	int baseMoves = GC.getDefineINT("MOVE_DENOMINATOR");

	for (iI = 0; iI < GC.getNumBuildInfos(); iI++)
	{
		eRoute = ((RouteTypes)(GC.getBuildInfo((BuildTypes)iI).getRoute()));

		if (eRoute != NO_ROUTE)
		{
			if (isRouteValid(eRoute, (BuildTypes)iI, pPlot, pBuilder))
			{
				iValue = GC.getRouteInfo(eRoute).getValue();
				//Assuming roads never hinder movement
				int iExtraMoves = std::max(0, baseMoves / std::min(baseMoves, GC.getRouteInfo(eRoute).getMovementCost()) - 1); //subtract 1 because we care about extra moves, all movement is 1 move by default
				if (!bConnect) {
					iValue -= GC.getBuildInfo((BuildTypes)iI).getTime() / 100; //number of turns
					iValue -= GC.getBuildInfo((BuildTypes)iI).getCost() / (AI_isFinancialTrouble() ? 1 : 2);
				}
				iValue += iExtraMoves;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
				if (iValue > iBestValue)
				{
					iBestValue = iValue;
					eBestRoute = eRoute;
					if ( NULL != eBestRouteBuild )
					{
						*eBestRouteBuild = (BuildTypes)iI;
					}
				}
			}
		}
	}

	return eBestRoute;
}


int CvPlayer::getImprovementUpgradeRateTimes100(ImprovementTypes eImprovement) const
{
	int iRate;
	int iRateModifier = getImprovementUpgradeRateModifierSpecific(eImprovement);
	iRateModifier += getImprovementUpgradeRateModifier();

	iRate = 100;

	iRate *= std::max(0, (iRateModifier + 100));
	iRate /= 100;

	return std::max(1,iRate);
}


int CvPlayer::calculateTotalYield(YieldTypes eYield) const
{
	CvCity* pLoopCity;
	int iTotalCommerce = 0;
	int iLoop = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iTotalCommerce += pLoopCity->getYieldRate(eYield);
	}

	return iTotalCommerce;
}


int CvPlayer::calculateTotalCityHappiness() const
{
	CvCity* pLoopCity;
	int iTotalHappiness = 0;
	int iLoop = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iTotalHappiness += pLoopCity->happyLevel();
	}

	return iTotalHappiness;
}


int CvPlayer::calculateTotalExports(YieldTypes eYield) const
{
	CvCity* pLoopCity;
	CvCity* pTradeCity;
	int iTotalExports = 0;
	int iLoop = 0, iTradeLoop = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
// BUG - Fractional Trade Routes - start
#ifdef _MOD_FRACTRADE
		int iCityExports = 0;
#endif

		for (iTradeLoop = 0; iTradeLoop < pLoopCity->getTradeRoutes(); iTradeLoop++)
		{
			pTradeCity = pLoopCity->getTradeCity(iTradeLoop);
			if (pTradeCity != NULL)
			{
				if (pTradeCity->getOwnerINLINE() != getID())
				{
#ifdef _MOD_FRACTRADE
					iCityExports += pLoopCity->calculateTradeYield(eYield, pLoopCity->calculateTradeProfitTimes100(pTradeCity));
#else
					iTotalExports += pLoopCity->calculateTradeYield(eYield, pLoopCity->calculateTradeProfit(pTradeCity));
#endif
				}
			}
		}

#ifdef _MOD_FRACTRADE
		iTotalExports += iCityExports / 100;
#endif
// BUG - Fractional Trade Routes - end
	}

	return iTotalExports;
}


int CvPlayer::calculateTotalImports(YieldTypes eYield) const
{
	CvCity* pLoopCity;
	CvCity* pTradeCity;
	int iTotalImports = 0;
	int iPlayerLoop = 0, iLoop = 0, iTradeLoop = 0;
	
	// Loop through players
	for (iPlayerLoop = 0; iPlayerLoop < MAX_CIV_PLAYERS; iPlayerLoop++)
	{
		if (iPlayerLoop != getID())
		{
// BUG - Fractional Trade Routes - start
#ifdef _MOD_FRACTRADE
			int iCityImports = 0;
#endif

			for (pLoopCity = GET_PLAYER((PlayerTypes) iPlayerLoop).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes) iPlayerLoop).nextCity(&iLoop))
			{
				for (iTradeLoop = 0; iTradeLoop < pLoopCity->getTradeRoutes(); iTradeLoop++)
				{
					pTradeCity = pLoopCity->getTradeCity(iTradeLoop);
					if (pTradeCity != NULL)
					{
						if (pTradeCity->getOwnerINLINE() == getID())
						{
#ifdef _MOD_FRACTRADE
							iCityImports += pLoopCity->calculateTradeYield(eYield, pLoopCity->calculateTradeProfitTimes100(pTradeCity));
#else
							iTotalImports += pLoopCity->calculateTradeYield(eYield, pLoopCity->calculateTradeProfit(pTradeCity));
#endif
						}
					}
				}
			}

#ifdef _MOD_FRACTRADE
			iTotalImports += iCityImports / 100;
#endif
// BUG - Fractional Trade Routes - end
		}
	}
	return iTotalImports;
}


int CvPlayer::calculateTotalCityUnhappiness() const
{
	CvCity* pLoopCity;
	int iTotalUnhappiness = 0;
	int iLoop = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iTotalUnhappiness += pLoopCity->unhappyLevel();
	}

	return iTotalUnhappiness;
}


int CvPlayer::calculateTotalCityHealthiness() const
{
	CvCity* pLoopCity;
	int iTotalHealthiness = 0;
	int iLoop = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iTotalHealthiness += pLoopCity->goodHealth();
	}

	return iTotalHealthiness;
}

int CvPlayer::calculateTotalCityUnhealthiness() const
{
	CvCity* pLoopCity;
	int iTotalUnhealthiness = 0;
	int iLoop = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iTotalUnhealthiness += pLoopCity->badHealth();
	}

	return iTotalUnhealthiness;
}


int CvPlayer::calculateUnitCost(int& iFreeUnits, int& iFreeMilitaryUnits, int& iPaidUnits, int& iPaidMilitaryUnits, int& iBaseUnitCost, int& iMilitaryCost, int& iExtraCost) const
{
	int iSupport;

	iFreeUnits = GC.getHandicapInfo(getHandicapType()).getFreeUnits();

	iFreeUnits += getBaseFreeUnits();
	iFreeUnits += ((getTotalPopulation() * getFreeUnitsPopulationPercent()) / 100);

	iFreeMilitaryUnits = getBaseFreeMilitaryUnits();
	iFreeMilitaryUnits += ((getTotalPopulation() * getFreeMilitaryUnitsPopulationPercent()) / 100);

/************************************************************************************************/
/* REVOLUTION_MOD                         02/04/09                                jdog5000      */
/*                                                                                              */
/* For rebels and BarbarianCiv                                                                  */
/************************************************************************************************/
	iFreeUnits += getFreeUnitCountdown();
	iFreeMilitaryUnits += getFreeUnitCountdown();
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/


/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      09/17/09                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/* original BTS code
	if (!isHuman())
	{
		if (GET_TEAM(getTeam()).hasMetHuman())
		{
			iFreeUnits += getNumCities(); // XXX
			iFreeMilitaryUnits += getNumCities(); // XXX
		}
	}
*/
	// Removed hidden AI bonus
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

	iPaidUnits = std::max(0, getNumUnits() - iFreeUnits);
	iPaidMilitaryUnits = std::max(0, getNumMilitaryUnits() - iFreeMilitaryUnits);

	iSupport = 0;

	iBaseUnitCost = iPaidUnits * getGoldPerUnit();
	iMilitaryCost = iPaidMilitaryUnits * getGoldPerMilitaryUnit();
	iExtraCost = getExtraUnitCost();

	iSupport = iMilitaryCost + iBaseUnitCost + iExtraCost;

	iSupport *= GC.getHandicapInfo(getHandicapType()).getUnitCostPercent();
	iSupport /= 100;

	if (!isHuman() && !isBarbarian())
	{
		iSupport *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIUnitCostPercent();
		iSupport /= 100;

		iSupport *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iSupport /= 100;
	}

	//ls612: Gold modifiers by Gamespeed
	iSupport = (iSupport*GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGoldModifier())/100;

	FAssert(iSupport >= 0);

	return std::max(0, iSupport);
}


int CvPlayer::calculateUnitCost() const
{
	if (isAnarchy())
	{
		return 0;
	}

	int iFreeUnits;
	int iFreeMilitaryUnits;
	int iPaidUnits;
	int iPaidMilitaryUnits;
	int iMilitaryCost;
	int iBaseUnitCost;
	int iExtraCost;
	
	return calculateUnitCost(iFreeUnits, iFreeMilitaryUnits, iPaidUnits, iPaidMilitaryUnits, iBaseUnitCost, iMilitaryCost, iExtraCost);
}

int CvPlayer::calculateUnitSupply() const
{
	int iPaidUnits;
	int iBaseSupplyCost;

	if (isAnarchy())
	{
		return 0;
	}

	//ls612: Gold Modifiers by Gamespeed
	int iCost = calculateUnitSupply(iPaidUnits, iBaseSupplyCost) * (GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGoldModifier());
	if (iCost != 0)
	{
		iCost /= 100;
	}

	return iCost;
}

int CvPlayer::calculateUnitSupply(int& iPaidUnits, int& iBaseSupplyCost) const
{
	int iSupply;

	iPaidUnits = std::max(0, (getNumOutsideUnits() - GC.getDefineINT("INITIAL_FREE_OUTSIDE_UNITS")));

	iBaseSupplyCost = iPaidUnits * GC.getDefineINT("INITIAL_OUTSIDE_UNIT_GOLD_PERCENT");
	iBaseSupplyCost /= 100;

/************************************************************************************************/
/* Afforess  Unit Distance Modifier   Start          12/4/09                                   */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	iBaseSupplyCost *= (100 + getDistantUnitSupportCostModifier());
	iBaseSupplyCost /= 100;
/************************************************************************************************/
/* Afforess  Unit Distance Modifier                          END                  		         */
/************************************************************************************************/	
	iSupply = iBaseSupplyCost;

	if (!isHuman() && !isBarbarian())
	{
		iSupply *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIUnitSupplyPercent();
		iSupply /= 100;

		iSupply *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iSupply /= 100;
	}

	FAssert(iSupply >= 0);

	return iSupply;
}


int CvPlayer::calculatePreInflatedCosts() const
{
/************************************************************************************************/
/* Afforess	                  Start		 04/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	long lResult = 0;
	if (GC.getUSE_EXTRA_PLAYER_COSTS_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		argsList.add(getID());
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "getExtraCost", argsList.makeFunctionArgs(), &lResult);
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

/************************************************************************************************/
/* Afforess	                  Start		 06/19/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	int iCosts = 0;
	//ls612: All of the following functions (except for Corporate Tax) are modified by a new Gamespeed Gold tag.
	//This is done in order for the displayed numbers in the Financial Advisor to be correct.
	iCosts += calculateUnitCost();
	iCosts += calculateUnitSupply();
	iCosts += getTotalMaintenance();
	iCosts += getCivicUpkeep();
	//ls612: Old Code
	//iCosts += (int)lResult;
	iCosts -= getCorporateTaxIncome();
	
	//ls612: New Code for Gamespeed Gold modifiers
	lResult *= (GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGoldModifier());

	if (lResult != 0)
	{
		lResult /= 100;
	}

	iCosts += (int)lResult;
	return iCosts;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
}

//	Called once per turn to update the current cost-to-turn-1-cost ratio
void CvPlayer::doInflation(bool pReinit)
{
    if (pReinit)
	{
		m_accruedCostRatioTimes10000 = 10000;
	}
	else
	{
		// Keep up to second order terms in binomial series
		int iAccruedCostRatioTimes10000 = (getEquilibriumInflationCostModifier()+100) * 100;

		// iAccruedCostRatioTimes10000 now holds the cost multiplier our CURRENT inflation rate would imply.  We
		// 'decay' the current cost multiplier towards this equilibrium value
		int iInflationRateMomentum = GC.getDefineINT("INFLATION_RATE_MOMENTUM", 50);

		iInflationRateMomentum *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getImprovementPercent();
		iInflationRateMomentum /= 100;

		if ( iInflationRateMomentum < 1 )
		{
			iInflationRateMomentum = 1;
		}
		m_accruedCostRatioTimes10000 += (iAccruedCostRatioTimes10000 - m_accruedCostRatioTimes10000 + (iAccruedCostRatioTimes10000 > m_accruedCostRatioTimes10000 ? 1 : -1)*(iInflationRateMomentum - 1))/iInflationRateMomentum;
		
		//Debug to check the evolution of the inflation value.
		OutputDebugString(CvString::format("\nnew m_accruedCostRatioTimes10000 : %d ",m_accruedCostRatioTimes10000).c_str());
	}
}

int CvPlayer::getCurrentInflationCostModifier(void) const
{
	return m_accruedCostRatioTimes10000/100 - 100;
}

int CvPlayer::getEquilibriumInflationCostModifier(void) const
{
	int iInflationPerTurnTimes10000 = getCurrentInflationPerTurnTimes10000();
	int iTurns = ((GC.getGameINLINE().getGameTurn() + GC.getGameINLINE().getElapsedGameTurns()) / 2);

	if (GC.getGameINLINE().getMaxTurns() > 0)
	{
		iTurns = std::min(GC.getGameINLINE().getMaxTurns(), iTurns);
	}

	iTurns += GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getInflationOffset();

	//	How many turns (max) do we compound inflation over?
	int	iInflationTurnCeiling = GC.getDefineINT("MAX_INFLATION_EFFECT_WINDOW", 200);

	if ( iTurns > iInflationTurnCeiling )
	{
		iTurns = iInflationTurnCeiling;
	}
	else if ( iTurns < 0 )
	{
		iTurns = 0;
	}

	// Keep up to second order terms in binomial series
	int iAccruedCostRatioTimes10000 = 10000 + iTurns * iInflationPerTurnTimes10000;
	iAccruedCostRatioTimes10000 += (iTurns * (iTurns - 1) * iInflationPerTurnTimes10000 * iInflationPerTurnTimes10000) / 20000;

	return iAccruedCostRatioTimes10000/100 - 100;
}

int CvPlayer::getCurrentInflationPerTurnTimes10000(void) const
{
	int iInflationPerTurnTimes10000 = GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getInflationPercent();
	iInflationPerTurnTimes10000 *= GC.getHandicapInfo(getHandicapType()).getInflationPercent();

	int iModifier = m_iInflationModifier;
	if (!isHuman() && !isBarbarian())
	{
		int iAIModifier = GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIInflationPercent();
		iAIModifier *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iAIModifier /= 100;

		iModifier += iAIModifier - 100;
	}

/************************************************************************************************/
/* REVOLUTION_MOD                         01/31/08                                jdog5000      */
/*                                                                                              */
/* Reduced inflation cost for rebels                                                            */
/************************************************************************************************/
	if( isRebel() )
		iModifier -= 50;
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
	iInflationPerTurnTimes10000 *= std::max(0, 100 + iModifier);
	iInflationPerTurnTimes10000 /= 100;
	
/************************************************************************************************/
/* Afforess	                  Start		 06/27/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	// ls612: remove inflation for hurrying things
	{
		int iCivicModifier = getCivicInflation();
		int iProjectModifier = getProjectInflation();
		int iTechInflation = getTechInflation();
		int iBuildingInflation = getBuildingInflation();
		int iHurryInflation = getHurriedCount();
		
		iInflationPerTurnTimes10000 *= std::max(0, 100 + iCivicModifier);
		iInflationPerTurnTimes10000 /= 100;
		
		iInflationPerTurnTimes10000 *= std::max(0, 100 + iProjectModifier);
		iInflationPerTurnTimes10000 /= 100;
		
		iInflationPerTurnTimes10000 *= std::max(0, 100 + iTechInflation);
		iInflationPerTurnTimes10000 /= 100;
		
		iInflationPerTurnTimes10000 *= std::max(0, 100 + iBuildingInflation);
		iInflationPerTurnTimes10000 /= 100;
		
		iInflationPerTurnTimes10000 *= std::max(0, 100 + iHurryInflation);
		iInflationPerTurnTimes10000 /= 100;
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/	

	return iInflationPerTurnTimes10000/100;
}

int CvPlayer::calculateInflationRate() const
{
	if (GC.isDISABLE_INFLATION())
	{
		return 0;
	}
	int iRatePercent = (m_accruedCostRatioTimes10000 == -1 ? 0 : (m_accruedCostRatioTimes10000-10000)/100);

	return iRatePercent;
}


int CvPlayer::calculateInflatedCosts() const
{
	int iCosts;

	iCosts = calculatePreInflatedCosts();

	iCosts *= std::max(0, (calculateInflationRate() + 100));
	iCosts /= 100;

	return iCosts;
}

/************************************************************************************************/
/* REVOLUTION_MOD                         02/04/09                                jdog5000      */
/*                                                                                              */
/* For rebels and BarbarianCiv                                                                  */
/************************************************************************************************/
int CvPlayer::getFreeUnitCountdown() const
{
	return m_iFreeUnitCountdown;
}

void CvPlayer::setFreeUnitCountdown( int iValue )
{
	m_iFreeUnitCountdown = std::max(0, iValue);
}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/


int CvPlayer::calculateBaseNetGold() const
{
	int iNetGold;

	iNetGold = (getCommerceRate(COMMERCE_GOLD) + getGoldPerTurn());

	iNetGold -= calculateInflatedCosts();
	
	return iNetGold;
}

int CvPlayer::calculateResearchModifier(TechTypes eTech) const
{
	int iModifier = 100;

	if (NO_TECH == eTech)
	{
		return iModifier;
	}

	int iKnownCount = 0;
	int iPossibleKnownCount = 0;

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      07/27/09                                jdog5000      */
/*                                                                                              */
/* Tech Diffusion                                                                               */
/************************************************************************************************/
	if( !GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_DIFFUSION) )
	{
		double knownExp = 0.0;
		// Tech flows better through open borders
		int iTeams = 0;
		int iMetTeams = 0;
		int iTeamsHaveTech = 0;
		for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
		{
			if (GET_TEAM((TeamTypes)iI).isAlive())
			{
				iTeams++;
				if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iI))
				{
					iMetTeams++;
					if (GET_TEAM((TeamTypes)iI).isHasTech(eTech))
					{
						iTeamsHaveTech++;

						knownExp += 0.5;

						if( GET_TEAM(getTeam()).isOpenBorders((TeamTypes)iI) || GET_TEAM((TeamTypes)iI).isVassal(getTeam()) )
						{
							knownExp += 1.5;
						}
						else if( GET_TEAM(getTeam()).isAtWar((TeamTypes)iI) || GET_TEAM(getTeam()).isVassal((TeamTypes)iI) )
						{
							knownExp += 0.5;
						}
					}
				}
			}
		}

		if (knownExp > 0.0) 
		{
			//If 1/3 the teams don't have the tech, diffusion is slow
			if (iTeamsHaveTech * 3 < iTeams)
			{
				knownExp /= 100;
			}
			//If 2/3 the teams do have the tech, diffusion is fast
			else if (iTeamsHaveTech * 3 > 2 * iTeams)
			{
				knownExp *= 3;
			}
		}

		//Scale diffusion based on the number of teams we know of
		knownExp *= iMetTeams;
		knownExp /= iTeams;

		int techDiffMod = GC.getTECH_DIFFUSION_KNOWN_TEAM_MODIFIER();
		if (knownExp > 0.0)
		{
			//ensure tech diffusion can not hurt research, only help
			int iTechDiffusion = std::max(0, techDiffMod - (int)(techDiffMod * pow(0.85, knownExp) + 0.5));
			iModifier += iTechDiffusion;
			GC.getGameINLINE().logMsg("Tech Diffusion base amount for %S: %d", getCivilizationDescription(), iTechDiffusion);
		}

		// Tech flows downhill to those who are far behind
		int iTechScorePercent = GET_TEAM(getTeam()).getBestKnownTechScorePercent();
		int iWelfareThreshold = GC.getTECH_DIFFUSION_WELFARE_THRESHOLD();
		if( iTechScorePercent < iWelfareThreshold )
		{
			if( knownExp > 0.0 )
			{
				int iWelfareMod = GC.getTECH_DIFFUSION_WELFARE_MODIFIER();
				//ensure tech diffusion can not hurt research, only help
				int iWelfareTechDiffusion = std::max(0, (iWelfareMod - (int)(iWelfareMod * pow(0.98, iWelfareThreshold - iTechScorePercent) + 0.5)));
				int iBestScore = 0;
				int iOurScore = calculateScore(false);
				for (int iI = 0; iI < MAX_PLAYERS; iI++)
				{
					if (GET_PLAYER((PlayerTypes)iI).isAlive() && iI != getID())
					{
						int iScore = GET_PLAYER((PlayerTypes)iI).calculateScore(false);
						if (iScore > iBestScore)
						{
							iBestScore = iScore;
						}
					}
				}
				//If iOurScore > iBestScore we are the best team in the game
				if (iOurScore < iBestScore)
				{
					float fRatio = iBestScore / ((float)iOurScore);
					GC.getGameINLINE().logMsg("Tech Welfare amount: %d, iOurScore: %d, iBestScore: %d, fRatio: %f, modified welfare amt: %d for civ: %S", iWelfareTechDiffusion, iOurScore, iBestScore, fRatio, ((int)(fRatio * iWelfareTechDiffusion)), getCivilizationDescription());
					iWelfareTechDiffusion = (int)(iWelfareTechDiffusion * fRatio);
					iModifier += iWelfareTechDiffusion;

				}
			}
		}
	}
	else
	{
		// Default BTS code
		for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
		{
			if (GET_TEAM((TeamTypes)iI).isAlive())
			{
				if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iI))
				{
					if (GET_TEAM((TeamTypes)iI).isHasTech(eTech))
					{
						iKnownCount++;
					}
				}

				iPossibleKnownCount++;
			}
		}

		if (iPossibleKnownCount > 0)
		{
			iModifier += (GC.getDefineINT("TECH_COST_TOTAL_KNOWN_TEAM_MODIFIER") * iKnownCount) / iPossibleKnownCount;
		}
	}

	return std::max(1,iModifier);
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
}

int CvPlayer::calculateBaseNetResearch(TechTypes eTech) const
{
	TechTypes eResearchTech;

	if (eTech != NO_TECH)
	{
		eResearchTech = eTech;
	}
	else
	{
		eResearchTech = getCurrentResearch();
	}

	return (((GC.getDefineINT("BASE_RESEARCH_RATE") + getCommerceRate(COMMERCE_RESEARCH)) * calculateResearchModifier(eResearchTech)) / 100);
}


int CvPlayer::calculateGoldRate() const
{
	int iRate = 0;

	if (isCommerceFlexible(COMMERCE_RESEARCH))
	{
		iRate = calculateBaseNetGold();
	}
	else
	{
		iRate = std::min(0, (calculateBaseNetResearch() + calculateBaseNetGold()));
	}

	//Afforess: tributes
	iRate += calculateTributeReceived();
	iRate -= calculateTributePayment();
	iRate += calculateTotalForeignConnectednessSeized();
	//Afforess end

	return iRate;
}


int CvPlayer::calculateResearchRate(TechTypes eTech) const
{
	int iRate = 0;

	if (isCommerceFlexible(COMMERCE_RESEARCH))
	{
		iRate = calculateBaseNetResearch(eTech);
	}
	else
	{
		iRate = std::max(1, (calculateBaseNetResearch(eTech) + calculateBaseNetGold()));
	}

	return iRate;
}

int CvPlayer::calculateTotalCommerce() const
{
	int iTotalCommerce = calculateBaseNetGold() + calculateBaseNetResearch();

	for (int i = 0; i < NUM_COMMERCE_TYPES; ++i)
	{
		if (COMMERCE_GOLD != i && COMMERCE_RESEARCH != i)
		{
			iTotalCommerce += getCommerceRate((CommerceTypes)i);
		}
	}

	return iTotalCommerce;
}

bool CvPlayer::isResearch() const
{
	if(GC.getUSE_IS_PLAYER_RESEARCH_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		long lResult;
		argsList.add(getID());
		lResult = 1;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "isPlayerResearch", argsList.makeFunctionArgs(), &lResult);
		if (lResult == 0)
		{
			return false;
		}
	}

	if (!isFoundedFirstCity())
	{
		return false;
	}

	return true;
}


bool CvPlayer::canEverResearch(TechTypes eTech) const
{
	if (GC.getTechInfo(eTech).isDisable())
	{
		return false;
	}

	if (GC.getCivilizationInfo(getCivilizationType()).isCivilizationDisableTechs(eTech))
	{
		return false;
	}
/************************************************************************************************/
/* Afforess	                  Start		 04/01/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (!GC.getGameINLINE().canEverResearch(eTech))
	{
		return false;
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	if(GC.getUSE_CANNOT_RESEARCH_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		argsList.add(getID());
		argsList.add(eTech);
		argsList.add(false);
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "cannotResearch", argsList.makeFunctionArgs(), &lResult);
		if (lResult == 1)
		{
			return false;
		}
	}

	return true;
}


bool CvPlayer::canResearch(TechTypes eTech, bool bTrade) const
{
	bool bFoundPossible;
	bool bFoundValid;
	int iI;

	if(GC.getUSE_CAN_RESEARCH_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		argsList.add(getID());
		argsList.add(eTech);
		argsList.add(bTrade);
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "canResearch", argsList.makeFunctionArgs(), &lResult);
		if (lResult == 1)
		{
			return true;
		}
	}

	if (!isResearch() && getAdvancedStartPoints() < 0)
	{
		return false;
	}

	if (GET_TEAM(getTeam()).isHasTech(eTech))
	{
		return false;
	}

	bFoundPossible = false;
	bFoundValid = false;

	for (iI = 0; iI < GC.getNUM_OR_TECH_PREREQS(); iI++)
	{
		TechTypes ePrereq = (TechTypes)GC.getTechInfo(eTech).getPrereqOrTechs(iI);
		if (ePrereq != NO_TECH)
		{
			bFoundPossible = true;

			if (GET_TEAM(getTeam()).isHasTech(ePrereq))
			{
				if (!bTrade || GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_BROKERING) || !GET_TEAM(getTeam()).isNoTradeTech(ePrereq))
				{
					bFoundValid = true;
					break;
				}
			}
		}
	}

	if (bFoundPossible && !bFoundValid)
	{
		return false;
	}

	for (iI = 0; iI < GC.getNUM_AND_TECH_PREREQS(); iI++)
	{
		TechTypes ePrereq = (TechTypes)GC.getTechInfo(eTech).getPrereqAndTechs(iI);
		if (ePrereq != NO_TECH)
		{
			if (!GET_TEAM(getTeam()).isHasTech(ePrereq))
			{
				return false;
			}
			
			if (bTrade && !GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_BROKERING) && GET_TEAM(getTeam()).isNoTradeTech(ePrereq))
			{
				return false;
			}
		}
	}

	if (!canEverResearch(eTech))
	{
		return false;
	}

/************************************************************************************************/
/* Afforess	                  Start		 04/01/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (!hasValidBuildings(eTech))
	{
		return false;
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	return true;
}


TechTypes CvPlayer::getCurrentResearch() const
{
	CLLNode<TechTypes>* pResearchNode;

	pResearchNode = headResearchQueueNode();

	if (pResearchNode != NULL)
	{
		return pResearchNode->m_data;
	}
	else
	{
		return NO_TECH;
	}
}


bool CvPlayer::isCurrentResearchRepeat() const
{
	TechTypes eCurrentResearch;

	eCurrentResearch = getCurrentResearch();

	if (eCurrentResearch == NO_TECH)
	{
		return false;
	}

	return GC.getTechInfo(eCurrentResearch).isRepeat();
}


bool CvPlayer::isNoResearchAvailable() const
{
	int iI;

	if (getCurrentResearch() != NO_TECH)
	{
		return false;
	}

	for (iI = 0; iI < GC.getNumTechInfos(); iI++)
	{
		if (canResearch((TechTypes)iI))
		{
			return false;
		}
	}

	return true;
}


int CvPlayer::getResearchTurnsLeft(TechTypes eTech, bool bOverflow) const
{
	int iTurnsLeft = getResearchTurnsLeftTimes100(eTech, bOverflow);

	iTurnsLeft = (iTurnsLeft + 99) / 100; // round up

	return std::max(1, iTurnsLeft);
}

int CvPlayer::getResearchTurnsLeftTimes100(TechTypes eTech, bool bOverflow) const
{
    int iResearchRate;
	int iOverflow;
	int iResearchLeft;
	int iTurnsLeft;
	int iI;

	iResearchRate = 0;
	iOverflow = 0;

	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam())
			{
				if ((iI == getID()) || (GET_PLAYER((PlayerTypes)iI).getCurrentResearch() == eTech))
				{
					iResearchRate += GET_PLAYER((PlayerTypes)iI).calculateResearchRate(eTech);
					iOverflow += (GET_PLAYER((PlayerTypes)iI).getOverflowResearch() * calculateResearchModifier(eTech)) / 100;
				}
			}
		}
	}

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      03/18/10                                jdog5000      */
/*                                                                                              */
/* Tech AI                                                                                      */
/************************************************************************************************/
	// Mainly just so debug display shows sensible value
	iResearchLeft = GET_TEAM(getTeam()).getResearchLeft(eTech);
	
	if (bOverflow)
	{
		iResearchLeft -= iOverflow;
	}
	
	int iMultiplier;

	if ( iResearchLeft < MAX_INT/100 )
	{
		iResearchLeft *= 100;
		iMultiplier = 1;
	}
	else
	{
		iMultiplier = 100;
	}

	if (iResearchRate == 0)
	{
		return iResearchLeft;
	}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

	iTurnsLeft = (iResearchLeft / iResearchRate);

	if (iTurnsLeft * iResearchRate < iResearchLeft)
	{
		++iTurnsLeft;
	}

	if ( iTurnsLeft < MAX_INT/iMultiplier )
	{
		iTurnsLeft *= iMultiplier;
	}
	else
	{
		iTurnsLeft = MAX_INT;
	}

	return std::max(1, iTurnsLeft);
}


bool CvPlayer::isCivic(CivicTypes eCivic) const
{
	int iI;

	for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		if (getCivics((CivicOptionTypes)iI) == eCivic)
		{
			return true;
		}
	}

	return false;
}


bool CvPlayer::canDoCivics(CivicTypes eCivic) const
{
	PROFILE_FUNC();

/************************************************************************************************/
/* UNOFFICIAL_PATCH                       02/16/10                                jdog5000      */
/*                                                                                              */
/* Bugfix                                                                                       */
/************************************************************************************************/
	// Circumvents second crash bug in simultaneous turns MP games
	if( eCivic == NO_CIVIC )
	{
		return true;
	}
/************************************************************************************************/
/* UNOFFICIAL_PATCH                        END                                                  */
/************************************************************************************************/	

	if (GC.getGameINLINE().isForceCivicOption((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType())))
	{
		return GC.getGameINLINE().isForceCivic(eCivic);
	}
/************************************************************************************************/
/* Afforess	                  Start		 5/28/11                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (!isBarbarian() && GC.getCivicInfo(eCivic).getCityLimit(getID()) > 0 && GC.getCivicInfo(eCivic).getCityOverLimitUnhappy() == 0) {
		if (GC.getCivicInfo(eCivic).getCityLimit(getID()) < getNumCities()) {
			return false;
		}
	}
/************************************************************************************************/
/* Afforess	                  End		 5/28/11                                                */
/************************************************************************************************/
	if(GC.getUSE_CAN_DO_CIVIC_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		argsList.add(getID());
		argsList.add(eCivic);
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "canDoCivic", argsList.makeFunctionArgs(), &lResult);
		if (lResult == 1)
		{
			return true;
		}
	}

	if (!isHasCivicOption((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType())) && !(GET_TEAM(getTeam()).isHasTech((TechTypes)(GC.getCivicInfo(eCivic).getTechPrereq()))))
	{
		return false;
	}

	if(GC.getUSE_CANNOT_DO_CIVIC_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList2; // XXX
		argsList2.add(getID());
		argsList2.add(eCivic);
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "cannotDoCivic", argsList2.makeFunctionArgs(), &lResult);
		if (lResult == 1)
		{
			return false;
		}
	}

	return true;
}


bool CvPlayer::canRevolution(CivicTypes* paeNewCivics) const
{
	int iI;

	if (isAnarchy())
	{
		return false;
	}

	if (getRevolutionTimer() > 0)
	{
		return false;
	}

	if (paeNewCivics == NULL)
	{
		// XXX is this necessary?
		for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
		{
			if (canDoCivics((CivicTypes)iI))
			{
				if (getCivics((CivicOptionTypes)GC.getCivicInfo((CivicTypes) iI).getCivicOptionType()) != iI)
				{
					return true;
				}
			}
		}
	}
	else
	{
		for (iI = 0; iI < GC.getNumCivicOptionInfos(); ++iI)
		{
			if (GC.getGameINLINE().isForceCivicOption((CivicOptionTypes)iI))
			{
				if (!GC.getGameINLINE().isForceCivic(paeNewCivics[iI]))
				{
					return false;
				}
			}

			if (getCivics((CivicOptionTypes)iI) != paeNewCivics[iI])
			{
				return true;
			}
		}
	}

	return false;
}


void CvPlayer::revolution(CivicTypes* paeNewCivics, bool bForce)
{
	int iAnarchyLength;
	int iI;
	int iCivicChanges = 0;

	if (!bForce && !canRevolution(paeNewCivics))
	{
		return;
	}

// BUG - Revolution Event - start
	CivicTypes* paeOldCivics = new CivicTypes[GC.getNumCivicOptionInfos()];

	for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		paeOldCivics[iI] = getCivics(((CivicOptionTypes)iI));
	}
// BUG - Revolution Event - end

	iAnarchyLength = getCivicAnarchyLength(paeNewCivics);

	if (iAnarchyLength > 0)
	{
		changeAnarchyTurns(iAnarchyLength);
	}

	for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		if ( paeOldCivics[iI] != paeNewCivics[iI] )
		{
			iCivicChanges++;
			if ( gPlayerLogLevel > 0)
			{
				logBBAI("Player %S switches from %S to %S",
						getCivilizationDescription(0),
						GC.getCivicInfo(paeOldCivics[iI]).getDescription(),
						GC.getCivicInfo(paeNewCivics[iI]).getDescription());
			}

			setCivics(((CivicOptionTypes)iI), paeNewCivics[iI]);

			civcSwitchInstance	switchInstance;

			switchInstance.iTurn = GC.getGameINLINE().getGameTurn();
			switchInstance.eFromCivic = paeOldCivics[iI];
			switchInstance.eToCivic = paeNewCivics[iI];
			switchInstance.bNoAnarchy = (iAnarchyLength == 0);
			m_civicSwitchHistory.push_back(switchInstance);
		}
	}

	NoteCivicsSwitched(iCivicChanges);

	setRevolutionTimer(std::max(1, ((100 + getAnarchyModifier()) * GC.getDefineINT("MIN_REVOLUTION_TURNS")) / 100) + iAnarchyLength);

	if (getID() == GC.getGameINLINE().getActivePlayer())
	{
		gDLL->getInterfaceIFace()->setDirty(Popup_DIRTY_BIT, true); // to force an update of the civic chooser popup
	}

// BUG - Revolution Event - start
	CvEventReporter::getInstance().playerRevolution(getID(), iAnarchyLength, paeOldCivics, paeNewCivics);
	delete [] paeOldCivics;
// BUG - Revolution Event - end
}


int CvPlayer::getCivicPercentAnger(CivicTypes eCivic, bool bIgnore) const
{
	int iCount;
	int iPossibleCount;
	int iI;

	if (GC.getCivicInfo(eCivic).getCivicPercentAnger() == 0)
	{
		return 0;
	}

	if (!bIgnore && (getCivics((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType())) == eCivic))
	{
		return 0;
	}

	iCount = 0;
	iPossibleCount = 0;

	for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() != getTeam())
			{
				if (GET_PLAYER((PlayerTypes)iI).getCivics((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType())) == eCivic)
				{
					iCount += GET_PLAYER((PlayerTypes)iI).getNumCities();
				}

				iPossibleCount += GET_PLAYER((PlayerTypes)iI).getNumCities();
			}
		}
	}

	if (iPossibleCount == 0)
	{
		return 0;
	}

	return ((GC.getCivicInfo(eCivic).getCivicPercentAnger() * iCount) / iPossibleCount);
}


bool CvPlayer::canDoReligion(ReligionTypes eReligion) const
{
	if (GET_TEAM(getTeam()).getHasReligionCount(eReligion) == 0)
	{
		return false;
	}

	return true;
}


bool CvPlayer::canChangeReligion() const
{
	int iI;

	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		if (canConvert((ReligionTypes)iI))
		{
			return true;
		}
	}

	return false;
}


bool CvPlayer::canConvert(ReligionTypes eReligion) const
{
	if (isBarbarian())
	{
		return false;
	}

	if (isAnarchy())
	{
		return false;
	}

	if (getConversionTimer() > 0)
	{
		return false;
	}

	if (!isStateReligion())
	{
		return false;
	}

	if (getLastStateReligion() == eReligion)
	{
		return false;
	}

	if (eReligion != NO_RELIGION)
	{
		if (!canDoReligion(eReligion))
		{
			return false;
		}
	}

	return true;
}


void CvPlayer::convert(ReligionTypes eReligion)
{
	int iAnarchyLength;

	if (!canConvert(eReligion))
	{
		return;
	}

	iAnarchyLength = getReligionAnarchyLength();

	changeAnarchyTurns(iAnarchyLength);

	setLastStateReligion(eReligion);

	setConversionTimer(std::max(1, ((100 + getAnarchyModifier()) * GC.getDefineINT("MIN_CONVERSION_TURNS")) / 100) + iAnarchyLength);
}


bool CvPlayer::hasHolyCity(ReligionTypes eReligion) const
{
	CvCity* pHolyCity;

	FAssertMsg(eReligion != NO_RELIGION, "Religion is not assigned a valid value");

	pHolyCity = GC.getGameINLINE().getHolyCity(eReligion);

	if (pHolyCity != NULL)
	{
		return (pHolyCity->getOwnerINLINE() == getID());
	}

	return false;
}


/************************************************************************************************/
/* REVDCM                                 04/29/10                                phungus420    */
/*                                                                                              */
/* Player Functions                                                                             */
/************************************************************************************************/
bool CvPlayer::hasHolyCity() const
{
	ReligionTypes eLoopReligion;
	int iI;
	
	for(iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		eLoopReligion = ReligionTypes(iI);
		if(hasHolyCity(eLoopReligion))
		{
			return true;
		}
	}

	return false;
}


bool CvPlayer::hasStateReligionHolyCity() const
{
	ReligionTypes eStateReligion = getStateReligion();
	if(eStateReligion == NO_RELIGION)
	{
		return false;
	}

	if(hasHolyCity(eStateReligion))
	{
		return true;
	}
	return false;
}


bool CvPlayer::hasStateReligionShrine() const
{
	ReligionTypes eStateReligion = getStateReligion();
	CvCity* pHolyCity;

	if(eStateReligion == NO_RELIGION)
	{
		return false;
	}

	pHolyCity = GC.getGameINLINE().getHolyCity(eStateReligion);

	if (pHolyCity != NULL)
	{
		if( pHolyCity->hasShrine(eStateReligion))
		{
			return (pHolyCity->getOwnerINLINE() == getID());
		}
	}
	return false;
}
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/

int CvPlayer::countHolyCities() const
{
	int iCount;
	int iI;

	iCount = 0;

	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		if (hasHolyCity((ReligionTypes)iI))
		{
			iCount++;
		}
	}

	return iCount;
}


void CvPlayer::foundReligion(ReligionTypes eReligion, ReligionTypes eSlotReligion, bool bAward)
{
	CvCity* pLoopCity;
	CvCity* pBestCity;
	UnitTypes eFreeUnit;
	bool bStarting;
	int iValue;
	int iBestValue;
	int iLoop;

/************************************************************************************************/
/* RevDCM	                  Start		 4/29/10                                                */
/*                                                                                              */
/* OC_LIMITED_RELIGIONS                                                                         */
/************************************************************************************************/
	FAssert(NO_RELIGION != eReligion);
	FAssert(canFoundReligion());
	FAssert(!(isBarbarian()));
	if( (NO_RELIGION == eReligion) || !(canFoundReligion()) )
	{
		return;
	}
	TechTypes eIndex = TechTypes(GC.getReligionInfo(eSlotReligion).getTechPrereq());
	FAssert(!GC.getGameINLINE().isReligionSlotTaken(eSlotReligion));
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/
	if (GC.getGameINLINE().isReligionFounded(eReligion))
	{
		if (isHuman())
		{
			CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_FOUND_RELIGION, eSlotReligion);
			if (NULL != pInfo)
			{
				gDLL->getInterfaceIFace()->addPopup(pInfo, getID());
			}
		}
		else
		{
			foundReligion(AI_chooseReligion(), eSlotReligion, bAward);
		}

		return;
	}

/************************************************************************************************/
/* RevDCM	                  Start		 4/29/10                                                */
/*                                                                                              */
/* OC_LIMITED_RELIGIONS                                                                         */
/************************************************************************************************/
	bStarting = ( (GC.getReligionInfo(eSlotReligion).getTechPrereq() == NO_TECH)
		|| GC.getGameINLINE().isGameStart() );
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/

	iBestValue = 0;
	pBestCity = NULL;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (!bStarting || !(pLoopCity->isHolyCity()))
		{
			iValue = 10;
			iValue += pLoopCity->getPopulation();
			iValue += GC.getGameINLINE().getSorenRandNum(GC.getDefineINT("FOUND_RELIGION_CITY_RAND"), "Found Religion");

			iValue /= (pLoopCity->getReligionCount() + 1);

			if (pLoopCity->isCapital())
			{
				iValue /= 8;
			}

			iValue = std::max(1, iValue);

			if (iValue > iBestValue)
			{
				iBestValue = iValue;
				pBestCity = pLoopCity;
			}
		}
		
	}

	if (pBestCity != NULL)
	{
/************************************************************************************************/
/* RevDCM	                  Start		 4/29/10                                                */
/*                                                                                              */
/* OC_LIMITED_RELIGIONS                                                                         */
/************************************************************************************************/
		GC.getGameINLINE().setReligionSlotTaken(eSlotReligion, true);
		GC.getGameINLINE().setTechCanFoundReligion(eIndex, true);
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/

		GC.getGameINLINE().setHolyCity(eReligion, pBestCity, true);

		if (bAward)
		{
			if (GC.getReligionInfo(eSlotReligion).getNumFreeUnits() > 0)
			{
				UnitClassTypes eFreeUnitClass = (UnitClassTypes)GC.getReligionInfo(eReligion).getFreeUnitClass();

				if ( eFreeUnitClass != NO_UNITCLASS )
				{
					eFreeUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(eFreeUnitClass)));

					if (eFreeUnit != NO_UNIT)
					{
						for (int i = 0; i < GC.getReligionInfo(eSlotReligion).getNumFreeUnits(); ++i)
						{
							initUnit(eFreeUnit, pBestCity->getX_INLINE(), pBestCity->getY_INLINE(), NO_UNITAI, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
						}
					}
				}
			}
		}
	}
}


bool CvPlayer::hasHeadquarters(CorporationTypes eCorporation) const
{
	CvCity* pHeadquarters = GC.getGameINLINE().getHeadquarters(eCorporation);

	FAssert(eCorporation != NO_CORPORATION);

	if (pHeadquarters != NULL)
	{
		return (pHeadquarters->getOwnerINLINE() == getID());
	}

	return false;
}


int CvPlayer::countHeadquarters() const
{
	int iCount = 0;

	for (int iI = 0; iI < GC.getNumCorporationInfos(); iI++)
	{
		if (hasHeadquarters((CorporationTypes)iI))
		{
			iCount++;
		}
	}

	return iCount;
}


int CvPlayer::countCorporations(CorporationTypes eCorporation) const
{
	int iCount = 0;

	int iLoop;
	for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->isHasCorporation(eCorporation))
		{
			++iCount;
		}
	}

	return iCount;
}


void CvPlayer::foundCorporation(CorporationTypes eCorporation)
{
	CvCity* pLoopCity;
	CvCity* pBestCity;
	bool bStarting;
	int iValue;
	int iBestValue;
	int iLoop;

	if (GC.getGameINLINE().isCorporationFounded(eCorporation))
	{
		return;
	}

	bStarting = ((GC.getCorporationInfo(eCorporation).getTechPrereq() == NO_TECH) || (GC.getTechInfo((TechTypes) GC.getCorporationInfo(eCorporation).getTechPrereq()).getEra() < GC.getGameINLINE().getStartEra()));

	iBestValue = 0;
	pBestCity = NULL;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (!bStarting || !(pLoopCity->isHeadquarters()))
		{
			iValue = 10;
			iValue += pLoopCity->getPopulation();

			for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
			{
				if (NO_BONUS != GC.getCorporationInfo(eCorporation).getPrereqBonus(i))
				{
					iValue += 10 * pLoopCity->getNumBonuses((BonusTypes)GC.getCorporationInfo(eCorporation).getPrereqBonus(i));
				}
			}

			iValue += GC.getGameINLINE().getSorenRandNum(GC.getDefineINT("FOUND_CORPORATION_CITY_RAND"), "Found Corporation");

			iValue /= (pLoopCity->getCorporationCount() + 1);

			iValue = std::max(1, iValue);

			if (iValue > iBestValue)
			{
				iBestValue = iValue;
				pBestCity = pLoopCity;
			}
		}
	}

	if (pBestCity != NULL)
	{
		pBestCity->setHeadquarters(eCorporation);
	}
}


int CvPlayer::getCivicAnarchyLength(CivicTypes* paeNewCivics) const
{
	bool bChange;
	int iAnarchyLength;
	int iI;

	if (getMaxAnarchyTurns() == 0)
	{
		return 0;
	}

	if (isGoldenAge())
	{
		return 0;
	}

	iAnarchyLength = 0;

	bChange = false;

	for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		if (paeNewCivics[iI] != getCivics((CivicOptionTypes)iI))
		{
			iAnarchyLength += GC.getCivicInfo(paeNewCivics[iI]).getAnarchyLength();

			bChange = true;
		}
	}

	if (bChange)
	{
		iAnarchyLength += GC.getDefineINT("BASE_CIVIC_ANARCHY_LENGTH");

		iAnarchyLength += ((getNumCities() * GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getNumCitiesAnarchyPercent()) / 100);
	}

	iAnarchyLength = ((iAnarchyLength * std::max(0, (getAnarchyModifier() + 100))) / 100);

	if (iAnarchyLength == 0)
	{
		return 0;
	}

	iAnarchyLength *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent();
	iAnarchyLength /= 100;

	iAnarchyLength *= GC.getEraInfo(GC.getGameINLINE().getStartEra()).getAnarchyPercent();
	iAnarchyLength /= 100;

/************************************************************************************************/
/* REVOLUTION_MOD                         02/01/08                                jdog5000      */
/*                                                                                              */
/* Rebels suffer less civic switch anarchy                                                      */
/************************************************************************************************/
	if( isRebel() )
		iAnarchyLength /= 2;
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

	return range(iAnarchyLength, 1, getMaxAnarchyTurns());
}


int CvPlayer::getReligionAnarchyLength() const
{
	int iAnarchyLength;

	if (getMaxAnarchyTurns() == 0)
	{
		return 0;
	}

	if (isGoldenAge())
	{
		return 0;
	}

	iAnarchyLength = GC.getDefineINT("BASE_RELIGION_ANARCHY_LENGTH");

	iAnarchyLength += ((getNumCities() * GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getNumCitiesAnarchyPercent()) / 100);

	iAnarchyLength = ((iAnarchyLength * std::max(0, (getAnarchyModifier() + 100))) / 100);

	if (iAnarchyLength == 0)
	{
		return 0;
	}

	iAnarchyLength *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent();
	iAnarchyLength /= 100;

	iAnarchyLength *= GC.getEraInfo(GC.getGameINLINE().getStartEra()).getAnarchyPercent();
	iAnarchyLength /= 100;

	return range(iAnarchyLength, 1, getMaxAnarchyTurns());
}



int CvPlayer::unitsRequiredForGoldenAge() const
{
	return (GC.getDefineINT("BASE_GOLDEN_AGE_UNITS") + (getNumUnitGoldenAges() * GC.getDefineINT("GOLDEN_AGE_UNITS_MULTIPLIER")));
}


int CvPlayer::unitsGoldenAgeCapable() const
{
	CvUnit* pLoopUnit;
	int iCount;
	int iLoop;

	iCount = 0;

	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		if (pLoopUnit->isGoldenAge())
		{
			iCount++;
		}
	}

	return iCount;
}


int CvPlayer::unitsGoldenAgeReady() const
{
	PROFILE_FUNC();

	CvUnit* pLoopUnit;
	bool* pabUnitUsed;
	int iCount;
	int iLoop;
	int iI;

	pabUnitUsed = new bool[GC.getNumUnitInfos()];

	for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
	{
		pabUnitUsed[iI] = false;
	}

	iCount = 0;

	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		if (!(pabUnitUsed[pLoopUnit->getUnitType()]))
		{
		if (pLoopUnit->isGoldenAge())
		{
				pabUnitUsed[pLoopUnit->getUnitType()] = true;
				iCount++;
			}
		}
	}

	SAFE_DELETE_ARRAY(pabUnitUsed);

	return iCount;
}


void CvPlayer::killGoldenAgeUnits(CvUnit* pUnitAlive)
{
	CvUnit* pLoopUnit;
	CvUnit* pBestUnit;
	bool* pabUnitUsed;
	int iUnitsRequired;
	int iValue;
	int iBestValue;
	int iLoop;
	int iI;

	pabUnitUsed = new bool[GC.getNumUnitInfos()];

	for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
	{
		pabUnitUsed[iI] = false;
	}

	iUnitsRequired = unitsRequiredForGoldenAge();

	if (pUnitAlive != NULL)
	{
		pabUnitUsed[pUnitAlive->getUnitType()] = true;
		iUnitsRequired--;
	}

	for (iI = 0; iI < iUnitsRequired; iI++)
	{
		iBestValue = 0;
		pBestUnit = NULL;

		for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if (pLoopUnit->isGoldenAge())
			{
				if (!(pabUnitUsed[pLoopUnit->getUnitType()]))
				{
					iValue = 10000;

					iValue /= (plotDistance(pLoopUnit->getX_INLINE(), pLoopUnit->getY_INLINE(), pUnitAlive->getX_INLINE(), pUnitAlive->getY_INLINE()) + 1);

					if (iValue > iBestValue)
					{
						iBestValue = iValue;
						pBestUnit = pLoopUnit;
					}
				}
			}
		}

		FAssert(pBestUnit != NULL);
		if (pBestUnit != NULL)
		{
			pabUnitUsed[pBestUnit->getUnitType()] = true;

			pBestUnit->kill(true);

			//play animations
			if (pBestUnit->plot()->isActiveVisible(false))
			{
				//kill removes bestUnit from any groups
				pBestUnit->getGroup()->pushMission(MISSION_GOLDEN_AGE, 0);
			}
		}
	}

	SAFE_DELETE_ARRAY(pabUnitUsed);
}


int CvPlayer::greatPeopleThreshold(bool bMilitary) const
{
	int iThreshold;

	if (bMilitary)
	{
		iThreshold = ((GC.getDefineINT("GREAT_GENERALS_THRESHOLD") * std::max(0, (getGreatGeneralsThresholdModifier() + 100))) / 100);
	}
	else
	{
		iThreshold = ((GC.getDefineINT("GREAT_PEOPLE_THRESHOLD") * std::max(0, (getGreatPeopleThresholdModifier() + 100))) / 100);
	}

	iThreshold *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGreatPeoplePercent();
	if (bMilitary)
	{
		iThreshold /= std::max(1, GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent());
	}
	else
	{
		iThreshold /= 100;
	}

	iThreshold *= GC.getEraInfo(GC.getGameINLINE().getStartEra()).getGreatPeoplePercent();
	iThreshold /= 100;


	return std::max(1, iThreshold);
}


int CvPlayer::specialistYield(SpecialistTypes eSpecialist, YieldTypes eYield) const
{
/************************************************************************************************/
/* Afforess	                  Start		 07/20/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
	return (GC.getSpecialistInfo(eSpecialist).getYieldChange(eYield) + getSpecialistExtraYield(eSpecialist, eYield));
*/
	return (GC.getSpecialistInfo(eSpecialist).getYieldChange(eYield) + getExtraSpecialistYield(eSpecialist, eYield) + getSpecialistExtraYield(eYield) + (getSpecialistYieldPercentChanges(eSpecialist, eYield) / 100));
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
}


int CvPlayer::specialistCommerce(SpecialistTypes eSpecialist, CommerceTypes eCommerce) const
{
	return specialistCommerceTimes100(eSpecialist, eCommerce)/100;
}

int CvPlayer::specialistCommerceTimes100(SpecialistTypes eSpecialist, CommerceTypes eCommerce) const
{
/************************************************************************************************/
/* Afforess	                  Start		 07/20/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
	return (GC.getSpecialistInfo(eSpecialist).getCommerceChange(eCommerce) + getSpecialistExtraCommerce(eCommerce));
*/
	return (100*GC.getSpecialistInfo(eSpecialist).getCommerceChange(eCommerce) + 100*getExtraSpecialistCommerce(eSpecialist, eCommerce) + 100*getSpecialistExtraCommerce(eCommerce) + (getSpecialistCommercePercentChanges(eSpecialist, eCommerce)));
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
}

CvPlot* CvPlayer::getStartingPlot() const
{
	return GC.getMapINLINE().plotSorenINLINE(m_iStartingX, m_iStartingY);
}


void CvPlayer::setStartingPlot(CvPlot* pNewValue, bool bUpdateStartDist)
{
	CvPlot* pOldStartingPlot;

	pOldStartingPlot = getStartingPlot();

	if (pOldStartingPlot != pNewValue)
	{
		if (pOldStartingPlot != NULL)
		{
			pOldStartingPlot->area()->changeNumStartingPlots(-1);

			if (bUpdateStartDist)
			{
				GC.getMapINLINE().updateMinOriginalStartDist(pOldStartingPlot->area());
			}
		}

		if (pNewValue == NULL)
		{
			m_iStartingX = INVALID_PLOT_COORD;
			m_iStartingY = INVALID_PLOT_COORD;
		}
		else
		{
			m_iStartingX = pNewValue->getX_INLINE();
			m_iStartingY = pNewValue->getY_INLINE();

			getStartingPlot()->area()->changeNumStartingPlots(1);

			if (bUpdateStartDist)
			{
				GC.getMapINLINE().updateMinOriginalStartDist(getStartingPlot()->area());
			}
		}
	}
}


int CvPlayer::getTotalPopulation() const
{
	return m_iTotalPopulation;
}


int CvPlayer::getAveragePopulation() const
{
	if (getNumCities() == 0)
	{
		return 0;
	}

	return ((getTotalPopulation() / getNumCities()) + 1);
}


void CvPlayer::changeTotalPopulation(int iChange)
{
	changeAssets(-(getPopulationAsset(getTotalPopulation())));
	changePower(-(getPopulationPower(getTotalPopulation())));
	changePopScore(-(getPopulationScore(getTotalPopulation())));

	m_iTotalPopulation = (m_iTotalPopulation + iChange);
	FAssert(getTotalPopulation() >= 0);

	changeAssets(getPopulationAsset(getTotalPopulation()));
	changePower(getPopulationPower(getTotalPopulation()));
	changePopScore(getPopulationScore(getTotalPopulation()));
}


long CvPlayer::getRealPopulation() const
{
	CvCity* pLoopCity;
	__int64 iTotalPopulation = 0;
	int iLoop = 0;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iTotalPopulation += pLoopCity->getRealPopulation();
	}

	if (iTotalPopulation > MAX_INT)
	{
		iTotalPopulation = MAX_INT;
	}

	return ((long)(iTotalPopulation));
}


int CvPlayer::getTotalLand() const
{
	return m_iTotalLand;
}


void CvPlayer::changeTotalLand(int iChange)
{
	m_iTotalLand = (m_iTotalLand + iChange);
	FAssert(getTotalLand() >= 0);
}


int CvPlayer::getTotalLandScored() const
{
	return m_iTotalLandScored;
}


void CvPlayer::changeTotalLandScored(int iChange)
{
	if (iChange != 0)
	{
		changeAssets(-(getLandPlotsAsset(getTotalLandScored())));
		changeLandScore(-(getLandPlotsScore(getTotalLandScored())));

		m_iTotalLandScored = (m_iTotalLandScored + iChange);
		FAssert(getTotalLandScored() >= 0);

		changeAssets(getLandPlotsAsset(getTotalLandScored()));
		changeLandScore(getLandPlotsScore(getTotalLandScored()));
	}
}


int CvPlayer::getGold() const
{
	return m_iGold;
}


void CvPlayer::setGold(int iNewValue)
{
	if (getGold() != iNewValue)
	{
		m_iGold = iNewValue;

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(MiscButtons_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(SelectionButtons_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}

void CvPlayer::changeGold(int iChange)
{
	setGold(getGold() + iChange);
}

int CvPlayer::getGoldPerTurn() const
{
	return m_iGoldPerTurn;
}

int CvPlayer::getAdvancedStartPoints() const
{
	return m_iAdvancedStartPoints;
}


void CvPlayer::setAdvancedStartPoints(int iNewValue)
{
	if (getAdvancedStartPoints() != iNewValue)
	{
		m_iAdvancedStartPoints = iNewValue;

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(MiscButtons_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(SelectionButtons_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}

void CvPlayer::changeAdvancedStartPoints(int iChange)
{
	setAdvancedStartPoints(getAdvancedStartPoints() + iChange);
}


int CvPlayer::getGoldenAgeTurns() const																		 
{
	return m_iGoldenAgeTurns;
}


bool CvPlayer::isGoldenAge() const																					 
{
	return (getGoldenAgeTurns() > 0);
}

void CvPlayer::reportGoldenAgeStart()
{
	CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_GOLDEN_AGE_BEGINS", getNameKey());
	GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szBuffer, -1, -1, (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));

	CvEventReporter::getInstance().goldenAge(getID());
}

void CvPlayer::changeGoldenAgeTurns(int iChange)
{
	CvWString szBuffer;
	bool bOldGoldenAge;
	int iI;

	if (iChange != 0)
	{
		bOldGoldenAge = isGoldenAge();

		m_iGoldenAgeTurns = (m_iGoldenAgeTurns + iChange);
		FAssert(getGoldenAgeTurns() >= 0);

		if (bOldGoldenAge != isGoldenAge())
		{
			if (isGoldenAge())
			{
				changeAnarchyTurns(-getAnarchyTurns());
				((CvPlayerAI*)this)->AI_startGoldenAge();
			}

			updateYield();

			if (isGoldenAge())
			{
				if ( m_bUpdatesDeferred )
				{
					m_bGoldenAgeStarted = true;
				}
				else
				{
					reportGoldenAgeStart();
				}
			}
			else
			{
				CvEventReporter::getInstance().endGoldenAge(getID());
			}

			for (iI = 0; iI < MAX_PLAYERS; iI++)
			{
				if (GET_PLAYER((PlayerTypes)iI).isAlive())
				{
					if (GET_TEAM(getTeam()).isHasMet(GET_PLAYER((PlayerTypes)iI).getTeam()))
					{
						MEMORY_TRACK_EXEMPT();

						if (isGoldenAge())
						{
							szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_GOLDEN_AGE_HAS_BEGUN", getNameKey());
							AddDLLMessage(((PlayerTypes)iI), (((PlayerTypes)iI) == getID()), GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_GOLDAGESTART", MESSAGE_TYPE_MAJOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));
						}
						else
						{
							szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_GOLDEN_AGE_ENDED", getNameKey());
							AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_GOLDAGEEND", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));
						}
					}
				}
			}
		}

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}

int CvPlayer::getGoldenAgeLength() const	
{
	return (GC.getGameINLINE().goldenAgeLength() * std::max(0, 100 + getGoldenAgeModifier())) / 100;
}

int CvPlayer::getNumUnitGoldenAges() const																			 
{
	return m_iNumUnitGoldenAges;
}


void CvPlayer::changeNumUnitGoldenAges(int iChange)												 
{
	m_iNumUnitGoldenAges = (m_iNumUnitGoldenAges + iChange);
	FAssert(getNumUnitGoldenAges() >= 0);
}


int CvPlayer::getStrikeTurns() const
{
	return m_iStrikeTurns;
}


void CvPlayer::changeStrikeTurns(int iChange)
{
	m_iStrikeTurns = (m_iStrikeTurns + iChange);
	FAssert(getStrikeTurns() >= 0);
}


int CvPlayer::getAnarchyTurns() const																			
{
	return m_iAnarchyTurns;
}


bool CvPlayer::isAnarchy() const																						
{
	return (getAnarchyTurns() > 0);
}

/************************************************************************************************/
/* Afforess	                  Start		 01/12/10                                               */
/*                                                                                              */
/*      Added new Parameter                                                                     */
/************************************************************************************************/
void CvPlayer::changeAnarchyTurns(int iChange, bool bHideMessages)
{
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	bool bOldAnarchy;

	if (iChange != 0)
	{
		bOldAnarchy = isAnarchy();

		m_iAnarchyTurns = (m_iAnarchyTurns + iChange);
		FAssert(getAnarchyTurns() >= 0);

		if (bOldAnarchy != isAnarchy())
		{
			setCommerceDirty();
			setMaintenanceDirty(true);
			updateTradeRoutes();
			updateCorporation();

			AI_makeAssignWorkDirty();
/************************************************************************************************/
/* Afforess	                  Start		 01/12/10                                               */
/*                                                                                              */
/*     Added new Parameter                                                                      */
/************************************************************************************************/
			if (isAnarchy() && !bHideMessages)
			{
				MEMORY_TRACK_EXEMPT();

				AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), gDLL->getText("TXT_KEY_MISC_REVOLUTION_HAS_BEGUN").GetCString(), "AS2D_REVOLTSTART", MESSAGE_TYPE_MAJOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));
			}
			else if (!bHideMessages)
			{
				MEMORY_TRACK_EXEMPT();

				AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), gDLL->getText("TXT_KEY_MISC_REVOLUTION_OVER").GetCString(), "AS2D_REVOLTEND", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));
			}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setDirty(MiscButtons_DIRTY_BIT, true);
			}

			if (getTeam() == GC.getGameINLINE().getActiveTeam())
			{
				gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
			}
		}

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getMaxAnarchyTurns() const																		 
{
	return m_iMaxAnarchyTurns;
}


void CvPlayer::updateMaxAnarchyTurns()
{
	int iBestValue;
	int iI;

	iBestValue = GC.getDefineINT("MAX_ANARCHY_TURNS");

	FAssertMsg((GC.getNumTraitInfos() > 0), "GC.getNumTraitInfos() is less than or equal to zero but is expected to be larger than zero in CvPlayer::updateMaxAnarchyTurns");
	for (iI = 0; iI < GC.getNumTraitInfos(); iI++)
	{
		if (hasTrait((TraitTypes)iI))
		{
			if (GC.getTraitInfo((TraitTypes)iI).getMaxAnarchy() >= 0)
			{
				if (GC.getTraitInfo((TraitTypes)iI).getMaxAnarchy() < iBestValue)
				{
					iBestValue = GC.getTraitInfo((TraitTypes)iI).getMaxAnarchy();
				}
			}
		}
	}

	m_iMaxAnarchyTurns = iBestValue;
	FAssert(getMaxAnarchyTurns() >= 0);
}


int CvPlayer::getAnarchyModifier() const
{
	return m_iAnarchyModifier;
}


void CvPlayer::changeAnarchyModifier(int iChange)
{
	if (0 != iChange)
	{
	m_iAnarchyModifier += iChange;

		setRevolutionTimer(std::max(0, ((100 + iChange) * getRevolutionTimer()) / 100));
		setConversionTimer(std::max(0, ((100 + iChange) * getConversionTimer()) / 100));
	}
}


int CvPlayer::getGoldenAgeModifier() const
{
	return m_iGoldenAgeModifier;
}


void CvPlayer::changeGoldenAgeModifier(int iChange)
{
	m_iGoldenAgeModifier += iChange;
}


int CvPlayer::getHurryModifier() const
{
	return m_iGlobalHurryModifier;
}


void CvPlayer::changeHurryModifier(int iChange)
{
	m_iGlobalHurryModifier = (m_iGlobalHurryModifier + iChange);
}


int CvPlayer::getGreatPeopleCreated() const
{
	return m_iGreatPeopleCreated;
}


void CvPlayer::incrementGreatPeopleCreated()
{
	m_iGreatPeopleCreated++;
}

int CvPlayer::getGreatGeneralsCreated() const
{
	return m_iGreatGeneralsCreated;
}

void CvPlayer::incrementGreatGeneralsCreated()
{
	m_iGreatGeneralsCreated++;
}

int CvPlayer::getGreatPeopleThresholdModifier() const
{
	return m_iGreatPeopleThresholdModifier;
}


void CvPlayer::changeGreatPeopleThresholdModifier(int iChange)
{
	m_iGreatPeopleThresholdModifier = (m_iGreatPeopleThresholdModifier + iChange);
}


int CvPlayer::getGreatGeneralsThresholdModifier() const
{
	return m_iGreatGeneralsThresholdModifier;
}


void CvPlayer::changeGreatGeneralsThresholdModifier(int iChange)
{
	m_iGreatGeneralsThresholdModifier += iChange;
}


int CvPlayer::getGreatPeopleRateModifier() const
{
	return m_iGreatPeopleRateModifier;
}


void CvPlayer::changeGreatPeopleRateModifier(int iChange)													
{
	m_iGreatPeopleRateModifier = (m_iGreatPeopleRateModifier + iChange);
}


int CvPlayer::getGreatGeneralRateModifier() const
{
	return m_iGreatGeneralRateModifier;
}


void CvPlayer::changeGreatGeneralRateModifier(int iChange)													
{
	m_iGreatGeneralRateModifier += iChange;
}


int CvPlayer::getDomesticGreatGeneralRateModifier() const
{
	return (GC.getDefineINT("COMBAT_EXPERIENCE_IN_BORDERS_PERCENT") + m_iDomesticGreatGeneralRateModifier);
}


void CvPlayer::changeDomesticGreatGeneralRateModifier(int iChange)													
{
	m_iDomesticGreatGeneralRateModifier += iChange;
}


int CvPlayer::getStateReligionGreatPeopleRateModifier() const
{
	return m_iStateReligionGreatPeopleRateModifier;
}


void CvPlayer::changeStateReligionGreatPeopleRateModifier(int iChange)													
{
	m_iStateReligionGreatPeopleRateModifier = (m_iStateReligionGreatPeopleRateModifier + iChange);
}


int CvPlayer::getMaxGlobalBuildingProductionModifier() const
{
	return m_iMaxGlobalBuildingProductionModifier;
}


void CvPlayer::changeMaxGlobalBuildingProductionModifier(int iChange)
{
	m_iMaxGlobalBuildingProductionModifier = (m_iMaxGlobalBuildingProductionModifier + iChange);
}


int CvPlayer::getMaxTeamBuildingProductionModifier() const												 
{
	return m_iMaxTeamBuildingProductionModifier;
}


void CvPlayer::changeMaxTeamBuildingProductionModifier(int iChange)
{
	m_iMaxTeamBuildingProductionModifier = (m_iMaxTeamBuildingProductionModifier + iChange);
}


int CvPlayer::getMaxPlayerBuildingProductionModifier() const												
{
	return m_iMaxPlayerBuildingProductionModifier;
}


void CvPlayer::changeMaxPlayerBuildingProductionModifier(int iChange)
{
	m_iMaxPlayerBuildingProductionModifier = (m_iMaxPlayerBuildingProductionModifier + iChange);
}


int CvPlayer::getFreeExperience() const																
{
	return m_iFreeExperience;
}


void CvPlayer::changeFreeExperience(int iChange)
{
	m_iFreeExperience = (m_iFreeExperience + iChange);
}


int CvPlayer::getFeatureProductionModifier() const
{
	return m_iFeatureProductionModifier;
}


void CvPlayer::changeFeatureProductionModifier(int iChange)
{
	m_iFeatureProductionModifier = (m_iFeatureProductionModifier + iChange);
}


int CvPlayer::getWorkerSpeedModifier() const
{
	return m_iWorkerSpeedModifier;
}


void CvPlayer::changeWorkerSpeedModifier(int iChange)
{
	m_iWorkerSpeedModifier = (m_iWorkerSpeedModifier + iChange);
}

// BUG - Partial Builds - start
/*
 * Returns the work rate for the first unit that can build <eBuild>.
 */
int CvPlayer::getWorkRate(BuildTypes eBuild) const
{
	int iRate = 0;
	int iBestScore = 0;
	CvCivilizationInfo& kCiv = GC.getCivilizationInfo(getCivilizationType());

	for (int iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
	{
		UnitTypes eUnit = (UnitTypes)kCiv.getCivilizationUnits(iI);
		if ( NO_UNIT != eUnit )
		{
			CvUnitInfo& kUnit = GC.getUnitInfo(eUnit);

			if (kUnit.getBuilds(eBuild))
			{
				bool	bHas = (getUnitClassCount((UnitClassTypes)iI) > 0);
				int iUnitRate = kUnit.getWorkRate();
				int iScore = 0;

				if ( bHas )
				{
					iScore = iUnitRate*10;
				}
				else if ( canTrain(eUnit) )
				{
					iScore = iUnitRate;
				}

				if ( iScore > iBestScore )
				{
					iBestScore = iScore;
					iRate = iUnitRate;
				}
			}
		}
	}

	iRate *= std::max(0, getWorkerSpeedModifier() + 100);
	iRate /= 100;

	if (!isHuman() && !isBarbarian())
	{
		iRate *= std::max(0, (GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIWorkRateModifier() + 100));
		iRate /= 100;
	}

	return iRate;
}
// BUG - Partial Builds - end


int CvPlayer::getImprovementUpgradeRateModifier() const
{
	return m_iImprovementUpgradeRateModifier;
}


void CvPlayer::changeImprovementUpgradeRateModifier(int iChange)
{
	m_iImprovementUpgradeRateModifier = (m_iImprovementUpgradeRateModifier + iChange);
}


int CvPlayer::getMilitaryProductionModifier() const
{
	return m_iMilitaryProductionModifier;
}


void CvPlayer::changeMilitaryProductionModifier(int iChange)
{
	m_iMilitaryProductionModifier = (m_iMilitaryProductionModifier + iChange);
}


int CvPlayer::getSpaceProductionModifier() const													 
{
	return m_iSpaceProductionModifier;
}


void CvPlayer::changeSpaceProductionModifier(int iChange)
{
	m_iSpaceProductionModifier = (m_iSpaceProductionModifier + iChange);
}

/************************************************************************************************/
/* Afforess  Civic Extra City Defense                               12/4/09                     */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/* OLD CODE
int CvPlayer::getCityDefenseModifier() const
{
	return m_iCityDefenseModifier;
}
*/

int CvPlayer::getCityDefenseModifier() const
{
	return m_iCityDefenseModifier + getExtraCityDefense();
}
/************************************************************************************************/
/* Afforess	                         END                                                        */
/************************************************************************************************/	

void CvPlayer::changeCityDefenseModifier(int iChange)
{
	m_iCityDefenseModifier = (m_iCityDefenseModifier + iChange);
}


/************************************************************************************************/
/* REVDCM                                 09/02/10                                phungus420    */
/*                                                                                              */
/* Player Functions                                                                             */
/************************************************************************************************/
bool CvPlayer::isNonStateReligionCommerce() const
{
	if (m_iNonStateReligionCommerceCount > 0)
	{
		return true;
	}
	return false;
}

void CvPlayer::changeNonStateReligionCommerce(int iNewValue)
{
	FAssert(m_iNonStateReligionCommerceCount >= 0 && m_iNonStateReligionCommerceCount <= 2);

    m_iNonStateReligionCommerceCount += iNewValue;

	if(iNewValue != 0)
	{
		updateReligionCommerce();
		AI_makeAssignWorkDirty();
    }
}

bool CvPlayer::isUpgradeAnywhere() const
{
	if(m_iUpgradeAnywhereCount > 0)
	{
		return true;
	}
	return false;
}

void CvPlayer::changeUpgradeAnywhere(int iNewValue)
{
	FAssert(m_iUpgradeAnywhereCount >= 0 && m_iUpgradeAnywhereCount <= 2);

    m_iUpgradeAnywhereCount += iNewValue;
}


int CvPlayer::getRevIdxLocal() const
{
	return m_iRevIdxLocal;
}

void CvPlayer::changeRevIdxLocal(int iChange)
{
	if (iChange != 0)
	{
		m_iRevIdxLocal = (m_iRevIdxLocal + iChange);
	}
}


int CvPlayer::getRevIdxNational() const
{
	return m_iRevIdxNational;
}


void CvPlayer::changeRevIdxNational(int iChange)
{
	if (iChange != 0)
	{
		m_iRevIdxNational = (m_iRevIdxNational + iChange);
	}
}


int CvPlayer::getRevIdxDistanceModifier() const
{
	return m_iRevIdxDistanceModifier;
}

void CvPlayer::changeRevIdxDistanceModifier(int iChange)
{
	if (iChange != 0)
	{
		m_iRevIdxDistanceModifier = (m_iRevIdxDistanceModifier + iChange);
	}
}


int CvPlayer::getRevIdxHolyCityGood() const
{
	return m_iRevIdxHolyCityGood;
}

void CvPlayer::changeRevIdxHolyCityGood(int iChange)
{
	if (iChange != 0)
	{
		m_iRevIdxHolyCityGood = (m_iRevIdxHolyCityGood + iChange);
	}
}


int CvPlayer::getRevIdxHolyCityBad() const
{
	return m_iRevIdxHolyCityBad;
}

void CvPlayer::changeRevIdxHolyCityBad(int iChange)
{
	if (iChange != 0)
	{
		m_iRevIdxHolyCityBad = (m_iRevIdxHolyCityBad + iChange);
	}
}


float CvPlayer::getRevIdxNationalityMod() const
{
	return m_fRevIdxNationalityMod;
}

void CvPlayer::changeRevIdxNationalityMod(float fChange)
{
	if (fChange != 0)
	{
		m_fRevIdxNationalityMod = (m_fRevIdxNationalityMod + fChange);
	}
}


float CvPlayer::getRevIdxBadReligionMod() const
{
	return m_fRevIdxBadReligionMod;
}

void CvPlayer::changeRevIdxBadReligionMod(float fChange)
{
	if (fChange != 0)
	{
		m_fRevIdxBadReligionMod = (m_fRevIdxBadReligionMod + fChange);
	}
}


float CvPlayer::getRevIdxGoodReligionMod() const
{
	return m_fRevIdxGoodReligionMod;
}

void CvPlayer::changeRevIdxGoodReligionMod(float fChange)
{
	if (fChange != 0)
	{
		m_fRevIdxGoodReligionMod = (m_fRevIdxGoodReligionMod + fChange);
	}
}


bool CvPlayer::isInquisitionConditions() const
{
	return m_bInquisitionConditions;
}

void CvPlayer::setInquisitionConditions()
{
	m_bInquisitionConditions = false;

	if (GC.getGameINLINE().isOption(GAMEOPTION_NO_INQUISITIONS))
		return;
	
	if (getStateReligion() == NO_RELIGION)
		return;
		
	for (int iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		if (GC.getCivicInfo(getCivics((CivicOptionTypes)iI)).isDisallowInquisitions())
		{
			return;
		}
		else if (GC.getCivicInfo(getCivics((CivicOptionTypes)iI)).isAllowInquisitions())
		{
			m_bInquisitionConditions = true;
		}
	}
}


int CvPlayer::getUnitUpgradePriceModifier() const
{
	return m_iUnitUpgradePriceModifier;
}

void CvPlayer::changeUnitUpgradePriceModifier(int iChange)
{
	m_iUnitUpgradePriceModifier = (m_iUnitUpgradePriceModifier + iChange);
}


bool CvPlayer::canFoundReligion() const
{
	if( getNumCities() < 1 || isBarbarian() 
	|| (GC.getGameINLINE().isGameStart() && GC.getGameINLINE().getElapsedGameTurns() < 3) )
	{
		return false;
	}

	if(GC.getGameINLINE().isOption(GAMEOPTION_LIMITED_RELIGIONS))
	{
		if( ((getNumCities() > 1) && !(isRebel())) || !GC.isLIMITED_RELIGIONS_EXCEPTIONS() )
		{
			if(hasHolyCity())
			{
				return false;
			}
		}
	}
	return true;
}

bool CvPlayer::isBuildingClassRequiredToTrain(BuildingClassTypes eBuildingClass, UnitTypes eUnit) const
{
	CvUnitInfo& kUnit = GC.getUnitInfo(eUnit);
	if (kUnit.isPrereqBuildingClass(eBuildingClass))
	{
		TechTypes eOverrideTech = (TechTypes) kUnit.getPrereqBuildingClassOverrideTech(eBuildingClass);
		if (eOverrideTech != NO_TECH && GET_TEAM(getTeam()).isHasTech(TechTypes(eOverrideTech)) )
		{
			return false;
		}
		EraTypes eOverrideEra = (EraTypes) kUnit.getPrereqBuildingClassOverrideEra(eBuildingClass);
		if (eOverrideEra != NO_ERA && EraTypes(getCurrentEra()) >= eOverrideEra)
		{
			return false;
		}
		return true;
	}
	return false;
}
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/


int CvPlayer::getNumNukeUnits() const
{
	return m_iNumNukeUnits;
}


void CvPlayer::changeNumNukeUnits(int iChange)
{
	m_iNumNukeUnits = (m_iNumNukeUnits + iChange);
	FAssert(getNumNukeUnits() >= 0);
}


int CvPlayer::getNumOutsideUnits() const
{
	return m_iNumOutsideUnits;
}


void CvPlayer::changeNumOutsideUnits(int iChange)
{
	if (iChange != 0)
	{
		m_iNumOutsideUnits += iChange;
		FAssert(getNumOutsideUnits() >= 0);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getBaseFreeUnits() const																		
{
	return m_iBaseFreeUnits;
}


void CvPlayer::changeBaseFreeUnits(int iChange)														
{
	if (iChange != 0)
	{
		m_iBaseFreeUnits = (m_iBaseFreeUnits + iChange);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getBaseFreeMilitaryUnits() const																		
{
	return m_iBaseFreeMilitaryUnits;
}


void CvPlayer::changeBaseFreeMilitaryUnits(int iChange)														
{
	if (iChange != 0)
	{
		m_iBaseFreeMilitaryUnits = (m_iBaseFreeMilitaryUnits + iChange);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getFreeUnitsPopulationPercent() const																	
{
	return m_iFreeUnitsPopulationPercent;
}


void CvPlayer::changeFreeUnitsPopulationPercent(int iChange)													
{
	if (iChange != 0)
	{
		m_iFreeUnitsPopulationPercent = (m_iFreeUnitsPopulationPercent + iChange);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getFreeMilitaryUnitsPopulationPercent() const															
{
	return m_iFreeMilitaryUnitsPopulationPercent;
}


void CvPlayer::changeFreeMilitaryUnitsPopulationPercent(int iChange)											
{
	if (iChange != 0)
	{
		m_iFreeMilitaryUnitsPopulationPercent = (m_iFreeMilitaryUnitsPopulationPercent + iChange);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getGoldPerUnit() const																		
{
	return m_iGoldPerUnit;
}


void CvPlayer::changeGoldPerUnit(int iChange)															
{
	if (iChange != 0)
	{
		m_iGoldPerUnit = (m_iGoldPerUnit + iChange);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getGoldPerMilitaryUnit() const
{
	return m_iGoldPerMilitaryUnit;
}


void CvPlayer::changeGoldPerMilitaryUnit(int iChange)
{
	if (iChange != 0)
	{
		m_iGoldPerMilitaryUnit = (m_iGoldPerMilitaryUnit + iChange);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getExtraUnitCost() const
{
	return m_iExtraUnitCost;
}


void CvPlayer::changeExtraUnitCost(int iChange)
{
	if (iChange != 0)
	{
		m_iExtraUnitCost = (m_iExtraUnitCost + iChange);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getNumMilitaryUnits() const
{
	return m_iNumMilitaryUnits;
}


void CvPlayer::changeNumMilitaryUnits(int iChange)													
{
	if (iChange != 0)
	{
		m_iNumMilitaryUnits = (m_iNumMilitaryUnits + iChange);
		FAssert(getNumMilitaryUnits() >= 0);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getHappyPerMilitaryUnit() const																
{
	return m_iHappyPerMilitaryUnit;
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeHappyPerMilitaryUnit(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iHappyPerMilitaryUnit = (m_iHappyPerMilitaryUnit + iChange);

		if (!bLimited)
		{
			AI_makeAssignWorkDirty();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getMilitaryFoodProductionCount() const														
{
	return m_iMilitaryFoodProductionCount;
}


bool CvPlayer::isMilitaryFoodProduction() const																
{
	return (getMilitaryFoodProductionCount() > 0);
}


/********************************************************************************/
/* 	New Civic AI						19.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeMilitaryFoodProductionCount(int iChange, bool bLimited)											
{
	if (iChange != 0)
	{
		m_iMilitaryFoodProductionCount = (m_iMilitaryFoodProductionCount + iChange);
		FAssert(getMilitaryFoodProductionCount() >= 0);

		if (!bLimited && getTeam() == GC.getGameINLINE().getActiveTeam())
		{
			gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getHighestUnitLevel()	const																
{
	return m_iHighestUnitLevel;
}


void CvPlayer::setHighestUnitLevel(int iNewValue)
{
	m_iHighestUnitLevel = iNewValue;
	FAssert(getHighestUnitLevel() >= 0);
}


int CvPlayer::getMaxConscript() const
{
	return std::max(0, m_iMaxConscript);
}


void CvPlayer::changeMaxConscript(int iChange)
{
	m_iMaxConscript = (m_iMaxConscript + iChange);
	//TB Note: this should be allowed to be negative.  BUT there's a report to the core so I'm going to leave this here and cap at 0 in getMaxConscript
	FAssert(getMaxConscript() >= 0);
}


int CvPlayer::getConscriptCount() const
{
	return m_iConscriptCount;
}


void CvPlayer::setConscriptCount(int iNewValue)
{
	m_iConscriptCount = iNewValue;
	FAssert(getConscriptCount() >= 0);
}


void CvPlayer::changeConscriptCount(int iChange)
{
	setConscriptCount(getConscriptCount() + iChange);
}


int CvPlayer::getOverflowResearch() const
{
	return m_iOverflowResearch;
}


void CvPlayer::setOverflowResearch(int iNewValue)
{
	m_iOverflowResearch = iNewValue;
	FAssert(getOverflowResearch() >= 0);
}


void CvPlayer::changeOverflowResearch(int iChange)
{
	setOverflowResearch(getOverflowResearch() + iChange);
}


int CvPlayer::getNoUnhealthyPopulationCount() const
{
	return m_iNoUnhealthyPopulationCount;
}


bool CvPlayer::isNoUnhealthyPopulation() const																		
{
	return (getNoUnhealthyPopulationCount() > 0);
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeNoUnhealthyPopulationCount(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iNoUnhealthyPopulationCount = (m_iNoUnhealthyPopulationCount + iChange);
		FAssert(getNoUnhealthyPopulationCount() >= 0);

		if (!bLimited)
		{
			AI_makeAssignWorkDirty();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getExpInBorderModifier() const
{
	return m_iExpInBorderModifier;
}


void CvPlayer::changeExpInBorderModifier(int iChange)
{
	if (iChange != 0)
	{
		m_iExpInBorderModifier += iChange;
	}
}


int CvPlayer::getBuildingOnlyHealthyCount() const
{
	return m_iBuildingOnlyHealthyCount;
}


bool CvPlayer::isBuildingOnlyHealthy() const																	
{
	return (getBuildingOnlyHealthyCount() > 0);
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeBuildingOnlyHealthyCount(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iBuildingOnlyHealthyCount = (m_iBuildingOnlyHealthyCount + iChange);
		FAssert(getBuildingOnlyHealthyCount() >= 0);

		if (!bLimited)
		{
			AI_makeAssignWorkDirty();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/

//DPII < Maintenance Modifiers >
int CvPlayer::getMaintenanceModifier()
{
    return m_iMaintenanceModifier;
}

void CvPlayer::changeMaintenanceModifier(int iChange)
{
    if (iChange != 0)
    {
        m_iMaintenanceModifier = (m_iMaintenanceModifier + iChange);

		setMaintenanceDirty(true);
    }
}

int CvPlayer::getCoastalDistanceMaintenanceModifier()
{
    return m_iCoastalDistanceMaintenanceModifier;
}

void CvPlayer::changeCoastalDistanceMaintenanceModifier(int iChange)
{
    if (iChange != 0)
    {
        m_iCoastalDistanceMaintenanceModifier = (m_iCoastalDistanceMaintenanceModifier + iChange);

		setMaintenanceDirty(true);
    }
}

int CvPlayer::getConnectedCityMaintenanceModifier()
{
    return m_iConnectedCityMaintenanceModifier;
}

void CvPlayer::changeConnectedCityMaintenanceModifier(int iChange)
{
    if (iChange != 0)
    {
        m_iConnectedCityMaintenanceModifier = (m_iConnectedCityMaintenanceModifier + iChange);

		setMaintenanceDirty(true);
    }
}
//DPII < Maintenance Modifiers >


int CvPlayer::getDistanceMaintenanceModifier() const
{
	return m_iDistanceMaintenanceModifier;
}


void CvPlayer::changeDistanceMaintenanceModifier(int iChange)
{
	if (iChange != 0)
	{
		m_iDistanceMaintenanceModifier += iChange;

		setMaintenanceDirty(true);
	}
}


int CvPlayer::getNumCitiesMaintenanceModifier() const
{
	return m_iNumCitiesMaintenanceModifier;
}


void CvPlayer::changeNumCitiesMaintenanceModifier(int iChange)
{
	if (iChange != 0)
	{
		m_iNumCitiesMaintenanceModifier += iChange;

		setMaintenanceDirty(true);
	}
}


int CvPlayer::getCorporationMaintenanceModifier() const
{
	return m_iCorporationMaintenanceModifier;
}


/********************************************************************************/
/* 	New Civic AI						19.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeCorporationMaintenanceModifier(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iCorporationMaintenanceModifier += iChange;

		if (!bLimited)
		{
			setMaintenanceDirty(true);
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getTotalMaintenance() const
{
	if ( m_bMaintenanceDirty && !m_bUpdatesDeferred )
	{
		updateMaintenance();
	}

	//ls612: Gold modifiers by Gamespeed
	int iCost = (m_iTotalMaintenance / 100) * (GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGoldModifier());
	if (iCost != 0)
	{
		iCost /= 100;
	}

	return iCost;
}

void CvPlayer::deferUpdates()
{
	if ( m_bMaintenanceDirty )
	{
		updateMaintenance();
	}

	m_bUpdatesDeferred = true;
	m_bGoldenAgeStarted = false;
}

void CvPlayer::resumeUpdates()
{
	m_bUpdatesDeferred = false;

	if ( m_bGoldenAgeStarted )
	{
		m_bGoldenAgeStarted = false;

		reportGoldenAgeStart();
	}

	if ( m_bMaintenanceDirty )
	{
		updateMaintenance();
	}

	for(int iI = 0; iI < NUM_COMMERCE_TYPES; iI++ )
	{
		if ( m_abCommerceDirty[iI] )
		{
			updateCommerce((CommerceTypes)iI, false);
		}
	}
}


int CvPlayer::getUpkeepModifier() const
{
	return m_iUpkeepModifier;
}


void CvPlayer::changeUpkeepModifier(int iChange)
{
	m_iUpkeepModifier = (m_iUpkeepModifier + iChange);
}


int CvPlayer::getLevelExperienceModifier() const
{
	return m_iLevelExperienceModifier;
}

void CvPlayer::changeLevelExperienceModifier(int iChange)
{
	m_iLevelExperienceModifier += iChange;
}



int CvPlayer::getExtraHealth() const
{
	// AIAndy: Barbarians do not get player wide unhealthiness
	if (isBarbarian())
	{
		if (m_iExtraHealth < 0)
		{
			return 0;
		}
	}	
	return m_iExtraHealth;
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeExtraHealth(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iExtraHealth = (m_iExtraHealth + iChange);

		//AIAndy: Barbarians do not get player wide unhealthiness
		if ((m_iExtraHealth < 0) && isBarbarian())
		{
			m_iExtraHealth = 0;
		}

		if (!bLimited)
		{
			AI_makeAssignWorkDirty();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getBuildingGoodHealth() const	
{
	return m_iBuildingGoodHealth;
}


void CvPlayer::changeBuildingGoodHealth(int iChange)
{
	if (iChange != 0)
	{
		m_iBuildingGoodHealth = (m_iBuildingGoodHealth + iChange);
		FAssert(getBuildingGoodHealth() >= 0);

		AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getBuildingBadHealth() const	
{
	return m_iBuildingBadHealth;
}


void CvPlayer::changeBuildingBadHealth(int iChange)
{
	if (iChange != 0)
	{
		m_iBuildingBadHealth = (m_iBuildingBadHealth + iChange);
		FAssert(getBuildingBadHealth() <= 0);

		AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getExtraHappiness() const
{
	// AIAndy: Barbarians do not get player wide unhappiness
	if (isBarbarian())
	{
		if (m_iExtraHappiness < 0)
		{
			return 0;
		}
	}	
	return m_iExtraHappiness;
}


void CvPlayer::changeExtraHappiness(int iChange)
{
	if (iChange != 0)
	{
		m_iExtraHappiness = (m_iExtraHappiness + iChange);

		//AIAndy: Barbarians do not get player wide unhappiness
		if ((m_iExtraHappiness < 0) && isBarbarian())
		{
			m_iExtraHappiness = 0;
		}

		AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getBuildingHappiness() const
{
	return m_iBuildingHappiness;
}


void CvPlayer::changeBuildingHappiness(int iChange)
{
	if (iChange != 0)
	{
		m_iBuildingHappiness = (m_iBuildingHappiness + iChange);

		AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getLargestCityHappiness() const
{
	return m_iLargestCityHappiness;
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeLargestCityHappiness(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iLargestCityHappiness = (m_iLargestCityHappiness + iChange);

		if (!bLimited)
		{
			AI_makeAssignWorkDirty();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getWarWearinessPercentAnger() const																 
{
	return m_iWarWearinessPercentAnger;
}


void CvPlayer::updateWarWearinessPercentAnger()
{
	PROFILE_FUNC()

	int iNewWarWearinessPercentAnger;
	int iI;

	iNewWarWearinessPercentAnger = 0;

	if (!isBarbarian() && !isMinorCiv())
	{
		for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
		{
			CvTeam& kTeam = GET_TEAM((TeamTypes)iI);
			if (kTeam.isAlive() && !kTeam.isMinorCiv())
			{
				if (kTeam.isAtWar(getTeam()))
				{
					iNewWarWearinessPercentAnger += (GET_TEAM(getTeam()).getWarWeariness((TeamTypes)iI) * std::max(0, 100 + kTeam.getEnemyWarWearinessModifier())) / 10000;
				}
			}
		}
	}

	iNewWarWearinessPercentAnger = getModifiedWarWearinessPercentAnger(iNewWarWearinessPercentAnger);

	if (getWarWearinessPercentAnger() != iNewWarWearinessPercentAnger)
	{
		m_iWarWearinessPercentAnger = iNewWarWearinessPercentAnger;

		AI_makeAssignWorkDirty();
	}
}

int CvPlayer::getModifiedWarWearinessPercentAnger(int iWarWearinessPercentAnger) const			
{
	iWarWearinessPercentAnger *= GC.getDefineINT("BASE_WAR_WEARINESS_MULTIPLIER");

	if (GC.getGameINLINE().isOption(GAMEOPTION_ALWAYS_WAR) || GC.getGameINLINE().isOption(GAMEOPTION_NO_CHANGING_WAR_PEACE))
	{
		iWarWearinessPercentAnger *= std::max(0, (GC.getDefineINT("FORCED_WAR_WAR_WEARINESS_MODIFIER") + 100));
		iWarWearinessPercentAnger /= 100;
	}

	if (GC.getGameINLINE().isGameMultiPlayer())
	{
		iWarWearinessPercentAnger *= std::max(0, (GC.getDefineINT("MULTIPLAYER_WAR_WEARINESS_MODIFIER") + 100));
		iWarWearinessPercentAnger /= 100;
	}

	iWarWearinessPercentAnger *= std::max(0, (GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getWarWearinessModifier() + 100));
	iWarWearinessPercentAnger /= 100;

	if (!isHuman() && !isBarbarian() && !isMinorCiv())
	{
		iWarWearinessPercentAnger *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIWarWearinessPercent();
		iWarWearinessPercentAnger /= 100;

		iWarWearinessPercentAnger *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iWarWearinessPercentAnger /= 100;
	}

	return iWarWearinessPercentAnger;
}


int CvPlayer::getWarWearinessModifier() const			
{
	return m_iWarWearinessModifier;
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeWarWearinessModifier(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iWarWearinessModifier = (m_iWarWearinessModifier + iChange);

		if (!bLimited)
		{
			AI_makeAssignWorkDirty();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getFreeSpecialist() const	
{
	return m_iFreeSpecialist;
}


void CvPlayer::changeFreeSpecialist(int iChange)
{
	if (iChange != 0)
	{
		m_iFreeSpecialist = (m_iFreeSpecialist + iChange);
		FAssert(getFreeSpecialist() >= 0);

		AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getNoForeignTradeCount() const
{
	return m_iNoForeignTradeCount;
}


bool CvPlayer::isNoForeignTrade() const
{
	return (getNoForeignTradeCount() > 0);
}


/********************************************************************************/
/* 	New Civic AI						19.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeNoForeignTradeCount(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iNoForeignTradeCount = (m_iNoForeignTradeCount + iChange);
		FAssert(getNoForeignTradeCount() >= 0);

		if (!bLimited)
		{
			GC.getGameINLINE().updateTradeRoutes();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getNoCorporationsCount() const
{
	return m_iNoCorporationsCount;
}


bool CvPlayer::isNoCorporations() const
{
	return (getNoCorporationsCount() > 0);
}


/********************************************************************************/
/* 	New Civic AI						19.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeNoCorporationsCount(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iNoCorporationsCount += iChange;
		FAssert(getNoCorporationsCount() >= 0);

		if (!bLimited)
		{
			updateCorporation();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getNoForeignCorporationsCount() const
{
	return m_iNoForeignCorporationsCount;
}


bool CvPlayer::isNoForeignCorporations() const
{
	return (getNoForeignCorporationsCount() > 0);
}


/********************************************************************************/
/* 	New Civic AI						19.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeNoForeignCorporationsCount(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iNoForeignCorporationsCount += iChange;
		FAssert(getNoForeignCorporationsCount() >= 0);

		if (!bLimited)
		{
			updateCorporation();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getCoastalTradeRoutes() const
{
	return m_iCoastalTradeRoutes;
}


void CvPlayer::changeCoastalTradeRoutes(int iChange)
{
	if (iChange != 0)
	{
		m_iCoastalTradeRoutes = (m_iCoastalTradeRoutes + iChange);
		FAssert(getCoastalTradeRoutes() >= 0);

		updateTradeRoutes();
	}
}


int CvPlayer::getTradeRoutes() const
{
	return std::max(0, m_iTradeRoutes);
}


void CvPlayer::changeTradeRoutes(int iChange)
{
	if (iChange != 0)
	{
		int	oldNumTradeRoutes = getTradeRoutes();

		m_iTradeRoutes = (m_iTradeRoutes + iChange);

		if ( oldNumTradeRoutes != getTradeRoutes() )
		{
			updateTradeRoutes();
		}
	}
}


int CvPlayer::getRevolutionTimer() const	
{
	return m_iRevolutionTimer;
}


void CvPlayer::setRevolutionTimer(int iNewValue)
{
	if (getRevolutionTimer() != iNewValue)
	{
		m_iRevolutionTimer = iNewValue;
		FAssert(getRevolutionTimer() >= 0);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(MiscButtons_DIRTY_BIT, true);
		}
	}
}


void CvPlayer::changeRevolutionTimer(int iChange)
{
	setRevolutionTimer(getRevolutionTimer() + iChange);
}


int CvPlayer::getConversionTimer() const	
{
	return m_iConversionTimer;
}


void CvPlayer::setConversionTimer(int iNewValue)
{
	if (getConversionTimer() != iNewValue)
	{
		m_iConversionTimer = iNewValue;
		FAssert(getConversionTimer() >= 0);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(MiscButtons_DIRTY_BIT, true);
		}
	}
}


void CvPlayer::changeConversionTimer(int iChange)
{
	setConversionTimer(getConversionTimer() + iChange);
}


int CvPlayer::getStateReligionCount() const																	
{
	return m_iStateReligionCount;
}


bool CvPlayer::isStateReligion() const	 
{
	return (getStateReligionCount() > 0);
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeStateReligionCount(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		// religion visibility now part of espionage
		//GC.getGameINLINE().updateCitySight(false, true);

		m_iStateReligionCount = (m_iStateReligionCount + iChange);
		FAssert(getStateReligionCount() >= 0);

		// religion visibility now part of espionage
		//GC.getGameINLINE().updateCitySight(true, true);

		if (!bLimited)
		{
			setMaintenanceDirty(true);
		}

		updateReligionHappiness(bLimited);

		if (!bLimited)
		{
			updateReligionCommerce();

			GC.getGameINLINE().AI_makeAssignWorkDirty();

			gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getNoNonStateReligionSpreadCount() const
{
	return m_iNoNonStateReligionSpreadCount;
}


bool CvPlayer::isNoNonStateReligionSpread() const
{
	return (getNoNonStateReligionSpreadCount() > 0);
}


void CvPlayer::changeNoNonStateReligionSpreadCount(int iChange)
{
	m_iNoNonStateReligionSpreadCount = (m_iNoNonStateReligionSpreadCount + iChange);
	FAssert(getNoNonStateReligionSpreadCount() >= 0);
}


int CvPlayer::getStateReligionHappiness() const								 
{
	return m_iStateReligionHappiness;
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeStateReligionHappiness(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iStateReligionHappiness = (m_iStateReligionHappiness + iChange);

		updateReligionHappiness(bLimited);
	}
}


int CvPlayer::getNonStateReligionHappiness() const 
{
	return m_iNonStateReligionHappiness;
}


//Fuyu bLimited
void CvPlayer::changeNonStateReligionHappiness(int iChange, bool bLimited)
{
	if (iChange != 0)
	{
		m_iNonStateReligionHappiness = (m_iNonStateReligionHappiness + iChange);

		updateReligionHappiness(bLimited);
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getStateReligionUnitProductionModifier() const	 
{
	return m_iStateReligionUnitProductionModifier;
}


void CvPlayer::changeStateReligionUnitProductionModifier(int iChange)
{
	if (iChange != 0)
	{
		m_iStateReligionUnitProductionModifier = (m_iStateReligionUnitProductionModifier + iChange);

		if (getTeam() == GC.getGameINLINE().getActiveTeam())
		{
			gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getStateReligionBuildingProductionModifier() const
{
	return m_iStateReligionBuildingProductionModifier;
}


void CvPlayer::changeStateReligionBuildingProductionModifier(int iChange)
{
	if (iChange != 0)
	{
		m_iStateReligionBuildingProductionModifier = (m_iStateReligionBuildingProductionModifier + iChange);

		if (getTeam() == GC.getGameINLINE().getActiveTeam())
		{
			gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getStateReligionFreeExperience() const
{
	return m_iStateReligionFreeExperience;
}


void CvPlayer::changeStateReligionFreeExperience(int iChange)
{
	m_iStateReligionFreeExperience = (m_iStateReligionFreeExperience + iChange);
}


CvCity* CvPlayer::getCapitalCity() const	 
{
	return getCity(m_iCapitalCityID);
}


void CvPlayer::setCapitalCity(CvCity* pNewCapitalCity)
{
	CvCity* pOldCapitalCity;
	bool bUpdatePlotGroups;

	pOldCapitalCity = getCapitalCity();

	if (pOldCapitalCity != pNewCapitalCity)
	{
		bUpdatePlotGroups = ((pOldCapitalCity == NULL) || (pNewCapitalCity == NULL) || (pOldCapitalCity->plot()->getOwnerPlotGroup() != pNewCapitalCity->plot()->getOwnerPlotGroup()));

		if (bUpdatePlotGroups)
		{
			startDeferredPlotGroupBonusCalculation();

			if (pOldCapitalCity != NULL)
			{
				pOldCapitalCity->plot()->updatePlotGroupBonus(false);
			}
			if (pNewCapitalCity != NULL)
			{
				pNewCapitalCity->plot()->updatePlotGroupBonus(false);
			}
		}

		if (pNewCapitalCity != NULL)
		{
			m_iCapitalCityID = pNewCapitalCity->getID();
		}
		else
		{
			m_iCapitalCityID = FFreeList::INVALID_INDEX;
		}
		
		//ls612: Embassy Visibility Fix (by Damgo)
		if (pOldCapitalCity != NULL)
		{
			for (int iI = 0; iI < MAX_TEAMS; iI++)
			{
				if (GET_TEAM(getTeam()).isHasEmbassy((TeamTypes)iI))
				{
					pOldCapitalCity->plot()->changeAdjacentSight((TeamTypes)iI, GC.getDefineINT("PLOT_VISIBILITY_RANGE"), false, NULL, bUpdatePlotGroups);
				}
			}
		}
		
		if (pNewCapitalCity != NULL)
		{
			for (int iI = 0; iI < MAX_TEAMS; iI++)
			{
				if (GET_TEAM(getTeam()).isHasEmbassy((TeamTypes)iI))
				{
					pNewCapitalCity->plot()->changeAdjacentSight((TeamTypes)iI, GC.getDefineINT("PLOT_VISIBILITY_RANGE"), true, NULL, bUpdatePlotGroups);
				}
			}
		}
		//ls612: End Embassy Visibility Fix (by Damgo)

		if (bUpdatePlotGroups)
		{
			if (pOldCapitalCity != NULL)
			{
				pOldCapitalCity->plot()->updatePlotGroupBonus(true);
			}
			if (pNewCapitalCity != NULL)
			{
				pNewCapitalCity->plot()->updatePlotGroupBonus(true);
			}
			
			endDeferredPlotGroupBonusCalculation();
		}
		//DPII < Maintenance Modifier >
		if (pOldCapitalCity != NULL)
		{
            if ((pOldCapitalCity->area()) != (pNewCapitalCity->area()))
            {
                pNewCapitalCity->area()->setHomeArea(getID(), pOldCapitalCity->area());
            }
		}
		else
		{
            pNewCapitalCity->area()->setHomeArea(getID(), NULL);
		}
		//DPII < Maintenance Modifier >
		setMaintenanceDirty(true);
		updateTradeRoutes();

		if (pOldCapitalCity != NULL)
		{
			for(int iI = 0; iI < NUM_COMMERCE_TYPES ; iI++ )
			{
				pOldCapitalCity->setCommerceModifierDirty((CommerceTypes)iI);
			}
			pOldCapitalCity->updateCommerce();

			pOldCapitalCity->setInfoDirty(true);
		}
		if (pNewCapitalCity != NULL)
		{
			for(int iI = 0; iI < NUM_COMMERCE_TYPES ; iI++ )
			{
				pNewCapitalCity->setCommerceModifierDirty((CommerceTypes)iI);
			}
			pNewCapitalCity->updateCommerce();

			pNewCapitalCity->setInfoDirty(true);
		}
	}
}


int CvPlayer::getCitiesLost() const
{
	return m_iCitiesLost;
}


void CvPlayer::changeCitiesLost(int iChange)
{
	m_iCitiesLost = (m_iCitiesLost + iChange);
}


int CvPlayer::getWinsVsBarbs() const		 
{
	return m_iWinsVsBarbs;
}


void CvPlayer::changeWinsVsBarbs(int iChange)
{
	m_iWinsVsBarbs = (m_iWinsVsBarbs + iChange);
	FAssert(getWinsVsBarbs() >= 0);
}


int CvPlayer::getAssets() const
{
	return m_iAssets;
}


void CvPlayer::changeAssets(int iChange)
{
	int iOldValue;

	//	Do this in a thread-safe manner
	do
	{
		iOldValue = m_iAssets;
	} while( InterlockedCompareExchange((volatile LONG*)&m_iAssets, iOldValue + iChange, iOldValue) != iOldValue );
	//m_iAssets = (m_iAssets + iChange);
	FAssert(getAssets() >= 0);
}


int CvPlayer::getPower() const
{
	return std::max(0, m_iPower + m_iTechPower + m_iUnitPower);
}

int CvPlayer::getTechPower() const
{
	return std::max(0, m_iTechPower);
}

int CvPlayer::getUnitPower() const
{
	return std::max(0, m_iUnitPower);
}


void CvPlayer::changePower(int iChange)
{
	int iOldValue;

	//	Do this in a thread-safe manner
	do
	{
		iOldValue = m_iPower;
	} while( InterlockedCompareExchange((volatile LONG*)&m_iPower, iOldValue + iChange, iOldValue) != iOldValue );
	//m_iPower = (m_iPower + iChange);
	FAssert(getPower() >= 0);
}

void CvPlayer::changeTechPower(int iChange)
{
	m_iTechPower = (m_iTechPower + iChange);
	FAssert(getTechPower() >= 0);
}

void CvPlayer::changeUnitPower(int iChange)
{
	m_iUnitPower = (m_iUnitPower + iChange);
	FAssert(getUnitPower() >= 0);
}


int CvPlayer::getPopScore(bool bCheckVassal) const		 
{
	if (bCheckVassal && GET_TEAM(getTeam()).isAVassal())
	{
		return m_iPopulationScore / 2;
	}

	int iVassalScore = 0;

	if (bCheckVassal)
	{
		for (int i = 0; i < MAX_CIV_PLAYERS; i++)
		{
			if (i != getID())
			{
				CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)i);
				if (kLoopPlayer.isAlive() && GET_TEAM(kLoopPlayer.getTeam()).isVassal(getTeam()))
				{
					iVassalScore += kLoopPlayer.getPopScore(false) / 2;
				}
			}
		}
	}

	return (m_iPopulationScore + iVassalScore / std::max(1, GET_TEAM(getTeam()).getNumMembers()));
}

void CvPlayer::changePopScore(int iChange)
{
	if (iChange != 0)
	{
		m_iPopulationScore += iChange;
		FAssert(getPopScore() >= 0);

		GC.getGameINLINE().setScoreDirty(true);
	}
}


int CvPlayer::getLandScore(bool bCheckVassal) const		 
{
	if (bCheckVassal && GET_TEAM(getTeam()).isAVassal())
	{
		return m_iLandScore / 2;
	}

	int iVassalScore = 0;

	if (bCheckVassal)
	{
		for (int i = 0; i < MAX_CIV_PLAYERS; i++)
		{
			if (i != getID())
			{
				CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)i);
				if (kLoopPlayer.isAlive() && GET_TEAM(kLoopPlayer.getTeam()).isVassal(getTeam()))
				{
					iVassalScore += kLoopPlayer.getLandScore(false) / 2;
				}
			}
		}
	}

	return (m_iLandScore + iVassalScore  / std::max(1, GET_TEAM(getTeam()).getNumMembers()));
}


void CvPlayer::changeLandScore(int iChange)
{
	if (iChange != 0)
	{
		m_iLandScore += iChange;
		FAssert(getLandScore() >= 0);

		GC.getGameINLINE().setScoreDirty(true);
	}
}


int CvPlayer::getWondersScore() const		 
{
	//TB Debug
	if (m_iWondersScore < 0)
	{
		return 0;
	}
	else
	{
	return m_iWondersScore;
	}
}


void CvPlayer::changeWondersScore(int iChange)
{
	if (iChange != 0)
	{
			int iOldValue;

		//	Do this in a thread-safe manner
		do
		{
			iOldValue = m_iWondersScore;
		} while( InterlockedCompareExchange((volatile LONG*)&m_iWondersScore, iOldValue + iChange, iOldValue) != iOldValue );
		//m_iWondersScore += iChange;
		FAssert(getWondersScore() >= 0);

		GC.getGameINLINE().setScoreDirty(true);
	}
}


int CvPlayer::getTechScore() const		 
{
	return m_iTechScore;
}


void CvPlayer::changeTechScore(int iChange)
{
	if (iChange != 0)
	{
		m_iTechScore += iChange;
		FAssert(getTechScore() >= 0);

		GC.getGameINLINE().setScoreDirty(true);

		//	Change in techs invalidates cached player level buildability of buildings
		for (int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
			m_bCanConstructCached[iI] = false;
			m_bCanConstructCachedDefaultParam[iI] = false;
		}
	}
}

int CvPlayer::getCombatExperience() const
{
	return m_iCombatExperience;
}

void CvPlayer::setCombatExperience(int iExperience)
{
	iExperience = std::max(0, iExperience);

	if (iExperience != getCombatExperience())
	{
		m_iCombatExperience = iExperience;
/*************************************************************************************************/
/**	Great Generals From Barbarian Combat Start													**/
/**			Oct 19 2009																			**/
/**																								**/
/*************************************************************************************************/
		if (!isBarbarian() || GC.getGameINLINE().isOption(GAMEOPTION_BARBARIAN_GENERALS))
/*************************************************************************************************/
		{
			int iExperienceThreshold = greatPeopleThreshold(true);
			if (m_iCombatExperience >= iExperienceThreshold && iExperienceThreshold > 0)
			{
				// create great person
				CvCity* pBestCity = NULL;
				int iBestValue = MAX_INT;
				int iLoop;
				for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
				{
					int iValue = 4 * GC.getGameINLINE().getSorenRandNum(getNumCities(), "Warlord City Selection");

					for (int i = 0; i < NUM_YIELD_TYPES; i++)
					{
						iValue += pLoopCity->findYieldRateRank((YieldTypes)i);
					}
					iValue += pLoopCity->findPopulationRank();

					if (iValue < iBestValue)
					{
						pBestCity = pLoopCity;
						iBestValue = iValue;
					}
				}

				if (pBestCity)
				{
					int iRandOffset = GC.getGameINLINE().getSorenRandNum(GC.getNumUnitInfos(), "Warlord Unit Generation");
					for (int iI = 0; iI < GC.getNumUnitInfos(); iI++)
					{
						UnitTypes eLoopUnit = (UnitTypes)((iI + iRandOffset) % GC.getNumUnitInfos());
						/************************************************************************************************/
						/* Afforess	                  Start		 12/19/09                                                */
						/*                                                                                              */
						/*                                                                                              */
						/************************************************************************************************/
						/* was:
						if (GC.getUnitInfo(eLoopUnit).getLeaderExperience() > 0 || GC.getUnitInfo(eLoopUnit).getLeaderPromotion() != NO_PROMOTION)
						*/
						if (GC.getUnitInfo(eLoopUnit).isGreatGeneral())
						/************************************************************************************************/
						/* Afforess	                     END                                                            */
						/************************************************************************************************/
						{
							pBestCity->createGreatPeople(eLoopUnit, false, true);
							setCombatExperience(getCombatExperience() - iExperienceThreshold);
							break;
						}
					}
				}
			}
		}
	}
}

void CvPlayer::changeCombatExperience(int iChange)
{
	setCombatExperience(getCombatExperience() + iChange);
}


bool CvPlayer::isConnected() const
{
	return gDLL->isConnected( getNetID() );
}

int CvPlayer::getNetID() const
{
	return GC.getInitCore().getNetID(getID());
}


void CvPlayer::setNetID(int iNetID)
{
	GC.getInitCore().setNetID(getID(), iNetID);
}

void CvPlayer::sendReminder()
{
	CvWString szYearStr;

	// Only perform this step if we have a valid email address on record,
	// and we have provided information about how to send emails
	if ( !getPbemEmailAddress().empty() && 
		!gDLL->GetPitbossSmtpHost().empty() )
	{
		PYTHON_ACCESS_LOCK_SCOPE

		GAMETEXT.setTimeStr(szYearStr, GC.getGameINLINE().getGameTurn(), true);

		// Generate our arguments
		CyArgsList argsList;
		argsList.add(getPbemEmailAddress());
		argsList.add(gDLL->GetPitbossSmtpHost());
		argsList.add(gDLL->GetPitbossSmtpLogin());
		argsList.add(gDLL->GetPitbossSmtpPassword());
		argsList.add(GC.getGameINLINE().getName());
		argsList.add(GC.getGameINLINE().isMPOption(MPOPTION_TURN_TIMER));
		argsList.add(GC.getGameINLINE().getPitbossTurnTime());
		argsList.add(gDLL->GetPitbossEmail());
		argsList.add(szYearStr);

		// Now send our email via Python
		long iResult;
		bool bOK = PYTHON_CALL_FUNCTION4(__FUNCTION__, PYPitBossModule, "sendEmail", argsList.makeFunctionArgs(), &iResult);

		FAssertMsg( bOK, "Pitboss Python call to onSendEmail failed!" );
		FAssertMsg( iResult == 0, "Pitboss Python fn onSendEmail encountered an error" );
	}
}

uint CvPlayer::getStartTime() const
{
	return m_uiStartTime;
}


void CvPlayer::setStartTime(uint uiStartTime)
{
	m_uiStartTime = uiStartTime;
}


uint CvPlayer::getTotalTimePlayed() const
{
	return ((timeGetTime() - m_uiStartTime)/1000);
}


bool CvPlayer::isMinorCiv() const
{
	return GC.getInitCore().getMinorNationCiv(m_eID);
}


bool CvPlayer::isAlive() const
{
	return m_bAlive;
}


bool CvPlayer::isEverAlive() const
{
	return m_bEverAlive;
}


void CvPlayer::setAlive(bool bNewValue)
{
	CvWString szBuffer;
	int iI;

	if (isAlive() != bNewValue)
	{
		m_bAlive = bNewValue;

		GET_TEAM(getTeam()).changeAliveCount((isAlive()) ? 1 : -1);

		// Report event to Python
		CvEventReporter::getInstance().setPlayerAlive(getID(), bNewValue);

		if (isAlive())
		{
			if (!isEverAlive())
			{
				m_bEverAlive = true;

				GET_TEAM(getTeam()).changeEverAliveCount(1);
			}

			if (getNumCities() == 0)
			{
				setFoundedFirstCity(false);
			}

			updatePlotGroups();

			if (GC.getGameINLINE().isMPOption(MPOPTION_SIMULTANEOUS_TURNS) || (GC.getGameINLINE().getNumGameTurnActive() == 0) || (GC.getGameINLINE().isSimultaneousTeamTurns() && GET_TEAM(getTeam()).isTurnActive()))
			{
				setTurnActive(true);
			}

			gDLL->openSlot(getID());
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      09/03/09                       poyuzhe & jdog5000     */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
			// From Sanguo Mod Performance, ie the CAR Mod
			// Attitude cache
			for( int iI = 0; iI < MAX_PLAYERS; iI++ )
			{
				GET_PLAYER((PlayerTypes)iI).AI_invalidateAttitudeCache(getID());
				GET_PLAYER(getID()).AI_invalidateAttitudeCache((PlayerTypes)iI);
			}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
		}
		else
		{
			clearResearchQueue();
			killUnits();
			killCities();
			killAllDeals();
/************************************************************************************************/
/* Afforess	                  Start		 08/20/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
			clearTileCulture();
			if (GC.getGameINLINE().isOption(GAMEOPTION_NO_REVOLUTION))
			{
				clearCityCulture();
			}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
			setTurnActive(false);

			gDLL->endMPDiplomacy();
			gDLL->endDiplomacy();

			if (!isHuman())
			{
				gDLL->closeSlot(getID());
			}

			if (GC.getGameINLINE().getElapsedGameTurns() > 0)
			{
				if (!isBarbarian())
				{
					szBuffer = gDLL->getText("TXT_KEY_MISC_CIV_DESTROYED", getCivilizationAdjectiveKey());

					for (iI = 0; iI < MAX_PLAYERS; iI++)
					{
						if (GET_PLAYER((PlayerTypes)iI).isAlive())
						{
/************************************************************************************************/
/* Afforess	                  Start		 04/26/10                                               */
/*                                                                                              */
/*  Report Deaths For Known Teams                                                               */
/************************************************************************************************/
							if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHasMet(getTeam()))
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
							{
								MEMORY_TRACK_EXEMPT();

								AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CIVDESTROYED", MESSAGE_TYPE_MAJOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));
							}
						}
					}

					GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szBuffer, -1, -1, (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));
				}
			}
		}

		GC.getGameINLINE().setScoreDirty(true);
	}
}

/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
//
// It appears that setAlive causes the new player's turn to fire out of turn (if it's not someone else's turn).
// This function is a copy of setAlive with that feature turned off.
void CvPlayer::setNewPlayerAlive(bool bNewValue)
{
	CvWString szBuffer;
	int iI;

	if (isAlive() != bNewValue)
	{
		m_bAlive = bNewValue;

		GET_TEAM(getTeam()).changeAliveCount((isAlive()) ? 1 : -1);

		// Report event to Python
		CvEventReporter::getInstance().setPlayerAlive(getID(), bNewValue);

		if (isAlive())
		{
			if (!isEverAlive())
			{
				m_bEverAlive = true;

				GET_TEAM(getTeam()).changeEverAliveCount(1);
			}

			if (getNumCities() == 0)
			{
				setFoundedFirstCity(false);
			}

			updatePlotGroups();

			// Turned off turn fire on next line
			/*
			if (GC.getGameINLINE().isMPOption(MPOPTION_SIMULTANEOUS_TURNS)) || (GC.getGameINLINE().getNumGameTurnActive() == 0) || (GC.getGameINLINE().isSimultaneousTeamTurns() && GET_TEAM(getTeam()).isTurnActive()))
			{
				setTurnActive(true);
			}
			*/
			gDLL->openSlot(getID());
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      09/03/09                       poyuzhe & jdog5000     */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
			// From Sanguo Mod Performance, ie the CAR Mod
			// Attitude cache
			for( int iI = 0; iI < MAX_PLAYERS; iI++ )
			{
				GET_PLAYER((PlayerTypes)iI).AI_invalidateAttitudeCache(getID());
				GET_PLAYER(getID()).AI_invalidateAttitudeCache((PlayerTypes)iI);
			}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
			// Declare war on all outside teams
			if ( isMinorCiv() )
			{
				GET_TEAM(getTeam()).declareWarAsMinor();
			}
		}
		else
		{
			clearResearchQueue();
			killUnits();
			killCities();
			killAllDeals();

			setTurnActive(false);

			gDLL->endMPDiplomacy();
			gDLL->endDiplomacy();

			if (!isHuman())
			{
				gDLL->closeSlot(getID());
			}

			if (GC.getGameINLINE().getElapsedGameTurns() > 0)
			{
				if (!isBarbarian())
				{
					szBuffer = gDLL->getText("TXT_KEY_MISC_CIV_DESTROYED", getCivilizationAdjectiveKey());

					for (iI = 0; iI < MAX_PLAYERS; iI++)
					{
						if (GET_PLAYER((PlayerTypes)iI).isAlive())
						{
							MEMORY_TRACK_EXEMPT();

							AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CIVDESTROYED", MESSAGE_TYPE_MAJOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));
						}
					}

					GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szBuffer, -1, -1, (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));
				}
			}

			//	Free the now-stale plot groups
			m_plotGroups.removeAll();
		}

		GC.getGameINLINE().setScoreDirty(true);
	}
}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

void CvPlayer::verifyAlive()
{
	bool bKill;

	if (isAlive())
	{
		bKill = false;

		if (!bKill)
		{
			if (!isBarbarian())
			{
				if (getNumCities() == 0 && getAdvancedStartPoints() < 0)
				{
/************************************************************************************************/
/* REVOLUTION_MOD                         02/07/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/* original code
					if ((getNumUnits() == 0) || (!(GC.getGameINLINE().isOption(GAMEOPTION_COMPLETE_KILLS)) && isFoundedFirstCity()))
*/
					// Keep a rebel player alive until they lose all units
					if (getNumUnits() == (AI_getNumAIUnits(UNITAI_SPY) + AI_getNumAIUnits(UNITAI_MERCHANT)) || (!(GC.getGameINLINE().isOption(GAMEOPTION_COMPLETE_KILLS)) && isFoundedFirstCity() && !(isRebel()))) //45° changed so that invisible units (especially Great Spies) are not counted because you can't see them and kill them
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
					{
						bKill = true;
					}
				}
			}
		}

		if (!bKill)
		{
			if (!isBarbarian())
			{
				if (GC.getGameINLINE().getMaxCityElimination() > 0)
				{
					if (getCitiesLost() >= GC.getGameINLINE().getMaxCityElimination())
					{
						bKill = true;
					}
				}
			}
		}

		if (bKill)
		{
			setAlive(false);
/************************************************************************************************/
/* REVOLUTION_MOD                                                                 lemmy101      */
/*                                                                                jdog5000      */
/*                                                                                              */
/************************************************************************************************/
// Choose a random AI to take over if we die when on autoplay. (Testing)
			if(isHumanDisabled())
			{
				int x;
				std::vector<int> Potentials;
				for(x=0;x<MAX_PLAYERS;x++)
				{
					if(GET_PLAYER((PlayerTypes)x).isAlive() && 
						!GET_PLAYER((PlayerTypes)x).isHumanDisabled() && 
						!GET_PLAYER((PlayerTypes)x).isHuman() &&
						GET_PLAYER((PlayerTypes)x).getNumCities() > 0)
					{
						Potentials.push_back(x);
					}
				}

				if(Potentials.empty())
				{
					if(GET_PLAYER((PlayerTypes)x).isAlive() && 
						!GET_PLAYER((PlayerTypes)x).isHumanDisabled() && 
						!GET_PLAYER((PlayerTypes)x).isHuman())
					{
						Potentials.push_back(x);
					}
				}

				int choose = GC.getGame().getSorenRand().get(Potentials.size(), "Picking new player for dead player...");

				GC.getGame().changeHumanPlayer((PlayerTypes)getID(), (PlayerTypes)choose);
			}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
		}
	}
	else
	{
		if ((getNumCities() > 0) || (getNumUnits() > 0))
		{
			setAlive(true);
		}
	}
}


bool CvPlayer::isTurnActive() const																			
{
	return m_bTurnActive;
}

void CvPlayer::setTurnActiveForPbem(bool bActive)
{
	FAssertMsg(GC.getGameINLINE().isPbem(), "You are using setTurnActiveForPbem. Are you sure you know what you're doing?");

	// does nothing more than to set the member variable before saving the game
	// the rest of the turn will be performed upon loading the game
	// This allows the player to browse the game in paused mode after he has generated the save
	if (isTurnActive() != bActive)
	{
		m_bTurnActive = bActive;
		GC.getGameINLINE().changeNumGameTurnActive(isTurnActive() ? 1 : -1);

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      08/21/09                                jdog5000      */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
		// Plot danger cache
		//if( GC.getGameINLINE().getNumGameTurnActive() != 1 )
		{
			GC.getMapINLINE().invalidateIsActivePlayerNoDangerCache();
		}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
	}
}


void CvPlayer::setTurnActive(bool bNewValue, bool bDoTurn)
{
	PROFILE_FUNC();

	MEMORY_TRACE_FUNCTION();

	int iI;

	if (isTurnActive() != bNewValue)
	{
		m_bTurnActive = bNewValue;

		if (isTurnActive())
		{
			PROFILE("CvPlayer::setTurnActive.SetActive");

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				stopProfilingDLL(true);
			}

			if (GC.getLogging())
			{
				if (gDLL->getChtLvl() > 0)
				{
					TCHAR szOut[1024];
					sprintf(szOut, "Player %d Turn ON\n", getID());
					gDLL->messageControlLog(szOut);
				}
			}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      10/26/09                                jdog5000      */
/*                                                                                              */
/* AI logging                                                                                   */
/************************************************************************************************/
			if( gPlayerLogLevel > 0 ) 
			{
				PROFILE("CvPlayer::setTurnActive.SetActive.Log0");

				logBBAI("Player %d (%S) setTurnActive for turn %d", getID(), getCivilizationDescription(0), GC.getGameINLINE().getGameTurn() );
			
				if( GC.getGameINLINE().getGameTurn() > 0 && (GC.getGameINLINE().getGameTurn() % 25) == 0 && !isBarbarian() )
				{
					CvWStringBuffer szBuffer;
					GAMETEXT.setScoreHelp(szBuffer, getID());
					logBBAI("%S", szBuffer.getCString());

					int iGameTurn = GC.getGameINLINE().getGameTurn();
					logBBAI("  Total Score: %d, Population Score: %d (%d total pop), Land Score: %d, Tech Score: %d, Wonder Score: %d", calculateScore(), getPopScore(false), getTotalPopulation(), getLandScore(false), getTechScore(), getWondersScore());
					
					int iEconomy = 0;
					int iProduction = 0;
					int iAgri = 0;
					int iCount = 0;
					for( int iI = 1; iI <= 5; iI++ )
					{
						if( iGameTurn - iI >= 0 )
						{
							iEconomy += getEconomyHistory(iGameTurn - iI);
							iProduction += getIndustryHistory(iGameTurn - iI);
							iAgri += getAgricultureHistory(iGameTurn - iI);
							iCount++;
						}
					}
					iEconomy /= std::max(1, iCount);
					iProduction /= std::max(1, iCount);
					iAgri /= std::max(1, iCount);

					logBBAI("  Economy avg: %d,  Industry avg: %d,  Agriculture avg: %d", iEconomy, iProduction, iAgri);
				}
			}
				
			if( gPlayerLogLevel >= 2 )
			{
				PROFILE("CvPlayer::setTurnActive.SetActive.Log2");

				CvWStringBuffer szBuffer;

				logBBAI("    Player %d (%S) has %d cities, %d pop, %d power, %d tech percent", getID(), getCivilizationDescription(0), getNumCities(), getTotalPopulation(), getPower(), GET_TEAM(getTeam()).getBestKnownTechScorePercent());

				if( GET_PLAYER(getID()).AI_isFinancialTrouble() )
				{
					logBBAI("    Financial trouble!");
				}

				szBuffer.append(CvWString::format(L"    Team %d has met: ", getTeam()));

				for( int iI = 0; iI < MAX_CIV_TEAMS; iI++ )
				{
					if( iI != getTeam() && GET_TEAM(getTeam()).isHasMet((TeamTypes)iI) )
					{
						if( GET_TEAM((TeamTypes)iI).isAlive() )
						{
							szBuffer.append(CvWString::format(L"%d,", iI));
						}
					}
				}

				if( GET_TEAM(getTeam()).getVassalCount() > 0 )
				{
					szBuffer.append(CvWString::format(L";  vassals: "));

					for( int iI = 0; iI < MAX_CIV_TEAMS; iI++ )
					{
						if( iI != getTeam() && GET_TEAM((TeamTypes)iI).isVassal(getTeam()) )
						{
							if( GET_TEAM((TeamTypes)iI).isAlive() )
							{
								szBuffer.append(CvWString::format(L"%d,", iI));
							}
						}
					}
				}

				if( GET_TEAM(getTeam()).getAtWarCount(false) > 0 )
				{
					szBuffer.append(CvWString::format(L";  at war with: "));

					for( int iI = 0; iI < MAX_CIV_TEAMS; iI++ )
					{
						if( iI != getTeam() && GET_TEAM(getTeam()).isAtWar((TeamTypes)iI) )
						{
							if( GET_TEAM((TeamTypes)iI).isAlive() )
							{
								szBuffer.append(CvWString::format(L"%d,", iI));
							}
						}
					}
				}

				if( GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0 )
				{
					szBuffer.append(CvWString::format(L";  planning war with: "));

					for( int iI = 0; iI < MAX_CIV_TEAMS; iI++ )
					{
						if( iI != getTeam() && !GET_TEAM(getTeam()).isAtWar((TeamTypes)iI) && GET_TEAM(getTeam()).AI_getWarPlan((TeamTypes)iI) != NO_WARPLAN )
						{
							if( GET_TEAM((TeamTypes)iI).isAlive() )
							{
								szBuffer.append(CvWString::format(L"%d,", iI));
							}
						}
					}
				}
				
				logBBAI("%S", szBuffer.getCString());

				szBuffer.clear();

				if( GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0 ) logBBAI("    Enemy power perc: %d (%d with others reduction)", GET_TEAM(getTeam()).AI_getEnemyPowerPercent(), GET_TEAM(getTeam()).AI_getEnemyPowerPercent(true));
			}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

			FAssertMsg(isAlive(), "isAlive is expected to be true");

			setEndTurn(false);
			GC.getGameINLINE().resetTurnTimer();

			{
				PROFILE("CvPlayer::setTurnActive.SetActive.CalcDanger");

				//	Calculate plot danger values for this player
				CvPlot* pLoopPlot;

				for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
				{
					pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

					//	Decay danger count from the previous turn
					pLoopPlot->setDangerCount(m_eID, 2*pLoopPlot->getDangerCount(m_eID)/3);
				}

				for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
				{
					pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

					//	Add in known dangers from visible enemy units
					if ( pLoopPlot->isVisible(getTeam(),false) )
					{
						//	Enemies are unconditionally dangerous, but any non-ally
						//	might become an enemy so non-ally troop build ups are also
						//	suspicious except in your own territory (where their
						//	presence implies a treaty)
						int	iDangerCount = pLoopPlot->getVisibleEnemyStrength(m_eID)*2;

						if ( getTeam() != pLoopPlot->getTeam() )
						{
							iDangerCount += pLoopPlot->getVisibleNonAllyStrength(m_eID);
						}
						addPlotDangerSource(pLoopPlot,
											iDangerCount/3);
					}
				}
			}

			// If we are the Pitboss, send this player an email
			if ( gDLL->IsPitbossHost() )
			{
				// If this guy is not currently connected, try sending him an email
				if ( isHuman() && !isConnected() )
				{
					sendReminder();
				}
			}

			if ((GC.getGameINLINE().isHotSeat() || GC.getGameINLINE().isPbem()) && isHuman() && bDoTurn)
			{
				gDLL->getInterfaceIFace()->clearEventMessages();
				GC.setResourceLayer(false);
				//gDLL->getEngineIFace()->setResourceLayer(false);

				GC.getGameINLINE().setActivePlayer(getID());
			}

			GC.getGameINLINE().changeNumGameTurnActive(1);

			//	Update the Great Wall at the start of the active player's turn
			if ( GC.getGame().getActivePlayer() == getID() )
			{
				PROFILE("CvPlayer::setTurnActive.ProcessGW");

				//	Out
				GC.getGame().processGreatWall(false);
				//	...and straight back in
				GC.getGame().processGreatWall(true);
			}

			if (bDoTurn)
			{
				PROFILE("CvPlayer::setTurnActive.SetActive.doTurn");

				m_contractBroker.reset();

				if (isAlive() && !isHuman() && !isBarbarian() && (getAdvancedStartPoints() >= 0))
				{
					AI_doAdvancedStart();
				}
						
				if (GC.getGameINLINE().getElapsedGameTurns() > 0)
				{
					if (isAlive())
					{
						//	Koshling - moved AI turn processing to the START of the turn (ie - before unit movement)
						//	so as to allow units to answer city unit requests
						if (GC.getGameINLINE().isMPOption(MPOPTION_SIMULTANEOUS_TURNS) || !isHuman() )
						{
							doTurn();
						}

						doTurnUnits();
					}
				}

				if ((getID() == GC.getGameINLINE().getActivePlayer()) && (GC.getGameINLINE().getElapsedGameTurns() > 0))
				{
					MEMORY_TRACK_EXEMPT();

					if (GC.getGameINLINE().isNetworkMultiPlayer())
					{
						AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), gDLL->getText("TXT_KEY_MISC_TURN_BEGINS").GetCString(), "AS2D_NEWTURN", MESSAGE_TYPE_DISPLAY_ONLY);
					}
					else
					{
						gDLL->getInterfaceIFace()->playGeneralSound("AS2D_NEWTURN");
					}
				}

				doWarnings();
			}

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				if (gDLL->getInterfaceIFace()->getLengthSelectionList() == 0)
				{
					gDLL->getInterfaceIFace()->setCycleSelectionCounter(1);
				}

				gDLL->getInterfaceIFace()->setDirty(SelectionCamera_DIRTY_BIT, true);
			}
		}
		else
		{
			PROFILE("CvPlayer::setTurnActive.SetInactive");

			setTurnHadUIInteraction(false);

			// start profiling DLL if desired
			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				startProfilingDLL(true);
			}

			if (GC.getLogging())
			{
				if (gDLL->getChtLvl() > 0)
				{
					TCHAR szOut[1024];
					sprintf(szOut, "Player %d Turn OFF\n", getID());
					gDLL->messageControlLog(szOut);
				}
			}

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setForcePopup(false);
				gDLL->getInterfaceIFace()->clearQueuedPopups();
				gDLL->getInterfaceIFace()->flushTalkingHeadMessages();
			}

			GC.getGameINLINE().changeNumGameTurnActive(-1);

			if (bDoTurn)
			{
				PROFILE("CvPlayer::setTurnActive.SetInactive.doTurn");

				if (!GC.getGameINLINE().isMPOption(MPOPTION_SIMULTANEOUS_TURNS))
				{
					if (isAlive())
					{
						if ( isHuman())
						{
							PROFILE("CvPlayer::setTurnActive.SetInactive.doTurn.Human");

							doTurn();
						}
						else
						{
#ifdef USE_UNIT_TENDERING
							getContractBroker().finalizeTenderContracts();
#endif
						}
					}

					if ((GC.getGameINLINE().isPbem() || GC.getGameINLINE().isHotSeat()) && isHuman() && GC.getGameINLINE().countHumanPlayersAlive() > 1)
					{
						GC.getGameINLINE().setHotPbemBetweenTurns(true);
					}

					if (GC.getGameINLINE().isSimultaneousTeamTurns())
					{
						if (!GET_TEAM(getTeam()).isTurnActive())
						{
							for (iI = (getTeam() + 1); iI < MAX_TEAMS; iI++)
							{
								if (GET_TEAM((TeamTypes)iI).isAlive())
								{
									GET_TEAM((TeamTypes)iI).setTurnActive(true);
									break;
								}
							}
						}
					}
					else
					{
						for (iI = (getID() + 1); iI < MAX_PLAYERS; iI++)
						{
							if (GET_PLAYER((PlayerTypes)iI).isAlive())
							{
								if (GC.getGameINLINE().isPbem() && GET_PLAYER((PlayerTypes)iI).isHuman())
								{
									if (!GC.getGameINLINE().getPbemTurnSent())
									{
										gDLL->sendPbemTurn((PlayerTypes)iI);
									}
								}
								else
								{
									GET_PLAYER((PlayerTypes)iI).setTurnActive(true);
								}
								break;
							}
						}
					}
				}
				else if ( isAlive() && !isHuman())
				{
#ifdef USE_UNIT_TENDERING
					getContractBroker().finalizeTenderContracts();
#endif
				}
			}
		}

		gDLL->getInterfaceIFace()->updateCursorType();

		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      08/21/09                                jdog5000      */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
		// Plot danger cache
		//if( GC.getGameINLINE().getNumGameTurnActive() != 1 )
		{
			GC.getMapINLINE().invalidateIsActivePlayerNoDangerCache();
		}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

	}
}

void CvPlayer::addPlotDangerSource(CvPlot* pPlot, int iStrength)
{
	if ( iStrength != 0 )
	{
		PROFILE_FUNC();

		//	Radiate danger to the immediate vicinity
		for (int iDX = -2; iDX <= 2; iDX++ )
		{
			for (int iDY = -2; iDY <= 2; iDY++ )
			{
				CvPlot* pLoopPlot = plotXY(pPlot->getX_INLINE(), pPlot->getY_INLINE(), iDX, iDY);

				if ( pLoopPlot != NULL && pLoopPlot->getArea() == pPlot->getArea() )
				{
					int	iStepDistance = std::max(abs(iDX),abs(iDY));

					pLoopPlot->setDangerCount(m_eID, pLoopPlot->getDangerCount(m_eID) + iStrength/(1<<iStepDistance));
				}
			}
		}
	}
}

bool CvPlayer::isAutoMoves() const																			
{
	return m_bAutoMoves;
}


void CvPlayer::setAutoMoves(bool bNewValue)
{
	PROFILE_FUNC();

	if (isAutoMoves() != bNewValue)
	{
		m_bAutoMoves = bNewValue;

		if (!isAutoMoves())
		{
			if ( isHuman() )
			{
				//	A unit ready to move at this point is one the player needs to interact with
				if ( hasReadyUnit(true) )
				{
					setTurnHadUIInteraction(true);
				}
			}

			if (isEndTurn() || (!isHuman() && !hasReadyUnit(true)))
			{
				setTurnActive(false);
			}
			else
			{
				if (getID() == GC.getGameINLINE().getActivePlayer())
				{
					gDLL->getInterfaceIFace()->setCycleSelectionCounter(1);
				}
			}
		}
	}
}


bool CvPlayer::isEndTurn() const																			
{
	return m_bEndTurn;
}


void CvPlayer::setEndTurn(bool bNewValue)
{
	if (isEndTurn() != bNewValue)
	{
		FAssertMsg(isTurnActive(), "isTurnActive is expected to be true");

		m_bEndTurn = bNewValue;

		if (isEndTurn())
		{
			CvPathGenerator::EnableMaxPerformance(true);
/************************************************************************************************/
/* Afforess	                  Start		 09/16/10                                               */
/*                                                                                              */
/* Advanced Automations                                                                         */
/************************************************************************************************/
			int iLoop;
			for(CvSelectionGroup* pLoopSelectionGroup = firstSelectionGroup(&iLoop); pLoopSelectionGroup; pLoopSelectionGroup = nextSelectionGroup(&iLoop))
			{
				if (pLoopSelectionGroup->getAutomateType() == AUTOMATE_SHADOW)
				{
					pLoopSelectionGroup->setForceUpdate(true);
					pLoopSelectionGroup->AI_update();
				}
			}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
			CvPathGenerator::EnableMaxPerformance(false);
			setAutoMoves(true);
		}
	}
}

bool CvPlayer::isTurnDone() const																			
{
	// if this returns true, popups and diplomacy will wait to appear until next turn
	if (!GC.getGameINLINE().isPbem() && !GC.getGameINLINE().isHotSeat())
	{
		return false;
	}
	if (!isHuman() )
	{
		return true;
	}
	if (!isEndTurn())
	{
		return false;
	}
	return (!isAutoMoves());
}

bool CvPlayer::isExtendedGame() const
{
	return m_bExtendedGame;
}


void CvPlayer::makeExtendedGame()
{
	m_bExtendedGame = true;
}


bool CvPlayer::isFoundedFirstCity() const
{
	return m_bFoundedFirstCity;
}


void CvPlayer::setFoundedFirstCity(bool bNewValue)
{
	if (isFoundedFirstCity() != bNewValue)
	{
		m_bFoundedFirstCity = bNewValue;

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(PercentButtons_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(ResearchButtons_DIRTY_BIT, true);
		}
	}
}


bool CvPlayer::isStrike() const																			
{
	return m_bStrike;
}


void CvPlayer::setStrike(bool bNewValue)
{
	if (isStrike() != bNewValue)
	{
		m_bStrike = bNewValue;

		if (isStrike())
		{
			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), gDLL->getText("TXT_KEY_MISC_UNITS_ON_STRIKE").GetCString(), "AS2D_STRIKE", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));

				gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
			}
		}
	}
}

PlayerTypes CvPlayer::getID() const
{
	return m_eID;
}


HandicapTypes CvPlayer::getHandicapType() const																
{
	return GC.getInitCore().getHandicap(getID());
}


CivilizationTypes CvPlayer::getCivilizationType() const														
{
	return GC.getInitCore().getCiv(getID());
}


LeaderHeadTypes CvPlayer::getLeaderType() const
{
	return GC.getInitCore().getLeader(getID());
}


LeaderHeadTypes CvPlayer::getPersonalityType() const
{
	return m_ePersonalityType;
}


void CvPlayer::setPersonalityType(LeaderHeadTypes eNewValue)
{
	m_ePersonalityType = eNewValue;
}


EraTypes CvPlayer::getCurrentEra() const
{
	return m_eCurrentEra;
}



void CvPlayer::setCurrentEra(EraTypes eNewValue)
{
	CvCity* pLoopCity;
	CvUnit* pLoopUnit;
	CvPlot* pLoopPlot;
	int iLoop;
	int iI;

	if (getCurrentEra() != eNewValue)
	{
		EraTypes eOldEra = m_eCurrentEra;
		m_eCurrentEra = eNewValue;

		if (GC.getGameINLINE().getActiveTeam() != NO_TEAM)
		{
			for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
			{
				pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
				pLoopPlot->updateGraphicEra();

				if (pLoopPlot->getRevealedImprovementType(GC.getGameINLINE().getActiveTeam(), true) != NO_IMPROVEMENT)
				{
					if ((pLoopPlot->getOwnerINLINE() == getID()) || (!(pLoopPlot->isOwned()) && (getID() == GC.getGameINLINE().getActivePlayer())))
					{
						pLoopPlot->setLayoutDirty(true);
					}
				}
			}
		}

		// dirty all of this player's cities...
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			if (pLoopCity->getOwnerINLINE() == getID())
			{
				pLoopCity->setLayoutDirty(true);
			}
		}

		//update unit eras
		for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if ( !pLoopUnit->isUsingDummyEntities() )
			{
				gDLL->getEntityIFace()->updateGraphicEra(pLoopUnit->getUnitEntity(), eOldEra);
			}
		}

		//update flag eras
		gDLL->getInterfaceIFace()->setDirty(Flag_DIRTY_BIT, true);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(Soundtrack_DIRTY_BIT, true);
		}

		if (isHuman() && (getCurrentEra() != GC.getGameINLINE().getStartEra()) && !GC.getGameINLINE().isNetworkMultiPlayer())
		{
			if (GC.getGameINLINE().isFinalInitialized() && !(gDLL->GetWorldBuilderMode()))
			{
				CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_PYTHON_SCREEN);
				if (NULL != pInfo)
				{
					pInfo->setData1(eNewValue);
					pInfo->setText(L"showEraMovie");
					addPopup(pInfo);
				}
			}
		}
	}
}


ReligionTypes CvPlayer::getLastStateReligion() const														
{
	return m_eLastStateReligion;
}


ReligionTypes CvPlayer::getStateReligion() const														
{
	return ((isStateReligion()) ? getLastStateReligion() : NO_RELIGION);
}


void CvPlayer::setLastStateReligion(ReligionTypes eNewValue)
{
	ReligionTypes eOldReligion;
	CvWString szBuffer;
	int iI;

	if (getLastStateReligion() != eNewValue)
	{
		// religion visibility now part of espionage
		//GC.getGameINLINE().updateCitySight(false, true);

		eOldReligion = getLastStateReligion();
		m_eLastStateReligion = eNewValue;

		// religion visibility now part of espionage
		//GC.getGameINLINE().updateCitySight(true, true);

		setMaintenanceDirty(true);
		updateReligionHappiness();
		updateReligionCommerce();

		GC.getGameINLINE().updateSecretaryGeneral();

		GC.getGameINLINE().AI_makeAssignWorkDirty();

		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);

		if (GC.getGameINLINE().isFinalInitialized())
		{
			if (gDLL->isDiplomacy() && (gDLL->getDiplomacyPlayer() == getID()))
			{
				gDLL->updateDiplomacyAttitude(true);
			}

/************************************************************************************************/
/* REVOLUTION_MOD                         01/01/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/* original code
			if (!isBarbarian())
*/
			// Silence announcement for civs who are not alive, ie rebels who may not be born
			if (!isBarbarian() && isAlive())
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
			{
				if (getLastStateReligion() != NO_RELIGION)
				{
					for (iI = 0; iI < MAX_PLAYERS; iI++)
					{
						if (GET_PLAYER((PlayerTypes)iI).isAlive())
						{
							if (GET_TEAM(getTeam()).isHasMet(GET_PLAYER((PlayerTypes)iI).getTeam()))
							{
								MEMORY_TRACK_EXEMPT();

								szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_CONVERT_RELIGION", getNameKey(), GC.getReligionInfo(getLastStateReligion()).getTextKeyWide());
								AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_RELIGION_CONVERT", MESSAGE_TYPE_MAJOR_EVENT);
							}
						}
					}

					szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_CONVERT_RELIGION", getNameKey(), GC.getReligionInfo(getLastStateReligion()).getTextKeyWide());
					GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szBuffer);
				}
			}

			// Python Event
			CvEventReporter::getInstance().playerChangeStateReligion(getID(), eNewValue, eOldReligion);
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      09/03/09                       poyuzhe & jdog5000     */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
			// From Sanguo Mod Performance, ie the CAR Mod
			// Attitude cache
			for (int iI = 0; iI < GC.getMAX_PLAYERS(); iI++)
			{
				if (GET_PLAYER((PlayerTypes)iI).isAlive() && GET_PLAYER((PlayerTypes)iI).getStateReligion() != NO_RELIGION)
				{
					GET_PLAYER(getID()).AI_invalidateAttitudeCache((PlayerTypes)iI);
					GET_PLAYER((PlayerTypes)iI).AI_invalidateAttitudeCache(getID());
				}
			}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
		}
	}
}

PlayerTypes CvPlayer::getParent() const
{
	return m_eParent;
}

void CvPlayer::setParent(PlayerTypes eParent)
{
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      09/03/09                       poyuzhe & jdog5000     */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
	// From Sanguo Mod Performance, ie the CAR Mod
	// Attitude cache
	if (m_eParent != eParent)
	{
		GET_PLAYER(getID()).AI_invalidateAttitudeCache(eParent);
	}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
	m_eParent = eParent;
}

TeamTypes CvPlayer::getTeam() const
{
	return m_eTeamType;
}

void CvPlayer::updateTeamType()
{
	if(getID() == NO_PLAYER)
	{
		m_eTeamType = NO_TEAM;
	}
	else
	{
		m_eTeamType = GC.getInitCore().getTeam(getID());
	}
}

void CvPlayer::setTeam(TeamTypes eTeam)
{
	FAssert(eTeam != NO_TEAM);
	FAssert(getTeam() != NO_TEAM);
/************************************************************************************************/
/* Afforess	                  Start		 07/19/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	TeamTypes eOldTeam = getTeam();
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	GET_TEAM(getTeam()).changeNumMembers(-1);
	if (isAlive())
	{
		GET_TEAM(getTeam()).changeAliveCount(-1);
	}
	if (isEverAlive())
	{
		GET_TEAM(getTeam()).changeEverAliveCount(-1);
	}
	GET_TEAM(getTeam()).changeNumCities(-(getNumCities()));
	GET_TEAM(getTeam()).changeTotalPopulation(-(getTotalPopulation()));
	GET_TEAM(getTeam()).changeTotalLand(-(getTotalLand()));

	GC.getInitCore().setTeam(getID(), eTeam);

	GET_TEAM(getTeam()).changeNumMembers(1);
	if (isAlive())
	{
		GET_TEAM(getTeam()).changeAliveCount(1);
	}
	if (isEverAlive())
	{
		GET_TEAM(getTeam()).changeEverAliveCount(1);
	}
	GET_TEAM(getTeam()).changeNumCities(getNumCities());
	GET_TEAM(getTeam()).changeTotalPopulation(getTotalPopulation());
	GET_TEAM(getTeam()).changeTotalLand(getTotalLand());
/************************************************************************************************/
/* Afforess	                  Start		 07/19/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	bool bAddedMembers = GET_TEAM(eOldTeam).getNumMembers() < GET_TEAM(getTeam()).getNumMembers();
	CvEventReporter::getInstance().addTeam(eOldTeam, getTeam(), bAddedMembers);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      09/03/09                       poyuzhe & jdog5000     */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
	// From Sanguo Mod Performance, ie the CAR Mod
	// Attitude cache
	if (GC.getGameINLINE().isFinalInitialized())
	{
		for (int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if( GET_PLAYER((PlayerTypes)iI).isAlive() )
			{
				GET_PLAYER(getID()).AI_invalidateAttitudeCache((PlayerTypes)iI);
				GET_PLAYER((PlayerTypes)iI).AI_invalidateAttitudeCache(getID());
			}
		}
	}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
}


/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
// RevolutionDCM start - new diplomacy option
void CvPlayer::setDoNotBotherStatus(PlayerTypes playerID)
{
	m_bDoNotBotherStatus = playerID;
}

bool CvPlayer::isDoNotBotherStatus(PlayerTypes playerID) const
{
	return m_bDoNotBotherStatus == playerID;
}
// RevolutionDCM end
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/


PlayerColorTypes CvPlayer::getPlayerColor() const
{
	return GC.getInitCore().getColor(getID());
}

int CvPlayer::getPlayerTextColorR() const
{
	FAssertMsg(getPlayerColor() != NO_PLAYERCOLOR, "getPlayerColor() is not expected to be equal with NO_PLAYERCOLOR");
	return ((int)(GC.getColorInfo((ColorTypes) GC.getPlayerColorInfo(getPlayerColor()).getTextColorType()).getColor().r * 255));
}


int CvPlayer::getPlayerTextColorG() const
{
	FAssertMsg(getPlayerColor() != NO_PLAYERCOLOR, "getPlayerColor() is not expected to be equal with NO_PLAYERCOLOR");
	return ((int)(GC.getColorInfo((ColorTypes) GC.getPlayerColorInfo(getPlayerColor()).getTextColorType()).getColor().g * 255));
}


int CvPlayer::getPlayerTextColorB() const
{
	FAssertMsg(getPlayerColor() != NO_PLAYERCOLOR, "getPlayerColor() is not expected to be equal with NO_PLAYERCOLOR");
	return ((int)(GC.getColorInfo((ColorTypes) GC.getPlayerColorInfo(getPlayerColor()).getTextColorType()).getColor().b * 255));
}


int CvPlayer::getPlayerTextColorA() const
{
	FAssertMsg(getPlayerColor() != NO_PLAYERCOLOR, "getPlayerColor() is not expected to be equal with NO_PLAYERCOLOR");
	return ((int)(GC.getColorInfo((ColorTypes) GC.getPlayerColorInfo(getPlayerColor()).getTextColorType()).getColor().a * 255));
}


int CvPlayer::getSeaPlotYield(YieldTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiSeaPlotYield[eIndex];
}


void CvPlayer::changeSeaPlotYield(YieldTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiSeaPlotYield[eIndex] = (m_aiSeaPlotYield[eIndex] + iChange);

		updateYield();
	}
}


int CvPlayer::getYieldRateModifier(YieldTypes eIndex) const		 
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiYieldRateModifier[eIndex];
}


void CvPlayer::changeYieldRateModifier(YieldTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiYieldRateModifier[eIndex] = (m_aiYieldRateModifier[eIndex] + iChange);

		invalidateYieldRankCache(eIndex);
		
		if (eIndex == YIELD_COMMERCE)
		{
			setCommerceDirty();
		}

		AI_makeAssignWorkDirty();

		if (getTeam() == GC.getGameINLINE().getActiveTeam())
		{
			gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getCapitalYieldRateModifier(YieldTypes eIndex) const		 
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiCapitalYieldRateModifier[eIndex];
}


void CvPlayer::changeCapitalYieldRateModifier(YieldTypes eIndex, int iChange)
{
	CvCity* pCapitalCity;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiCapitalYieldRateModifier[eIndex] = (m_aiCapitalYieldRateModifier[eIndex] + iChange);

		invalidateYieldRankCache(eIndex);

		pCapitalCity = getCapitalCity();

		if (pCapitalCity != NULL)
		{
			if (eIndex == YIELD_COMMERCE)
			{
				pCapitalCity->updateCommerce();
			}

			pCapitalCity->AI_setAssignWorkDirty(true);

			if (pCapitalCity->getTeam() == GC.getGameINLINE().getActiveTeam())
			{
				pCapitalCity->setInfoDirty(true);
			}
		}
	}
}


int CvPlayer::getExtraYieldThreshold(YieldTypes eIndex) const	
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiExtraYieldThreshold[eIndex];
}


void CvPlayer::updateExtraYieldThreshold(YieldTypes eIndex)
{
	int iBestValue;
	int iI;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	iBestValue = 0;

	FAssertMsg((GC.getNumTraitInfos() > 0), "GC.getNumTraitInfos() is less than or equal to zero but is expected to be larger than zero in CvPlayer::updateExtraYieldThreshold");
	for (iI = 0; iI < GC.getNumTraitInfos(); iI++)
	{
		if (hasTrait((TraitTypes)iI))
		{
			if (GC.getTraitInfo((TraitTypes) iI).getExtraYieldThreshold(eIndex) > 0)
			{
				if ((iBestValue == 0) || (GC.getTraitInfo((TraitTypes) iI).getExtraYieldThreshold(eIndex) < iBestValue))
				{
					iBestValue = GC.getTraitInfo((TraitTypes) iI).getExtraYieldThreshold(eIndex);
				}
			}
		}
	}

	if (getExtraYieldThreshold(eIndex) != iBestValue)
	{
		m_aiExtraYieldThreshold[eIndex] = iBestValue;
		FAssert(getExtraYieldThreshold(eIndex) >= 0);

		updateYield();
	}
}


int CvPlayer::getTradeYieldModifier(YieldTypes eIndex) const	
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiTradeYieldModifier[eIndex];
}


void CvPlayer::changeTradeYieldModifier(YieldTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiTradeYieldModifier[eIndex] = (m_aiTradeYieldModifier[eIndex] + iChange);

		updateTradeRoutes();
	}
}


int CvPlayer::getFreeCityCommerce(CommerceTypes eIndex) const												
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	return m_aiFreeCityCommerce[eIndex];
}


void CvPlayer::changeFreeCityCommerce(CommerceTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiFreeCityCommerce[eIndex] = (m_aiFreeCityCommerce[eIndex] + iChange);
		//TB Note: A negative should be allowed

		setCommerceDirty(eIndex);
	}
}


int CvPlayer::getCommercePercent(CommerceTypes eIndex) const												
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiCommercePercent[eIndex];
}


void CvPlayer::setCommercePercent(CommerceTypes eIndex, int iNewValue)
{
	int iTotalCommercePercent;
	int iOldValue;
	int iI;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	iOldValue = getCommercePercent(eIndex);

	m_aiCommercePercent[eIndex] = range(iNewValue, 0, 100);

	if (iOldValue != getCommercePercent(eIndex))
	{
		iTotalCommercePercent = 0;

		for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
		{
			iTotalCommercePercent += getCommercePercent((CommerceTypes)iI);
		}

		for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
		{
			if (iI != eIndex)
			{
				if (100 != iTotalCommercePercent)
				{
					int iAdjustment = std::min(m_aiCommercePercent[iI], iTotalCommercePercent - 100);
					m_aiCommercePercent[iI] -= iAdjustment;
					iTotalCommercePercent -= iAdjustment;
				}
				else
				{
					break;
				}
			}
		}

		FAssert(100 == iTotalCommercePercent);

		setCommerceDirty();

		AI_makeAssignWorkDirty();

		if (getTeam() == GC.getGameINLINE().getActiveTeam())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(CityScreen_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(Financial_Screen_DIRTY_BIT, true);
		}
	}
}


void CvPlayer::changeCommercePercent(CommerceTypes eIndex, int iChange)								
{
	setCommercePercent(eIndex, (getCommercePercent(eIndex) + iChange));
}

int CvPlayer::getCommerceRate(CommerceTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if ( !m_bUpdatesDeferred && m_abCommerceDirty[eIndex] )
	{
		updateCommerce(eIndex, false);
	}

	int iRate = m_aiCommerceRate[eIndex];
	if (GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
	{
		if (eIndex == COMMERCE_CULTURE)
		{
			iRate += m_aiCommerceRate[COMMERCE_ESPIONAGE];
		}
		else if (eIndex == COMMERCE_ESPIONAGE)
		{
			iRate = 0;
		}
	}

	return iRate / 100;  
}
	
int CvPlayer::getTotalCityBaseCommerceRate(CommerceTypes eIndex) const
{
	PROFILE_FUNC();

	int iLoop;
	int	iResult = 0;

	for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iResult += pLoopCity->getBaseCommerceRateTimes100(eIndex);
	}

	return iResult/100;
}

void CvPlayer::changeCommerceRate(CommerceTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiCommerceRate[eIndex] += iChange;

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}

int CvPlayer::getCommerceRateModifier(CommerceTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiCommerceRateModifier[eIndex];
}


void CvPlayer::changeCommerceRateModifier(CommerceTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiCommerceRateModifier[eIndex] = (m_aiCommerceRateModifier[eIndex] + iChange);

		setCityCommerceModifierDirty(eIndex);
		setCommerceDirty(eIndex);

		AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getCapitalCommerceRateModifier(CommerceTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiCapitalCommerceRateModifier[eIndex];
}


void CvPlayer::changeCapitalCommerceRateModifier(CommerceTypes eIndex, int iChange)
{
	CvCity* pCapitalCity;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiCapitalCommerceRateModifier[eIndex] = (m_aiCapitalCommerceRateModifier[eIndex] + iChange);

		pCapitalCity = getCapitalCity();

		if (pCapitalCity != NULL)
		{
			pCapitalCity->setCommerceModifierDirty(eIndex);

			pCapitalCity->AI_setAssignWorkDirty(true);
		}
	}
}


int CvPlayer::getStateReligionBuildingCommerce(CommerceTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiStateReligionBuildingCommerce[eIndex];
}


void CvPlayer::changeStateReligionBuildingCommerce(CommerceTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiStateReligionBuildingCommerce[eIndex] = (m_aiStateReligionBuildingCommerce[eIndex] + iChange);
		FAssert(getStateReligionBuildingCommerce(eIndex) >= 0);

		setCommerceDirty(eIndex);
	}
}


int CvPlayer::getSpecialistExtraCommerce(CommerceTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiSpecialistExtraCommerce[eIndex];
}


void CvPlayer::changeSpecialistExtraCommerce(CommerceTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiSpecialistExtraCommerce[eIndex] = (m_aiSpecialistExtraCommerce[eIndex] + iChange);
		FAssert(getSpecialistExtraCommerce(eIndex) >= 0);

		setCommerceDirty(eIndex);

		AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getCommerceFlexibleCount(CommerceTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiCommerceFlexibleCount[eIndex];
}


bool CvPlayer::isCommerceFlexible(CommerceTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (!isFoundedFirstCity())
	{
		return false;
	}

	if (eIndex == COMMERCE_ESPIONAGE)
	{
		if (0 == GET_TEAM(getTeam()).getHasMetCivCount(true) || GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
		{
			return false;
		}
	}

	return (GC.getCommerceInfo(eIndex).isFlexiblePercent() || (getCommerceFlexibleCount(eIndex) > 0) || GET_TEAM(getTeam()).isCommerceFlexible(eIndex));
}


void CvPlayer::changeCommerceFlexibleCount(CommerceTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_COMMERCE_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiCommerceFlexibleCount[eIndex] = (m_aiCommerceFlexibleCount[eIndex] + iChange);
		FAssert(getCommerceFlexibleCount(eIndex) >= 0);

		if (!isCommerceFlexible(eIndex))
		{
			setCommercePercent(eIndex, 0);
		}

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(PercentButtons_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getGoldPerTurnByPlayer(PlayerTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiGoldPerTurnByPlayer[eIndex];
}


void CvPlayer::changeGoldPerTurnByPlayer(PlayerTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_iGoldPerTurn = (m_iGoldPerTurn + iChange);
		m_aiGoldPerTurnByPlayer[eIndex] = (m_aiGoldPerTurnByPlayer[eIndex] + iChange);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}

		if (!isHuman())
		{
			AI_doCommerce();
		}
	}
}


bool CvPlayer::isFeatAccomplished(FeatTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_FEAT_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_abFeatAccomplished[eIndex];
}


void CvPlayer::setFeatAccomplished(FeatTypes eIndex, bool bNewValue)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_FEAT_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	m_abFeatAccomplished[eIndex] = bNewValue;
}


bool CvPlayer::isOption(PlayerOptionTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_PLAYEROPTION_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_abOptions[eIndex];
}


void CvPlayer::setOption(PlayerOptionTypes eIndex, bool bNewValue)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_PLAYEROPTION_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	m_abOptions[eIndex] = bNewValue;
}

bool CvPlayer::isPlayable() const
{
	return GC.getInitCore().getPlayableCiv(getID());
}

void CvPlayer::setPlayable(bool bNewValue)
{
	GC.getInitCore().setPlayableCiv(getID(), bNewValue);
}


int CvPlayer::getBonusExport(BonusTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBonusInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiBonusExport ? m_paiBonusExport[eIndex] : 0;
}


void CvPlayer::changeBonusExport(BonusTypes eIndex, int iChange)
{
	CvCity* pCapitalCity;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBonusInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		pCapitalCity = getCapitalCity();
		// Koshling - optimised - no need to recalculate the entire plot group's
		// full set of bonuses - jyust adjust the one that is changing
		//if (pCapitalCity != NULL)
		//{
		//	pCapitalCity->plot()->updatePlotGroupBonus(false);
		//}
		m_paiBonusExport[eIndex] = (m_paiBonusExport[eIndex] + iChange);
		FAssert(getBonusExport(eIndex) >= 0);
		if (pCapitalCity != NULL)
		{
			CvPlotGroup*	ownerPlotGroup = pCapitalCity->plotGroup(getID());

			if ( ownerPlotGroup != NULL )
			{
				ownerPlotGroup->changeNumBonuses(eIndex, -iChange);
			}
			//pCapitalCity->plot()->updatePlotGroupBonus(true);
		}
	}
}


int CvPlayer::getBonusImport(BonusTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBonusInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiBonusImport ? m_paiBonusImport[eIndex] : 0;
}


void CvPlayer::changeBonusImport(BonusTypes eIndex, int iChange)
{
	CvCity* pCapitalCity;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBonusInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		pCapitalCity = getCapitalCity();
		// Koshling - optimised - no need to recalculate the entire plot group's
		// full set of bonuses - jyust adjust the one that is changing
		//if (pCapitalCity != NULL)
		//{
		//	pCapitalCity->plot()->updatePlotGroupBonus(false);
		//}
		m_paiBonusImport[eIndex] = (m_paiBonusImport[eIndex] + iChange);
		FAssert(getBonusImport(eIndex) >= 0);
		if (pCapitalCity != NULL)
		{
			CvPlotGroup*	ownerPlotGroup = pCapitalCity->plotGroup(getID());

			if ( ownerPlotGroup != NULL )
			{
				ownerPlotGroup->changeNumBonuses(eIndex, iChange);
			}
			//pCapitalCity->plot()->updatePlotGroupBonus(true);
		}
	}
}


int CvPlayer::getImprovementCount(ImprovementTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumImprovementInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiImprovementCount ? m_paiImprovementCount[eIndex] : 0;
}


void CvPlayer::changeImprovementCount(ImprovementTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumImprovementInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	m_paiImprovementCount[eIndex] = (m_paiImprovementCount[eIndex] + iChange);
	FAssert(getImprovementCount(eIndex) >= 0);
}


int CvPlayer::getFreeBuildingCount(BuildingTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiFreeBuildingCount[eIndex];
}

int CvPlayer::getFreeAreaBuildingCount(BuildingTypes eIndex, CvArea* area) const
{
	int iLoop;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if ( pLoopCity->area() == area )
		{
			//	During city initialisation this can be self-referential so the first city
			//	queried could be the one asking.  Hence take the first non-0 value seen
			if ( pLoopCity->getNumFreeAreaBuilding(eIndex) > 0 )
			{
				return pLoopCity->getNumFreeAreaBuilding(eIndex);
			}
		}
	}

	return 0;
}


bool CvPlayer::isBuildingFree(BuildingTypes eIndex, CvArea* area)	const															
{
	return (getFreeBuildingCount(eIndex) > 0 || (area != NULL && getFreeAreaBuildingCount(eIndex, area) > 0));
}


void CvPlayer::changeFreeBuildingCount(BuildingTypes eIndex, int iChange)
{
	CvCity* pLoopCity;
	int iOldFreeBuildingCount;
	int iLoop;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	iOldFreeBuildingCount = getFreeBuildingCount(eIndex);
	//	Don't allow things to go negative - this has been observed when buildings get disabled across asset chnages
	if ( (iChange > 0 || iOldFreeBuildingCount != 0) && iChange != 0)
	{
		m_paiFreeBuildingCount[eIndex] = (m_paiFreeBuildingCount[eIndex] + iChange);
		FAssert(getFreeBuildingCount(eIndex) >= 0);

		if (iOldFreeBuildingCount == 0)
		{
			FAssertMsg(getFreeBuildingCount(eIndex) > 0, "getFreeBuildingCount(eIndex) is expected to be greater than 0");

			for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->setNumFreeBuilding(eIndex, 1);
			}
		}
		else if (getFreeBuildingCount(eIndex) == 0)
		{
			FAssertMsg(iOldFreeBuildingCount > 0, "iOldFreeBuildingCount is expected to be greater than 0");

			for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->setNumFreeBuilding(eIndex, 0);
			}
		}
	}
}

void CvPlayer::changeFreeAreaBuildingCount(BuildingTypes eIndex, CvArea* area, int iChange)
{
	CvCity* pLoopCity;
	int iOldFreeAreaBuildingCount;
	int iLoop;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	iOldFreeAreaBuildingCount = getFreeAreaBuildingCount(eIndex, area);
	//	Don't allow things to go negative - this has been observed when buildings get disabled across asset changes
	if ( (iChange > 0 || iOldFreeAreaBuildingCount != 0) && iChange != 0)
	{
		int iNewFreeBuildingCount = iOldFreeAreaBuildingCount + iChange;
		FAssert(iNewFreeBuildingCount >= 0);

		if (iOldFreeAreaBuildingCount == 0)
		{
			for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				if ( pLoopCity->area() == area )
				{
					pLoopCity->setNumFreeAreaBuilding(eIndex, 1);
				}
			}
		}
		else if (iNewFreeBuildingCount == 0)
		{
			FAssertMsg(iOldFreeAreaBuildingCount > 0, "iOldFreeAreaBuildingCount is expected to be greater than 0");

			for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				if ( pLoopCity->area() == area )
				{
					pLoopCity->setNumFreeAreaBuilding(eIndex, 0);
				}
			}
		}
	}
}


int CvPlayer::getExtraBuildingHappiness(BuildingTypes eIndex) const 
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiExtraBuildingHappiness[eIndex];
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeExtraBuildingHappiness(BuildingTypes eIndex, int iChange, bool bLimited)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_paiExtraBuildingHappiness[eIndex] += iChange;

		updateExtraBuildingHappiness(bLimited);
	}
}

int CvPlayer::getExtraBuildingHealth(BuildingTypes eIndex) const 
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiExtraBuildingHealth[eIndex];
}


//Fuyu bLimited
void CvPlayer::changeExtraBuildingHealth(BuildingTypes eIndex, int iChange, bool bLimited)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_paiExtraBuildingHealth[eIndex] += iChange;

		updateExtraBuildingHealth(bLimited);
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getFeatureHappiness(FeatureTypes eIndex) const 
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumFeatureInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiFeatureHappiness[eIndex];
}


/********************************************************************************/
/* 	New Civic AI						02.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeFeatureHappiness(FeatureTypes eIndex, int iChange, bool bLimited)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumFeatureInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_paiFeatureHappiness[eIndex] = (m_paiFeatureHappiness[eIndex] + iChange);

		updateFeatureHappiness(bLimited);
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


int CvPlayer::getUnitClassCount(UnitClassTypes eIndex) const 
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumUnitClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiUnitClassCount[eIndex];
}


bool CvPlayer::isUnitClassMaxedOut(UnitClassTypes eIndex, int iExtra) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumUnitClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (!isNationalUnitClass(eIndex))
	{
		return false;
	}
	
	if (GC.getUnitClassInfo(eIndex).isUnlimitedException())
	{
		return false;
	}
	
	FAssertMsg(getUnitClassCount(eIndex) <= GC.getUnitClassInfo(eIndex).getMaxPlayerInstances(), "getUnitClassCount is expected to be less than maximum bound of MaxPlayerInstances (invalid index)");

	return ((getUnitClassCount(eIndex) + iExtra) >= GC.getUnitClassInfo(eIndex).getMaxPlayerInstances());
}


void CvPlayer::changeUnitClassCount(UnitClassTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumUnitClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	m_paiUnitClassCount[eIndex] = (m_paiUnitClassCount[eIndex] + iChange);
	FAssert(getUnitClassCount(eIndex) >= 0);
}


int CvPlayer::getUnitClassMaking(UnitClassTypes eIndex) const									 
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumUnitClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiUnitClassMaking[eIndex];
}


void CvPlayer::changeUnitClassMaking(UnitClassTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumUnitClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		int iOldValue;

		//	Do this in a thread-safe manner
		do
		{
			iOldValue = m_paiUnitClassMaking[eIndex];
		} while( InterlockedCompareExchange((volatile LONG*)&m_paiUnitClassMaking[eIndex], iOldValue + iChange, iOldValue) != iOldValue );
		//m_paiUnitClassMaking[eIndex] = (m_paiUnitClassMaking[eIndex] + iChange);
		FAssert(getUnitClassMaking(eIndex) >= 0);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(Help_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getUnitClassCountPlusMaking(UnitClassTypes eIndex) const
{
	return (getUnitClassCount(eIndex) + getUnitClassMaking(eIndex));
}


int CvPlayer::getBuildingClassCount(BuildingClassTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiBuildingClassCount ? std::max(0, m_paiBuildingClassCount[eIndex]) : 0;
}


bool CvPlayer::isBuildingClassMaxedOut(BuildingClassTypes eIndex, int iExtra) const
{
	PROFILE_FUNC();

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (!isNationalWonderClass(eIndex))
	{
		return false;
	}

	FAssertMsg(getBuildingClassCount(eIndex) <= (GC.getBuildingClassInfo(eIndex).getMaxPlayerInstances() + GC.getBuildingClassInfo(eIndex).getExtraPlayerInstances()), "BuildingClassCount is expected to be less than or match the number of max player instances plus extra player instances");

	return ((getBuildingClassCount(eIndex) + iExtra) >= (GC.getBuildingClassInfo(eIndex).getMaxPlayerInstances() + GC.getBuildingClassInfo(eIndex).getExtraPlayerInstances()));
}


void CvPlayer::changeBuildingClassCount(BuildingClassTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	int iOldValue;

	//	Do this in a thread-safe manner
	do
	{
		iOldValue = m_paiBuildingClassCount[eIndex];
	} while( InterlockedCompareExchange((volatile LONG*)&m_paiBuildingClassCount[eIndex], iOldValue + iChange, iOldValue) != iOldValue );
	//m_paiBuildingClassCount[eIndex] = (m_paiBuildingClassCount[eIndex] + iChange);
	FAssert(getBuildingClassCount(eIndex) >= 0);
		
	clearCanConstructCacheForClass(eIndex);
}


int CvPlayer::getBuildingClassMaking(BuildingClassTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiBuildingClassMaking ? m_paiBuildingClassMaking[eIndex] : 0;
}


void CvPlayer::changeBuildingClassMaking(BuildingClassTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumBuildingClassInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		int iOldValue;

		//	Do this in a thread-safe manner
		do
		{
			iOldValue = m_paiBuildingClassMaking[eIndex];
		} while( InterlockedCompareExchange((volatile LONG*)&m_paiBuildingClassMaking[eIndex], iOldValue + iChange, iOldValue) != iOldValue );
		//m_paiBuildingClassMaking[eIndex] = (m_paiBuildingClassMaking[eIndex] + iChange);
		FAssert(getBuildingClassMaking(eIndex) >= 0);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(Help_DIRTY_BIT, true);
		}

		clearCanConstructCacheForClass(eIndex);
	}
}


int CvPlayer::getBuildingClassCountPlusMaking(BuildingClassTypes eIndex) const
{
	return (getBuildingClassCount(eIndex) + getBuildingClassMaking(eIndex));
}


int CvPlayer::getHurryCount(HurryTypes eIndex) const														
{
	FAssert(eIndex >= 0);
	FAssert(eIndex < GC.getNumHurryInfos());
	return m_paiHurryCount[eIndex];
}


bool CvPlayer::canHurry(HurryTypes eIndex) const
{
	return (getHurryCount(eIndex) > 0);
}


bool CvPlayer::canPopRush()
{
	return (m_iPopRushHurryCount > 0);
}

void CvPlayer::changeHurryCount(HurryTypes eIndex, int iChange)										
{
	FAssert(eIndex >= 0);
	FAssert(eIndex < GC.getNumHurryInfos());

	int oldHurryCount = m_paiHurryCount[eIndex];
	m_paiHurryCount[eIndex] = (m_paiHurryCount[eIndex] + iChange);
	FAssert(getHurryCount(eIndex) >= 0);
	
	// if we just went from 0 to 1 (or the reverse)
	if ((oldHurryCount > 0) != (m_paiHurryCount[eIndex] > 0))
	{
		// does this hurry reduce population?
		if (GC.getHurryInfo(eIndex).getProductionPerPopulation() > 0)
		{
			m_iPopRushHurryCount += iChange;
			FAssert(m_iPopRushHurryCount >= 0);
		}
	}
}

int CvPlayer::getSpecialBuildingNotRequiredCount(SpecialBuildingTypes eIndex) const														
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumSpecialBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiSpecialBuildingNotRequiredCount[eIndex];
}


bool CvPlayer::isSpecialBuildingNotRequired(SpecialBuildingTypes eIndex) const
{
	return (getSpecialBuildingNotRequiredCount(eIndex) > 0);
}


void CvPlayer::changeSpecialBuildingNotRequiredCount(SpecialBuildingTypes eIndex, int iChange)										
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumSpecialBuildingInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	m_paiSpecialBuildingNotRequiredCount[eIndex] = (m_paiSpecialBuildingNotRequiredCount[eIndex] + iChange);
	FAssert(getSpecialBuildingNotRequiredCount(eIndex) >= 0);
}


int CvPlayer::getHasCivicOptionCount(CivicOptionTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumCivicOptionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiHasCivicOptionCount[eIndex];
}


bool CvPlayer::isHasCivicOption(CivicOptionTypes eIndex) const
{
	return (getHasCivicOptionCount(eIndex) > 0);
}


void CvPlayer::changeHasCivicOptionCount(CivicOptionTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumCivicOptionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	m_paiHasCivicOptionCount[eIndex] = (m_paiHasCivicOptionCount[eIndex] + iChange);
	FAssert(getHasCivicOptionCount(eIndex) >= 0);
}


int CvPlayer::getNoCivicUpkeepCount(CivicOptionTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumCivicOptionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiNoCivicUpkeepCount[eIndex];
}


bool CvPlayer::isNoCivicUpkeep(CivicOptionTypes eIndex) const
{
	return (getNoCivicUpkeepCount(eIndex) > 0);
}


void CvPlayer::changeNoCivicUpkeepCount(CivicOptionTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumCivicOptionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_paiNoCivicUpkeepCount[eIndex] = (m_paiNoCivicUpkeepCount[eIndex] + iChange);
		FAssert(getNoCivicUpkeepCount(eIndex) >= 0);

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getHasReligionCount(ReligionTypes eIndex) const													
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumReligionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paiHasReligionCount[eIndex];
}


int CvPlayer::countTotalHasReligion() const
{
	int iCount;
	int iI;

	iCount = 0;

	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		iCount += getHasReligionCount((ReligionTypes)iI);
	}

	return iCount;
}

int CvPlayer::getHasCorporationCount(CorporationTypes eIndex) const													
{
	if (!isActiveCorporation(eIndex))
	{
		return 0;
	}

	return m_paiHasCorporationCount[eIndex];
}


int CvPlayer::countTotalHasCorporation() const
{
	int iCount = 0;

	for (int iI = 0; iI < GC.getNumCorporationInfos(); iI++)
	{
		iCount += getHasCorporationCount((CorporationTypes)iI);
	}

	return iCount;
}

bool CvPlayer::isActiveCorporation(CorporationTypes eIndex) const
{
	if (isNoCorporations())
	{
		return false;
	}

	if (isNoForeignCorporations() && !hasHeadquarters(eIndex))
	{
		return false;
	}
/************************************************************************************************/
/* Afforess	                  Start		 02/17/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (GC.getCorporationInfo(eIndex).getObsoleteTech() != NO_TECH)
	{
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getCorporationInfo(eIndex).getObsoleteTech()))
		{
			return false;
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	return true;
}


int CvPlayer::findHighestHasReligionCount() const
{
	int iValue;
	int iBestValue;
	int iI;

	iBestValue = 0;

	for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
	{
		iValue = getHasReligionCount((ReligionTypes)iI);

		if (iValue > iBestValue)
		{
			iBestValue = iValue;
		}
	}

	return iBestValue;
}


void CvPlayer::changeHasReligionCount(ReligionTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumReligionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_paiHasReligionCount[eIndex] = (m_paiHasReligionCount[eIndex] + iChange);
		FAssert(getHasReligionCount(eIndex) >= 0);

		//AIAndy: Commented out for now to make interfaith project work properly
		//GC.getGameINLINE().updateBuildingCommerce();

		//GC.getGameINLINE().AI_makeAssignWorkDirty();
	}
}


void CvPlayer::changeHasCorporationCount(CorporationTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumCorporationInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_paiHasCorporationCount[eIndex] += iChange;
		FAssert(getHasCorporationCount(eIndex) >= 0);

		//AIAndy: Commented out to keep same as religion one, this expensive function will be called at next turn change anyway
		//GC.getGameINLINE().updateBuildingCommerce();

		//GC.getGameINLINE().AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getUpkeepCount(UpkeepTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumUpkeepInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(m_paiUpkeepCount != NULL, "m_paiUpkeepCount is not expected to be equal with NULL");
	return m_paiUpkeepCount[eIndex];
}


void CvPlayer::changeUpkeepCount(UpkeepTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumUpkeepInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		FAssertMsg(m_paiUpkeepCount != NULL, "m_paiUpkeepCount is not expected to be equal with NULL");
		m_paiUpkeepCount[eIndex] = (m_paiUpkeepCount[eIndex] + iChange);
		FAssertMsg(getUpkeepCount(eIndex) >= 0, "getUpkeepCount(eIndex) is expected to be non-negative (invalid Index)");

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		}
	}
}


int CvPlayer::getSpecialistValidCount(SpecialistTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumSpecialistInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(m_paiSpecialistValidCount != NULL, "m_paiSpecialistValidCount is not expected to be equal with NULL");
	return m_paiSpecialistValidCount[eIndex];
}


bool CvPlayer::isSpecialistValid(SpecialistTypes eIndex) const
{
	return (getSpecialistValidCount(eIndex) > 0);
}


/********************************************************************************/
/* 	New Civic AI						19.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::changeSpecialistValidCount(SpecialistTypes eIndex, int iChange, bool bLimited)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumSpecialistInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		FAssertMsg(m_paiSpecialistValidCount != NULL, "m_paiSpecialistValidCount is not expected to be equal with NULL");
		m_paiSpecialistValidCount[eIndex] = (m_paiSpecialistValidCount[eIndex] + iChange);
		FAssertMsg(getSpecialistValidCount(eIndex) >= 0, "getSpecialistValidCount(eIndex) is expected to be non-negative (invalid Index)");

		if (!bLimited)
		{
			AI_makeAssignWorkDirty();
		}
	}
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/


bool CvPlayer::isResearchingTech(TechTypes eIndex) const	
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumTechInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_pabResearchingTech ? m_pabResearchingTech[eIndex] : false;
}


void CvPlayer::setResearchingTech(TechTypes eIndex, bool bNewValue)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumTechInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");

	if (isResearchingTech(eIndex) != bNewValue)
	{
		m_pabResearchingTech[eIndex] = bNewValue;

		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setDirty(Popup_DIRTY_BIT, true); // to check whether we still need the tech chooser popup
		}
	}
}

bool CvPlayer::isLoyalMember(VoteSourceTypes eVoteSource) const
{
	FAssertMsg(eVoteSource >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eVoteSource < GC.getNumVoteSourceInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_pabLoyalMember[eVoteSource];
}

void CvPlayer::setLoyalMember(VoteSourceTypes eVoteSource, bool bNewValue)
{
	FAssertMsg(eVoteSource >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eVoteSource < MAX_PLAYERS, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (isLoyalMember(eVoteSource) != bNewValue)
	{
		processVoteSourceBonus(eVoteSource, false);
		m_pabLoyalMember[eVoteSource] = bNewValue;
		processVoteSourceBonus(eVoteSource, true);

		GC.getGameINLINE().updateSecretaryGeneral();
	}
}

CivicTypes CvPlayer::getCivics(CivicOptionTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumCivicOptionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_paeCivics != NULL ? m_paeCivics[eIndex] : NO_CIVIC;
}


int CvPlayer::getSingleCivicUpkeep(CivicTypes eCivic, bool bIgnoreAnarchy) const
{
	int iUpkeep;

	if (eCivic == NO_CIVIC)
	{
		return 0;
	}

	if (isNoCivicUpkeep((CivicOptionTypes)(GC.getCivicInfo(eCivic).getCivicOptionType())))
	{
		return 0;
	}

	if (GC.getCivicInfo(eCivic).getUpkeep() == NO_UPKEEP)
	{
		return 0;
	}

	if (!bIgnoreAnarchy)
	{
		if (isAnarchy())
		{
			return 0;
		}
	}

	iUpkeep = 0;

	// BBAI TODO: WTF? civic option type added and subtracted below
/************************************************************************************************/
/* Afforess	                  Start		 06/13/10                                               */
/*                                                                                              */
/*  Sanity Check                                                                                */
/************************************************************************************************/
/*
	iUpkeep += ((std::max(0, (getTotalPopulation() + GC.getDefineINT("UPKEEP_POPULATION_OFFSET") - GC.getCivicInfo(eCivic).getCivicOptionType())) * GC.getUpkeepInfo((UpkeepTypes)(GC.getCivicInfo(eCivic).getUpkeep())).getPopulationPercent()) / 100);
	iUpkeep += ((std::max(0, (getNumCities() + GC.getDefineINT("UPKEEP_CITY_OFFSET") + GC.getCivicInfo(eCivic).getCivicOptionType() - (GC.getNumCivicOptionInfos() / 2))) * GC.getUpkeepInfo((UpkeepTypes)(GC.getCivicInfo(eCivic).getUpkeep())).getCityPercent()) / 100);
*/

	int iTotalPop = getTotalPopulation();
	iTotalPop += GC.getDefineINT("UPKEEP_POPULATION_OFFSET");
	iUpkeep += std::max(0, iTotalPop * GC.getUpkeepInfo((UpkeepTypes)(GC.getCivicInfo(eCivic).getUpkeep())).getPopulationPercent() / 100);
	
	int iNumCities = getNumCities();
	iNumCities += GC.getDefineINT("UPKEEP_CITY_OFFSET");
	iUpkeep += std::max(0, iNumCities * GC.getUpkeepInfo((UpkeepTypes)(GC.getCivicInfo(eCivic).getUpkeep())).getCityPercent() / 100);
	
	iUpkeep *= std::max(0, calculateInflationRate() + 100);
	iUpkeep /= 100;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	iUpkeep *= std::max(0, (getUpkeepModifier() + 100));
	iUpkeep /= 100;

	iUpkeep *= GC.getHandicapInfo(getHandicapType()).getCivicUpkeepPercent();
	iUpkeep /= 100;

	if (!isHuman() && !isBarbarian())
	{
		iUpkeep *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAICivicUpkeepPercent();
		iUpkeep /= 100;

		iUpkeep *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iUpkeep /= 100;
	}

	//ls612: Gold modifiers by Gamespeed
	iUpkeep *= (GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGoldModifier());
	if (iUpkeep != 0)
	{
		iUpkeep /= 100;
	}

	return std::max(0, iUpkeep);
}


int CvPlayer::getCivicUpkeep(CivicTypes* paeCivics, bool bIgnoreAnarchy) const
{
	int iTotalUpkeep;
	int iI;

	if (paeCivics == NULL)
	{
		paeCivics = m_paeCivics;
	}

	iTotalUpkeep = 0;

	for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		iTotalUpkeep += getSingleCivicUpkeep(paeCivics[iI], bIgnoreAnarchy);
	}

/************************************************************************************************/
/* REVOLUTION_MOD                         02/01/08                                jdog5000      */
/*                                                                                              */
/* Rebels pay less civic upkeep                                                                 */
/************************************************************************************************/
	if( isRebel() )
		iTotalUpkeep /= 2;
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

	return iTotalUpkeep;
}


void CvPlayer::setCivics(CivicOptionTypes eIndex, CivicTypes eNewValue)
{
	PROFILE_FUNC();

	CvWString szBuffer;
	CivicTypes eOldCivic;
	int iI;
	CvCity* pLoopCity;

	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < GC.getNumCivicOptionInfos(), "eIndex is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eNewValue >= 0, "eNewValue is expected to be non-negative (invalid Index)");
	FAssertMsg(eNewValue < GC.getNumCivicInfos(), "eNewValue is expected to be within maximum bounds (invalid Index)");

	eOldCivic = getCivics(eIndex);

	if (eOldCivic != eNewValue)
	{
		m_paeCivics[eIndex] = eNewValue;

		if (eOldCivic != NO_CIVIC)
		{
			processCivics(eOldCivic, -1);
		}
		if (getCivics(eIndex) != NO_CIVIC)
		{
			processCivics(getCivics(eIndex), 1);
		}
/************************************************************************************************/
/* Afforess	                  Start		 07/20/10                                               */
/*                                                                                              */
/* Check Buildings, Clear Caches                                                                */
/************************************************************************************************/
		int iLoop;
		bool bUpdateHealth = false;
		bool bUpdateHappiness = false;
		if (eNewValue != NO_CIVIC && eOldCivic != NO_CIVIC)
		{
			CvCivicInfo& kCivic = GC.getCivicInfo(getCivics(eIndex));
			CvCivicInfo& kOldCivic = GC.getCivicInfo(eOldCivic);
			for (iI = 0; iI < GC.getNumImprovementInfos(); iI++)
			{
				if (kCivic.getImprovementHealthPercentChanges(iI) != kOldCivic.getImprovementHealthPercentChanges(iI))
				{
					bUpdateHealth = true;
				}
				if (kCivic.getImprovementHappinessChanges(iI) != kOldCivic.getImprovementHappinessChanges(iI))
				{
					bUpdateHappiness = true;
				}
				if (bUpdateHappiness && bUpdateHealth)
				{
					break;
				}
			}
		}
		else
		{	
			bUpdateHappiness = true;
			bUpdateHealth = true;
		}
		for (pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
		{
			pLoopCity->checkBuildings(false, true, false, false, false);
			if (bUpdateHappiness)
				pLoopCity->updateFeatureHappiness();
			if (bUpdateHealth)
				pLoopCity->updateImprovementHealth();
		}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

		GC.getGameINLINE().updateSecretaryGeneral();

		GC.getGameINLINE().AI_makeAssignWorkDirty();

		if (GC.getGameINLINE().isFinalInitialized())
		{
			if (gDLL->isDiplomacy() && (gDLL->getDiplomacyPlayer() == getID()))
			{
				gDLL->updateDiplomacyAttitude(true);
			}
/************************************************************************************************/
/* REVOLUTION_MOD                         04/28/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
			if (!isBarbarian())
*/
			// Silence announcement for civs that are not alive, ie rebel civs who may not be born
			// and also for minor civs
			if (!isBarbarian() && !isMinorCiv() && isAlive())
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
			{
				if (getCivics(eIndex) != NO_CIVIC)
				{
					if (getCivics(eIndex) != GC.getCivilizationInfo(getCivilizationType()).getCivilizationInitialCivics(eIndex))
					{
						for (iI = 0; iI < MAX_PLAYERS; iI++)
						{
							if (GET_PLAYER((PlayerTypes)iI).isAlive())
							{
								if (GET_TEAM(getTeam()).isHasMet(GET_PLAYER((PlayerTypes)iI).getTeam()))
								{
									MEMORY_TRACK_EXEMPT();

									szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_ADOPTED_CIVIC", getNameKey(), GC.getCivicInfo(getCivics(eIndex)).getTextKeyWide());
									AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MAJOR_EVENT);
								}
							}
						}

						szBuffer = gDLL->getText("TXT_KEY_MISC_PLAYER_ADOPTED_CIVIC", getNameKey(), GC.getCivicInfo(getCivics(eIndex)).getTextKeyWide());
						GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szBuffer);

						CvEventReporter::getInstance().civicChanged(getID(), eOldCivic, getCivics(eIndex));
					}
				}
			}
		}

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      09/03/09                       poyuzhe & jdog5000     */
/*                                                                                              */
/* Efficiency                                                                                   */
/************************************************************************************************/
		// From Sanguo Mod Performance, ie the CAR Mod
		// Attitude cache
		for (iI = 0; iI < MAX_PLAYERS; iI++)
		{
			GET_PLAYER(getID()).AI_invalidateAttitudeCache((PlayerTypes)iI);
			GET_PLAYER((PlayerTypes)iI).AI_invalidateAttitudeCache(getID());
		}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

		//	A new civic can effect best plot build decisions so mark stale in all cities
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			pLoopCity->AI_markBestBuildValuesStale();
		}
	}
}


int CvPlayer::getExtraSpecialistYield(SpecialistTypes eIndex1, YieldTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 expected to be >= 0");
	FAssertMsg(eIndex1 < GC.getNumSpecialistInfos(), "eIndex1 expected to be < GC.getNumSpecialistInfos()");
	FAssertMsg(eIndex2 >= 0, "eIndex2 expected to be >= 0");
	FAssertMsg(eIndex2 < NUM_YIELD_TYPES, "eIndex2 expected to be < NUM_YIELD_TYPES");
	return m_ppaaiSpecialistExtraYield[eIndex1][eIndex2];
}


void CvPlayer::changeExtraSpecialistYield(SpecialistTypes eIndex1, YieldTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 expected to be >= 0");
	FAssertMsg(eIndex1 < GC.getNumSpecialistInfos(), "eIndex1 expected to be < GC.getNumSpecialistInfos()");
	FAssertMsg(eIndex2 >= 0, "eIndex2 expected to be >= 0");
	FAssertMsg(eIndex2 < NUM_YIELD_TYPES, "eIndex2 expected to be < NUM_YIELD_TYPES");

	if (iChange != 0)
	{
		m_ppaaiSpecialistExtraYield[eIndex1][eIndex2] = (m_ppaaiSpecialistExtraYield[eIndex1][eIndex2] + iChange);
		//TB Note: it should be ok to have a negative total Extra Specialist Yield now

		updateExtraSpecialistYield();

		AI_makeAssignWorkDirty();
	}
}


int CvPlayer::getImprovementYieldChange(ImprovementTypes eIndex1, YieldTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumImprovementInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_YIELD_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_ppaaiImprovementYieldChange[eIndex1][eIndex2];
}


void CvPlayer::changeImprovementYieldChange(ImprovementTypes eIndex1, YieldTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumImprovementInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_YIELD_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_ppaaiImprovementYieldChange[eIndex1][eIndex2] = (m_ppaaiImprovementYieldChange[eIndex1][eIndex2] + iChange);
		updateYield();
	}
}

//	When a node is updated in the cycle we assume it won't have chnaged
//	position by more than SEARCH_HORIZON nodes unless bFarMove is true.
//	This is basically just saying that we expect groups which have not moved very far
//	to still be near the units they weer near before they moved, and dramatuically
//	allows us to reduce serach times.  In the evnt of the assumtpion being incorrect
//	the only fall-out is that units will select in not quite the most convenient order
#define	REINSERT_SEARCH_HORIZON	5

// XXX should pUnit be a CvSelectionGroup???
void CvPlayer::updateGroupCycle(CvUnit* pUnit, bool bFarMove)
{
	PROFILE_FUNC();

	CLLNode<IDInfo>* pUnitNode;
	CLLNode<int>* pReinsertSearchStart;
	CLLNode<int>* pSelectionGroupNode;
	CLLNode<int>* pBestSelectionGroupNode;
	CvSelectionGroup* pLoopSelectionGroup;
	CvUnit* pHeadUnit;
	CvUnit* pBeforeUnit;
	CvUnit* pAfterUnit;
	CvUnit* pLoopUnit;
	CvPlot* pPlot;
	int iValue;
	int iBestValue;

	if (!(pUnit->onMap()))
	{
		return;
	}

	if ( isTempUnit(pUnit) )
	{
		return;
	}

	EnterCriticalSection(&c_GroupCycleSection);

	FAssertMsg(pUnit->getGroup() != NULL, "Unit->getGroup() is not assigned a valid value");

	pReinsertSearchStart = removeGroupCycle(pUnit->getGroupID());

	pPlot = pUnit->plot();

	pBeforeUnit = NULL;
	pAfterUnit = NULL;

//TB OOS Fix: Another longshot that did seem to help
	if ( pUnit->getGroup() == NULL )
	{
			::MessageBox(NULL,
						pUnit->getGroupID() == FFreeList::INVALID_INDEX ? "Unit with NULL group ID on call to CvPlayer::updateGroupCycle\n" : "Unit with no group on call to CvPlayer::updateGroupCycle\n",
						"CvGameCoreDLL Diagnostics",
						MB_OK);
	}
	pUnitNode = pPlot->headUnitNode();

	while (pUnitNode != NULL)
	{
		pLoopUnit = ::getUnit(pUnitNode->m_data);
		pUnitNode = pPlot->nextUnitNode(pUnitNode);

 		if ( pLoopUnit->getGroup() == NULL )
		{
			::MessageBox(NULL,
						pLoopUnit->getGroupID() == FFreeList::INVALID_INDEX ? "Unit with NULL group ID found in stack on call to CvPlayer::updateGroupCycle\n" : "Unit with no group found in stack on call to CvPlayer::updateGroupCycle\n",
						"CvGameCoreDLL Diagnostics",
						MB_OK);
		}
		else if (pLoopUnit->isGroupHead())
		{
			if (pLoopUnit != pUnit)
			{
				if (!isBeforeUnitCycle(pLoopUnit, pUnit))
				{
					pBeforeUnit = pLoopUnit;
					break;
				}
				else
				{
					pAfterUnit = pLoopUnit;
				}
			}
		}
	}

	iBestValue = MAX_INT;
	pBestSelectionGroupNode = NULL;

	int	iSearchHorizon;
	
	if ( !bFarMove && pBeforeUnit == NULL && pAfterUnit == NULL )
	{
		iSearchHorizon = REINSERT_SEARCH_HORIZON;

		while( pReinsertSearchStart != NULL && iSearchHorizon-- > 0 )
		{
			pReinsertSearchStart = previousGroupCycleNode(pReinsertSearchStart);
		}
	}

	if ( bFarMove )
	{
		pSelectionGroupNode = headGroupCycleNode();
		iSearchHorizon = MAX_INT;
	}
	else
	{
		pSelectionGroupNode = (pReinsertSearchStart == NULL ? headGroupCycleNode() : pReinsertSearchStart);
		iSearchHorizon = REINSERT_SEARCH_HORIZON*2;	//Horizon in each direction
	}

	while (pSelectionGroupNode != NULL && iSearchHorizon-- > 0)
	{
		pLoopSelectionGroup = getSelectionGroup(pSelectionGroupNode->m_data);
		FAssertMsg(pLoopSelectionGroup != NULL, "LoopSelectionGroup is not assigned a valid value");

		pHeadUnit = pLoopSelectionGroup->getHeadUnit();

		if (pHeadUnit != NULL)
		{
			if (pBeforeUnit != NULL)
			{
				if (pBeforeUnit == pHeadUnit)
				{
					pBestSelectionGroupNode = pSelectionGroupNode;
					break;
				}
			}
			else if (pAfterUnit != NULL)
			{
				if (pAfterUnit == pHeadUnit)
				{
					pBestSelectionGroupNode = nextGroupCycleNode(pSelectionGroupNode);
					break;
				}
			}
			else
			{
				iValue = plotDistance(pUnit->getX_INLINE(), pUnit->getY_INLINE(), pHeadUnit->getX_INLINE(), pHeadUnit->getY_INLINE());

				if (iValue < iBestValue)
				{
					iBestValue = iValue;
					pBestSelectionGroupNode = pSelectionGroupNode;
				}
			}
		}

		pSelectionGroupNode = nextGroupCycleNode(pSelectionGroupNode);
	}

	if (pBestSelectionGroupNode != NULL)
	{
		m_groupCycle.insertBefore(pUnit->getGroupID(), pBestSelectionGroupNode);
	}
	else
	{
		m_groupCycle.insertAtEnd(pUnit->getGroupID());
	}

	LeaveCriticalSection(&c_GroupCycleSection);
}


CLLNode<int>* CvPlayer::removeGroupCycle(int iID)
{
	PROFILE_FUNC();

	CLLNode<int>* pSelectionGroupNode;
	CLLNode<int>* pPreviousNode = NULL;

	EnterCriticalSection(&c_GroupCycleSection);

	pSelectionGroupNode = headGroupCycleNode();

	while (pSelectionGroupNode != NULL)
	{
		if (pSelectionGroupNode->m_data == iID)
		{
			pSelectionGroupNode = deleteGroupCycleNode(pSelectionGroupNode);
			break;
		}
		else
		{
			pPreviousNode = pSelectionGroupNode;
			pSelectionGroupNode = nextGroupCycleNode(pSelectionGroupNode);
		}
	}

	LeaveCriticalSection(&c_GroupCycleSection);

	return pPreviousNode;
}


CLLNode<int>* CvPlayer::deleteGroupCycleNode(CLLNode<int>* pNode)
{
	return m_groupCycle.deleteNode(pNode);
}


CLLNode<int>* CvPlayer::nextGroupCycleNode(CLLNode<int>* pNode) const
{
	return m_groupCycle.next(pNode);
}


CLLNode<int>* CvPlayer::previousGroupCycleNode(CLLNode<int>* pNode) const
{
	return m_groupCycle.prev(pNode);
}


CLLNode<int>* CvPlayer::headGroupCycleNode() const
{
	return m_groupCycle.head();
}


CLLNode<int>* CvPlayer::tailGroupCycleNode() const
{
	return m_groupCycle.tail();
}

// AIAndy: This can cause a large huge amount of paths to be created if there are lots of OR with lots of subsets the same (so especially a very expensive operation when the target tech is far away)
void	CvPlayer::constructTechPathSet(TechTypes eTech, std::vector<techPath*>& pathSet, techPath& rootPath) const
{
	PROFILE_FUNC();

	int i;

	// AIAndy: Consider using a set for efficient testing
	if (GET_TEAM(getTeam()).isHasTech(eTech) || std::find(rootPath.begin(), rootPath.end(), eTech) != rootPath.end())
	{
		//	We have this tech, no reason to add this to the pre-reqs
		return;
	}

	rootPath.push_back(eTech);

	//	Cycle through the and paths and add their tech paths
	for (i = 0; i < GC.getNUM_AND_TECH_PREREQS(); i++)
	{
		TechTypes ePreReq = (TechTypes)GC.getTechInfo(eTech).getPrereqAndTechs(i);

		if (ePreReq != NO_TECH)
		{
			constructTechPathSet(ePreReq, pathSet, rootPath);
		}
	}

	//TechTypes eShortestOr = NO_TECH;
	//int iLowestCost = MAX_INT;
	//	Find the shortest OR tech
	for (i = 0; i < GC.getNUM_OR_TECH_PREREQS(); i++)
	{
		//	Grab the tech
		TechTypes ePreReq = (TechTypes)GC.getTechInfo(eTech).getPrereqOrTechs(i);

		//	If this is a valid tech
		if (ePreReq != NO_TECH)
		{
			techPath* seedPath;

			if ( i == 0 )
			{
				seedPath = &rootPath;
			}
			else
			{
				//	Spawn a copy
				seedPath = new techPath(rootPath);
				pathSet.push_back(seedPath);
			}

			//	Recurse
			constructTechPathSet(ePreReq, pathSet, *seedPath);
		}
	}
}


//	Finds the path length from this tech type to one you already know
int CvPlayer::findPathLength(TechTypes eTech, bool bCost) const
{
	MEMORY_TRACK()

	PROFILE_FUNC();

	if (GET_TEAM(getTeam()).isHasTech(eTech))
	{
		//	We have this tech, no reason to add this to the pre-reqs
		//	Base case return 0, we know it...
		return 0;
	}

	FAssert(eTech >= 0);
	FAssert(eTech < GC.getNumTechInfos());
	if ( (bCost ? m_aiCostPathLengthCache[eTech] : m_aiPathLengthCache[eTech]) == -1 )
	{
		std::vector<techPath*> possiblePaths;
		techPath*	initialSeed = new techPath();

		possiblePaths.push_back(initialSeed);

		constructTechPathSet(eTech, possiblePaths, *initialSeed);

		//	Find the lowest cost of the possible paths
		int	iValue;
		int	iBestValue = MAX_INT;
		//techPath* bestPath = NULL;

		for(std::vector<techPath*>::const_iterator itr = possiblePaths.begin(); itr != possiblePaths.end(); ++itr)
		{
			if ( bCost )
			{
				iValue = 0;

				for(std::vector<TechTypes>::const_iterator itrTechs = (*itr)->begin(); itrTechs != (*itr)->end(); ++itrTechs)
				{
					CvTechInfo& techInfo = GC.getTechInfo(*itrTechs);

					iValue += techInfo.getResearchCost();
				}
			}
			else
			{
				iValue = (*itr)->size();
			}

			if ( iValue < iBestValue )
			{
				iBestValue = iValue;
			}

			delete *itr;
		}
#if 0
		int i;
		int iNumSteps = 0;
		int iShortestPath = 0;
		int iPathLength = 0;
		TechTypes ePreReq;
		TechTypes eShortestOr;

		//	Cycle through the and paths and add up their tech lengths
		for (i = 0; i < GC.getNUM_AND_TECH_PREREQS(); i++)
		{
			ePreReq = (TechTypes)GC.getTechInfo(eTech).getPrereqAndTechs(i);

			if (ePreReq != NO_TECH)
			{
				iPathLength += findPathLength(ePreReq, bCost);
			}
		}

		eShortestOr = NO_TECH;
		iShortestPath = MAX_INT;
		//	Find the shortest OR tech
		for (i = 0; i < GC.getNUM_OR_TECH_PREREQS(); i++)
		{
			//	Grab the tech
			ePreReq = (TechTypes)GC.getTechInfo(eTech).getPrereqOrTechs(i);

			//	If this is a valid tech
			if (ePreReq != NO_TECH)
			{
				//	Recursively find the path length (takes into account all ANDs)
				iNumSteps = findPathLength(ePreReq, bCost);

				//	If the prereq is a valid tech and its the current shortest, mark it as such
				if (iNumSteps < iShortestPath)
				{
					eShortestOr = ePreReq;
					iShortestPath = iNumSteps;
				}
			}
		}

		//	If the shortest OR is a valid tech, add the steps to it...
		if (eShortestOr != NO_TECH)
		{
			iPathLength += iShortestPath;
		}
#endif

		if ( bCost )
		{
			m_aiCostPathLengthCache[eTech] = iBestValue;
		}
		else
		{
			m_aiPathLengthCache[eTech] = iBestValue;
		}
	}

	return bCost ? m_aiCostPathLengthCache[eTech] : m_aiPathLengthCache[eTech];
}


//	Function specifically for python/tech chooser screen
int CvPlayer::getQueuePosition(TechTypes eTech) const
{
	int i = 1;
	CLLNode<TechTypes>* pResearchNode;

	for (pResearchNode = headResearchQueueNode(); pResearchNode; pResearchNode = nextResearchQueueNode(pResearchNode))
	{
		if (pResearchNode->m_data == eTech)
		{
			return i;
		}
		i++;
	}

	return -1;
}


void CvPlayer::clearResearchQueue()
{
	int iI;

	m_researchQueue.clear();

	for (iI = 0; iI < GC.getNumTechInfos(); iI++)
	{
		setResearchingTech(((TechTypes)iI), false);
	}

	if (getTeam() == GC.getGameINLINE().getActiveTeam())
	{
		gDLL->getInterfaceIFace()->setDirty(ResearchButtons_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
	}
}


//	Pushes research onto the queue.  If it is an append if will put it
//	and its pre-reqs into the queue.  If it is not an append it will change
//	research immediately and should be used with clear.  Clear will clear the entire queue.
bool CvPlayer::pushResearch(TechTypes eTech, bool bClear)
{
	int i;
	int iNumSteps;
	int iShortestPath;
	bool bOrPrereqFound;
	TechTypes ePreReq;
	TechTypes eShortestOr;

	FAssertMsg(eTech != NO_TECH, "Tech is not assigned a valid value");

	if (GET_TEAM(getTeam()).isHasTech(eTech) || isResearchingTech(eTech))
	{
		//	We have this tech, no reason to add this to the pre-reqs
		return true;
	}

	if (!canEverResearch(eTech))
	{
		return false;
	}

	//	Pop the entire queue...
	if (bClear)
	{
		clearResearchQueue();
	}

	//	Add in all the pre-reqs for the and techs...
	for (i = 0; i < GC.getNUM_AND_TECH_PREREQS(); i++)
	{
		ePreReq = (TechTypes)GC.getTechInfo(eTech).getPrereqAndTechs(i);

		if (ePreReq != NO_TECH)
		{
			if (!pushResearch(ePreReq))
			{
				return false;
			}
		}
	}

	// Will return the shortest path of all the or techs.  Tie breaker goes to the first one...
	eShortestOr = NO_TECH;
	iShortestPath = MAX_INT;
	bOrPrereqFound = false;
	//	Cycle through all the OR techs
	for (i = 0; i < GC.getNUM_OR_TECH_PREREQS(); i++)
	{
		ePreReq = (TechTypes)GC.getTechInfo(eTech).getPrereqOrTechs(i);

		if (ePreReq != NO_TECH)
		{
			bOrPrereqFound = true;

			//	If the pre-req exists, and we have it, it is the shortest path, get out, we're done
			if (GET_TEAM(getTeam()).isHasTech(ePreReq))
			{
				eShortestOr = ePreReq;
				break;
			}

			if (canEverResearch(ePreReq))
			{
				//	Find the length of the path to this pre-req
				iNumSteps = findPathLength(ePreReq);

				//	If this pre-req is a valid tech, and its the shortest current path, set it as such
				if (iNumSteps < iShortestPath)
				{
					eShortestOr = ePreReq;
					iShortestPath = iNumSteps;
				}
			}
		}
	}

	//	If the shortest path tech is valid, push it (and its children) on to the research queue recursively
	if (eShortestOr != NO_TECH)
	{
		if (!pushResearch(eShortestOr))
		{
			return false;
		}
	}
	else if (bOrPrereqFound)
	{
		return false;
	}

	//	Insert this tech at the end of the queue
	m_researchQueue.insertAtEnd(eTech);

	setResearchingTech(eTech, true);

	//	Set the dirty bits
	if (getTeam() == GC.getGameINLINE().getActiveTeam())
	{
		gDLL->getInterfaceIFace()->setDirty(ResearchButtons_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
	}

	// ONEVENT - Tech selected (any)
	CvEventReporter::getInstance().techSelected(eTech, getID());

	return true;
}


//	If bHead is true we delete the entire queue...
void CvPlayer::popResearch(TechTypes eTech)
{
	CLLNode<TechTypes>* pResearchNode;

	for (pResearchNode = headResearchQueueNode(); pResearchNode; pResearchNode = nextResearchQueueNode(pResearchNode))
	{
		if (pResearchNode->m_data == eTech)
		{
			m_researchQueue.deleteNode(pResearchNode);
			break;
		}
	}

	setResearchingTech(eTech, false);

	if (getTeam() == GC.getGameINLINE().getActiveTeam())
	{
		gDLL->getInterfaceIFace()->setDirty(ResearchButtons_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
	}
}


int CvPlayer::getLengthResearchQueue() const
{
	return m_researchQueue.getLength();
}


CLLNode<TechTypes>* CvPlayer::nextResearchQueueNode(CLLNode<TechTypes>* pNode) const						
{
	return m_researchQueue.next(pNode);
}


CLLNode<TechTypes>* CvPlayer::headResearchQueueNode() const													
{
	return m_researchQueue.head();
}


CLLNode<TechTypes>* CvPlayer::tailResearchQueueNode() const													 
{
	return m_researchQueue.tail();
}


void CvPlayer::addCityName(const CvWString& szName)
{
	m_cityNames.insertAtEnd(szName);
}


int CvPlayer::getNumCityNames() const
{
	return m_cityNames.getLength();
}


CvWString CvPlayer::getCityName(int iIndex) const
{
	CLLNode<CvWString>* pCityNameNode;

	pCityNameNode = m_cityNames.nodeNum(iIndex);

	if (pCityNameNode != NULL)
	{
		return pCityNameNode->m_data;
	}
	else
	{
		return L"";
	}
}


CLLNode<CvWString>* CvPlayer::nextCityNameNode(CLLNode<CvWString>* pNode) const
{
	return m_cityNames.next(pNode);
}


CLLNode<CvWString>* CvPlayer::headCityNameNode() const
{
	return m_cityNames.head();
}


CvPlotGroup* CvPlayer::firstPlotGroup(int *pIterIdx, bool bRev) const
{
	return !bRev ? m_plotGroups.beginIter(pIterIdx) : m_plotGroups.endIter(pIterIdx);
}


CvPlotGroup* CvPlayer::nextPlotGroup(int *pIterIdx, bool bRev) const
{
	return !bRev ? m_plotGroups.nextIter(pIterIdx) : m_plotGroups.prevIter(pIterIdx);
}


int CvPlayer::getNumPlotGroups() const																		
{
	return m_plotGroups.getCount();
}


CvPlotGroup* CvPlayer::getPlotGroup(int iID) const															
{
	return((CvPlotGroup *)(m_plotGroups.getAt(iID)));
}


CvPlotGroup* CvPlayer::addPlotGroup()																	
{
	return((CvPlotGroup *)(m_plotGroups.add()));
}


void CvPlayer::deletePlotGroup(int iID)																
{
#ifdef VALIDATION_FOR_PLOT_GROUPS
	for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

		if ( pLoopPlot->getPlotGroup(getID()) != NULL && pLoopPlot->getPlotGroup(getID())->getID() == iID )
		{
			::MessageBox(NULL, "Deleting in-use plot group!", "CvGameCoreDLL", MB_OK);
		}
	}
#endif
	m_plotGroups.removeAt(iID);
}


CvCity* CvPlayer::firstCity(int *pIterIdx, bool bRev) const
{
	if (bRev)
	{
		*pIterIdx = m_unitsList.size() - 1;
	}
	else
	{
		*pIterIdx = 0;
	}
	CvCityAI* pResult = NULL;
	if (*pIterIdx >= 0 && *pIterIdx < (int)m_citiesList.size())
	{
		pResult = m_citiesList.at(*pIterIdx);
	}
	return pResult;
	//return !bRev ? m_cities.beginIter(pIterIdx) : m_cities.endIter(pIterIdx);
}

CvCity* CvPlayer::nextCity(int *pIterIdx, bool bRev) const
{
	if (bRev)
	{
		(*pIterIdx)--;
	}
	else
	{
		(*pIterIdx)++;
	}
	CvCityAI* pResult = NULL;
	if (*pIterIdx >= 0 && *pIterIdx < (int)m_citiesList.size())
	{
		pResult = m_citiesList.at(*pIterIdx);
	}

	return pResult;
	//return !bRev ? m_cities.nextIter(pIterIdx) : m_cities.prevIter(pIterIdx);
}


CvCity* CvPlayer::nextCityExternal(int *pIterIdx, bool bRev) const
{
	CvCityAI* pResult = (CvCityAI*)nextCity(pIterIdx, bRev);

	while (pResult && !pResult->isInViewport())
	{
		pResult = (CvCityAI*)nextCity(pIterIdx, bRev);
	}

	return pResult;
}

CvCity* CvPlayer::firstCityExternal(int *pIterIdx, bool bRev) const
{
	CvCityAI* pResult = (CvCityAI*)firstCity(pIterIdx, bRev);

	if (pResult && !pResult->isInViewport())
	{
		pResult = (CvCityAI*)nextCityExternal(pIterIdx, bRev);
	}

	return pResult;
}


int CvPlayer::getNumCities() const																			
{
	return m_citiesList.size();
	//return m_cities.getCount();
}


CvCity* CvPlayer::getCity(int iID) const
{
	CvCityAI* pCity = NULL;

	EnterCriticalSection(&m_cModifySection);

	stdext::hash_map<int, CvCityAI*>::const_iterator it = m_citiesMap.find(iID);
	if (it != m_citiesMap.end())
	{
		pCity = it->second;
	}

	LeaveCriticalSection(&m_cModifySection);

	return pCity;
	//return(m_cities.getAt(iID));
}


CvCity* CvPlayer::addCity()
{
	EnterCriticalSection(&m_cModifySection);

	CvCityAI* pCity = new CvCityAI;

	//Ensure we do not collide with an existing id
	CvCity* temp = NULL;
	int id;
	do {
		//Increment id space
		id = m_iLastCityId + 1;
		m_iLastCityId = id;
		temp = getCity(id);
	} while (temp != NULL);

	pCity->setID(id);
	m_citiesList.push_back(pCity);
	m_citiesMap[id] = pCity;

	LeaveCriticalSection(&m_cModifySection);

	return pCity;
	//return(m_cities.add());
}


void CvPlayer::deleteCity(int iID)
{
	EnterCriticalSection(&m_cModifySection);

	CvCityAI* pCity = (CvCityAI*) getCity(iID);

	m_citiesMap.erase(iID);

	std::vector<CvCityAI*>::iterator it;
	for (it = m_citiesList.begin(); it != m_citiesList.end(); ++it)
	{
		CvCityAI* pLoopCity = *it;
		if (pLoopCity == pCity)
		{
			m_citiesList.erase(it);
			break;
		}
	}
	SAFE_DELETE(pCity);

	LeaveCriticalSection(&m_cModifySection);
	//m_cities.removeAt(iID);
}

void CvPlayer::clearAllCities()
{
	std::vector<CvCityAI*>::iterator it;
	for (it = m_citiesList.begin(); it != m_citiesList.end(); ++it)
	{
		CvCityAI* pLoopCity = *it;
		m_citiesMap.erase(pLoopCity->getID());

		SAFE_DELETE(pLoopCity);
	}
	m_citiesList.clear();
	m_citiesMap.clear();
	m_iLastCityId = 0;
}

CvUnit* CvPlayer::firstUnit(int *pIterIdx, bool bRev) const
{
	if (bRev)
	{
		*pIterIdx = m_unitsList.size() - 1;
	}
	else
	{
		*pIterIdx = 0;
	}
	CvUnit* pResult = NULL;
	if (*pIterIdx >= 0 && *pIterIdx < (int)m_unitsList.size())
	{
		pResult = m_unitsList.at(*pIterIdx);
	}

	/*
	CvUnit* pResult = !bRev ? m_units.beginIter(pIterIdx) : m_units.endIter(pIterIdx);
	*/

	if (pResult != NULL && pResult == m_pTempUnit)
	{
		pResult = nextUnit(pIterIdx, bRev);
	}
	return pResult;
}


CvUnit* CvPlayer::nextUnit(int *pIterIdx, bool bRev) const
{
	if (bRev)
	{
		(*pIterIdx)--;
	}
	else
	{
		(*pIterIdx)++;
	}
	CvUnit* pResult = NULL;
	if (*pIterIdx >= 0 && *pIterIdx < (int)m_unitsList.size())
	{
		pResult = m_unitsList.at(*pIterIdx);
	}

	/*
	CvUnit* pResult = !bRev ? m_units.nextIter(pIterIdx) : m_units.prevIter(pIterIdx);
	*/
	if ( pResult != NULL && pResult == m_pTempUnit )
	{
		pResult = nextUnit(pIterIdx, bRev);
	}

	return pResult;
}

CvUnit* CvPlayer::firstUnitExternal(int *pIterIdx, bool bRev) const
{
	CvUnit*	pResult = firstUnit(pIterIdx, bRev);

	if(pResult && !pResult->isInViewport())
	{
		pResult = nextUnitExternal(pIterIdx, bRev);
	}

	return pResult;
}


CvUnit* CvPlayer::nextUnitExternal(int *pIterIdx, bool bRev) const
{
	CvUnit*	pResult = nextUnit(pIterIdx, bRev);

	while(pResult && !pResult->isInViewport())
	{
		pResult = nextUnit(pIterIdx, bRev);
	}

	return pResult;
}


int CvPlayer::getNumUnits() const
{
	return m_unitsList.size() - (m_pTempUnit != NULL ? 1 : 0);
	//return m_units.getCount() - (m_pTempUnit != NULL ? 1 : 0);
}


CvUnit* CvPlayer::getUnit(int iID) const
{
	//return (m_units.getAt(iID));
	CvUnitAI* pUnit = NULL;

	EnterCriticalSection(&m_cModifySection);

	stdext::hash_map<int, CvUnitAI*>::const_iterator it = m_unitsMap.find(iID);
	if (it != m_unitsMap.end())
	{
		pUnit = it->second;
	}

	LeaveCriticalSection(&m_cModifySection);

	return pUnit;
}

CvUnit* CvPlayer::addUnit()																			
{
	EnterCriticalSection(&m_cModifySection);

	CvUnitAI* pUnit = new CvUnitAI;

	//Ensure we do not collide with an existing id
	CvUnit* temp = NULL;
	int id;
	do {
		//Increment id space
		id = m_iLastUnitId + 1;
		m_iLastUnitId = id;
		temp = getUnit(id);
	} while (temp != NULL);

	pUnit->setID(id);
	m_unitsList.push_back(pUnit);
	m_unitsMap[id] = pUnit;

	LeaveCriticalSection(&m_cModifySection);

	return pUnit;
	//return m_units.add();
}


void CvPlayer::deleteUnit(int iID)																	
{
	EnterCriticalSection(&m_cModifySection);

	CvUnitAI* pUnit = (CvUnitAI*)getUnit(iID);

/************************************************************************************************/
/* Afforess	                  Start		 02/27/10                      Coded By: KillMePlease   */
/*                                                                                              */
/* Great Commanders                                                                             */
/************************************************************************************************/
	if (pUnit->isCommander())
	{
		for (int i=0; i < (int)Commanders.size(); i++)
		{
			if (Commanders[i]->getID() == iID)
			{
				Commanders.erase(Commanders.begin() + i);
				//loop through units and delete commander from m_pUsedCommander fields:
				CvUnit* pLoopUnit;
				int iLoop;
				for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
				{
					if (pLoopUnit->getUsedCommander() != NULL && pLoopUnit->getUsedCommander()->getID() == iID)
					{
						pLoopUnit->nullUsedCommander();
					}
				}
				break;
			}
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	
	m_unitsMap.erase(iID);

	std::vector<CvUnitAI*>::iterator it;
	for (it = m_unitsList.begin(); it != m_unitsList.end(); ++it)
	{
		CvUnitAI* pLoopUnit = *it;
		if (pLoopUnit == pUnit)
		{
			m_unitsList.erase(it);
			break;
		}
	}
	SAFE_DELETE(pUnit);

	LeaveCriticalSection(&m_cModifySection);
	//m_units.removeAt(iID);
}

void CvPlayer::clearAllUnits()
{
	std::vector<CvUnitAI*>::iterator it;
	for (it = m_unitsList.begin(); it != m_unitsList.end(); ++it)
	{
		CvUnitAI* pLoopUnit = *it;
		m_unitsMap.erase(pLoopUnit->getID());

		SAFE_DELETE(pLoopUnit);
	}
	m_unitsList.clear();
	m_unitsMap.clear();
	m_iLastUnitId = 0;
	m_pTempUnit = NULL;
}


CvSelectionGroup* CvPlayer::firstSelectionGroup(int *pIterIdx, bool bRev) const
{
	CvSelectionGroup* pResult = !bRev ? m_selectionGroups.beginIter(pIterIdx) : m_selectionGroups.endIter(pIterIdx);

	if ( pResult != NULL && pResult->getHeadUnit() == m_pTempUnit )
	{
		pResult = nextSelectionGroup(pIterIdx, bRev);
	}

	return pResult;
}


CvSelectionGroup* CvPlayer::nextSelectionGroup(int *pIterIdx, bool bRev) const
{
	CvSelectionGroup* pResult = !bRev ? m_selectionGroups.nextIter(pIterIdx) : m_selectionGroups.prevIter(pIterIdx);

	if ( pResult != NULL && pResult->getHeadUnit() == m_pTempUnit )
	{
		pResult = nextSelectionGroup(pIterIdx, bRev);
	}

	return pResult;
}

CvSelectionGroup* CvPlayer::firstSelectionGroupExternal(int *pIterIdx, bool bRev) const
{
	CvSelectionGroup*	pResult = firstSelectionGroup(pIterIdx, bRev);

	if(pResult && pResult->getHeadUnit() != NULL && !pResult->getHeadUnit()->isInViewport())
	{
		pResult = nextSelectionGroupExternal(pIterIdx, bRev);
	}

	return pResult;
}


CvSelectionGroup* CvPlayer::nextSelectionGroupExternal(int *pIterIdx, bool bRev) const
{
	CvSelectionGroup*	pResult = nextSelectionGroup(pIterIdx, bRev);

	while(pResult && pResult->getHeadUnit() != NULL && !pResult->getHeadUnit()->isInViewport())
	{
		pResult = nextSelectionGroup(pIterIdx, bRev);
	}

	return pResult;
}


int CvPlayer::getNumSelectionGroups() const																
{
	return m_selectionGroups.getCount() - (m_pTempUnit != NULL ? 1 : 0);
}


CvSelectionGroup* CvPlayer::getSelectionGroup(int iID) const												
{
	return ((CvSelectionGroup *)(m_selectionGroups.getAt(iID)));
}


CvSelectionGroup* CvPlayer::addSelectionGroup()
{
	return ((CvSelectionGroup *)(m_selectionGroups.add()));
}


void CvPlayer::deleteSelectionGroup(int iID)
{
	bool bRemoved = m_selectionGroups.removeAt(iID);
	
	FAssertMsg(bRemoved, "could not find group, delete failed");
}

EventTriggeredData* CvPlayer::firstEventTriggered(int *pIterIdx, bool bRev) const
{
	return !bRev ? m_eventsTriggered.beginIter(pIterIdx) : m_eventsTriggered.endIter(pIterIdx);
}

EventTriggeredData* CvPlayer::nextEventTriggered(int *pIterIdx, bool bRev) const
{
	return !bRev ? m_eventsTriggered.nextIter(pIterIdx) : m_eventsTriggered.prevIter(pIterIdx);
}

int CvPlayer::getNumEventsTriggered() const
{
	return m_eventsTriggered.getCount();
}

EventTriggeredData* CvPlayer::getEventTriggered(int iID) const
{
	return ((EventTriggeredData*)(m_eventsTriggered.getAt(iID)));
}

EventTriggeredData* CvPlayer::addEventTriggered()
{
	return ((EventTriggeredData*)(m_eventsTriggered.add()));
}

void CvPlayer::deleteEventTriggered(int iID)
{
	m_eventsTriggered.removeAt(iID);
}


void CvPlayer::addMessage(const CvTalkingHeadMessage& message)
{
	MEMORY_TRACK_EXEMPT();

	m_listGameMessages.push_back(message);
}


void CvPlayer::clearMessages()
{
	m_listGameMessages.clear();
}


const CvMessageQueue& CvPlayer::getGameMessages() const
{
	return (m_listGameMessages);
}


void CvPlayer::expireMessages()
{
	CvMessageQueue::iterator it = m_listGameMessages.begin();
	bool bFoundExpired = false;
	while(it != m_listGameMessages.end())
	{
		CvTalkingHeadMessage& message = *it;
		if (GC.getGameINLINE().getGameTurn() >= message.getExpireTurn())
		{
			it = m_listGameMessages.erase(it);
			bFoundExpired = true;
		}
		else
		{
			++it;
		}
	}
	if (bFoundExpired)
	{
		gDLL->getInterfaceIFace()->dirtyTurnLog(getID());
	}
}


void CvPlayer::addPopup(CvPopupInfo* pInfo, bool bFront)
{
	if (isHuman())
	{
		if (bFront)
		{
			m_listPopups.push_front(pInfo);
		}
		else
		{
			m_listPopups.push_back(pInfo);
		}
	}
	else
	{
		SAFE_DELETE(pInfo);
	}
}


void CvPlayer::clearPopups()
{
	CvPopupQueue::iterator it;
	for (it = m_listPopups.begin(); it != m_listPopups.end(); ++it)
	{
		CvPopupInfo* pInfo = *it;
		if (NULL != pInfo)
		{
			delete pInfo;
		}
	}
	m_listPopups.clear();
}


CvPopupInfo* CvPlayer::popFrontPopup()
{
	CvPopupInfo* pInfo = NULL;
	if (!m_listPopups.empty())
	{
		pInfo = m_listPopups.front();
		m_listPopups.pop_front();
	}
	return pInfo;
}


const CvPopupQueue& CvPlayer::getPopups() const
{
	return (m_listPopups);
}


void CvPlayer::addDiplomacy(CvDiploParameters* pDiplo)
{
	if (NULL != pDiplo)
	{
		m_listDiplomacy.push_back(pDiplo);
	}
}


void CvPlayer::clearDiplomacy()
{
	CvDiploQueue::iterator it;
	for (it = m_listDiplomacy.begin(); it != m_listDiplomacy.end(); ++it)
	{
		CvDiploParameters* pDiplo = *it;
		if (NULL != pDiplo)
		{
			delete pDiplo;
		}
	}
	m_listDiplomacy.clear();
}


const CvDiploQueue& CvPlayer::getDiplomacy() const
{
	return (m_listDiplomacy);
}


CvDiploParameters* CvPlayer::popFrontDiplomacy()
{
	CvDiploParameters* pDiplo = NULL;
	if (!m_listDiplomacy.empty())
	{
		pDiplo = m_listDiplomacy.front();
		m_listDiplomacy.pop_front();
	}
	return pDiplo;
}


void CvPlayer::showSpaceShip()
{
	CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_PYTHON_SCREEN);
	pInfo->setData1(-1);
	pInfo->setText(L"showSpaceShip");
	addPopup(pInfo);
}

void CvPlayer::clearSpaceShipPopups()
{
	//clear all spaceship popups
	CvPopupQueue::iterator it;
	for (it = m_listPopups.begin(); it != m_listPopups.end(); )
	{
		CvPopupInfo* pInfo = *it;
		if (NULL != pInfo)
		{
			if(pInfo->getText().compare(L"showSpaceShip") == 0)
			{
				it = m_listPopups.erase(it);
				SAFE_DELETE(pInfo);
			}
			else
			{
				++it;
			}
		}
		else
		{
			++it;
		}
	}
}

int CvPlayer::getScoreHistory(int iTurn) const
{
	CvTurnScoreMap::const_iterator it = m_mapScoreHistory.find(iTurn);
	if (it != m_mapScoreHistory.end())
	{
		return it->second;
	}
	return 0;
}

void CvPlayer::updateScoreHistory(int iTurn, int iBestScore)
{
	if ( isEverAlive() )
	{
		m_mapScoreHistory[iTurn] = iBestScore;
	}
}

int CvPlayer::getEconomyHistory(int iTurn) const
{
	CvTurnScoreMap::const_iterator it = m_mapEconomyHistory.find(iTurn);
	if (it != m_mapEconomyHistory.end())
	{
		return it->second;
	}
	return 0;
}

void CvPlayer::updateEconomyHistory(int iTurn, int iBestEconomy)
{
	m_mapEconomyHistory[iTurn] = iBestEconomy;
}

int CvPlayer::getIndustryHistory(int iTurn) const
{
	CvTurnScoreMap::const_iterator it = m_mapIndustryHistory.find(iTurn);
	if (it != m_mapIndustryHistory.end())
	{
		return it->second;
	}
	return 0;
}

void CvPlayer::updateIndustryHistory(int iTurn, int iBestIndustry)
{
	m_mapIndustryHistory[iTurn] = iBestIndustry;
}

int CvPlayer::getAgricultureHistory(int iTurn) const
{
	CvTurnScoreMap::const_iterator it = m_mapAgricultureHistory.find(iTurn);
	if (it != m_mapAgricultureHistory.end())
	{
		return it->second;
	}
	return 0;
}

void CvPlayer::updateAgricultureHistory(int iTurn, int iBestAgriculture)
{
	m_mapAgricultureHistory[iTurn] = iBestAgriculture;
}

int CvPlayer::getPowerHistory(int iTurn) const
{
	CvTurnScoreMap::const_iterator it = m_mapPowerHistory.find(iTurn);
	if (it != m_mapPowerHistory.end())
	{
		return it->second;
	}
	return 0;
}

void CvPlayer::updatePowerHistory(int iTurn, int iBestPower)
{
	m_mapPowerHistory[iTurn] = iBestPower;
}

int CvPlayer::getCultureHistory(int iTurn) const
{
	CvTurnScoreMap::const_iterator it = m_mapCultureHistory.find(iTurn);
	if (it != m_mapCultureHistory.end())
	{
		return it->second;
	}
	return 0;
}

void CvPlayer::updateCultureHistory(int iTurn, int iBestCulture)
{
	m_mapCultureHistory[iTurn] = iBestCulture;
}

int CvPlayer::getEspionageHistory(int iTurn) const
{
	CvTurnScoreMap::const_iterator it = m_mapEspionageHistory.find(iTurn);
	if (it != m_mapEspionageHistory.end())
	{
		return it->second;
	}
	return 0;
}

void CvPlayer::updateEspionageHistory(int iTurn, int iBestEspionage)
{
	m_mapEspionageHistory[iTurn] = iBestEspionage;
}


/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
// RevolutionDCM - record revolution stability history start
// Data is used for the CvInfo graphs
int CvPlayer::getRevolutionStabilityHistory(int iTurn) const
{
	CvTurnScoreMap::const_iterator it = m_mapRevolutionStabilityHistory.find(iTurn);
	if (it != m_mapRevolutionStabilityHistory.end())
	{
		return it->second;
	}
	return 0;
}

void CvPlayer::updateRevolutionStabilityHistory(int iTurn, int iRevolutionStability)
{
	m_mapRevolutionStabilityHistory[iTurn] = iRevolutionStability;
}
// RevolutionDCM end
/************************************************************************************************/
/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
/************************************************************************************************/


std::string CvPlayer::getScriptData() const
{
	return m_szScriptData;
}

void CvPlayer::setScriptData(std::string szNewValue)
{
	m_szScriptData = szNewValue;
}

const CvString CvPlayer::getPbemEmailAddress() const
{
	return GC.getInitCore().getEmail(getID());
}

void CvPlayer::setPbemEmailAddress(const char* szAddress)
{
	GC.getInitCore().setEmail(getID(), szAddress);
}

const CvString CvPlayer::getSmtpHost() const
{
	return GC.getInitCore().getSmtpHost(getID());
}

void CvPlayer::setSmtpHost(const char* szHost)
{
	GC.getInitCore().setSmtpHost(getID(), szHost);
}

// Protected Functions...

void CvPlayer::doGold()
{
	PROFILE_FUNC()

	bool bStrike;
	int iGoldChange;
	int iDisbandUnit;
	int iI;

/************************************************************************************************/
/* Afforess	                  Start		 12/21/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if(GC.getUSE_CAN_DO_GOLD_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		argsList.add(getID());
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "doGold", argsList.makeFunctionArgs(), &lResult);
		if (lResult == 1)
		{
			return;
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	iGoldChange = calculateGoldRate();

	//	KOSHLING - this assert appears to be out of date.  It gets hit and then handled by the strike
	//	code immediately below which doesn't really have any other purpose
	//FAssert(isHuman() || isBarbarian() || ((getGold() + iGoldChange) >= 0) || isAnarchy());

	changeGold(iGoldChange);

	bStrike = false;

	if (getGold() < 0)
	{
		setGold(0);

		if (!isBarbarian() && (getNumCities() > 0))
		{
			bStrike = true;
		}
	}

	if (bStrike)
	{
		setStrike(true);
		changeStrikeTurns(1);

		if (getStrikeTurns() > 1)
		{
			iDisbandUnit = (getStrikeTurns() / 2); // XXX mod?

			for (iI = 0; iI < iDisbandUnit; iI++)
			{
				disbandUnit(true);

				if (calculateGoldRate() >= 0)
				{
					break;
				}
			}
		}
	}
	else
	{
		setStrike(false);
	}
}


void CvPlayer::doResearch()
{
	PROFILE_FUNC()

	bool bForceResearchChoice;
	int iOverflowResearch;

	for (int iI = 0; iI < GC.getNumTechInfos(); iI++)
	{
		m_aiPathLengthCache[iI] = -1;
		m_aiCostPathLengthCache[iI] = -1;
	}

/************************************************************************************************/
/* Afforess	                  Start		 12/21/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if(GC.getUSE_CAN_DO_RESEARCH_CALLBACK())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		CyArgsList argsList;
		argsList.add(getID());
		long lResult=0;
		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "doResearch", argsList.makeFunctionArgs(), &lResult);
		if (lResult == 1)
		{
			return;
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	if (isResearch())
	{
		bForceResearchChoice = false;

		if (getCurrentResearch() == NO_TECH)
		{
			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				chooseTech();
			}

			if (GC.getGameINLINE().getElapsedGameTurns() > 4)
			{
				AI_chooseResearch();

				bForceResearchChoice = true;
			}
		}

		TechTypes eCurrentTech = getCurrentResearch();
		if (eCurrentTech == NO_TECH)
		{
			int iOverflow = (100 * calculateResearchRate()) / std::max(1, calculateResearchModifier(eCurrentTech));
			changeOverflowResearch(iOverflow);
		}
		else
		{
			iOverflowResearch = (getOverflowResearch() * calculateResearchModifier(eCurrentTech)) / 100;
			setOverflowResearch(0);
			GET_TEAM(getTeam()).changeResearchProgress(eCurrentTech, (calculateResearchRate() + iOverflowResearch), getID());
		}

		if (bForceResearchChoice)
		{
			clearResearchQueue();
		}
	}
}

void CvPlayer::doEspionageOneOffPoints(int iChange)
{
	PROFILE_FUNC()

	if (iChange > 0)
	{
		GET_TEAM(getTeam()).changeEspionagePointsEver(iChange);

		int iSpending = 0;

		// Divide up Espionage between Teams
		for (int iLoop = 0; iLoop < MAX_CIV_TEAMS; iLoop++)
		{
			if (getTeam() != iLoop)
			{
				if (GET_TEAM((TeamTypes)iLoop).isAlive())
				{
					if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iLoop))
					{
						iSpending = getEspionageSpending((TeamTypes)iLoop, iChange);

						if (iSpending > 0)
						{
							GET_TEAM(getTeam()).changeEspionagePointsAgainstTeam((TeamTypes)iLoop, iSpending);
						}
					}
				}
			}
		}
	}	
}

void CvPlayer::doEspionagePoints()
{
	doEspionageOneOffPoints(getCommerceRate(COMMERCE_ESPIONAGE));
}

int CvPlayer::getEspionageSpending(TeamTypes eAgainstTeam, int iTotal) const
{
	int iSpendingValue = 0;

	int iTotalPoints = (iTotal == -1 ? getCommerceRate(COMMERCE_ESPIONAGE) : iTotal);
	int iAvailablePoints = iTotalPoints;

	int iTotalWeight = 0;
	int iBestWeight = 0;

	bool bFoundTeam = false;

	int iLoop;

	// Get sum of all weights to be used later on
	for (iLoop = 0; iLoop < MAX_CIV_TEAMS; iLoop++)
	{
		if (getTeam() != iLoop)
		{
			if (GET_TEAM((TeamTypes)iLoop).isAlive())
			{
				if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iLoop))
				{
					if (iLoop == int(eAgainstTeam))
					{
						bFoundTeam = true;
					}

					int iWeight = getEspionageSpendingWeightAgainstTeam((TeamTypes)iLoop);

					if (iWeight > iBestWeight)
					{
						iBestWeight = iWeight;
					}
					
					iTotalWeight += iWeight;
				}
			}
		}
	}

	// The player requested is not valid
	if (!bFoundTeam)
	{
		return -1;
	}

	// Split up Espionage Point budget based on weights (if any weights have been assigned)
	if (iTotalWeight > 0)
	{
		for (iLoop = 0; iLoop < MAX_CIV_TEAMS; iLoop++)
		{
			if (getTeam() != iLoop)
			{
				if (GET_TEAM((TeamTypes)iLoop).isAlive())
				{
					if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iLoop))
					{
						int iChange = (iTotalPoints * getEspionageSpendingWeightAgainstTeam((TeamTypes)iLoop) / iTotalWeight);
						iAvailablePoints -= iChange;
						
						if (iLoop == int(eAgainstTeam))
						{
							iSpendingValue += iChange;
						}
					}
				}
			}
		}
	}

	// Divide remainder evenly among top Teams
	while (iAvailablePoints > 0)
	{
		for (iLoop = 0; iLoop < MAX_CIV_TEAMS; iLoop++)
		{
			if (getTeam() != iLoop)
			{
				if (GET_TEAM((TeamTypes)iLoop).isAlive())
				{
					if (GET_TEAM(getTeam()).isHasMet((TeamTypes)iLoop))
					{
						if (getEspionageSpendingWeightAgainstTeam((TeamTypes)iLoop) == iBestWeight)
						{
							if (iLoop == int(eAgainstTeam))
							{
								++iSpendingValue;
							}
							--iAvailablePoints;

							if (iAvailablePoints <= 0)
							{
								break;
							}
						}
					}
				}
			}
		}
	}
	
	return iSpendingValue;
}

bool CvPlayer::canDoEspionageMission(EspionageMissionTypes eMission, PlayerTypes eTargetPlayer, const CvPlot* pPlot, int iExtraData, const CvUnit* pUnit) const
{
	if (getID() == eTargetPlayer || NO_PLAYER == eTargetPlayer)
	{
		return false;
	}

	if (!GET_PLAYER(eTargetPlayer).isAlive() || !GET_TEAM(getTeam()).isHasMet(GET_PLAYER(eTargetPlayer).getTeam()))
	{
		return false;
	}

	CvEspionageMissionInfo& kMission = GC.getEspionageMissionInfo(eMission);

	// Need Tech Prereq, if applicable
	if (kMission.getTechPrereq() != NO_TECH)
	{
		if (!GET_TEAM(getTeam()).isHasTech((TechTypes)kMission.getTechPrereq()))
		{
			return false;
		}
	}

	int iCost = getEspionageMissionCost(eMission, eTargetPlayer, pPlot, iExtraData, pUnit);
	if (iCost < 0)
	{
		return false;
	}

	if (NO_PLAYER != eTargetPlayer)
	{
		int iEspionagePoints = GET_TEAM(getTeam()).getEspionagePointsAgainstTeam(GET_PLAYER(eTargetPlayer).getTeam());

		if (iEspionagePoints < iCost)
		{
			return false;
		}

		if (iEspionagePoints <= 0)
		{
			return false;
		}
	}
/************************************************************************************************/
/* SUPER_SPIES                             RevolutionDCM                                                  */
/************************************************************************************************/
	// RevolutionDCM - Super Spies
	// Mod espionage mission control to stop a mission from appearing in the interface where
	// any mission will appear there if it has a cost attached to it. The BTS mission system
	// has no mission state variable for enabling/disabling individual missions.
	CvEspionageMissionInfo& kMissionInfo = GC.getEspionageMissionInfo((EspionageMissionTypes)eMission);

	//Bribe
	if (kMissionInfo.getBuyUnitCostFactor() > 0 && !GC.isSS_BRIBE())
	{
		return false;
	}
	//Assassinate
	if (kMissionInfo.getDestroyUnitCostFactor() > 0 && !GC.isSS_ASSASSINATE())
	{
		return false;
	}
	// RevolutionDCM - end
/************************************************************************************************/
/* SUPER_SPIES                             END                                                  */
/************************************************************************************************/
	
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (kMission.getPrereqGameOption() != NO_GAMEOPTION)
	{
		if (!GC.getGameINLINE().isOption((GameOptionTypes)kMission.getPrereqGameOption()))
		{
			return false;
		}
	}
	if (kMission.isNuke() && !isNukesValid())
	{
		return false;
	}
	if (kMission.isRevolt() && GC.getGameINLINE().isOption(GAMEOPTION_NO_REVOLUTION))
	{
		return false;
	}
	if (kMission.isDisablePower())
	{
		if (pPlot == NULL)
		{
			return false;
		}
		CvCity* pCity = pPlot->getPlotCity();
		if (pCity == NULL)
		{
			return false;
		}
		if (!pCity->isPower())
		{
			return false;
		}
	}
	if (kMission.getWarWearinessCounter() > 0)
	{
		if (GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam()).getAtWarCount(true) == 0)
		{
			return false;
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	return true;
}

int CvPlayer::getEspionageMissionCost(EspionageMissionTypes eMission, PlayerTypes eTargetPlayer, const CvPlot* pPlot, int iExtraData, const CvUnit* pSpyUnit) const
{
	int iMissionCost = getEspionageMissionBaseCost(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit);

	if (-1 == iMissionCost)
	{
		return -1;
	}

	iMissionCost *= getEspionageMissionCostModifier(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit);
	iMissionCost /= 100;

	// Multiply cost of mission * number of team members
	iMissionCost *= GET_TEAM(getTeam()).getNumMembers();

	return std::max(0, iMissionCost);
}

int CvPlayer::getEspionageMissionBaseCost(EspionageMissionTypes eMission, PlayerTypes eTargetPlayer, const CvPlot* pPlot, int iExtraData, const CvUnit* pSpyUnit) const
{
	CvEspionageMissionInfo& kMission = GC.getEspionageMissionInfo(eMission);
	int iBaseMissionCost = kMission.getCost();

	// -1 means this mission is disabled
	if (iBaseMissionCost == -1)
	{
		return -1;
	}

	CvCity* pCity = NULL;
	if (NULL != pPlot)
	{
		pCity = pPlot->getPlotCity();
	}

	if (kMission.isSelectPlot())
	{
		if (NULL == pPlot)
		{
			return -1;
		}

		if (!pPlot->isRevealed(getTeam(), false))
		{
			return -1;
		}
	}

	if (NULL == pCity && kMission.isTargetsCity())
	{
		return -1;
	}

	int iMissionCost = -1;

	if (kMission.getStealTreasuryTypes() > 0)
	{
		// Steal Treasury
		int iNumTotalGold = (GET_PLAYER(eTargetPlayer).getGold() * kMission.getStealTreasuryTypes()) / 100;

		if (NULL != pCity)
		{
			iNumTotalGold *= pCity->getPopulation();
			iNumTotalGold /= std::max(1, GET_PLAYER(eTargetPlayer).getTotalPopulation());
		}

		if (iNumTotalGold > 0)
		{
			iMissionCost = (iBaseMissionCost * iNumTotalGold) / 100;
		}
	}
	else if (kMission.getBuyTechCostFactor() > 0)
	{
		// Buy (Steal) Tech
		TechTypes eTech = (TechTypes)iExtraData;
		int iProdCost = MAX_INT;

		if (NO_TECH == eTech)
		{
			for (int iTech = 0; iTech < GC.getNumTechInfos(); ++iTech)
			{
				if (canStealTech(eTargetPlayer, (TechTypes)iTech))
				{
					int iCost = GET_TEAM(getTeam()).getResearchCost((TechTypes)iTech);
					if (iCost < iProdCost)
					{
						iProdCost = iCost;
						eTech = (TechTypes)iTech;
					}
				}
			}
		}
		else
		{
			iProdCost = GET_TEAM(getTeam()).getResearchCost(eTech);
		}

		if (NO_TECH != eTech)
		{
			if (canStealTech(eTargetPlayer, eTech))
			{
				iMissionCost = iBaseMissionCost + ((100 + kMission.getBuyTechCostFactor()) * iProdCost) / 100;
			}
		}
	}
	else if (kMission.getSwitchCivicCostFactor() > 0)
	{
		// Switch Civics
		CivicTypes eCivic = (CivicTypes)iExtraData;

		if (NO_CIVIC == eCivic)
		{
			for (int iCivic = 0; iCivic < GC.getNumCivicInfos(); ++iCivic)
			{
				if (canForceCivics(eTargetPlayer, (CivicTypes)iCivic))
				{
					eCivic = (CivicTypes)iCivic;
					break;
				}
			}
		}

		if (NO_CIVIC != eCivic)
		{
			if (canForceCivics(eTargetPlayer, eCivic))
			{
				iMissionCost = iBaseMissionCost + (kMission.getSwitchCivicCostFactor() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent()) / 100;
			}
		}
	}
	else if (kMission.getSwitchReligionCostFactor() > 0)
	{
		// Switch Religions
		ReligionTypes eReligion = (ReligionTypes)iExtraData;

		if (NO_RELIGION == eReligion)
		{
			for (int iReligion = 0; iReligion < GC.getNumReligionInfos(); ++iReligion)
			{
				if (canForceReligion(eTargetPlayer, (ReligionTypes)iReligion))
				{
					eReligion = (ReligionTypes)iReligion;
					break;
				}
			}
		}

		if (NO_RELIGION != eReligion)
		{
			if (canForceReligion(eTargetPlayer, eReligion))
			{
				iMissionCost = iBaseMissionCost + (kMission.getSwitchReligionCostFactor() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent()) / 100;
			}
		}
	}
	else if (kMission.getDestroyUnitCostFactor() > 0)
	{
/************************************************************************************************/
/* SUPER_SPIES                             RevolutionDCM                                                  */
/************************************************************************************************/
		//RevolutionDCM start
		//Assassinate
		if (NULL != pSpyUnit)
		{
			if (pSpyUnit->canAssassin(pPlot, false))
			{
				iMissionCost = iBaseMissionCost * kMission.getDestroyUnitCostFactor();
			}
		}
		//RevolutionDCM end
/************************************************************************************************/
/* SUPER_SPIES                             END                                                  */
/************************************************************************************************/
	}	
	else if (kMission.getDestroyProjectCostFactor() > 0)
	{
		ProjectTypes eProject = (ProjectTypes) iExtraData;
		int iCost = MAX_INT;

		if (NO_PROJECT == eProject)
		{
			for (int iProject = 0; iProject < GC.getNumProjectInfos(); ++iProject)
			{
				if (canSpyDestroyProject(eTargetPlayer, (ProjectTypes)iProject))
				{
					int iValue = getProductionNeeded((ProjectTypes)iProject);

					if (iValue < iCost)
					{
						iCost = iValue;
						eProject = (ProjectTypes)iProject;
					}
				}
			}
		}
		else
		{
			iCost = getProductionNeeded(eProject);
		}

		if (NO_PROJECT != eProject)
		{
			if (canSpyDestroyProject(eTargetPlayer, eProject))
			{
				iMissionCost = iBaseMissionCost + ((100 + kMission.getDestroyProjectCostFactor()) * iCost) / 100;
			}
		}
	}
	else if (kMission.getDestroyProductionCostFactor() > 0)
	{
		FAssert(NULL != pCity);
		if (NULL != pCity)
		{
			iMissionCost = iBaseMissionCost + ((100 + kMission.getDestroyProductionCostFactor()) * pCity->getProduction()) / 100;
		}
	}
	else if (kMission.getBuyUnitCostFactor() > 0)
	{
/************************************************************************************************/
/* SUPER_SPIES                             RevolutionDCM                                                  */
/************************************************************************************************/
		//RevolutionDCM start
		//Bribe
		if (NULL != pSpyUnit)
		{
			if (pSpyUnit->canBribe(pPlot, false))
			{
				iMissionCost = iBaseMissionCost * kMission.getBuyUnitCostFactor();
			}
		}
		//RevolutionDCM end
/************************************************************************************************/
/* SUPER_SPIES                             END                                                  */
/************************************************************************************************/
	}
	else if (kMission.getDestroyBuildingCostFactor() > 0)
	{
		BuildingTypes eBuilding = (BuildingTypes) iExtraData;
		int iCost = MAX_INT;

		if (NO_BUILDING == eBuilding)
		{
			for (int iBuilding = 0; iBuilding < GC.getNumBuildingInfos(); ++iBuilding)
			{
				if (NULL != pCity && pCity->getNumRealBuilding((BuildingTypes)iBuilding) > 0)
				{
					if (canSpyDestroyBuilding(eTargetPlayer, (BuildingTypes)iBuilding))
					{
						int iValue = getProductionNeeded((BuildingTypes)iBuilding);

						if (iValue < iCost)
						{
							iCost = iValue;
							eBuilding = (BuildingTypes)iBuilding;
						}
					}
				}
			}
		}
		else
		{
			iCost = getProductionNeeded(eBuilding);
		}

		if (NO_BUILDING != eBuilding)
		{
			if (NULL != pCity && pCity->getNumRealBuilding(eBuilding) > 0)
			{
				if (canSpyDestroyBuilding(eTargetPlayer, eBuilding))
				{
					iMissionCost = iBaseMissionCost + ((100 + kMission.getDestroyBuildingCostFactor()) * iCost) / 100;
				}
			}
		}
	}
	else if (kMission.getBuyCityCostFactor() > 0)
	{
		// Buy City
		if (NULL != pCity)
		{
			iMissionCost = iBaseMissionCost + (kMission.getBuyCityCostFactor() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent()) / 10000;
		}
	}
	else if (kMission.getCityInsertCultureCostFactor() > 0)
	{
		// Insert Culture into City
		if (NULL != pPlot && pPlot->getCulture(getID()) > 0)
		{
			int iCultureAmount = kMission.getCityInsertCultureAmountFactor() *  pCity->countTotalCultureTimes100();
			iCultureAmount /= 10000;
			iCultureAmount = std::max(1, iCultureAmount);
			iMissionCost = iBaseMissionCost + (kMission.getCityInsertCultureCostFactor() * iCultureAmount) / 100;
		}
	}
	else if (kMission.isDestroyImprovement())
	{
		if (NULL != pPlot && !pPlot->isCity())
		{
			if (pPlot->getImprovementType() != NO_IMPROVEMENT || pPlot->getRouteType() != NO_ROUTE)
			{
				iMissionCost = (iBaseMissionCost * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getBuildPercent()) / 100;
			}
		}
	}
	else if (kMission.getCityPoisonWaterCounter() > 0)
	{
		FAssert(NULL != pCity);
		// Cannot poison a city's water supply if it's already poisoned (value is negative when active)
		if (NULL != pCity && pCity->getEspionageHealthCounter() <= 0)
		{
			iMissionCost = iBaseMissionCost;
		}
	}

	// Make city unhappy
	else if (kMission.getCityUnhappinessCounter() > 0)
	{
		FAssert(NULL != pCity);
		// Cannot make a city unhappy if you've already done it (value is negative when active)
		if (NULL != pCity && pCity->getEspionageHappinessCounter() <= 0)
		{
			iMissionCost = iBaseMissionCost;
		}
	}

	// Make city Revolt
	else if (kMission.getCityRevoltCounter() > 0)
	{
		FAssert(NULL != pCity);
		// Cannot make a city revolt if it's already revolting
		if (NULL != pCity && pCity->getOccupationTimer() == 0)
		{
			iMissionCost = iBaseMissionCost;
		}
	}
	else if (kMission.getCounterespionageMod() > 0)
	{
		if (GET_TEAM(getTeam()).getCounterespionageTurnsLeftAgainstTeam(GET_PLAYER(eTargetPlayer).getTeam()) <= 0)
		{
			iMissionCost = (iBaseMissionCost * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent()) / 100;
		}
	}
	else if (kMission.getPlayerAnarchyCounter() > 0)
	{
		// Player anarchy timer: can't add more turns of anarchy to player already in the midst of it
		if (!GET_PLAYER(eTargetPlayer).isAnarchy())
		{
			iMissionCost = (iBaseMissionCost * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent()) / 100;
		}
	}
/************************************************************************************************/
/* Afforess	                  Start		 07/12/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	else if (kMission.getSabatogeResearchCostFactor() > 0)
	{
		if (GET_PLAYER(eTargetPlayer).getCurrentResearch() != NO_TECH)
		{
			if (GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam()).getResearchProgress(GET_PLAYER(eTargetPlayer).getCurrentResearch()) > 0)
			{
				iMissionCost = iBaseMissionCost + (kMission.getSabatogeResearchCostFactor() * GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam()).getResearchProgress(GET_PLAYER(eTargetPlayer).getCurrentResearch()) / 100);
			}
		}
	}
	else if (kMission.getRemoveReligionsCostFactor() > 0)
	{
		if (NULL != pCity)
		{
			ReligionTypes eReligion = (ReligionTypes)iExtraData;
			
			if (NO_RELIGION == eReligion)
			{
				for (int iReligion = 0; iReligion < GC.getNumReligionInfos(); ++iReligion)
				{
					if (pCity->isHasReligion((ReligionTypes)iReligion) && !pCity->isHolyCity((ReligionTypes)iReligion))
					{
						eReligion = (ReligionTypes)iReligion;
						break;
					}
				}
			}

			if (NO_RELIGION != eReligion)
			{
				if (pCity->isHasReligion(eReligion) && !pCity->isHolyCity(eReligion))
				{
					iMissionCost = iBaseMissionCost + (kMission.getRemoveReligionsCostFactor() * pCity->getPopulation() / pCity->getNonHolyReligionCount());
					if (pCity->getNonHolyReligionCount() == 1)
					{
						iMissionCost *= 2;
					}
					iMissionCost *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent();
					iMissionCost /= 100;
					if (GET_PLAYER(eTargetPlayer).getStateReligion() == eReligion)
					{
						iMissionCost *= 2;
					}
				}
			}
		}
	}
	else if (kMission.getRemoveCorporationsCostFactor() > 0)
	{
		if (NULL != pCity)
		{
			CorporationTypes eCorporation = (CorporationTypes)iExtraData;
			
			if (NO_CORPORATION == eCorporation)
			{
				for (int iCorp = 0; iCorp < GC.getNumCorporationInfos(); ++iCorp)
				{
					if (pCity->isActiveCorporation((CorporationTypes)iCorp) && GC.getGameINLINE().getHeadquarters((CorporationTypes)iCorp) != pCity)
					{
						eCorporation = (CorporationTypes)iCorp;
						break;
					}
				}
			}

			if (NO_CORPORATION != eCorporation)
			{
				if (pCity->isActiveCorporation(eCorporation)&& GC.getGameINLINE().getHeadquarters(eCorporation) != pCity)
				{
					iMissionCost = iBaseMissionCost + (kMission.getRemoveCorporationsCostFactor() * pCity->getPopulation() / pCity->getCorporationCount());
					iMissionCost *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent();
					iMissionCost /= 100;
					if (GC.getGameINLINE().getHeadquarters(eCorporation) != NULL && GC.getGameINLINE().getHeadquarters(eCorporation)->getOwnerINLINE() == eTargetPlayer)
					{
						iMissionCost *= 2;
					}
				}
			}
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	else if (kMission.isPassive())
	{
		iMissionCost = (iBaseMissionCost * (100 + GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam()).getEspionagePointsAgainstTeam(getTeam()))) / 100;
	}
	else
	{
		iMissionCost = (iBaseMissionCost * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent()) / 100;
	}

	if (iMissionCost < 0)
	{
		return -1;
	}

	return iMissionCost;
}


int CvPlayer::getEspionageMissionCostModifier(EspionageMissionTypes eMission, PlayerTypes eTargetPlayer, const CvPlot* pPlot, int iExtraData, const CvUnit* pSpyUnit) const
{
	CvEspionageMissionInfo& kMission = GC.getEspionageMissionInfo(eMission);
	int iModifier = 100;

	CvCity* pCity = NULL;
	if (NULL != pPlot)
	{
		pCity = pPlot->getPlotCity();
	}

	if (NO_PLAYER == eTargetPlayer)
	{
		eTargetPlayer = getID();
	}

	if (pCity != NULL && kMission.isTargetsCity())
	{
		// City Population
		iModifier *= 100 + (GC.getDefineINT("ESPIONAGE_CITY_POP_EACH_MOD") * (pCity->getPopulation() - 1));
		iModifier /= 100;

		// Trade Route
		if (pCity->isTradeRoute(getID()))
		{
			iModifier *= 100 + GC.getDefineINT("ESPIONAGE_CITY_TRADE_ROUTE_MOD");
			iModifier /= 100;
		}

		ReligionTypes eReligion = getStateReligion();
		if (NO_RELIGION != eReligion)
		{
			int iReligionModifier = 0;

			// City has Your State Religion
			if (pCity->isHasReligion(eReligion))
			{
				if (GET_PLAYER(eTargetPlayer).getStateReligion() != eReligion)
				{
					iReligionModifier += GC.getDefineINT("ESPIONAGE_CITY_RELIGION_STATE_MOD");
				}

				if (hasHolyCity(eReligion))
				{
					iReligionModifier += GC.getDefineINT("ESPIONAGE_CITY_HOLY_CITY_MOD");
				}
			}

			iModifier *= 100 + iReligionModifier;
			iModifier /= 100;

		}

		// City's culture affects cost
		iModifier *= 100 - (pCity->getCultureTimes100(getID()) * GC.getDefineINT("ESPIONAGE_CULTURE_MULTIPLIER_MOD")) / std::max(1, pCity->getCultureTimes100(eTargetPlayer) + pCity->getCultureTimes100(getID()));
		iModifier /= 100;

		iModifier *= 100 + pCity->getEspionageDefenseModifier();
		iModifier /= 100;
	}

	// Distance mod
	if (pPlot != NULL)
	{
		int iDistance = GC.getMap().maxPlotDistance();

		CvCity* pOurCapital = getCapitalCity();
		if (NULL != pOurCapital)
		{
			if (kMission.isSelectPlot() || kMission.isTargetsCity())
			{
				iDistance = plotDistance(pOurCapital->getX_INLINE(), pOurCapital->getY_INLINE(), pPlot->getX_INLINE(), pPlot->getY_INLINE());
			}
			else
			{
				CvCity* pTheirCapital = GET_PLAYER(eTargetPlayer).getCapitalCity();
				if (NULL != pTheirCapital)
				{
					iDistance = plotDistance(pOurCapital->getX_INLINE(), pOurCapital->getY_INLINE(), pTheirCapital->getX_INLINE(), pTheirCapital->getY_INLINE());
				}
			}
		}

		iModifier *= (iDistance + GC.getMapINLINE().maxPlotDistance()) * GC.getDefineINT("ESPIONAGE_DISTANCE_MULTIPLIER_MOD") / GC.getMapINLINE().maxPlotDistance();
		iModifier /= 100;
	}

	// Spy presence mission cost alteration
	if (NULL != pSpyUnit)
	{
        //TSHEEP - add in discount promotions
        //iModifier *= 100 - (pSpyUnit->getFortifyTurns() * GC.getDefineINT("ESPIONAGE_EACH_TURN_UNIT_COST_DECREASE"));
        iModifier *= 100 - (std::min(5,(pSpyUnit->getFortifyTurns() + (pSpyUnit->getUpgradeDiscount()/10))) * GC.getDefineINT("ESPIONAGE_EACH_TURN_UNIT_COST_DECREASE"));
        //TSHEEP End
		iModifier /= 100;
	}

	// My points VS. Your points to mod cost
	int iTargetPoints = GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam()).getEspionagePointsEver();
	int iOurPoints = GET_TEAM(getTeam()).getEspionagePointsEver();
	iModifier *= (GC.getDefineINT("ESPIONAGE_SPENDING_MULTIPLIER") * (2 * iTargetPoints + iOurPoints)) / std::max(1, iTargetPoints + 2 * iOurPoints);
	iModifier /= 100;
	
	// Counterespionage Mission Mod
	CvTeam& kTargetTeam = GET_TEAM(GET_PLAYER(eTargetPlayer).getTeam());
	if (kTargetTeam.getCounterespionageModAgainstTeam(getTeam()) > 0)
	{
		iModifier *= kTargetTeam.getCounterespionageModAgainstTeam(getTeam());
		iModifier /= 100;
	}

/************************************************************************************************/
/* Afforess	                  Start		 6/27/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
    if (pCity != NULL)
	{
		if (pCity == GET_PLAYER(eTargetPlayer).getCapitalCity() && GET_TEAM(getTeam()).isHasEmbassy(GET_PLAYER(eTargetPlayer).getTeam()))
		{
			iModifier *= 100 - GC.getDefineINT("EMBASSY_ESPIONAGE_MISSION_COST_MODIFIER");
			iModifier /= 100;
		}
		if (GET_TEAM(getTeam()).isFreeTradeAgreement(GET_PLAYER(eTargetPlayer).getTeam()))
		{
			iModifier *= 100 - GC.getDefineINT("FREE_TRADE_AGREEMENT_ESPIONAGE_MISSION_COST_MODIFIER");
			iModifier /= 100;
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	return iModifier;
}

/************************************************************************************************/
/* Afforess	                  Start		 02/01/10                                               */
/*                                                                                              */
/*        New Parameter                                                                         */
/************************************************************************************************/
bool CvPlayer::doEspionageMission(EspionageMissionTypes eMission, PlayerTypes eTargetPlayer, CvPlot* pPlot, int iExtraData, CvUnit* pSpyUnit, bool bCaught)
{
	TCHAR szSound[1024] = "AS2D_DEAL_CANCELLED";

/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	if (!canDoEspionageMission(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit))
	{
		return false;
	}

	TeamTypes eTargetTeam = NO_TEAM;
	if (NO_PLAYER != eTargetPlayer)
	{
		eTargetTeam = GET_PLAYER(eTargetPlayer).getTeam();
	}

	CvEspionageMissionInfo& kMission = GC.getEspionageMissionInfo(eMission);

	bool bSomethingHappened = false;
	bool bShowExplosion = false;
	CvWString szBuffer;
	int iMissionCost = getEspionageMissionCost(eMission, eTargetPlayer, pPlot, iExtraData, pSpyUnit);

	
	//////////////////////////////
	// Destroy Improvement

	if (kMission.isDestroyImprovement())
	{
		if (NULL != pPlot)
		{
			// Blow it up
			//TSHEEP - Add nearby city to plot destruction message (if any)
			CvCity* pNearCity = GC.getMapINLINE().findCity(pPlot->getX_INLINE(), pPlot->getY_INLINE(), eTargetPlayer, GET_PLAYER(eTargetPlayer).getTeam(), true, false);
			if (pNearCity != NULL)
			{
			if (pPlot->getImprovementType() != NO_IMPROVEMENT)
			{
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_DESTROYED_NEAR_CITY", GC.getImprovementInfo(pPlot->getImprovementType()).getDescription(), pNearCity->getNameKey()).GetCString();
					pPlot->setImprovementType((ImprovementTypes)(GC.getImprovementInfo(pPlot->getImprovementType()).getImprovementPillage()));
					bSomethingHappened = true;
				}
				else if (pPlot->getRouteType() != NO_ROUTE)
				{
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_DESTROYED_NEAR_CITY", GC.getRouteInfo(pPlot->getRouteType()).getDescription(), pNearCity->getNameKey()).GetCString();
					pPlot->setRouteType(NO_ROUTE, true);
					bSomethingHappened = true;
				}
			}
		    else if (pPlot->getImprovementType() != NO_IMPROVEMENT)
			//if (pPlot->getImprovementType() != NO_IMPROVEMENT)
			//TSHEEP End
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_DESTROYED", GC.getImprovementInfo(pPlot->getImprovementType()).getDescription()).GetCString();
				pPlot->setImprovementType((ImprovementTypes)(GC.getImprovementInfo(pPlot->getImprovementType()).getImprovementPillage()));
				bSomethingHappened = true;
			}
			else if (pPlot->getRouteType() != NO_ROUTE)
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_DESTROYED", GC.getRouteInfo(pPlot->getRouteType()).getDescription()).GetCString();
				pPlot->setRouteType(NO_ROUTE, true);
				bSomethingHappened = true;
			}
			//TSHEEP Add Radiation Effect
			if(pSpyUnit->isAmphib())
			{
				pPlot->setFeatureType((FeatureTypes)(GC.getDefineINT("NUKE_FEATURE")));
				szBuffer.append(NEWLINE);
				szBuffer.append(gDLL->getText("TXT_KEY_ESPIONAGE_USED_RADIATION").GetCString());
			}
			//TSHEEP End

			if (bSomethingHappened)
			{
				bShowExplosion = true;
			}
		}		
	}

	//////////////////////////////
	// Destroy Building

	if (kMission.getDestroyBuildingCostFactor() > 0)
	{
		BuildingTypes eTargetBuilding = (BuildingTypes)iExtraData;

		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_DESTROYED_IN", GC.getBuildingInfo(eTargetBuilding).getDescription(), pCity->getNameKey()).GetCString();
				//TSHEEP - This part of the fix may not actually be necessary
				//During the test game though it appeared that the AIs had somehow managed to accrue more than one instance of the same building, although it did not display as such.
				pCity->setNumRealBuilding(eTargetBuilding, pCity->getNumRealBuilding(eTargetBuilding) - 1);
				//pCity->setNumRealBuilding(eTargetBuilding, 0);//Setting the number of buildings to 0 guarantees a successful destruction, only drawback would be mods that use multiple instances of buildings, base game does not appear to.
				//TSHEEP - End


				bSomethingHappened = true;
				bShowExplosion = true;
			}
		}
	}

	//////////////////////////////
	// Destroy Project

	if (kMission.getDestroyProjectCostFactor() > 0)
	{
		ProjectTypes eTargetProject = (ProjectTypes)iExtraData;

		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_DESTROYED_IN", GC.getProjectInfo(eTargetProject).getDescription(), pCity->getNameKey()).GetCString();
				GET_TEAM(eTargetTeam).changeProjectCount(eTargetProject, -1);

				bSomethingHappened = true;
				bShowExplosion = true;
			}
		}
	}

	//////////////////////////////
	// Destroy Production

	if (kMission.getDestroyProductionCostFactor() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_PRODUCTION_DESTROYED_IN", pCity->getProductionName(), pCity->getNameKey());
				pCity->setProduction(0);

				bSomethingHappened = true;
				bShowExplosion = true;
			}
		}
	}
/************************************************************************************************/
/* SUPER_SPIES                             RevolutionDCM                                                 */
/************************************************************************************************/
	//////////////////////////////
	// RevolutionDCM start
	// Assassinate(Destroy Unit)

	if (kMission.getDestroyUnitCostFactor() > 0)
	{

		if (pSpyUnit->canAssassin(pPlot, false))
		{
			SpecialistTypes theGreatSpecialistTarget = (SpecialistTypes)iExtraData;
			if (theGreatSpecialistTarget >= 7)
			{
				//Assassinate
				CvCity* pCity = pPlot->getPlotCity();
				if (NULL != pCity)
				{
					pCity->changeFreeSpecialistCount(theGreatSpecialistTarget, -1);
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_ASSASSINATED", GC.getSpecialistInfo(theGreatSpecialistTarget).getDescription(), pCity->getNameKey()).GetCString();
					bSomethingHappened = true;
				}
			}
		}
	}
/* Original code
	if (kMission.getDestroyUnitCostFactor() > 0)
	{
		if (NO_PLAYER != eTargetPlayer)
		{
			int iTargetUnitID = iExtraData;

			CvUnit* pUnit = GET_PLAYER(eTargetPlayer).getUnit(iTargetUnitID);

			if (NULL != pUnit)
			{
				FAssert(pUnit->plot() == pPlot);
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_DESTROYED", pUnit->getNameKey()).GetCString();
				pUnit->kill(false, getID());

				bSomethingHappened = true;
				bShowExplosion = true;
			}
		}
	}
*/

	//////////////////////////////
	// RevolutionDCM start
	// (Bribe)Buy Unit

	if (kMission.getBuyUnitCostFactor() > 0)
	{
		if(pSpyUnit->canBribe(pPlot, false))
		{
			CvUnit* pTargetUnit;
			if (pPlot->plotCheck(PUF_isOtherTeam, getID(), -1, NO_PLAYER, NO_TEAM, PUF_isVisible, getID()))
			{
				for (int i = 0; i < pPlot->getNumUnits(); i++) 
				{
					pTargetUnit = pPlot->getUnitByIndex(i);
					if (NULL != pTargetUnit && pTargetUnit->AI_getUnitAIType() == UNITAI_WORKER) 
					{
						if (pTargetUnit->getTeam() == eTargetTeam) break;
						pTargetUnit = NULL;
					}
				}
			}
								
			if (NO_PLAYER != eTargetPlayer)
			{
				if (NULL != pTargetUnit)
				{
					if (pTargetUnit->getTeam() == eTargetTeam)
					{
						FAssert(pTargetUnit->plot() == pPlot);
						CvCity* pNearCity = GC.getMapINLINE().findCity(pPlot->getX_INLINE(), pPlot->getY_INLINE(), eTargetPlayer, GET_PLAYER(eTargetPlayer).getTeam(), true, false);
						if (pNearCity != NULL)
							szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_BRIBED_NEAR_CITY", pTargetUnit->getNameKey(), pNearCity->getNameKey()).GetCString();
						else
							szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SOMETHING_BRIBED", pTargetUnit->getNameKey()).GetCString();

						int iX = pTargetUnit->getX_INLINE();
						int iY = pTargetUnit->getY_INLINE();
						pTargetUnit->kill(false, getID());
						CvUnit* acquiredWorker = initUnit(pTargetUnit->getUnitType(), iX, iY, UNITAI_WORKER, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
						CvCity* pCapital = this->getCapitalCity();
						if (NULL != pCapital)
						{
							iX = pCapital->getX_INLINE();
							iY = pCapital->getY_INLINE();
							acquiredWorker->setXY(iX, iY, false, false, false);
							acquiredWorker->finishMoves();
						}	
						bSomethingHappened = true;
					}
				}
			}
		}
/* Original code
		if (NO_PLAYER != eTargetPlayer)
		{
			int iTargetUnitID = iExtraData;

			CvUnit* pUnit = GET_PLAYER(eTargetPlayer).getUnit(iTargetUnitID);

			if (NULL != pUnit)
			{
				FAssert(pUnit->plot() == pPlot);

				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_UNIT_BOUGHT", pUnit->getNameKey()).GetCString();

				UnitTypes eUnitType = pUnit->getUnitType();
				int iX = pUnit->getX_INLINE();
				int iY = pUnit->getY_INLINE();
				pUnit->kill(false, getID());
				initUnit(eUnitType, iX, iY, NO_UNITAI);

				bSomethingHappened = true;
			}
}*/
		}
	// RevolutionDCM end
/************************************************************************************************/
/* SUPER_SPIES                             END                                                  */
/************************************************************************************************/

	//////////////////////////////
	// Buy City

	if (kMission.getBuyCityCostFactor() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
/************************************************************************************************/
/* Afforess	                  Start		 07/25/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
				GET_PLAYER(pCity->getOwnerINLINE()).AI_changeMemoryCount(getID(), MEMORY_EVENT_BAD_TO_US, std::max(4, pCity->getPopulation()));
				for (int iI = 0; iI < MAX_PLAYERS; iI++)
				{
					if (GET_PLAYER((PlayerTypes)iI).isAlive())
					{
						if ( GET_PLAYER((PlayerTypes)iI).AI_getAttitude(pCity->getOwnerINLINE()) >= ATTITUDE_PLEASED)
						{
							GET_PLAYER((PlayerTypes)iI).AI_changeMemoryCount(getID(), MEMORY_EVENT_BAD_TO_US, std::max(2, pCity->getPopulation() / 3));
						}
					}
				}
				
				if (GET_PLAYER(pCity->getOwnerINLINE()).AI_getMemoryCount(getID(), MEMORY_EVENT_BAD_TO_US) > 15)
				{
					GET_TEAM(pCity->getTeam()).declareWar(getTeam(), true, WARPLAN_TOTAL);
				}
				
				strcpy(szSound, "AS2D_REVOLTSTART");
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_CITY_BOUGHT", pCity->getNameKey()).GetCString();
				acquireCity(pCity, false, true, true);

				bSomethingHappened = true;
			}
		}
	}

	//////////////////////////////
	// Insert Culture into City

	if (kMission.getCityInsertCultureCostFactor() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_CITY_CULTURE_INSERTED", pCity->getNameKey()).GetCString();				

				int iCultureAmount = kMission.getCityInsertCultureAmountFactor() * pCity->countTotalCultureTimes100();
				iCultureAmount /= 10000;
				iCultureAmount = std::max(1, iCultureAmount);
				
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
				int iPlotCulture = pCity->plot()->countTotalCulture();
				int iPlotCultureAmount;
				
				if ( iPlotCulture > MAX_INT/10000 )
				{
					iPlotCulture /= 100;
					iPlotCultureAmount = kMission.getCityInsertCultureAmountFactor() * iPlotCulture;
				}
				else
				{
					iPlotCultureAmount = kMission.getCityInsertCultureAmountFactor() * iPlotCulture * 100;
					iPlotCultureAmount /= 10000;
				}
				iPlotCultureAmount = std::max(1, iPlotCultureAmount);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
				
				int iNumTurnsApplied = (GC.getDefineINT("GREAT_WORKS_CULTURE_TURNS") * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getUnitGreatWorkPercent()) / 100;

				for (int i = 0; i < iNumTurnsApplied; ++i)
				{
					pCity->changeCulture(getID(), iCultureAmount / iNumTurnsApplied, true, true);
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
					pCity->plot()->changeCulture(getID(), iPlotCultureAmount / iNumTurnsApplied, true);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
				}

				if (iNumTurnsApplied > 0)
				{
					pCity->changeCulture(getID(), iCultureAmount % iNumTurnsApplied, false, true);
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
					pCity->plot()->changeCulture(getID(), iPlotCultureAmount % iNumTurnsApplied, true);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
				}

				bSomethingHappened = true;
			}

		}
	}

	//////////////////////////////
	// Poison City's Water Supply

	if (kMission.getCityPoisonWaterCounter() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_CITY_POISONED", pCity->getNameKey()).GetCString();
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
				int iTurns = (kMission.getCityPoisonWaterCounter() * (100 + pSpyUnit->getExtraFriendlyHeal()))/100;
				if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_ESPIONAGE))
				{
					iTurns *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
					iTurns /= 100;
				}
				
				pCity->changeEspionageHealthCounter(iTurns);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

				bShowExplosion = true;
				bSomethingHappened = true;
			}
		}
	}

	//////////////////////////////
	// Make city Unhappy

	if (kMission.getCityUnhappinessCounter() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_CITY_UNHAPPY", pCity->getNameKey()).GetCString();
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
				int iTurns = (kMission.getCityUnhappinessCounter() * (100 + pSpyUnit->getExtraEnemyHeal()))/100;
				if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_ESPIONAGE))
				{
					iTurns *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
					iTurns /= 100;
				}
				
				pCity->changeEspionageHappinessCounter(iTurns);
				
				strcpy(szSound, "AS2D_REVOLTSTART");
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

				bShowExplosion = true;
				bSomethingHappened = true;
			}
		}
	}

	//////////////////////////////
	// Make city Revolt

	if (kMission.getCityRevoltCounter() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_CITY_REVOLT", pCity->getNameKey()).GetCString();
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
				int iTurns = (kMission.getCityRevoltCounter() * (100 + pSpyUnit->getExtraNeutralHeal()))/100;
				if (GC.getGameINLINE().isOption(GAMEOPTION_ADVANCED_ESPIONAGE))
				{
					iTurns *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
					iTurns /= 100;
				}
				
				pCity->changeCultureUpdateTimer(iTurns);
				pCity->changeOccupationTimer(iTurns);
				
				strcpy(szSound, "AS2D_REVOLTSTART");
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
				bSomethingHappened = true;
				bShowExplosion = true;

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      01/12/10                                jdog5000      */
/*                                                                                              */
/* AI logging                                                                                   */
/************************************************************************************************/
				if( gUnitLogLevel >= 2 )
				{
					logBBAI("      Spy for player %d (%S) causes revolt in %S, owned by %S (%d)", getID(), getCivilizationDescription(0), pCity->getName().GetCString(), GET_PLAYER(pCity->getOwner()).getCivilizationDescription(0), pCity->getOwner() );
				}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
			}
		}
	}

	//////////////////////////////
	// Steal Treasury

	if (kMission.getStealTreasuryTypes() > 0)
	{
		if (NO_PLAYER != eTargetPlayer)
		{
			int iNumTotalGold = (GET_PLAYER(eTargetPlayer).getGold() * kMission.getStealTreasuryTypes()) / 100;

			if (NULL != pPlot)
			{
				CvCity* pCity = pPlot->getPlotCity();

				if (NULL != pCity)
				{
					iNumTotalGold *= pCity->getPopulation();
					iNumTotalGold /= std::max(1, GET_PLAYER(eTargetPlayer).getTotalPopulation());
				}
			}
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
			iNumTotalGold *= std::max(0, calculateInflationRate() + 100);
			iNumTotalGold /= 100;
			
			strcpy(szSound, "AS2D_WONDERGOLD");
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
			szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_STEAL_TREASURY").GetCString();
			changeGold(iNumTotalGold);
			if (NO_PLAYER != eTargetPlayer)
			{
				GET_PLAYER(eTargetPlayer).changeGold(-iNumTotalGold);
			}
			
			bSomethingHappened = true;
		}
	}

	//////////////////////////////
	// Buy (Steal) Tech

	if (kMission.getBuyTechCostFactor() > 0)
	{
		int iTech = iExtraData;

		szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_TECH_BOUGHT", GC.getTechInfo((TechTypes) iTech).getDescription()).GetCString();
		GET_TEAM(getTeam()).setHasTech((TechTypes) iTech, true, getID(), false, true);
		GET_TEAM(getTeam()).setNoTradeTech((TechTypes)iTech, true);

		bSomethingHappened = true;
	}

	//////////////////////////////
	// Switch Civic

	if (kMission.getSwitchCivicCostFactor() > 0)
	{
		if (NO_PLAYER != eTargetPlayer)
		{
			int iCivic = iExtraData;

			szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SWITCH_CIVIC", GC.getCivicInfo((CivicTypes) iCivic).getDescription()).GetCString();
			GET_PLAYER(eTargetPlayer).setCivics((CivicOptionTypes) GC.getCivicInfo((CivicTypes) iCivic).getCivicOptionType(), (CivicTypes) iCivic);
			GET_PLAYER(eTargetPlayer).setRevolutionTimer(std::max(1, ((100 + GET_PLAYER(eTargetPlayer).getAnarchyModifier()) * GC.getDefineINT("MIN_REVOLUTION_TURNS")) / 100));
			bSomethingHappened = true;
		}
	}

	//////////////////////////////
	// Switch Religion

	if (kMission.getSwitchReligionCostFactor() > 0)
	{
		if (NO_PLAYER != eTargetPlayer)
		{
			int iReligion = iExtraData;

			strcpy(szSound, GC.getReligionInfo((ReligionTypes) iReligion).getSound());

			szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_SWITCH_RELIGION", GC.getReligionInfo((ReligionTypes) iReligion).getDescription()).GetCString();
			GET_PLAYER(eTargetPlayer).setLastStateReligion((ReligionTypes) iReligion);
			GET_PLAYER(eTargetPlayer).setConversionTimer(std::max(1, ((100 + GET_PLAYER(eTargetPlayer).getAnarchyModifier()) * GC.getDefineINT("MIN_CONVERSION_TURNS")) / 100));
			bSomethingHappened = true;
		}
	}

	//////////////////////////////
	// Player Anarchy

	if (kMission.getPlayerAnarchyCounter() > 0)
	{
		if (NO_PLAYER != eTargetPlayer)
		{
			int iTurns = (kMission.getPlayerAnarchyCounter() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent()) / 100;
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/

			strcpy(szSound, "AS2D_REVOLTSTART");
			if (bCaught)
				szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_PLAYER_ANARCHY_CAUGHT", getCivilizationAdjectiveKey()).GetCString();
			else
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
			szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_PLAYER_ANARCHY").GetCString();
			GET_PLAYER(eTargetPlayer).changeAnarchyTurns(iTurns);

			bSomethingHappened = true;
		}
	}

	//////////////////////////////
	// Counterespionage

	if (kMission.getCounterespionageNumTurns() > 0 && kMission.getCounterespionageMod() > 0)
	{
		szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_TARGET_COUNTERESPIONAGE").GetCString();

		if (NO_TEAM != eTargetTeam)
		{
			int iTurns = (kMission.getCounterespionageNumTurns() * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getResearchPercent()) / 100;
			GET_TEAM(getTeam()).changeCounterespionageTurnsLeftAgainstTeam(eTargetTeam, iTurns);
			//TSHEEP Add Intercept to counter espionage mod
			GET_TEAM(getTeam()).changeCounterespionageModAgainstTeam(eTargetTeam, (kMission.getCounterespionageMod() + (5 * pSpyUnit->currInterceptionProbability())));
			//GET_TEAM(getTeam()).changeCounterespionageModAgainstTeam(eTargetTeam, kMission.getCounterespionageMod());
			//TSHEEP End
	
			bSomethingHappened = true;

		}		
	}
/************************************************************************************************/
/* Afforess	                  Start		 06/29/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	//////////////////////////////
	// Nuclear Bomb
	bool bNuked = false;
	if (kMission.isNuke())
	{
		if (NULL != pPlot)
		{
			if (NULL != pSpyUnit)
			{
				if (pSpyUnit->spyNuke(pPlot->getX_INLINE(), pPlot->getY_INLINE(), bCaught))
				{
					bNuked = true;
				}
			}
		}
	}
	//////////////////////////////
	// Incite City Revolution
	if (kMission.isRevolt())
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				pCity->changeRevolutionIndex(1000 + GC.getGameINLINE().getSorenRandNum(1000, "City Revolt"));
				pCity->changeOccupationTimer(kMission.getCityRevoltCounter());
				bSomethingHappened = true;
				
				strcpy(szSound, "AS2D_REVOLTSTART");
				
				if (bCaught)
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_INCITE_REVOLUTION_CAUGHT", pCity->getNameKey(), getCivilizationDescription()).GetCString();
				else
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_INCITE_REVOLUTION", pCity->getNameKey()).GetCString();
			}
		}
	}
	//////////////////////////////
	// Disable Power
	if (kMission.isDisablePower())
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				int iTurns = 6;
				iTurns *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
				iTurns /= 100;
				pCity->changeDisabledPowerTimer(iTurns);
				bSomethingHappened = true;
				
				strcpy(szSound, "AS2D_BUILD_PLANTNUCLEAR");
				
				if (bCaught)
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_POWER_CUT_CAUGHT", pCity->getNameKey(), getCivilizationDescription()).GetCString();
				else
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_POWER_CUT", pCity->getNameKey()).GetCString();
			}
		}
	}
	//////////////////////////////
	// Cause War Weariness
	if (kMission.getWarWearinessCounter() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				int iAmount = kMission.getWarWearinessCounter();
				iAmount *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
				iAmount /= 100;
				pCity->changeWarWearinessTimer(iAmount);
				bSomethingHappened = true;
				
				strcpy(szSound, "AS2D_STRIKE");
				
				if (bCaught)
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_WAR_WEARINESS_CAUGHT", pCity->getNameKey(), getCivilizationAdjectiveKey()).GetCString();
				else
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_WAR_WEARINESS", pCity->getNameKey()).GetCString();
			}
		}
	}
	//////////////////////////////
	// Sabatoge Research
	if (kMission.getSabatogeResearchCostFactor() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				GET_TEAM(pCity->getTeam()).setResearchProgress(GET_PLAYER(pCity->getOwnerINLINE()).getCurrentResearch(), 0, pCity->getOwnerINLINE());
				bSomethingHappened = true;
				if (bCaught)
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_RESEARCH_SABATAGED_CAUGHT", GC.getTechInfo(GET_PLAYER(pCity->getOwnerINLINE()).getCurrentResearch()).getDescription(), getCivilizationAdjectiveKey()).GetCString();
				else
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_RESEARCH_SABATAGED", GC.getTechInfo(GET_PLAYER(pCity->getOwnerINLINE()).getCurrentResearch()).getDescription());
			}
		}
	}
	//////////////////////////////
	// Remove Religion
	if (kMission.getRemoveReligionsCostFactor() > 0)
	{
		if (NULL != pPlot)
		{
			ReligionTypes eTargetReligion = (ReligionTypes)iExtraData;
			CvCity* pCity = pPlot->getPlotCity();

			if (NULL != pCity)
			{
				pCity->setHasReligion(eTargetReligion, false, false, false);
				strcpy(szSound, GC.getReligionInfo(eTargetReligion).getSound());
				bSomethingHappened = true;
				if (bCaught)
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_RELIGION_REMOVED_CAUGHT", pCity->getNameKey(), getCivilizationAdjectiveKey(), GC.getReligionInfo(eTargetReligion).getTextKeyWide()).GetCString();
				else
					szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_RELIGION_REMOVED", pCity->getNameKey(), GC.getReligionInfo(eTargetReligion).getTextKeyWide());
			}
		}
	}
	//////////////////////////////
	// Remove Corporation
	if (kMission.getRemoveCorporationsCostFactor() > 0)
	{
		if (NULL != pPlot)
		{
			CvCity* pCity = pPlot->getPlotCity();
			if (NULL != pCity)
			{
				CorporationTypes eCorporation = (CorporationTypes)iExtraData;

				if (NO_CORPORATION != eCorporation)
				{
					if (pCity->isActiveCorporation(eCorporation)&& GC.getGameINLINE().getHeadquarters(eCorporation) != pCity)
					{
						pCity->setHasCorporation(eCorporation, false, false, false);
						strcpy(szSound, GC.getCorporationInfo(eCorporation).getSound());
						bSomethingHappened = true;
						if (bCaught)
							szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_CORPORATION_REMOVED_CAUGHT", pCity->getNameKey(), getCivilizationAdjectiveKey(), GC.getCorporationInfo(eCorporation).getTextKeyWide()).GetCString();
						else
							szBuffer = gDLL->getText("TXT_KEY_ESPIONAGE_CORPORATION_REMOVED", pCity->getNameKey(), GC.getCorporationInfo(eCorporation).getTextKeyWide());
					}
				}
			}
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	int iHave = 0;
	if (NO_TEAM != eTargetTeam)
	{
		iHave = GET_TEAM(getTeam()).getEspionagePointsAgainstTeam(eTargetTeam);

		if (bSomethingHappened || bNuked)
		{
			GET_TEAM(getTeam()).changeEspionagePointsAgainstTeam(eTargetTeam, -iMissionCost);
		}
	}

	if (bShowExplosion)
	{
		if (pPlot)
		{
			if (pPlot->isVisible(GC.getGame().getActiveTeam(), false))
			{
				EffectTypes eEffect = GC.getEntityEventInfo(GC.getMissionInfo(MISSION_BOMBARD).getEntityEvent()).getEffectType();
				gDLL->getEngineIFace()->TriggerEffect(eEffect, pPlot->getPoint(), (float)(GC.getASyncRand().get(360)));
				gDLL->getInterfaceIFace()->playGeneralSound("AS3D_UN_CITY_EXPLOSION", pPlot->getPoint());
			}
		}
	}

	if (bSomethingHappened)
	{
		MEMORY_TRACK_EXEMPT();

		int iX = -1;
		int iY = -1;
		if (NULL != pPlot)
		{
			iX = pPlot->getX_INLINE();
			iY = pPlot->getY_INLINE();
		}

		AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), gDLL->getText("TXT_KEY_ESPIONAGE_MISSION_PERFORMED"), "AS2D_POSITIVE_DINK", MESSAGE_TYPE_INFO, ARTFILEMGR.getInterfaceArtInfo("ESPIONAGE_BUTTON")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_GREEN"), iX, iY, true, true);
	}
	else if ((getID() == GC.getGameINLINE().getActivePlayer()) && !bNuked)
	{
		CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_TEXT);
		if (iHave < iMissionCost)
		{
			pInfo->setText(gDLL->getText("TXT_KEY_ESPIONAGE_TOO_EXPENSIVE", iMissionCost, iHave));
		}
		else
		{
			pInfo->setText(gDLL->getText("TXT_KEY_ESPIONAGE_CANNOT_DO_MISSION"));
		}

		addPopup(pInfo);
	}

	if (bSomethingHappened && !szBuffer.empty())
	{
		int iX = -1;
		int iY = -1;
		if (NULL != pPlot)
		{
			iX = pPlot->getX_INLINE();
			iY = pPlot->getY_INLINE();
		}

		if (NO_PLAYER != eTargetPlayer)
		{
			MEMORY_TRACK_EXEMPT();

/************************************************************************************************/
/* Afforess	                  Start		 07/28/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
			AddDLLMessage(eTargetPlayer, true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_DEAL_CANCELLED", MESSAGE_TYPE_INFO, ARTFILEMGR.getInterfaceArtInfo("ESPIONAGE_BUTTON")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), iX, iY, true, true);
*/
			AddDLLMessage(eTargetPlayer, true, GC.getEVENT_MESSAGE_TIME(), szBuffer, szSound, MESSAGE_TYPE_INFO, ARTFILEMGR.getInterfaceArtInfo("ESPIONAGE_BUTTON")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), iX, iY, true, true);
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

		}
	}

	return bSomethingHappened || bNuked;
}

int CvPlayer::getEspionageSpendingWeightAgainstTeam(TeamTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < MAX_TEAMS, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiEspionageSpendingWeightAgainstTeam[eIndex];
}

void CvPlayer::setEspionageSpendingWeightAgainstTeam(TeamTypes eIndex, int iValue)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < MAX_TEAMS, "eIndex is expected to be within maximum bounds (invalid Index)");
	FAssert(iValue >= 0);

	iValue = std::min(std::max(0, iValue), 99);

	if (iValue != getEspionageSpendingWeightAgainstTeam(eIndex))
	{
		m_aiEspionageSpendingWeightAgainstTeam[eIndex] = iValue;

		gDLL->getInterfaceIFace()->setDirty(Espionage_Advisor_DIRTY_BIT, true);
	}
}

void CvPlayer::changeEspionageSpendingWeightAgainstTeam(TeamTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < MAX_TEAMS, "eIndex is expected to be within maximum bounds (invalid Index)");

	setEspionageSpendingWeightAgainstTeam(eIndex, getEspionageSpendingWeightAgainstTeam(eIndex) + iChange);
}

void CvPlayer::doAdvancedStartAction(AdvancedStartActionTypes eAction, int iX, int iY, int iData, bool bAdd)
{
	if (getAdvancedStartPoints() < 0)
	{
		return;
	}

	CvPlot* pPlot = GC.getMap().plot(iX, iY);

	if (0 == getNumCities())
	{
		switch (eAction)
		{
		case ADVANCEDSTARTACTION_EXIT:
			//Try to build this player's empire
			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setBusy(true);
			}
			AI_doAdvancedStart(true);			
			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setBusy(false);
			}
			break;
		case ADVANCEDSTARTACTION_AUTOMATE:
		case ADVANCEDSTARTACTION_CITY:
			break;
		default:
			// The first action must be to place a city
			// so players can lose by spending everything
			return;
		}
	}

	switch (eAction)
	{
	case ADVANCEDSTARTACTION_EXIT:
		changeGold(getAdvancedStartPoints());
		setAdvancedStartPoints(-1);
		if (GC.getGameINLINE().getActivePlayer() == getID())
		{
			gDLL->getInterfaceIFace()->setInAdvancedStart(false);
		}

		if (isHuman())
		{
			int iLoop;
			for (CvCity* pCity = firstCity(&iLoop); NULL != pCity; pCity = nextCity(&iLoop))
			{
				pCity->chooseProduction();
			}

			chooseTech();

			if (canRevolution(NULL))
			{
				CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_CHANGECIVIC);
				if (NULL != pInfo)
				{
					gDLL->getInterfaceIFace()->addPopup(pInfo, getID());
				}
			}
		}
		break;
	case ADVANCEDSTARTACTION_AUTOMATE:
		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setBusy(true);
		}
		AI_doAdvancedStart(true);			
		if (getID() == GC.getGameINLINE().getActivePlayer())
		{
			gDLL->getInterfaceIFace()->setBusy(false);
		}
		break;
	case ADVANCEDSTARTACTION_UNIT:
		{
			if(pPlot == NULL)
				return;

			UnitTypes eUnit = (UnitTypes) iData;
			int iCost = getAdvancedStartUnitCost(eUnit, bAdd, pPlot);

			if (bAdd && iCost < 0)
			{
				return;
			}

			// Add unit to the map
			if (bAdd)
			{
				if (getAdvancedStartPoints() >= iCost)
				{
					CvUnit* pUnit = initUnit(eUnit, iX, iY, NO_UNITAI, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
					if (NULL != pUnit)
					{
						pUnit->finishMoves();
						changeAdvancedStartPoints(-iCost);
					}
				}
			}

			// Remove unit from the map
			else
			{
				// If cost is -1 we already know this unit isn't present
				if (iCost != -1)
				{
					CLLNode<IDInfo>* pUnitNode = pPlot->headUnitNode();
					while (pUnitNode != NULL)
					{
						CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
						pUnitNode = pPlot->nextUnitNode(pUnitNode);

						if (pLoopUnit->getUnitType() == eUnit)
						{
							pLoopUnit->kill(false);
							changeAdvancedStartPoints(iCost);
							return;
						}
					}
				}

				// Proper unit not found above, delete first found
				CLLNode<IDInfo>* pUnitNode = pPlot->headUnitNode();
				if (pUnitNode != NULL)
				{
					CvUnit* pUnit = ::getUnit(pUnitNode->m_data);

					iCost = getAdvancedStartUnitCost(pUnit->getUnitType(), false);
					FAssertMsg(iCost != -1, "If this is -1 then that means it's going to try to delete a unit which shouldn't exist");
					pUnit->kill(false);
					changeAdvancedStartPoints(iCost);
				}
			}

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setDirty(Advanced_Start_DIRTY_BIT, true);
			}
		}
		break;
	case ADVANCEDSTARTACTION_CITY:
		{
			if(pPlot == NULL)
				return;

			int iCost = getAdvancedStartCityCost(bAdd, pPlot);

			if (iCost < 0)
			{
				return;
			}

			// Add City to the map
			if (bAdd)
			{
				if (0 == getNumCities())
				{
					PlayerTypes eClosestPlayer = NO_PLAYER;
					int iMinDistance = MAX_INT;
					for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; iPlayer++)
					{
						CvPlayer& kPlayer = GET_PLAYER((PlayerTypes)iPlayer);
						if (kPlayer.isAlive())
						{
							if (kPlayer.getTeam() == getTeam())
							{
								if (0 == kPlayer.getNumCities())
								{
									FAssert(kPlayer.getStartingPlot() != NULL);
									int iDistance = plotDistance(iX, iY, kPlayer.getStartingPlot()->getX_INLINE(), kPlayer.getStartingPlot()->getY_INLINE());
									if (iDistance < iMinDistance)
									{
										eClosestPlayer = kPlayer.getID();
										iMinDistance = iDistance;
									}
								}
							}
						}
					}
					FAssertMsg(eClosestPlayer != NO_PLAYER, "Self at a minimum should always be valid");
					if (eClosestPlayer != getID())
					{
						CvPlot* pTempPlot = GET_PLAYER(eClosestPlayer).getStartingPlot();
						GET_PLAYER(eClosestPlayer).setStartingPlot(getStartingPlot(), false);
						setStartingPlot(pTempPlot, false);					
					}
				}
				if (getAdvancedStartPoints() >= iCost || 0 == getNumCities())
				{
					found(iX, iY);
					changeAdvancedStartPoints(-std::min(iCost, getAdvancedStartPoints()));
					GC.getGameINLINE().updateColoredPlots();
					CvCity* pCity = pPlot->getPlotCity();
					if (pCity != NULL)
					{
						if (pCity->getPopulation() > 1)
						{
							pCity->setFood(pCity->growthThreshold() / 2);
						}
					}
				}
			}

			// Remove City from the map
			else
			{
				pPlot->setRouteType(NO_ROUTE, true);
				pPlot->getPlotCity()->kill(true);
				pPlot->setImprovementType(NO_IMPROVEMENT);
				changeAdvancedStartPoints(iCost);
			}

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setDirty(Advanced_Start_DIRTY_BIT, true);
			}
		}
		break;
	case ADVANCEDSTARTACTION_POP:
		{
			if(pPlot == NULL)
				return;

			CvCity* pCity = pPlot->getPlotCity();

			if (pCity != NULL)
			{
				int iCost = getAdvancedStartPopCost(bAdd, pCity);
				
				if (iCost < 0)
				{
					return;
				}

				bool bPopChanged = false;
				if (bAdd)
				{
					if (getAdvancedStartPoints() >= iCost)
					{
						pCity->changePopulation(1);
						changeAdvancedStartPoints(-iCost);
						bPopChanged = true;
					}
				}
				else
				{
					pCity->changePopulation(-1);
					changeAdvancedStartPoints(iCost);
					bPopChanged = true;
				}

				if (bPopChanged)
				{
					pCity->setHighestPopulation(pCity->getPopulation());
					if (pCity->getPopulation() == 1)
					{
						pCity->setFood(0);
						pCity->setFoodKept(0);
					}
					else if (pCity->getPopulation() > 1)
					{
						pCity->setFood(pCity->growthThreshold() / 2);
						pCity->setFoodKept((pCity->getFood() * pCity->getMaxFoodKeptPercent()) / 100);
					}
				}
			}
		}
		break;
	case ADVANCEDSTARTACTION_CULTURE:
		{
			if(pPlot == NULL)
				return;

			CvCity* pCity = pPlot->getPlotCity();

			if (pCity != NULL)
			{
				int iCost = getAdvancedStartCultureCost(bAdd, pCity);

				if (iCost < 0)
				{
					return;
				}

				// Add Culture to the City
				if (bAdd)
				{
					if (getAdvancedStartPoints() >= iCost)
					{
						pCity->setCulture(getID(), pCity->getCultureThreshold(), true, true);
						changeAdvancedStartPoints(-iCost);
					}
				}

				// Remove Culture from the city
				else
				{
					CultureLevelTypes eLevel = (CultureLevelTypes)std::max(0, pCity->getCultureLevel() - 1);
					pCity->setCulture(getID(), pCity->getCultureThreshold(eLevel), true, true);
					changeAdvancedStartPoints(iCost);
				}
			}
		}
		break;
	case ADVANCEDSTARTACTION_BUILDING:
		{
			if(pPlot == NULL)
				return;

			CvCity* pCity = pPlot->getPlotCity();

			if (pCity != NULL)
			{
				BuildingTypes eBuilding = (BuildingTypes) iData;
				int iCost = getAdvancedStartBuildingCost(eBuilding, bAdd, pCity);

				if (iCost < 0)
				{
					return;
				}

				// Add Building to the City
				if (bAdd)
				{
					if (getAdvancedStartPoints() >= iCost)
					{
						pCity->setNumRealBuilding(eBuilding, pCity->getNumRealBuilding(eBuilding)+1);
						changeAdvancedStartPoints(-iCost);
						if (GC.getBuildingInfo(eBuilding).getFoodKept() != 0)
						{
							pCity->setFoodKept((pCity->getFood() * pCity->getMaxFoodKeptPercent()) / 100);
						}
					}
				}

				// Remove Building from the map
				else
				{
					pCity->setNumRealBuilding(eBuilding, pCity->getNumRealBuilding(eBuilding)-1);
					changeAdvancedStartPoints(iCost);
					if (GC.getBuildingInfo(eBuilding).getFoodKept() != 0)
					{
						pCity->setFoodKept((pCity->getFood() * pCity->getMaxFoodKeptPercent()) / 100);
					}
				}
			}

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setDirty(Advanced_Start_DIRTY_BIT, true);
			}
		}
		break;
	case ADVANCEDSTARTACTION_ROUTE:
		{
			if(pPlot == NULL)
				return;

			RouteTypes eRoute = (RouteTypes) iData;
			int iCost = getAdvancedStartRouteCost(eRoute, bAdd, pPlot);

			if (bAdd && iCost < 0)
			{
				return;
			}

			// Add Route to the plot
			if (bAdd)
			{
				if (getAdvancedStartPoints() >= iCost)
				{
					pPlot->setRouteType(eRoute, true);
					changeAdvancedStartPoints(-iCost);
				}
			}

			// Remove Route from the Plot
			else
			{
				if (pPlot->getRouteType() != eRoute)
				{
					eRoute = pPlot->getRouteType();
					iCost = getAdvancedStartRouteCost(eRoute, bAdd);
				}
				
				if (iCost < 0)
				{
					return;
				}

				pPlot->setRouteType(NO_ROUTE, true);
				changeAdvancedStartPoints(iCost);
			}

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setDirty(Advanced_Start_DIRTY_BIT, true);
			}
		}
		break;
	case ADVANCEDSTARTACTION_IMPROVEMENT:
		{
			if(pPlot == NULL)
				return;

			ImprovementTypes eImprovement = (ImprovementTypes) iData;
			int iCost = getAdvancedStartImprovementCost(eImprovement, bAdd, pPlot);

			if (bAdd && iCost < 0)
			{
				return;
			}

			// Add Improvement to the plot
			if (bAdd)
			{
				if (getAdvancedStartPoints() >= iCost)
				{
					if (pPlot->getFeatureType() != NO_FEATURE)
					{
						for (int iI = 0; iI < GC.getNumBuildInfos(); ++iI)
						{
							ImprovementTypes eLoopImprovement = ((ImprovementTypes)(GC.getBuildInfo((BuildTypes)iI).getImprovement()));

							if (eImprovement == eLoopImprovement)
							{
								if (GC.getBuildInfo((BuildTypes)iI).isFeatureRemove(pPlot->getFeatureType()) && canBuild(pPlot, (BuildTypes)iI))
								{
									pPlot->setFeatureType(NO_FEATURE);
									break;
								}
							}
						}
					}

					pPlot->setImprovementType(eImprovement);

					changeAdvancedStartPoints(-iCost);
				}
			}

			// Remove Improvement from the Plot
			else
			{
				if (pPlot->getImprovementType() != eImprovement)
				{
					eImprovement = pPlot->getImprovementType();
					iCost = getAdvancedStartImprovementCost(eImprovement, bAdd, pPlot);
				}

				if (iCost < 0)
				{
					return;
				}

				pPlot->setImprovementType(NO_IMPROVEMENT);
				changeAdvancedStartPoints(iCost);
			}

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setDirty(Advanced_Start_DIRTY_BIT, true);
			}
		}
		break;
	case ADVANCEDSTARTACTION_TECH:
		{
			TechTypes eTech = (TechTypes) iData;
			int iCost = getAdvancedStartTechCost(eTech, bAdd);

			if (iCost < 0)
			{
				return;
			}

			// Add Tech to team
			if (bAdd)
			{
				if (getAdvancedStartPoints() >= iCost)
				{
					GET_TEAM(getTeam()).setHasTech(eTech, true, getID(), false, false);
					changeAdvancedStartPoints(-iCost);
				}
			}

			// Remove Tech from the Team
			else
			{
				GET_TEAM(getTeam()).setHasTech(eTech, false, getID(), false, false);
				changeAdvancedStartPoints(iCost);
			}

			if (getID() == GC.getGameINLINE().getActivePlayer())
			{
				gDLL->getInterfaceIFace()->setDirty(Advanced_Start_DIRTY_BIT, true);
			}
		}
		break;
	case ADVANCEDSTARTACTION_VISIBILITY:
		{
			if(pPlot == NULL)
				return;

			int iCost = getAdvancedStartVisibilityCost(bAdd, pPlot);

			if (iCost < 0)
			{
				return;
			}

			// Add Visibility to the plot
			if (bAdd)
			{
				if (getAdvancedStartPoints() >= iCost)
				{
					pPlot->setRevealed(getTeam(), true, true, NO_TEAM, true);
					changeAdvancedStartPoints(-iCost);
				}
			}

			// Remove Visibility from the Plot
			else
			{
				pPlot->setRevealed(getTeam(), false, true, NO_TEAM, true);
				changeAdvancedStartPoints(iCost);
			}
		}
		break;
	default:
		FAssert(false);
		break;
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing a unit
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartUnitCost(UnitTypes eUnit, bool bAdd, CvPlot* pPlot) const
{
	int iLoop;
	int iNumUnitType = 0;

	if (0 == getNumCities())
	{
		return -1;
	}

	int iCost = (getProductionNeeded(eUnit) * GC.getUnitInfo(eUnit).getAdvancedStartCost()) / 100;
	if (iCost < 0)
	{
		return -1;
	}

	if (NULL == pPlot)
	{
		if (bAdd)
		{
			bool bValid = false;
			int iLoop;
			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				if (pLoopCity->canTrain(eUnit))
				{
					bValid = true;
					break;
				}
			}

			if (!bValid)
			{
				return -1;
			}
		}
	}
	else
	{
		CvCity* pCity = NULL;

		if (0 == GC.getDefineINT("ADVANCED_START_ALLOW_UNITS_OUTSIDE_CITIES"))
		{
			pCity = pPlot->getPlotCity();

			if (NULL == pCity || pCity->getOwnerINLINE() != getID())
			{
				return -1;
			}

			iCost *= 100;
			iCost /= std::max(1, 100 + pCity->getProductionModifier(eUnit));
		}
		else
		{
			if (pPlot->getOwnerINLINE() != getID())
			{
				return -1;
			}

			iCost *= 100;
			iCost /= std::max(1, 100 + getProductionModifier(eUnit));
		}


		if (bAdd)
		{
			int iMaxUnitsPerCity = GC.getDefineINT("ADVANCED_START_MAX_UNITS_PER_CITY");
			if (iMaxUnitsPerCity >= 0)
			{
				if (GC.getUnitInfo(eUnit).isMilitarySupport() && getNumMilitaryUnits() >= iMaxUnitsPerCity * getNumCities())
				{
					return -1;
				}
			}

			if (NULL != pCity)
			{
				if (!pCity->canTrain(eUnit))
				{
					return -1;
				}
			}
			else
			{
				if (!pPlot->canTrain(eUnit, false, false))
				{
					return -1;
				}

				if (pPlot->isImpassable() && !GC.getUnitInfo(eUnit).isCanMoveImpassable())
				{
					return -1;
				}

				if (pPlot->getFeatureType() != NO_FEATURE)
				{
					if (GC.getUnitInfo(eUnit).getFeatureImpassable(pPlot->getFeatureType()))
					{
						TechTypes eTech = (TechTypes)GC.getUnitInfo(eUnit).getFeaturePassableTech(pPlot->getFeatureType());
						if (NO_TECH == eTech || !GET_TEAM(getTeam()).isHasTech(eTech))
						{
							return -1;
						}
					}
				}
				else
				{
					if (GC.getUnitInfo(eUnit).getTerrainImpassable(pPlot->getTerrainType()))
					{
						TechTypes eTech = (TechTypes)GC.getUnitInfo(eUnit).getTerrainPassableTech(pPlot->getTerrainType());
						if (NO_TECH == eTech || !GET_TEAM(getTeam()).isHasTech(eTech))
						{
							return -1;
						}
					}
				}
			}
		}
		// Must be this unit at plot in order to remove
		else
		{
			bool bUnitFound = false;

			CLLNode<IDInfo>* pUnitNode = pPlot->headUnitNode();
			while (pUnitNode != NULL)
			{
				CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
				pUnitNode = pPlot->nextUnitNode(pUnitNode);

				if (pLoopUnit->getUnitType() == eUnit)
				{
					bUnitFound = true;
				}
			}

			if (!bUnitFound)
			{
				return -1;
			}
		}
	}

	// Increase cost if the XML defines that additional units will cost more
	if (0 != GC.getUnitInfo(eUnit).getAdvancedStartCostIncrease())
	{
		for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if (pLoopUnit->getUnitType() == eUnit)
			{
				++iNumUnitType;
			}
		}

		if (!bAdd)
		{
			--iNumUnitType;
		}

		if (iNumUnitType > 0)
		{
			iCost *= 100 + GC.getUnitInfo(eUnit).getAdvancedStartCostIncrease() * iNumUnitType;
			iCost /= 100;
		}
	}
	
	return iCost;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing a City
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartCityCost(bool bAdd, CvPlot* pPlot) const
{
	int iNumCities = getNumCities();

	int iCost = getNewCityProductionValue();

	if (iCost < 0)
	{
		return -1;
	}
	
	// Valid plot?
	if (pPlot != NULL)
	{
		// Need valid plot to found on if adding
		if (bAdd)
		{
			if (!canFound(pPlot->getX(), pPlot->getY(), false))
			{
				return -1;
			}
		}
		// Need your own city present to remove
		else
		{
			if (pPlot->isCity())
			{
				if (pPlot->getPlotCity()->getOwnerINLINE() != getID())
				{
					return -1;
				}
			}
			else
			{
				return -1;
			}
		}

		// Is there a distance limit on how far a city can be placed from a player's start/another city?
		if (GC.getDefineINT("ADVANCED_START_CITY_PLACEMENT_MAX_RANGE") > 0)
		{
			PlayerTypes eClosestPlayer = NO_PLAYER;
			int iClosestDistance = MAX_INT;

			for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
			{
				CvPlayer& kPlayer = GET_PLAYER((PlayerTypes)iPlayer);

				if (kPlayer.isAlive())
				{
					CvPlot* pStartingPlot = kPlayer.getStartingPlot();

					if (NULL != pStartingPlot)
					{
						int iDistance = ::plotDistance(pPlot->getX_INLINE(), pPlot->getY_INLINE(), pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE());
						if (iDistance <= GC.getDefineINT("ADVANCED_START_CITY_PLACEMENT_MAX_RANGE"))
						{
							if (iDistance < iClosestDistance || (iDistance == iClosestDistance && getTeam() != kPlayer.getTeam()))
							{
								iClosestDistance = iDistance;
								eClosestPlayer = kPlayer.getID();
							}
						}				
					}
				}
			}

			if (NO_PLAYER == eClosestPlayer || GET_PLAYER(eClosestPlayer).getTeam() != getTeam())
			{
				return -1;
			}
			//Only allow founding a city at someone elses start point if 
			//We have no cities and they have no cities.
			if ((getID() != eClosestPlayer) && ((getNumCities() > 0) || (GET_PLAYER(eClosestPlayer).getNumCities() > 0)))
			{
				return -1;
			}
		}
	}

	// Increase cost if the XML defines that additional units will cost more
	if (0 != GC.getDefineINT("ADVANCED_START_CITY_COST_INCREASE"))
	{
		if (!bAdd)
		{
			--iNumCities;
		}

		if (iNumCities > 0)
		{
			iCost *= 100 + GC.getDefineINT("ADVANCED_START_CITY_COST_INCREASE") * iNumCities;
			iCost /= 100;
		}
	}
	
	return iCost;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing Population
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartPopCost(bool bAdd, CvCity* pCity) const
{
	if (0 == getNumCities())
	{
		return -1;
	}

	int iCost = (getGrowthThreshold(1) * GC.getDefineINT("ADVANCED_START_POPULATION_COST")) / 100;

	if (NULL != pCity)
	{
		if (pCity->getOwnerINLINE() != getID())
		{
			return -1;
		}

		int iPopulation = pCity->getPopulation();

		// Need to have Population to remove it
		if (!bAdd)
		{
			--iPopulation;

			if (iPopulation < GC.getDefineINT("INITIAL_CITY_POPULATION") + GC.getEraInfo(GC.getGameINLINE().getStartEra()).getFreePopulation())
			{
				return -1;
			}
		}

		iCost = (getGrowthThreshold(iPopulation) * GC.getDefineINT("ADVANCED_START_POPULATION_COST")) / 100;

		// Increase cost if the XML defines that additional Pop will cost more
		if (0 != GC.getDefineINT("ADVANCED_START_POPULATION_COST_INCREASE"))
		{
			--iPopulation;

			if (iPopulation > 0)
			{
				iCost *= 100 + GC.getDefineINT("ADVANCED_START_POPULATION_COST_INCREASE") * iPopulation;
				iCost /= 100;
			}
		}
	}

	return iCost;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing Culture
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartCultureCost(bool bAdd, CvCity* pCity) const
{
	if (0 == getNumCities())
	{
		return -1;
	}

	int iCost = GC.getDefineINT("ADVANCED_START_CULTURE_COST");
	if (iCost < 0)
	{
		return -1;
	}

	if (NULL != pCity)
	{
		if (pCity->getOwnerINLINE() != getID())
		{
			return -1;
		}

		// Need to have enough culture to remove it
		if (!bAdd)
		{
			if (pCity->getCultureLevel() <= 0)
			{
				return -1;
			}
		}

		int iCulture;
		if (bAdd)
		{
			iCulture = pCity->getCultureThreshold((CultureLevelTypes)(pCity->getCultureLevel() + 1)) - pCity->getCulture(getID());
		}
		else
		{
			iCulture = pCity->getCulture(getID()) - pCity->getCultureThreshold((CultureLevelTypes)(pCity->getCultureLevel() - 1));
		}

		iCost *= iCulture;
		iCost /= std::max(1, GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getHurryPercent());
	}

	return iCost;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing a Building from a city
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartBuildingCost(BuildingTypes eBuilding, bool bAdd, CvCity* pCity) const
{
	if (0 == getNumCities())
	{
		return -1;
	}

	int iNumBuildingType = 0;

	int iCost = (getProductionNeeded(eBuilding) * GC.getBuildingInfo(eBuilding).getAdvancedStartCost()) / 100;

	if (iCost < 0)
	{
		return -1;
	}

	if (GC.getBuildingInfo(eBuilding).getFreeStartEra() != NO_ERA && GC.getGameINLINE().getStartEra() >=  GC.getBuildingInfo(eBuilding).getFreeStartEra())
	{
		// you get this building for free
		return -1;
	}

	if (NULL == pCity)
	{
		if (bAdd)
		{
			bool bValid = false;
			int iLoop;
			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				if (pLoopCity->canConstruct(eBuilding))
				{
					bValid = true;
					break;
				}
			}

			if (!bValid)
			{
				return -1;
			}
		}
	}
	if (NULL != pCity)
	{
		if (pCity->getOwnerINLINE() != getID())
		{
			return -1;
		}

		iCost *= 100;
		iCost /= std::max(1, 100 + pCity->getProductionModifier(eBuilding));

		if (bAdd)
		{
			if (!pCity->canConstruct(eBuilding, true, false, false))
			{
				return -1;
			}
		}
		else
		{
			if (pCity->getNumRealBuilding(eBuilding) <= 0)
			{
				return -1;
			}

			// Check other buildings in this city and make sure none of them require this one

			// Loop through Buildings to see which are present
			for (int iBuildingLoop = 0; iBuildingLoop < GC.getNumBuildingInfos(); iBuildingLoop++)
			{
				BuildingTypes eBuildingLoop = (BuildingTypes) iBuildingLoop;

				if (pCity->getNumBuilding(eBuildingLoop) > 0)
				{
					// Loop through present Building's requirements
					for (int iBuildingClassPrereqLoop = 0; iBuildingClassPrereqLoop < GC.getNumBuildingClassInfos(); iBuildingClassPrereqLoop++)
					{
						if (GC.getBuildingInfo(eBuildingLoop).isBuildingClassNeededInCity(iBuildingClassPrereqLoop))
						{
							if ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iBuildingClassPrereqLoop)) == eBuilding)
							{
								return -1;
							}
						}
					}
				}
			}
		}
	}

	// Increase cost if the XML defines that additional Buildings will cost more
	if (0 != GC.getBuildingInfo(eBuilding).getAdvancedStartCostIncrease())
	{
		iNumBuildingType = countNumBuildings(eBuilding);
		
		if (!bAdd)
		{
			--iNumBuildingType;
		}

		if (iNumBuildingType > 0)
		{
			iCost *= 100 + GC.getBuildingInfo(eBuilding).getAdvancedStartCostIncrease() * std::max(0, iNumBuildingType - getNumCities());
			iCost /= 100;
		}
	}

	return iCost;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing Route
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartRouteCost(RouteTypes eRoute, bool bAdd, CvPlot* pPlot) const
{
	if (0 == getNumCities())
	{
		return -1;
	}

	if (eRoute == NO_ROUTE)
	{
		return -1;
	}

	int iNumRoutes = 0;

	int iCost = GC.getRouteInfo(eRoute).getAdvancedStartCost();

	// This denotes cities may not be purchased through Advanced Start
	if (iCost < 0)
	{
		return -1;
	}

	iCost *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getBuildPercent();
	iCost /= 100;

	// No invalid plots!
	if (pPlot != NULL)
	{
		if (pPlot->isCity())
		{
			return -1;
		}

		if (bAdd)
		{
		/************************************************************************************************/
		/* Afforess	Mountains Start		 09/18/09                                           		 */
		/*                                                                                              */
		/*                                                                                              */
		/************************************************************************************************/
			if (pPlot->isImpassable(getTeam()) || pPlot->isWater()) // added getTeam()
		/************************************************************************************************/
		/* Afforess	Mountains End       END        		                                             */
		/************************************************************************************************/
			{
				return -1;
			}
			// Can't place twice
			if (pPlot->getRouteType() == eRoute)
			{
				return -1;
			}
		}
		else
		{
			// Need Route to remove it
			if (pPlot->getRouteType() != eRoute)
			{
				return -1;
			}
		}

		// Must be owned by me
		if (pPlot->getOwnerINLINE() != getID())
		{
			return -1;
		}
	}

	// Tech requirement
	for (int iBuildLoop = 0; iBuildLoop < GC.getNumBuildInfos(); iBuildLoop++)
	{
		if (GC.getBuildInfo((BuildTypes) iBuildLoop).getRoute() == eRoute)
		{
			if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getBuildInfo((BuildTypes) iBuildLoop).getTechPrereq())))
			{
				return -1;
			}
		}
	}

	// Increase cost if the XML defines that additional units will cost more
	if (0 != GC.getRouteInfo(eRoute).getAdvancedStartCostIncrease())
	{
		int iPlotLoop = 0;
		CvPlot* pPlot;

		for (iPlotLoop = 0; iPlotLoop < GC.getMapINLINE().numPlots(); iPlotLoop++)
		{
			pPlot = GC.getMapINLINE().plotByIndex(iPlotLoop);

			if (pPlot->getRouteType() == eRoute)
			{
				++iNumRoutes;
			}
		}

		if (!bAdd)
		{
			--iNumRoutes;
		}

		if (iNumRoutes > 0)
		{
			iCost *= 100 + GC.getRouteInfo(eRoute).getAdvancedStartCostIncrease() * iNumRoutes;
			iCost /= 100;
		}
	}

	return iCost;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing Improvement
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartImprovementCost(ImprovementTypes eImprovement, bool bAdd, CvPlot* pPlot) const
{
	if (eImprovement == NO_IMPROVEMENT)
	{
		return -1;
	}

	if (0 == getNumCities())
	{
		return -1;
	}

	int iNumImprovements = 0;
	int iCost = GC.getImprovementInfo(eImprovement).getAdvancedStartCost();

		// This denotes cities may not be purchased through Advanced Start
	if (iCost < 0)
	{
		return -1;
	}

	iCost *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getBuildPercent();
	iCost /= 100;

	// Can this Improvement be on our plot?
	if (pPlot != NULL)
	{
		if (bAdd)
		{
			// Valid Plot
			if (!pPlot->canHaveImprovement(eImprovement, getTeam(), false))
			{
				return -1;
			}

			bool bValid = false;

			for (int iI = 0; iI < GC.getNumBuildInfos(); ++iI)
			{
				CvBuildInfo& kBuild = GC.getBuildInfo((BuildTypes)iI);
				ImprovementTypes eLoopImprovement = ((ImprovementTypes)(kBuild.getImprovement()));

				if (eImprovement == eLoopImprovement && canBuild(pPlot, (BuildTypes)iI))
				{
					bValid = true;

					FeatureTypes eFeature = pPlot->getFeatureType();
					if (NO_FEATURE != eFeature && kBuild.isFeatureRemove(eFeature))
					{
						iCost += GC.getFeatureInfo(eFeature).getAdvancedStartRemoveCost();
					}

					break;
				}
			}

			if (!bValid)
			{
				return -1;
			}

			// Can't place twice
			if (pPlot->getImprovementType() == eImprovement)
			{
				return -1;
			}
		}
		else
		{
			// Need this improvement in order to remove it
			if (pPlot->getImprovementType() != eImprovement)
			{
				return -1;
			}
		}

		// Must be owned by me
		if (pPlot->getOwnerINLINE() != getID())
		{
			return -1;
		}
	}
	
	// Tech requirement
	for (int iBuildLoop = 0; iBuildLoop < GC.getNumBuildInfos(); iBuildLoop++)
	{
		if (GC.getBuildInfo((BuildTypes) iBuildLoop).getImprovement() == eImprovement)
		{
			if (!(GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getBuildInfo((BuildTypes) iBuildLoop).getTechPrereq())))
			{
				return -1;
			}
		}
	}

	// Increase cost if the XML defines that additional units will cost more
	if (0 != GC.getImprovementInfo(eImprovement).getAdvancedStartCostIncrease())
	{
		int iPlotLoop = 0;
		CvPlot* pPlot;

		for (iPlotLoop = 0; iPlotLoop < GC.getMapINLINE().numPlots(); iPlotLoop++)
		{
			pPlot = GC.getMapINLINE().plotByIndex(iPlotLoop);
			
			if (pPlot->getImprovementType() == eImprovement)
			{
				++iNumImprovements;
			}
		}

		if (!bAdd)
		{
			--iNumImprovements;
		}

		if (iNumImprovements > 0)
		{
			iCost *= 100 + GC.getImprovementInfo(eImprovement).getAdvancedStartCostIncrease() * iNumImprovements;
			iCost /= 100;
		}
	}

	return iCost;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing Tech
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartTechCost(TechTypes eTech, bool bAdd) const
{
	if (eTech == NO_TECH)
	{
		return -1;
	}

	if (0 == getNumCities())
	{
		return -1;
	}

	int iNumTechs = 0;
		
	int iCost = (GET_TEAM(getTeam()).getResearchCost(eTech) * GC.getTechInfo(eTech).getAdvancedStartCost()) / 100;
	if (iCost < 0)
	{
		return -1;
	}

	if (bAdd)
	{
		if (!canResearch(eTech, false))
		{
			return -1;
		}
	}
	else if (!bAdd)
	{
		if (!GET_TEAM(getTeam()).isHasTech(eTech))
		{
			return -1;
		}
		
		// Search through all techs to see if any of the currently owned ones requires this tech
		for (int iTechLoop = 0; iTechLoop < GC.getNumTechInfos(); iTechLoop++)
		{
			TechTypes eTechLoop = (TechTypes) iTechLoop;

			if (GET_TEAM(getTeam()).isHasTech(eTechLoop))
			{
				int iPrereqLoop;

				// Or Prereqs
				for (iPrereqLoop = 0; iPrereqLoop < GC.getNUM_OR_TECH_PREREQS(); iPrereqLoop++)
				{
					if (GC.getTechInfo(eTechLoop).getPrereqOrTechs(iPrereqLoop) == eTech)
					{
						return -1;
					}
				}

				// And Prereqs
				for (iPrereqLoop = 0; iPrereqLoop < GC.getNUM_AND_TECH_PREREQS(); iPrereqLoop++)
				{
					if (GC.getTechInfo(eTechLoop).getPrereqAndTechs(iPrereqLoop) == eTech)
					{
						return -1;
					}
				}
			}
		}
		
		// If player has placed anything on the map which uses this tech then you cannot remove it
		int iLoop;

		// Units
		CvUnit* pLoopUnit;
		for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if (pLoopUnit->getUnitInfo().getPrereqAndTech() == eTech)
			{
				return -1;
			}

			for (int iI = 0; iI < GC.getNUM_UNIT_AND_TECH_PREREQS(); iI++)
			{
				if (pLoopUnit->getUnitInfo().getPrereqAndTechs(iI) == eTech)
				{
					return -1;
				}
			}
		}

		// Cities
		CvCity* pLoopCity;
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			// All Buildings
			for (int iBuildingLoop = 0; iBuildingLoop < GC.getNumBuildingInfos(); iBuildingLoop++)
			{
				BuildingTypes eBuilding = (BuildingTypes) iBuildingLoop;

				if (pLoopCity->getNumRealBuilding(eBuilding) > 0)
				{
					if (GC.getBuildingInfo(eBuilding).getPrereqAndTech() == eTech)
					{
						return -1;
					}

					for (int iI = 0; iI < GC.getNUM_BUILDING_AND_TECH_PREREQS(); iI++)
					{
						if (GC.getBuildingInfo(eBuilding).getPrereqAndTechs(iI) == eTech)
						{
							return -1;
						}
					}
				}
			}
		}

	}

	// Increase cost if the XML defines that additional units will cost more
	if (0 != GC.getTechInfo(eTech).getAdvancedStartCostIncrease())
	{
		for (int iTechLoop = 0; iTechLoop < GC.getNumTechInfos(); iTechLoop++)
		{
			if (GET_TEAM(getTeam()).isHasTech((TechTypes) iTechLoop))
			{
				++iNumTechs;
			}
		}

		if (!bAdd)
		{
			--iNumTechs;
		}

		if (iNumTechs > 0)
		{
			iCost *= 100 + GC.getTechInfo(eTech).getAdvancedStartCostIncrease() * iNumTechs;
			iCost /= 100;
		}
	}

	return iCost;
}

/////////////////////////////////////////////////////////////////////////////////////////////
// Adding or removing Visibility
/////////////////////////////////////////////////////////////////////////////////////////////

int CvPlayer::getAdvancedStartVisibilityCost(bool bAdd, CvPlot* pPlot) const
{
	if (0 == getNumCities())
	{
		return -1;
	}

	int iNumVisiblePlots = 0;
	int iCost = GC.getDefineINT("ADVANCED_START_VISIBILITY_COST");

	// This denotes Visibility may not be purchased through Advanced Start
	if (iCost == -1)
	{
		return -1;
	}

	// Valid Plot?
	if (pPlot != NULL)
	{
		if (bAdd)
		{
			if (pPlot->isRevealed(getTeam(), false))
			{
				return -1;
			}
			if (!pPlot->isAdjacentRevealed(getTeam()))
			{
				return -1;
			}
		}
		else
		{
			if (!pPlot->isRevealed(getTeam(), false))
			{
				return -1;
			}
		}
	}

	// Increase cost if the XML defines that additional units will cost more
	if (0 != GC.getDefineINT("ADVANCED_START_VISIBILITY_COST_INCREASE"))
	{
		int iPlotLoop = 0;
		CvPlot* pPlot;

		for (iPlotLoop = 0; iPlotLoop < GC.getMapINLINE().numPlots(); iPlotLoop++)
		{
			pPlot = GC.getMapINLINE().plotByIndex(iPlotLoop);

			if (pPlot->isRevealed(getTeam(), false))
			{
				++iNumVisiblePlots;
			}
		}

		if (!bAdd)
		{
			--iNumVisiblePlots;
		}

		if (iNumVisiblePlots > 0)
		{
			iCost *= 100 + GC.getDefineINT("ADVANCED_START_VISIBILITY_COST_INCREASE") * iNumVisiblePlots;
			iCost /= 100;
		}
	}

	return iCost;
}

void CvPlayer::doWarnings()
{
	PROFILE_FUNC();

	CvCity* pNearestCity;
	CvPlot* pLoopPlot;
	CvUnit* pLoopUnit;
	wchar szBuffer[1024];
	int iMaxCount;
	int iI;

	//update enemy unit in your territory glow
	int iLoop;
	for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		//update glow
		if ( !pLoopUnit->isUsingDummyEntities() )
		{
			gDLL->getEntityIFace()->updateEnemyGlow(pLoopUnit->getUnitEntity());
		}
	}

// BUG - Ignore Harmless Barbarians - start
	bool bCheckBarbarians = false;
	bool bCheckBarbariansInitialized = !isHuman();
// BUG - Ignore Harmless Barbarians - end

	//update enemy units close to your territory
	iMaxCount = range(((getNumCities() + 4) / 7), 2, 5);
	for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		if (iMaxCount == 0)
		{
			break;
		}

		pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

		if (pLoopPlot->isAdjacentPlayer(getID()))
		{
			if (!(pLoopPlot->isCity()))
			{
				if (pLoopPlot->isVisible(getTeam(), false))
				{
					CvUnit *pUnit = pLoopPlot->getVisibleEnemyDefender(getID());
					if (pUnit != NULL)
					{
						if (!pUnit->isAnimal())
						{
// BUG - Ignore Harmless Barbarians - start
							if (!bCheckBarbariansInitialized && GC.getGameINLINE().getElapsedGameTurns() > 0)
							{
								bCheckBarbarians = getBugOptionBOOL("Actions__IgnoreHarmlessBarbarians", true, "BUG_IGNORE_HARMLESS_BARBARIANS");
								bCheckBarbariansInitialized = true;
							}
							if (bCheckBarbarians && pUnit->isBarbarian() && pUnit->getDomainType() == DOMAIN_LAND)
							{
								CvArea* pArea = pUnit->area();
								if (pArea && pArea->isBorderObstacle(getTeam()))
								{
									// don't show warning for land-based barbarians when player has Great Wall
									continue;
								}
							}
// BUG - Ignore Harmless Barbarians - end

							pNearestCity = GC.getMapINLINE().findCity(pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), getID(), NO_TEAM, !(pLoopPlot->isWater()));

							if (pNearestCity != NULL)
							{	
								MEMORY_TRACK_EXEMPT();

								//OutputDebugString("UI interaction - enemy spotted\n");
								setTurnHadUIInteraction(true);

								swprintf(szBuffer, gDLL->getText("TXT_KEY_MISC_ENEMY_TROOPS_SPOTTED", pNearestCity->getNameKey()).GetCString());
								AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_ENEMY_TROOPS", MESSAGE_TYPE_INFO, pUnit->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE(), true, true);

								iMaxCount--;
							}
						}
					}
				}
			}
		}
	}
}


void CvPlayer::verifyGoldCommercePercent()
{
	PROFILE_FUNC()

	while ((getGold() + calculateGoldRate()) < 0)
	{
		changeCommercePercent(COMMERCE_GOLD, GC.getDefineINT("COMMERCE_PERCENT_CHANGE_INCREMENTS"));

		if (getCommercePercent(COMMERCE_GOLD) == 100)
		{
			break;
		}
	}
}

int CvPlayer::getCivicHealth(void) const
{
	int	iTotal = 0;

	for(int iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		CivicTypes eCivic = getCivics((CivicOptionTypes)iI);

		if ( eCivic != NO_CIVIC )
		{
			CvCivicInfo& kCivic = GC.getCivicInfo(eCivic);

			iTotal += kCivic.getExtraHealth();
		}
	}

	return iTotal;
}

/********************************************************************************/
/* 	New Civic AI						19.08.2010				Fuyu			*/
/********************************************************************************/
//Fuyu bLimited
void CvPlayer::processCivics(CivicTypes eCivic, int iChange, bool bLimited)
{
	int iI, iJ;
	 //DPII < Maintenance Modifiers >
    CvArea* pLoopArea = NULL;

    int iLoop = 0;
    //DPII < Maintenance Modifiers >
/************************************************************************************************/
/* Afforess	                  Start		 5/28/11                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	CvCivicInfo& kCivic = GC.getCivicInfo(eCivic);
	//Speed Optimizations
	if (bLimited)
	{
		CvCivicInfo& kCivic = GC.getCivicInfo(eCivic);

		changeCivicHappiness(kCivic.getCivicHappiness() * iChange);
		changeNoCapitalUnhappiness(kCivic.isNoCapitalUnhappiness() ? iChange : 0);

		changeTaxRateUnhappiness(kCivic.getTaxRateUnhappiness() * iChange);
		changePopulationgrowthratepercentage(kCivic.getPopulationgrowthratepercentage(),(iChange==1));
		//+: doesn't change values of other civics but maybe should
		//changeGreatPeopleRateModifier(kCivic.getGreatPeopleRateModifier() * iChange);
		//changeGreatGeneralRateModifier(kCivic.getGreatGeneralRateModifier() * iChange);
		//changeDomesticGreatGeneralRateModifier(kCivic.getDomesticGreatGeneralRateModifier() * iChange);
		//changeStateReligionGreatPeopleRateModifier(kCivic.getStateReligionGreatPeopleRateModifier() * iChange);
		//changeDistanceMaintenanceModifier(kCivic.getDistanceMaintenanceModifier() * iChange);
		//changeNumCitiesMaintenanceModifier(kCivic.getNumCitiesMaintenanceModifier() * iChange);
		changeCorporationMaintenanceModifier(kCivic.getCorporationMaintenanceModifier() * iChange, bLimited);
		changeExtraHealth(kCivic.getExtraHealth() * iChange, bLimited);
		//changeFreeExperience(kCivic.getFreeExperience() * iChange);
		//changeWorkerSpeedModifier(kCivic.getWorkerSpeedModifier() * iChange);
		//changeImprovementUpgradeRateModifier(kCivic.getImprovementUpgradeRateModifier() * iChange);
		//changeMilitaryProductionModifier(kCivic.getMilitaryProductionModifier() * iChange);
		//changeBaseFreeUnits(kCivic.getBaseFreeUnits() * iChange);
		//changeBaseFreeMilitaryUnits(kCivic.getBaseFreeMilitaryUnits() * iChange);
		//changeFreeUnitsPopulationPercent(kCivic.getFreeUnitsPopulationPercent() * iChange);
		//changeFreeMilitaryUnitsPopulationPercent(kCivic.getFreeMilitaryUnitsPopulationPercent() * iChange);
		//changeGoldPerUnit(kCivic.getGoldPerUnit() * iChange);
		//changeGoldPerMilitaryUnit(kCivic.getGoldPerMilitaryUnit() * iChange);
		changeHappyPerMilitaryUnit(kCivic.getHappyPerMilitaryUnit() * iChange,  bLimited);
		changeMilitaryFoodProductionCount(((kCivic.isMilitaryFoodProduction()) ? iChange : 0), bLimited);
		//changeMaxConscript(getWorldSizeMaxConscript(eCivic) * iChange);
		changeNoUnhealthyPopulationCount(((kCivic.isNoUnhealthyPopulation()) ? iChange : 0), bLimited);
		changeBuildingOnlyHealthyCount(((kCivic.isBuildingOnlyHealthy()) ? iChange : 0), bLimited);
		changeLargestCityHappiness((kCivic.getLargestCityHappiness() * iChange), bLimited);
		if (getWarWearinessPercentAnger() != 0)
		{
			changeWarWearinessModifier((kCivic.getWarWearinessModifier() * iChange), bLimited);
		}
		//changeFreeSpecialist(kCivic.getFreeSpecialist() * iChange);
		//changeTradeRoutes(kCivic.getTradeRoutes() * iChange);
		changeNoForeignTradeCount(kCivic.isNoForeignTrade() * iChange, bLimited);
		changeNoCorporationsCount(kCivic.isNoCorporations() * iChange, bLimited);
		changeNoForeignCorporationsCount(kCivic.isNoForeignCorporations() * iChange, bLimited);
		changeStateReligionCount(((kCivic.isStateReligion()) ? iChange : 0), bLimited);
		changeNoNonStateReligionSpreadCount((kCivic.isNoNonStateReligionSpread()) ? iChange : 0);
		changeStateReligionHappiness(kCivic.getStateReligionHappiness() * iChange, bLimited);
		changeNonStateReligionHappiness(kCivic.getNonStateReligionHappiness() * iChange, bLimited);
		//changeStateReligionUnitProductionModifier(kCivic.getStateReligionUnitProductionModifier() * iChange);
		//changeStateReligionBuildingProductionModifier(kCivic.getStateReligionBuildingProductionModifier() * iChange);
		//changeStateReligionFreeExperience(kCivic.getStateReligionFreeExperience() * iChange);
		//changeExpInBorderModifier(kCivic.getExpInBorderModifier() * iChange);
		changeRevIdxLocal(GC.getCivicInfo(eCivic).getRevIdxLocal() * iChange);
		changeRevIdxNational(GC.getCivicInfo(eCivic).getRevIdxNational() * iChange);
		changeRevIdxDistanceModifier(GC.getCivicInfo(eCivic).getRevIdxDistanceModifier() * iChange);

		changeCityLimit(kCivic.getCityLimit(getID()) * iChange);
		changeCityOverLimitUnhappy(kCivic.getCityOverLimitUnhappy() * iChange);
		changeForeignUnhappyPercent(kCivic.getForeignerUnhappyPercent() * iChange);
		//for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
		//{
		//	changeYieldRateModifier(((YieldTypes)iI), (kCivic.getYieldModifier(iI) * iChange));
		//	changeCapitalYieldRateModifier(((YieldTypes)iI), (kCivic.getCapitalYieldModifier(iI) * iChange));
		//	changeTradeYieldModifier(((YieldTypes)iI), (kCivic.getTradeYieldModifier(iI) * iChange));
		//}

		//for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
		//{
		//	changeCommerceRateModifier(((CommerceTypes)iI), (kCivic.getCommerceModifier(iI) * iChange));
		//	changeCapitalCommerceRateModifier(((CommerceTypes)iI), (kCivic.getCapitalCommerceModifier(iI) * iChange));
		//	changeSpecialistExtraCommerce(((CommerceTypes)iI), (kCivic.getSpecialistExtraCommerce(iI) * iChange));
		//}

		if (kCivic.isAnyBuildingHappinessChange() || kCivic.isAnyBuildingHealthChange())
		{
			for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
			{
				BuildingTypes eOurBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI);
				if (NO_BUILDING != eOurBuilding)
				{
					changeExtraBuildingHappiness(eOurBuilding, (kCivic.getBuildingHappinessChanges(iI) * iChange), bLimited);
					changeExtraBuildingHealth(eOurBuilding, (kCivic.getBuildingHealthChanges(iI) * iChange), bLimited);
				}
			}
		}

		if (kCivic.isAnyFeatureHappinessChange())
		{
			for (iI = 0; iI < GC.getNumFeatureInfos(); iI++)
			{
				changeFeatureHappiness(((FeatureTypes)iI), (kCivic.getFeatureHappinessChanges(iI) * iChange), bLimited);
			}
		}

		for (iI = 0; iI < GC.getNumHurryInfos(); iI++)
		{
			changeHurryCount(((HurryTypes)iI), ((kCivic.isHurry(iI)) ? iChange : 0));
		}

		for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); iI++)
		{
			changeSpecialBuildingNotRequiredCount(((SpecialBuildingTypes)iI), ((kCivic.isSpecialBuildingNotRequired(iI)) ? iChange : 0));
		}

		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			changeSpecialistValidCount(((SpecialistTypes)iI), ((kCivic.isSpecialistValid(iI)) ? iChange : 0), bLimited);
		}

		//for (iI = 0; iI < GC.getNumImprovementInfos(); iI++)
		//{
		//	for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
		//	{
		//		changeImprovementYieldChange(((ImprovementTypes)iI), ((YieldTypes)iJ), (kCivic.getImprovementYieldChanges(iI, iJ) * iChange));
		//	}
		//}


	}
	else
	{
		FAssert(iChange == 1 || iChange == -1);

		changeGreatPeopleRateModifier(kCivic.getGreatPeopleRateModifier() * iChange);
		changeGreatGeneralRateModifier(kCivic.getGreatGeneralRateModifier() * iChange);
		changeDomesticGreatGeneralRateModifier(kCivic.getDomesticGreatGeneralRateModifier() * iChange);
		changeStateReligionGreatPeopleRateModifier(kCivic.getStateReligionGreatPeopleRateModifier() * iChange);
		changeDistanceMaintenanceModifier(kCivic.getDistanceMaintenanceModifier() * iChange);
		changeNumCitiesMaintenanceModifier(kCivic.getNumCitiesMaintenanceModifier() * iChange);
		if (GC.getGameINLINE().isOption(GAMEOPTION_REALISTIC_CORPORATIONS))
		{
			changeCorporationMaintenanceModifier(kCivic.getRealCorporationMaintenanceModifier() * iChange);
		}
		else
		{
			changeCorporationMaintenanceModifier(kCivic.getCorporationMaintenanceModifier() * iChange);
		}
		changeExtraHealth(kCivic.getExtraHealth() * iChange);
		changeFreeExperience(kCivic.getFreeExperience() * iChange);
		changeWorkerSpeedModifier(kCivic.getWorkerSpeedModifier() * iChange);
		changeImprovementUpgradeRateModifier(kCivic.getImprovementUpgradeRateModifier() * iChange);
		changeMilitaryProductionModifier(kCivic.getMilitaryProductionModifier() * iChange);
		changeBaseFreeUnits(kCivic.getBaseFreeUnits() * iChange);
		changeBaseFreeMilitaryUnits(kCivic.getBaseFreeMilitaryUnits() * iChange);
		changeFreeUnitsPopulationPercent(kCivic.getFreeUnitsPopulationPercent() * iChange);
		changeFreeMilitaryUnitsPopulationPercent(kCivic.getFreeMilitaryUnitsPopulationPercent() * iChange);
		changeGoldPerUnit(kCivic.getGoldPerUnit() * iChange);
		changeGoldPerMilitaryUnit(kCivic.getGoldPerMilitaryUnit() * iChange);
		changeHappyPerMilitaryUnit(kCivic.getHappyPerMilitaryUnit() * iChange);
		changeMilitaryFoodProductionCount((kCivic.isMilitaryFoodProduction()) ? iChange : 0);
		changeMaxConscript(getWorldSizeMaxConscript(eCivic) * iChange);
		changeNoUnhealthyPopulationCount((kCivic.isNoUnhealthyPopulation()) ? iChange : 0);
		changeBuildingOnlyHealthyCount((kCivic.isBuildingOnlyHealthy()) ? iChange : 0);
		changeLargestCityHappiness(kCivic.getLargestCityHappiness() * iChange);
		changeWarWearinessModifier(kCivic.getWarWearinessModifier() * iChange);
		changeFreeSpecialist(kCivic.getFreeSpecialist() * iChange);
		changeTradeRoutes(kCivic.getTradeRoutes() * iChange);
		changeNoForeignTradeCount(kCivic.isNoForeignTrade() * iChange);
		changeNoCorporationsCount(kCivic.isNoCorporations() * iChange);
		changeNoForeignCorporationsCount(kCivic.isNoForeignCorporations() * iChange);
		changeStateReligionCount((kCivic.isStateReligion()) ? iChange : 0);
		changeNoNonStateReligionSpreadCount((kCivic.isNoNonStateReligionSpread()) ? iChange : 0);
		changeStateReligionHappiness(kCivic.getStateReligionHappiness() * iChange);
		changeNonStateReligionHappiness(kCivic.getNonStateReligionHappiness() * iChange);
		changeStateReligionUnitProductionModifier(kCivic.getStateReligionUnitProductionModifier() * iChange);
		changeStateReligionBuildingProductionModifier(kCivic.getStateReligionBuildingProductionModifier() * iChange);
		changeStateReligionFreeExperience(kCivic.getStateReligionFreeExperience() * iChange);
		changeExpInBorderModifier(kCivic.getExpInBorderModifier() * iChange);
		updateSeizedForeignConnectednessPercent();
		
		 //DPII < Maintenance Modifiers >
		if ((GC.getCivicInfo(eCivic).getOtherAreaMaintenanceModifier() != 0) || (GC.getCivicInfo(eCivic).getHomeAreaMaintenanceModifier() != 0))
		{
			for (pLoopArea = GC.getMapINLINE().firstArea(&iLoop); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoop))
			{
				if (pLoopArea->isHomeArea(getID()))
				{
					pLoopArea->changeHomeAreaMaintenanceModifier(getID(), (GC.getCivicInfo(eCivic).getHomeAreaMaintenanceModifier()  * iChange));
				}
				else
				{
					pLoopArea->changeOtherAreaMaintenanceModifier(getID(), (GC.getCivicInfo(eCivic).getOtherAreaMaintenanceModifier()  * iChange));
				}
			}
		}
		//DPII < Maintenance Modifiers >
		
	/************************************************************************************************/
	/* REVDCM                                 02/16/10                                phungus420    */
	/*                                                                                              */
	/* RevCivic Effects                                                                             */
	/************************************************************************************************/
			changeUpgradeAnywhere((GC.getCivicInfo(eCivic).isUpgradeAnywhere())? iChange : 0);
			changeRevIdxLocal(GC.getCivicInfo(eCivic).getRevIdxLocal() * iChange);
			changeRevIdxNational(GC.getCivicInfo(eCivic).getRevIdxNational() * iChange);
			changeRevIdxDistanceModifier(GC.getCivicInfo(eCivic).getRevIdxDistanceModifier() * iChange);
			changeRevIdxHolyCityGood(GC.getCivicInfo(eCivic).getRevIdxHolyCityGood() * iChange);
			changeRevIdxHolyCityBad(GC.getCivicInfo(eCivic).getRevIdxHolyCityBad() * iChange);
			changeRevIdxNationalityMod(GC.getCivicInfo(eCivic).getRevIdxNationalityMod() * static_cast<float>(iChange));
			changeRevIdxBadReligionMod(GC.getCivicInfo(eCivic).getRevIdxBadReligionMod() * static_cast<float>(iChange));
			changeRevIdxGoodReligionMod(GC.getCivicInfo(eCivic).getRevIdxGoodReligionMod() * static_cast<float>(iChange));
			if ( GC.getCivicInfo(eCivic).isAllowInquisitions() || GC.getCivicInfo(eCivic).isDisallowInquisitions() )
			{
				setInquisitionConditions();
			}
	/************************************************************************************************/
	/* REVDCM                                  END                                                  */
	/************************************************************************************************/

		for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
		{
			changeYieldRateModifier(((YieldTypes)iI), (kCivic.getYieldModifier(iI) * iChange));
			changeCapitalYieldRateModifier(((YieldTypes)iI), (kCivic.getCapitalYieldModifier(iI) * iChange));
			changeTradeYieldModifier(((YieldTypes)iI), (kCivic.getTradeYieldModifier(iI) * iChange));
			changeLandmarkYield((YieldTypes)iI, kCivic.getLandmarkYieldChanges(iI) * iChange);
		}

		for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
		{
			changeCommerceRateModifier(((CommerceTypes)iI), (kCivic.getCommerceModifier(iI) * iChange));
			changeCapitalCommerceRateModifier(((CommerceTypes)iI), (kCivic.getCapitalCommerceModifier(iI) * iChange));
			changeSpecialistExtraCommerce(((CommerceTypes)iI), (kCivic.getSpecialistExtraCommerce(iI) * iChange));
		}
		
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			BuildingTypes eOurBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI);
			if (NO_BUILDING != eOurBuilding)
			{
				changeExtraBuildingHappiness(eOurBuilding, (kCivic.getBuildingHappinessChanges(iI) * iChange));
				changeExtraBuildingHealth(eOurBuilding, (kCivic.getBuildingHealthChanges(iI) * iChange));
			}
			changeBuildingClassProductionModifier(((BuildingClassTypes)iI), (kCivic.getBuildingClassProductionModifier(iI) * iChange));
		}
	/************************************************************************************************/
	/* Afforess	                  Start		 5/29/11                                                */
	/*                                                                                              */
	/*                                                                                              */
	/************************************************************************************************/
		for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
		{
			changeUnitClassProductionModifier(((UnitClassTypes)iI), kCivic.getUnitClassProductionModifier(iI) * iChange);
		}
	/************************************************************************************************/
	/* Afforess	                     END                                                            */
	/************************************************************************************************/
		for (iI = 0; iI < GC.getNumFeatureInfos(); iI++)
		{
			changeFeatureHappiness(((FeatureTypes)iI), (kCivic.getFeatureHappinessChanges(iI) * iChange));
		}

		for (iI = 0; iI < GC.getNumHurryInfos(); iI++)
		{
			changeHurryCount(((HurryTypes)iI), ((kCivic.isHurry(iI)) ? iChange : 0));
		}

		for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); iI++)
		{
			changeSpecialBuildingNotRequiredCount(((SpecialBuildingTypes)iI), ((kCivic.isSpecialBuildingNotRequired(iI)) ? iChange : 0));
		}

		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			changeSpecialistValidCount(((SpecialistTypes)iI), ((kCivic.isSpecialistValid(iI)) ? iChange : 0));
			changeFreeSpecialistCount((SpecialistTypes)iI, (kCivic.getFreeSpecialistCount(iI) * iChange));
		}

		for (iI = 0; iI < GC.getNumImprovementInfos(); iI++)
		{
			for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
			{
				changeImprovementYieldChange(((ImprovementTypes)iI), ((YieldTypes)iJ), (kCivic.getImprovementYieldChanges(iI, iJ) * iChange));
			}
		}

		changeCivicHappiness(kCivic.getCivicHappiness() * iChange);
		changeForeignTradeRouteModifier(kCivic.getForeignTradeRouteModifier() * iChange);
		changeTaxRateUnhappiness(kCivic.getTaxRateUnhappiness() * iChange);
		changePopulationgrowthratepercentage(kCivic.getPopulationgrowthratepercentage(),(iChange==1));
		changeReligionSpreadRate(kCivic.getReligionSpreadRate() * iChange);
		changeCorporationSpreadModifier(kCivic.getCorporationSpreadRate() * iChange);
		changeDistantUnitSupportCostModifier(kCivic.getDistantUnitSupportCostModifier() * iChange);
		changeExtraCityDefense(kCivic.getExtraCityDefense() * iChange);
		changeEnslavementChance(kCivic.getEnslavementChance() * iChange);
		changeNoCapitalUnhappiness(kCivic.isNoCapitalUnhappiness() ? iChange : 0);
		changeTaxationAnger(kCivic.isTaxationAnger() ? iChange : 0);
		changeCivicInflation(kCivic.getInflationModifier() * iChange);
		changeHurryCostModifier(kCivic.getHurryCostModifier() * iChange);
		changeHurryInflationModifier(kCivic.getHurryInflationModifier() * iChange);
		changeLandmarkHappiness(kCivic.getLandmarkHappiness() * iChange);
		changeNoLandmarkAngerCount(kCivic.isNoLandmarkAnger() ? iChange : 0);
		changeMADNukesCount(kCivic.isEnablesMAD() ? iChange : 0);
		changeCityLimit(kCivic.getCityLimit(getID()) * iChange);
		changeCityOverLimitUnhappy(kCivic.getCityOverLimitUnhappy() * iChange);
		changeForeignUnhappyPercent(kCivic.getForeignerUnhappyPercent() * iChange);
		changeFixedBordersCount(kCivic.IsFixedBorders() ? iChange : 0);
		changeFractionalXPEarnedInCity(kCivic.getFractionalXPEarnedInCity() * iChange);
		AI_makeAssignWorkDirty();
		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
			{
				changeSpecialistYieldPercentChanges((SpecialistTypes)iI, (YieldTypes)iJ, kCivic.getSpecialistYieldPercentChanges(iI, iJ) * iChange);
			}
			for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
			{
				changeSpecialistCommercePercentChanges((SpecialistTypes)iI, (CommerceTypes)iJ, kCivic.getSpecialistCommercePercentChanges(iI, iJ) * iChange);
			}
		}
		for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
		{
			for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
			{	
				changeBuildingCommerceModifier((BuildingTypes)iI, (CommerceTypes)iJ, kCivic.getBuildingCommerceModifier(iI, iJ) * iChange);
			}
		}
		
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
			{
				for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
				{
					changeBuildingClassCommerceChange((BuildingClassTypes)iI, (CommerceTypes)iJ, kCivic.getBuildingClassCommerceChange(iI, iJ) * iChange);
				}
			}

		for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
		{
			changeBonusMintedPercent((BonusTypes)iI, kCivic.getBonusMintedPercent(iI) * iChange);
			for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
			{	
				changeBonusCommerceModifier((BonusTypes)iI, (CommerceTypes)iJ, kCivic.getBonusCommerceModifier(iI, iJ) * iChange);
			}
		}
		if (iChange == -1)
		{
			for (int iI = 0; iI < GC.getNumVoteSourceInfos(); ++iI)
			{
				if (GC.getVoteSourceInfo((VoteSourceTypes)iI).getCivic() == eCivic)
				{
					if (GC.getGameINLINE().getSecretaryGeneral((VoteSourceTypes)iI) == getTeam())
					{
						GC.getGameINLINE().clearSecretaryGeneral((VoteSourceTypes)iI);
					}
				}
			}
			
		}
		for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
		{
			changeUnitCombatProductionModifier(((UnitCombatTypes)iI), (kCivic.getUnitCombatProductionModifier(iI) * iChange));
		}

		for (iI = 0; iI < GC.getNumTerrainInfos(); iI++)
		{
			for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
			{
				changeTerrainYieldChange(((TerrainTypes)iI), ((YieldTypes)iJ), (kCivic.getTerrainYieldChanges(iI, iJ) * iChange));
			}
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
}
/********************************************************************************/
/* 	New Civic AI												END 			*/
/********************************************************************************/

void CvPlayer::showMissedMessages()
{
	CvMessageQueue::iterator it = m_listGameMessages.begin();
	while (it != m_listGameMessages.end())
	{
		CvTalkingHeadMessage& msg = *it;
		if (!msg.getShown())
		{
			msg.setShown(true);
			gDLL->getInterfaceIFace()->showMessage(msg);
		}
		++it;
	}
}

bool CvPlayer::isPbemNewTurn() const
{
	return m_bPbemNewTurn;
}

void CvPlayer::setPbemNewTurn(bool bNew)
{
	m_bPbemNewTurn = bNew;
}



//
// read object from a stream
// used during load
//
void CvPlayer::read(FDataStreamBase* pStream)
{
	int iI;

	MEMORY_TRACE_FUNCTION();

	CvTaggedSaveFormatWrapper&	wrapper = CvTaggedSaveFormatWrapper::getSaveFormatWrapper();

	wrapper.AttachToStream(pStream);

	WRAPPER_READ_OBJECT_START(wrapper);

	uint uiFlag=0;
	WRAPPER_READ(wrapper, "CvPlayer", &uiFlag);	// flags for expansion

	if ((uiFlag& PLAYER_UI_FLAG_OMITTED) == 0)
	{
		// Init data before load
		reset();

		// < M.A.D. Nukes Start >
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMADDeterrent);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMADIncoming);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMADOutgoing);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMADNukesCount);
		// < M.A.D. Nukes End   >
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStartingX);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStartingY);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTotalPopulation);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTotalLand);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTotalLandScored);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGold);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGoldPerTurn);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iAdvancedStartPoints);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGoldenAgeTurns);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumUnitGoldenAges);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStrikeTurns);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iAnarchyTurns);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMaxAnarchyTurns);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iAnarchyModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGoldenAgeModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGlobalHurryModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGreatPeopleCreated);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGreatGeneralsCreated);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGreatPeopleThresholdModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGreatGeneralsThresholdModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGreatPeopleRateModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGreatGeneralRateModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iDomesticGreatGeneralRateModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStateReligionGreatPeopleRateModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMaxGlobalBuildingProductionModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMaxTeamBuildingProductionModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMaxPlayerBuildingProductionModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iFreeExperience);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iFeatureProductionModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iWorkerSpeedModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iImprovementUpgradeRateModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMilitaryProductionModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iSpaceProductionModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCityDefenseModifier);
		/************************************************************************************************/
		/* REVDCM                                 09/02/10                                phungus420    */
		/*                                                                                              */
		/* Player Functions                                                                             */
		/************************************************************************************************/
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNonStateReligionCommerceCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iUpgradeAnywhereCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iRevIdxLocal);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iRevIdxNational);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iRevIdxDistanceModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iRevIdxHolyCityGood);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iRevIdxHolyCityBad);
		WRAPPER_READ(wrapper, "CvPlayer", &m_fRevIdxNationalityMod);
		WRAPPER_READ(wrapper, "CvPlayer", &m_fRevIdxBadReligionMod);
		WRAPPER_READ(wrapper, "CvPlayer", &m_fRevIdxGoodReligionMod);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bInquisitionConditions);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iUnitUpgradePriceModifier);
		/************************************************************************************************/
		/* REVDCM                                  END                                                  */
		/************************************************************************************************/
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumNukeUnits);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumOutsideUnits);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iBaseFreeUnits);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iBaseFreeMilitaryUnits);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iFreeUnitsPopulationPercent);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iFreeMilitaryUnitsPopulationPercent);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGoldPerUnit);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iGoldPerMilitaryUnit);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iExtraUnitCost);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumMilitaryUnits);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iHappyPerMilitaryUnit);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMilitaryFoodProductionCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iConscriptCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMaxConscript);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iHighestUnitLevel);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iOverflowResearch);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNoUnhealthyPopulationCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iExpInBorderModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iBuildingOnlyHealthyCount);
		//DPII < Maintenance Modifiers >
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMaintenanceModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCoastalDistanceMaintenanceModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iConnectedCityMaintenanceModifier);
		//DPII < Maintenance Modifiers >
		WRAPPER_READ(wrapper, "CvPlayer", &m_iDistanceMaintenanceModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumCitiesMaintenanceModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCorporationMaintenanceModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTotalMaintenance);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iUpkeepModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iLevelExperienceModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iExtraHealth);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iBuildingGoodHealth);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iBuildingBadHealth);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iExtraHappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iBuildingHappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iLargestCityHappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iWarWearinessPercentAnger);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iWarWearinessModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iFreeSpecialist);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNoForeignTradeCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNoCorporationsCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNoForeignCorporationsCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCoastalTradeRoutes);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTradeRoutes);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iRevolutionTimer);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iConversionTimer);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStateReligionCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNoNonStateReligionSpreadCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStateReligionHappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNonStateReligionHappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStateReligionUnitProductionModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStateReligionBuildingProductionModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStateReligionFreeExperience);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCapitalCityID);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCitiesLost);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iWinsVsBarbs);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iAssets);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iPower);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTechPower);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iUnitPower);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iPopulationScore);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iLandScore);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iWondersScore);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTechScore);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCombatExperience);

		WRAPPER_READ(wrapper, "CvPlayer", &m_bAlive);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bEverAlive);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bTurnActive);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bAutoMoves);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bEndTurn);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bPbemNewTurn);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bExtendedGame);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bFoundedFirstCity);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bStrike);
		//TB Nukefix (Reversal) Should NOT comment out the following line
		WRAPPER_READ(wrapper, "CvPlayer", &m_bNukesValid);

		/************************************************************************************************/
		/* AI_AUTO_PLAY                           07/09/08                                jdog5000      */
		/*                                                                                              */
		/*                                                                                              */
		/************************************************************************************************/
		WRAPPER_READ(wrapper, "CvPlayer", &m_bDisableHuman);
		/************************************************************************************************/
		/* AI_AUTO_PLAY                            END                                                  */
		/************************************************************************************************/
		/************************************************************************************************/
		/* REVOLUTION_MOD                         02/04/09                                jdog5000      */
		/*                                                                                              */
		/*                                                                                              */
		/************************************************************************************************/
		WRAPPER_READ(wrapper, "CvPlayer", &m_iFreeUnitCountdown);

		WRAPPER_READ(wrapper, "CvPlayer", &m_iStabilityIndex);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iStabilityIndexAverage);

		WRAPPER_READ(wrapper, "CvPlayer", &m_bRebel);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iMotherPlayer);
		WRAPPER_READ(wrapper, "CvPlayer", &m_bDoNotBotherStatus);

		// Used for DynamicCivNames
		WRAPPER_READ_STRING(wrapper, "CvPlayer", m_szName);
		WRAPPER_READ_STRING(wrapper, "CvPlayer", m_szCivDesc);
		WRAPPER_READ_STRING(wrapper, "CvPlayer", m_szCivShort);
		WRAPPER_READ_STRING(wrapper, "CvPlayer", m_szCivAdj);
		/************************************************************************************************/
		/* REVOLUTION_MOD                          END                                                  */
		/************************************************************************************************/
		WRAPPER_READ(wrapper, "CvPlayer", (int*)&m_eID);

		m_contractBroker.init(m_eID);

		WRAPPER_READ(wrapper, "CvPlayer", (int*)&m_ePersonalityType);
		//	The above should be a class enum but to avoid screwing up existing saves doing a manual translation
		m_ePersonalityType = (LeaderHeadTypes)wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_LEADERHEADS, m_ePersonalityType, true);
		if (m_ePersonalityType == -1)
		{
			//	Just accept the default for the leaderhead if the one that was being used has been removed
			m_ePersonalityType = getLeaderType();
		}
		WRAPPER_READ(wrapper, "CvPlayer", (int*)&m_eCurrentEra);
		WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_RELIGIONS, (int*)&m_eLastStateReligion);
		WRAPPER_READ(wrapper, "CvPlayer", (int*)&m_eParent);
		updateTeamType(); //m_eTeamType not saved
		updateHuman();

		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiSeaPlotYield);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiYieldRateModifier);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiCapitalYieldRateModifier);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiExtraYieldThreshold);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiTradeYieldModifier);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiFreeCityCommerce);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCommercePercent);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCommerceRate);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCommerceRateModifier);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCapitalCommerceRateModifier);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiStateReligionBuildingCommerce);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiSpecialistExtraCommerce);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCommerceFlexibleCount);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", MAX_PLAYERS, m_aiGoldPerTurnByPlayer);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", MAX_TEAMS, m_aiEspionageSpendingWeightAgainstTeam);

		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_FEAT_TYPES, m_abFeatAccomplished);
		WRAPPER_READ_ARRAY_ALLOW_TRUNCATE(wrapper, "CvPlayer", NUM_PLAYEROPTION_TYPES, m_abOptions);

		WRAPPER_READ_STRING(wrapper, "CvPlayer", m_szScriptData);

		FAssertMsg((0 < GC.getNumBonusInfos()), "GC.getNumBonusInfos() is not greater than zero but it is expected to be in CvPlayer::read");
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, GC.getNumBonusInfos(), m_paiBonusExport);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, GC.getNumBonusInfos(), m_paiBonusImport);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_IMPROVEMENTS, GC.getNumImprovementInfos(), m_paiImprovementCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDINGS, GC.getNumBuildingInfos(), m_paiFreeBuildingCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDINGS, GC.getNumBuildingInfos(), m_paiExtraBuildingHappiness);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDINGS, GC.getNumBuildingInfos(), m_paiExtraBuildingHealth);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_FEATURES, GC.getNumFeatureInfos(), m_paiFeatureHappiness);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, GC.getNumUnitClassInfos(), m_paiUnitClassCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, GC.getNumUnitClassInfos(), m_paiUnitClassMaking);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDING_CLASSES, GC.getNumBuildingClassInfos(), m_paiBuildingClassCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDING_CLASSES, GC.getNumBuildingClassInfos(), m_paiBuildingClassMaking);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_HURRIES, GC.getNumHurryInfos(), m_paiHurryCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_SPECIAL_BUILDINGS, GC.getNumSpecialBuildingInfos(), m_paiSpecialBuildingNotRequiredCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVIC_OPTIONS, GC.getNumCivicOptionInfos(), m_paiHasCivicOptionCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVIC_OPTIONS, GC.getNumCivicOptionInfos(), m_paiNoCivicUpkeepCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_RELIGIONS, GC.getNumReligionInfos(), m_paiHasReligionCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CORPORATIONS, GC.getNumCorporationInfos(), m_paiHasCorporationCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UPKEEPS, GC.getNumUpkeepInfos(), m_paiUpkeepCount);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_SPECIALISTS, GC.getNumSpecialistInfos(), m_paiSpecialistValidCount);

		/************************************************************************************************/
		/* Afforess	                  Start		 12/9/09                                                */
		/*                                                                                              */
		/*                                                                                              */
		/************************************************************************************************/
		WRAPPER_READ(wrapper, "CvPlayer", &m_iForeignTradeRouteModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTaxRateUnhappiness);

		m_fPopulationgrowthratepercentageLog = INVALID_GROWTH_PERCENT_LOG;

		WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_iPopulationgrowthratepercentage, SAVE_VALUE_ANY);
		WRAPPER_READ(wrapper, "CvPlayer", &m_fPopulationgrowthratepercentageLog);

		WRAPPER_READ(wrapper, "CvPlayer", &m_iReligionSpreadRate);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCivicHappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iDistantUnitSupportCostModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iExtraCityDefense);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iEnslavementChance);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNoCapitalUnhappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTaxationAnger);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iLastTurnTaxRate);

		if (GC.getLoadedInitCore().getGameSaveSvnRev() < 709)
		{
			int m_iLastElectionTimer;
			WRAPPER_READ(wrapper, "CvPlayer", &m_iLastElectionTimer);
			int m_iCanDoElection;
			WRAPPER_READ(wrapper, "CvPlayer", &m_iCanDoElection);
			int m_iElectionAnger;
			WRAPPER_READ(wrapper, "CvPlayer", &m_iElectionAnger);
			int m_iCanHaveSlaves;
			WRAPPER_READ(wrapper, "CvPlayer", &m_iCanHaveSlaves);
			int m_iFreeSlaves;
			WRAPPER_READ(wrapper, "CvPlayer", &m_iFreeSlaves);
			int m_iDarkAgeTurns;
			WRAPPER_READ(wrapper, "CvPlayer", &m_iDarkAgeTurns);
			bool m_bDargAgeCapable;
			WRAPPER_READ(wrapper, "CvPlayer", &m_bDargAgeCapable);
			int m_iExtraDarkAgePoints;
			WRAPPER_READ(wrapper, "CvPlayer", &m_iExtraDarkAgePoints);

			int m_aiBestRankings[NUM_RANKINGS];
			WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_RANKINGS, m_aiBestRankings);
		}

		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiLandmarkYield);
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", MAX_PLAYERS, m_aiCeaseContactCounter);

		WRAPPER_READ(wrapper, "CvPlayer", &m_iWorldHealth);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iWorldHappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iProjectHealth);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iProjectHappiness);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iForceAllTradeRoutes);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iWorldTradeRoutes);

		WRAPPER_READ(wrapper, "CvPlayer", &m_iCivilizationHealth);
		if (GC.getLoadedInitCore().getGameSaveSvnRev() < 709)
		{
			int m_iGoldenAgeTurnsPast;
			WRAPPER_READ(wrapper, "CvPlayer", &m_iGoldenAgeTurnsPast);
		}

		WRAPPER_READ(wrapper, "CvPlayer", &m_iBuildingInflation);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iProjectInflation);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iTechInflation);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCivicInflation);

		//	Cope with old saves not having an accrued cost ratio value
		//	Use a sentinel value of -1, which will be taken as a signal to
		//	initialise using the old calculation on first recalculation
		//	opportunity
		m_accruedCostRatioTimes10000 = -1;
		WRAPPER_READ(wrapper, "CvPlayer", &m_accruedCostRatioTimes10000);

		WRAPPER_READ(wrapper, "CvPlayer", &m_iHurryCostModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iHurryInflationModifier);

		WRAPPER_READ(wrapper, "CvPlayer", &m_iHurryCount);

		WRAPPER_READ(wrapper, "CvPlayer", &m_iNoLandmarkAngerCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iLandmarkHappiness);

		if (GC.getLoadedInitCore().getGameSaveSvnRev() < 709)
		{
			BonusTypes m_eCurrency;
			WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, (int*)&m_eCurrency);
			bool m_bChooseCurrency;
			WRAPPER_READ(wrapper, "CvPlayer", &m_bChooseCurrency);
		}
		
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCorporationSpreadModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCorporateTaxIncome);
		
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCityLimit);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCityOverLimitUnhappy);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iForeignUnhappyPercent);
		
		// Calculate player culture as the sum of city culture if not present in save game
		m_iCulture = -1;
		WRAPPER_READ(wrapper, "CvPlayer", &m_iCulture);
		WRAPPER_READ(wrapper, "CvPlayer", (int*)&m_eCurrentCulturalAge);
		WRAPPER_READ(wrapper, "CvPlayer", (int*)&m_eCurrentAgeSegment);

		//	Subdue and construct-by-unit stats
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumAnimalsSubdued);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumAnarchyTurns);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumCivicSwitches);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNumCivicsSwitched);
		int iNumBuildingTypes = 0;
		WRAPPER_READ(wrapper, "CvPlayer", &iNumBuildingTypes);
		while(iNumBuildingTypes-- > 0)
		{
			int	eBuilding;
			int iCount;

			WRAPPER_READ(wrapper, "CvPlayer", &eBuilding);
			WRAPPER_READ(wrapper, "CvPlayer", &iCount);

			m_unitConstructionCounts.insert(std::make_pair((BuildingTypes)eBuilding, iCount));
		}

		WRAPPER_READ_CLASS_ARRAY_ALLOW_MISSING(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDS, GC.getNumBuildInfos(), m_pabAutomatedCanBuild);

		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, GC.getNumBonusInfos(), m_paiBonusMintedPercent);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_COMBATINFOS, GC.getNumUnitCombatInfos(), m_paiUnitCombatProductionModifier);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDING_CLASSES, GC.getNumBuildingClassInfos(), m_paiBuildingClassProductionModifier);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, GC.getNumUnitClassInfos(), m_paiUnitClassProductionModifier);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, GC.getNumBonusInfos(), m_paiResourceConsumption);
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_SPECIALISTS, GC.getNumSpecialistInfos(), m_paiFreeSpecialistCount);
		
		WRAPPER_READ(wrapper, "CvPlayer", (int*)&m_ePledgedVote);
		WRAPPER_READ(wrapper, "CvPlayer", (int*)&m_eSecretaryGeneralVote);

		civcSwitchInstance switchInstance;

		do
		{
			switchInstance.iTurn = -1;
			WRAPPER_READ(wrapper, "CvPlayer", &switchInstance.iTurn);

			if ( switchInstance.iTurn != -1 )
			{
				WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVICS, &switchInstance.eFromCivic);
				WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVICS, &switchInstance.eToCivic);
				WRAPPER_READ(wrapper, "CvPlayer", &switchInstance.bNoAnarchy);

				m_civicSwitchHistory.push_back(switchInstance);
			}
		} while(switchInstance.iTurn != -1);

		m_Properties.readWrapper(pStream);

		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_TERRAINS); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_TERRAINS, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_ppaaiTerrainYieldChange[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppaaiTerrainYieldChange[iI], SAVE_VALUE_TYPE_INT_ARRAY);
			}
		}
		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_BUILDINGS); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_BUILDINGS, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppiBuildingCommerceModifier[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppiBuildingCommerceModifier[iI], SAVE_VALUE_TYPE_INT_ARRAY);
			}
		}
		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_BUILDING_CLASSES); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_BUILDING_CLASSES, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppiBuildingClassCommerceChange[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppiBuildingClassCommerceChange[iI], SAVE_VALUE_TYPE_INT_ARRAY);
			}
		}
		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_BONUSES); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_BONUSES, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppiBonusCommerceModifier[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppiBonusCommerceModifier[iI], SAVE_VALUE_TYPE_INT_ARRAY);
			}
		}
		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_SPECIALISTS); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_SPECIALISTS, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_ppiSpecialistYieldPercentChanges[iI]);
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppiSpecialistCommercePercentChanges[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppiSpecialistYieldPercentChanges[iI], SAVE_VALUE_TYPE_INT_ARRAY);
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppiSpecialistCommercePercentChanges[iI], SAVE_VALUE_TYPE_INT_ARRAY);
			}
		}
	/************************************************************************************************/
	/* Afforess	                     END                                                            */
	/************************************************************************************************/

		FAssertMsg((0 < GC.getNumTechInfos()), "GC.getNumTechInfos() is not greater than zero but it is expected to be in CvPlayer::read");
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_TECHS, GC.getNumTechInfos(), m_pabResearchingTech);

		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_VOTE_SOURCES, GC.getNumVoteSourceInfos(), m_pabLoyalMember);

		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_CIVIC_OPTIONS); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_CIVIC_OPTIONS, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_CLASS_ENUM_ALLOW_MISSING(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVICS, (int*)&m_paeCivics[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_paeCivics[iI], SAVE_VALUE_TYPE_CLASS_ENUM);
			}
		}

		//	If any new civics were added they need to be initialized sensibly for extant civilizations
		if ( wrapper.isUsingTaggedFormat() && getCivilizationType() != NO_CIVILIZATION)
		{
			m_iCityLimit = 0;	//	Will be set correctly below for the civics in force
			m_iCityOverLimitUnhappy = 0;

			for(int i = 0; i < GC.getNumCivicOptionInfos(); i++)
			{
				// AIAndy: Check for no civic set or a civic of the wrong category set
				if ( (m_paeCivics[i] == NO_CIVIC) || (GC.getCivicInfo(m_paeCivics[i]).getCivicOptionType() != (CivicOptionTypes)i ) )
				{
					m_paeCivics[i] = (CivicTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationInitialCivics(i);
				}

				//	Also need to fix iCityLimits if its defintion got changed in an active civic.  The way we do this
				//	is slightly kludgy, and is based on the fact that the iCityLimit system is anyway somewhat broken in
				//	that it processes as a cumulative number, which makes no sense if limits are defiend on multiple
				//	civicOptions.  As such we ASSUME only one civivOption can be defining a limit and therefoer it has
				//	a single source, so we can directly set its value from the currently in-use civic that has a limit (if any)
				if (GC.getCivicInfo(m_paeCivics[i]).getCityLimit(getID()) != 0)
				{
					m_iCityLimit = GC.getCivicInfo(m_paeCivics[i]).getCityLimit(getID());
					m_iCityOverLimitUnhappy = GC.getCivicInfo(m_paeCivics[i]).getCityOverLimitUnhappy();
				}
			}
		}

		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_SPECIALISTS); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_SPECIALISTS, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_ppaaiSpecialistExtraYield[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppaaiSpecialistExtraYield[iI], SAVE_VALUE_TYPE_INT_ARRAY);
			}
		}

		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_IMPROVEMENTS); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_IMPROVEMENTS, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_ppaaiImprovementYieldChange[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppaaiImprovementYieldChange[iI], SAVE_VALUE_TYPE_INT_ARRAY);
			}
		}

		m_groupCycle.Read(pStream);
		m_researchQueue.Read(pStream);

		//	The research queue itself is not a streamable type so is serialized in raw
		//	binary image, which means we need to do some explicit translation on load
		//	if we are using the tagged format
		if ( wrapper.isUsingTaggedFormat() )
		{
			CLLNode<TechTypes>* pNode = headResearchQueueNode();
			while (pNode != NULL)
			{
				bool bDeleteNode = false;

				if (pNode->m_data != NO_TECH)
				{
					bDeleteNode = ((pNode->m_data = (TechTypes)wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_TECHS,pNode->m_data, true)) == -1);
				}

				if ( bDeleteNode )
				{
					pNode = m_researchQueue.deleteNode(pNode);
				}
				else
				{
					pNode = nextResearchQueueNode(pNode);
				}
			}
		}

		{
			m_cityNames.clear();
			CvWString szBuffer;
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numCities");
			for (uint i = 0; i < iSize; i++)
			{
				WRAPPER_READ_STRING_DECORATED(wrapper, "CvPlayer", szBuffer, "cityName");
				m_cityNames.insertAtEnd(szBuffer);
			}
		}

		ReadStreamableFFreeListTrashArray(m_plotGroups, pStream);

		int iCitySaveFormat = 0;
		WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iCitySaveFormat, "iCitySaveFormat");
		if (iCitySaveFormat == 0)
		{
			FFreeListTrashArray<CvCityAI> flist;
			ReadStreamableFFreeListTrashArray(flist, pStream);
			flist.cancelDeinitialize();
			for (int i = 0; i < flist.getIndexAfterLast(); i++)
			{
				if (flist.getAt(i))
				{
					CvCityAI* pUnit = flist.getAt(i);
					m_citiesList.push_back(pUnit);
					m_citiesMap[pUnit->getID()] = pUnit;
				}
			}
		}
		else if (iCitySaveFormat == 1)
		{
			clearAllCities();
			int iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "m_citiesList::size");
			for (int i = 0; i < iSize; i++)
			{
				CvCityAI* pCity = new CvCityAI();
				pCity->read(pStream);
				m_citiesList.push_back(pCity);
				m_citiesMap[pCity->getID()] = pCity;
			}

			WRAPPER_READ(wrapper, "CvPlayer", &m_iLastCityId);
		}
		//ReadStreamableFFreeListTrashArray(m_cities, pStream);

		int iUnitSaveFormat = 0;
		WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iUnitSaveFormat, "iUnitSaveFormat");
		if (iUnitSaveFormat == 0)
		{
			FFreeListTrashArray<CvUnitAI> flist;
			ReadStreamableFFreeListTrashArray(flist, pStream);
			flist.cancelDeinitialize();
			for (int i = 0; i < flist.getIndexAfterLast(); i++)
			{
				if (flist.getAt(i))
				{
					CvUnitAI* pUnit = flist.getAt(i);
					m_unitsList.push_back(pUnit);
					m_unitsMap[pUnit->getID()] = pUnit;
				}
			}
		}
		else if (iUnitSaveFormat == 1)
		{
			clearAllUnits();
			int iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "m_unitsList::size");
			for (int i = 0; i < iSize; i++)
			{
				CvUnitAI* pUnit = new CvUnitAI();
				pUnit->read(pStream);
				m_unitsList.push_back(pUnit);
				m_unitsMap[pUnit->getID()] = pUnit;
			}

			WRAPPER_READ(wrapper, "CvPlayer", &m_iLastUnitId);
		}
		//ReadStreamableFFreeListTrashArray(m_units, pStream);
	/************************************************************************************************/
	/* Afforess	                  Start		 03/30/10                                               */
	/*                                                                                              */
	/*                                                                                              */
	/************************************************************************************************/
	//Must be loaded AFTER units.
		Commanders.clear();
		int iLoop;
		for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if (pLoopUnit->isCommander())	//search for GGs among loaded units and add them to Commanders array
			{
				Commanders.push_back(pLoopUnit);
			}
			if (pLoopUnit->isZoneOfControl())
			{
				GC.getGameINLINE().toggleAnyoneHasUnitZoneOfControl();
			}
		}
	/************************************************************************************************/
	/* Afforess	                     END                                                            */
	/************************************************************************************************/	
		ReadStreamableFFreeListTrashArray(m_selectionGroups, pStream);
		ReadStreamableFFreeListTrashArray(m_eventsTriggered, pStream);

		std::map<CvUnit*,bool> unitsPresent;

		std::vector<CvUnit*>	plotlessUnits;

		for (CvSelectionGroup* pLoopGroup = firstSelectionGroup(&iLoop); pLoopGroup != NULL; pLoopGroup = nextSelectionGroup(&iLoop))
		{
			CLLNode<IDInfo>* pUnitNode;

			OutputDebugString(CvString::format("Check group %d:\n", pLoopGroup->getID()).c_str());
			unitsPresent.clear();
			pUnitNode = pLoopGroup->headUnitNode();
			while (pUnitNode != NULL)
			{
				CvUnit* pUnit = ::getUnit(pUnitNode->m_data);
				CvSelectionGroup* putativeGroup = pUnit->getGroup();
				pUnitNode = pLoopGroup->nextUnitNode(pUnitNode);

				OutputDebugString(CvString::format("\tUnit %d\n", pUnit->getID()).c_str());
				if(putativeGroup != pLoopGroup)
				{
					FAssertMsg(false, "Corrupt group detected on load");
					OutputDebugString(CvString::format("\t\tunit claims to be in group %d\n", putativeGroup->getID()).c_str());

					//	Try to fix it
					pLoopGroup->removeUnit(pUnit);

					if ( !putativeGroup->containsUnit(pUnit) )
					{
						if ( !putativeGroup->addUnit(pUnit,true) )
						{
							pUnit->joinGroup(NULL);
						}
					}
				}
				else
				{
					if ( unitsPresent.find(pUnit) != unitsPresent.end() )
					{
						//	Duplicate
						pLoopGroup->removeUnit(pUnit);
					}
					else
					{
						unitsPresent.insert(std::make_pair(pUnit,true));
					}
				}

				if (pUnit->plot() == NULL)
				{
					plotlessUnits.push_back(pUnit);
				}
			}

			pLoopGroup->validateLocations(true);
			//	Koshling - added death processing on load to clean up units that should have been
			//	removed, but due to bugs are 'ghosting' in the save
			pLoopGroup->doDelayedDeath();
		}

#ifdef _DEBUG
		for (CvSelectionGroup* pLoopGroup = firstSelectionGroup(&iLoop); pLoopGroup != NULL; pLoopGroup = nextSelectionGroup(&iLoop))
		{
			pLoopGroup->validateLocations(false);
		}
#endif

		{
			CvMessageQueue::_Alloc::size_type iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numListGameMessages");
			for (CvMessageQueue::_Alloc::size_type i = 0; i < iSize; i++)
			{
				CvTalkingHeadMessage message;
				message.read(*pStream);
				m_listGameMessages.push_back(message);
			}
		}

		{
			clearPopups();
			CvPopupQueue::_Alloc::size_type iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numPopups");
			for (CvPopupQueue::_Alloc::size_type i = 0; i < iSize; i++)
			{
				CvPopupInfo* pInfo = new CvPopupInfo();
				if (NULL != pInfo)
				{
					pInfo->read(*pStream);
					m_listPopups.push_back(pInfo);
				}
			}
		}

		{
			clearDiplomacy();
			CvDiploQueue::_Alloc::size_type iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numDiploParams");
			for (CvDiploQueue::_Alloc::size_type i = 0; i < iSize; i++)
			{
				CvDiploParameters* pDiplo = new CvDiploParameters(NO_PLAYER);
				if (NULL != pDiplo)
				{
					pDiplo->read(*pStream);
					m_listDiplomacy.push_back(pDiplo);
				}
			}
		}

		{
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numScoreHistEntries");
			for (uint i = 0; i < iSize; i++)
			{
				int iTurn;
				int iScore;
				WRAPPER_READ(wrapper, "CvPlayer", &iTurn);
				WRAPPER_READ(wrapper, "CvPlayer", &iScore);
				m_mapScoreHistory[iTurn] = iScore;
			}
		}

		{
			m_mapEconomyHistory.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numEconHistEntries");
			for (uint i = 0; i < iSize; i++)
			{
				int iTurn;
				int iScore;
				WRAPPER_READ(wrapper, "CvPlayer", &iTurn);
				WRAPPER_READ(wrapper, "CvPlayer", &iScore);
				m_mapEconomyHistory[iTurn] = iScore;
			}
		}

		{
			m_mapIndustryHistory.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numIndHistEntries");
			for (uint i = 0; i < iSize; i++)
			{
				int iTurn;
				int iScore;
				WRAPPER_READ(wrapper, "CvPlayer", &iTurn);
				WRAPPER_READ(wrapper, "CvPlayer", &iScore);
				m_mapIndustryHistory[iTurn] = iScore;
			}
		}

		{
			m_mapAgricultureHistory.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numAgriHistEntries");
			for (uint i = 0; i < iSize; i++)
			{
				int iTurn;
				int iScore;
				WRAPPER_READ(wrapper, "CvPlayer", &iTurn);
				WRAPPER_READ(wrapper, "CvPlayer", &iScore);
				m_mapAgricultureHistory[iTurn] = iScore;
			}
		}

		{
			m_mapPowerHistory.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numPowerHistEntries");
			for (uint i = 0; i < iSize; i++)
			{
				int iTurn;
				int iScore;
				WRAPPER_READ(wrapper, "CvPlayer", &iTurn);
				WRAPPER_READ(wrapper, "CvPlayer", &iScore);
				m_mapPowerHistory[iTurn] = iScore;
			}
		}

		{
			m_mapCultureHistory.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numCultHistEntries");
			for (uint i = 0; i < iSize; i++)
			{
				int iTurn;
				int iScore;
				WRAPPER_READ(wrapper, "CvPlayer", &iTurn);
				WRAPPER_READ(wrapper, "CvPlayer", &iScore);
				m_mapCultureHistory[iTurn] = iScore;
			}
		}

		{
			m_mapEspionageHistory.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numEspHistEntries");
			for (uint i = 0; i < iSize; i++)
			{
				int iTurn;
				int iScore;
				WRAPPER_READ(wrapper, "CvPlayer", &iTurn);
				WRAPPER_READ(wrapper, "CvPlayer", &iScore);
				m_mapEspionageHistory[iTurn] = iScore;
			}
		}


	/************************************************************************************************/
	/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
	/*                                                                                              */
	/*                                                                                              */
	/************************************************************************************************/
		// RevolutionDCM - read revolution stability history data from disk
		{
			m_mapRevolutionStabilityHistory.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numRevHistEntries");
			for (uint i = 0; i < iSize; i++)
			{
				int iTurn;
				int iScore;
				WRAPPER_READ(wrapper, "CvPlayer", &iTurn);
				WRAPPER_READ(wrapper, "CvPlayer", &iScore);
				m_mapRevolutionStabilityHistory[iTurn] = iScore;
			}
		}
		// RevolutionDCM end
	/************************************************************************************************/
	/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
	/************************************************************************************************/

		{
			m_mapEventsOccured.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numEventsOcurred");
			for (uint i = 0; i < iSize; i++)
			{
				EventTriggeredData kData;
				EventTypes eEvent = NO_EVENT;
				WRAPPER_READ_CLASS_ENUM_ALLOW_MISSING(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_EVENTS, (int*)&eEvent);

				if ( eEvent == NO_EVENT )
				{
					//	Old format so go for a raw read as the best we can do
					WRAPPER_READ(wrapper, "CvPlayer", (int*)&eEvent);
				}
				kData.read(pStream);
				if ( eEvent != NO_EVENT )
				{
					m_mapEventsOccured[eEvent] = kData;
				}
			}
		}

		{
			m_mapEventCountdown.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numCountdownEvents");
			for (uint i = 0; i < iSize; i++)
			{
				EventTriggeredData kData;
				EventTypes eEvent;
				WRAPPER_READ(wrapper, "CvPlayer", (int*)&eEvent);
				kData.read(pStream);
				m_mapEventCountdown[eEvent] = kData;
			}
		}

		{
			m_aFreeUnitCombatPromotions.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numFreeCombatPromotions");
			for (uint i = 0; i < iSize; i++)
			{
				int iUnitCombat;
				int iPromotion;
				WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_COMBATINFOS, &iUnitCombat);
				WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_PROMOTIONS, &iPromotion);
				m_aFreeUnitCombatPromotions.push_back(std::make_pair((UnitCombatTypes)iUnitCombat, (PromotionTypes)iPromotion));
			}
		}

		{
			m_aFreeUnitClassPromotions.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numFreeUnitClassPromotions");
			for (uint i = 0; i < iSize; i++)
			{
				int iUnitClass;
				int iPromotion;
				WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, &iUnitClass);
				WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_PROMOTIONS, &iPromotion);
				m_aFreeUnitClassPromotions.push_back(std::make_pair((UnitClassTypes)iUnitClass, (PromotionTypes)iPromotion));
			}
		}

		{
			m_aVote.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numVotes");
			for (uint i = 0; i < iSize; i++)
			{
				int iId;
				PlayerVoteTypes eVote;
				WRAPPER_READ(wrapper, "CvPlayer", &iId);
				WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_VOTES, (int*)&eVote);
				m_aVote.push_back(std::make_pair(iId, eVote));
			}
		}

		{
			m_aUnitExtraCosts.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numUnitCosts");
			for (uint i = 0; i < iSize; i++)
			{
				int iCost;
				UnitClassTypes eUnit;
				WRAPPER_READ_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, (int*)&eUnit);
				WRAPPER_READ(wrapper, "CvPlayer", &iCost);
				m_aUnitExtraCosts.push_back(std::make_pair(eUnit, iCost));
			}
		}

		if (uiFlag > 0)
		{
			m_triggersFired.clear();
			uint iSize;
			WRAPPER_READ_DECORATED(wrapper, "CvPlayer", &iSize, "numEventTriggers");
			for (uint i = 0; i < iSize; i++)
			{
				int iTrigger = -2;

				WRAPPER_READ_CLASS_ENUM_ALLOW_MISSING(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_EVENT_TRIGGERS, &iTrigger);

				if ( iTrigger == -2 && wrapper.isUsingTaggedFormat() )
				{
					//	Consume the value for older formats since the information cannot be
					//	believed anyway
					WRAPPER_READ(wrapper, "CvPlayer", &iTrigger);
				}
				else if ( iTrigger != -1 )
				{
					m_triggersFired.push_back((EventTriggerTypes)iTrigger);
				}
			}
		}
		else
		{
			int iNumEventTriggers = std::min(176, GC.getNumEventTriggerInfos()); // yuck, hardcoded number of eventTriggers in the epic game in initial release
			for (iI=0; iI < iNumEventTriggers; iI++) 
			{
				bool bTriggered;
				WRAPPER_READ(wrapper, "CvPlayer", &bTriggered);
				if (bTriggered)
				{
					m_triggersFired.push_back((EventTriggerTypes)iI);
				}
			}
		}

		if (!isBarbarian())
		{
			// Get the NetID from the initialization structure
			setNetID(gDLL->getAssignedNetworkID(getID()));
		}

		WRAPPER_READ(wrapper, "CvPlayer", &m_iPopRushHurryCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iInflationModifier);

		int	iTempUnitId = -1;
		WRAPPER_READ(wrapper, "CvPlayer", &iTempUnitId);
		if ( iTempUnitId != -1 )
		{
			m_pTempUnit = getUnit(iTempUnitId);

			FAssert(m_pTempUnit != NULL);
		}

		for(int iI = 0; iI < (int)plotlessUnits.size(); iI++)
		{
			if ( plotlessUnits[iI] != m_pTempUnit )
			{
				plotlessUnits[iI]->kill(false);
			}
		}

		//	Handle dead units that somehow get into saves!
		for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if (pLoopUnit->plot() == NULL)
			{
				CvSelectionGroup* pGroup = pLoopUnit->getGroup();
				pLoopUnit->joinGroup(NULL, false, false);

				deleteUnit(pLoopUnit->getID());
				if ( pGroup->getNumUnits() == 0 )
				{
					pGroup->kill();
				}
			}
		}

		CLLNode<int>* pCurrUnitNode;
		CLLNode<int>* pNextUnitNode;
		pCurrUnitNode = headGroupCycleNode();

		while (pCurrUnitNode != NULL)
		{
			CvSelectionGroup* pLoopSelectionGroup = getSelectionGroup(pCurrUnitNode->m_data);
			pNextUnitNode = nextGroupCycleNode(pCurrUnitNode);

			if ( pLoopSelectionGroup == NULL || pLoopSelectionGroup->plot() == NULL )
			{
				removeGroupCycle(pCurrUnitNode->m_data);

				if ( pLoopSelectionGroup != NULL )
				{
					deleteSelectionGroup(pCurrUnitNode->m_data);
				}
			}

			pCurrUnitNode = pNextUnitNode;
		}
		WRAPPER_READ_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_IMPROVEMENTS, GC.getNumImprovementInfos(), m_paiImprovementUpgradeRateModifierSpecific);
		for (int i = 0; i < wrapper.getNumClassEnumValues(REMAPPED_CLASS_TYPE_SPECIALISTS); ++i)
		{
			int	iI = wrapper.getNewClassEnumValue(REMAPPED_CLASS_TYPE_SPECIALISTS, i, true);

			if ( iI != -1 )
			{
				WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppaaiSpecialistExtraCommerce[iI]);
			}
			else
			{
				//	Consume the values
				WRAPPER_SKIP_ELEMENT(wrapper, "CvPlayer", m_ppaaiSpecialistExtraCommerce[iI], SAVE_VALUE_TYPE_INT_ARRAY);
			}
		}
		WRAPPER_READ_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiSpecialistExtraYield);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNationalHurryAngerModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iNationalEnemyWarWearinessModifier);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iFixedBordersCount);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iWarMongerIndex);
		WRAPPER_READ(wrapper, "CvPlayer", &m_iSeizedForeignConnectednessPercent);
	}
	else
	{
		m_bEverAlive = false;
		m_bAlive = false;

		uninit();
	}


	WRAPPER_READ_OBJECT_END(wrapper);
/************************************************************************************************/
/* Afforess	                  Start		 08/18/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	updateCache();
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	if ( GC.viewportsEnabled() && GC.getGameINLINE().getActivePlayer() == m_eID )
	{
		//	Set the initial viewport to centre on the active player's capital until we
		//	know better (avoids an initial viewport move in most cases)
		if ( GC.getCurrentViewport()->getState() == VIEWPORT_MODE_UNINITIALIZED )
		{
			CvCity* pCapital = getCapitalCity();

			if ( pCapital != NULL )
			{
				GC.getCurrentViewport()->setOffsetToShow(pCapital->getX_INLINE(), pCapital->getY_INLINE());
			}
		}
	}

	setTurnHadUIInteraction(true);
}

//
// save object to a stream
// used during save
//
void CvPlayer::write(FDataStreamBase* pStream)
{
	int iI;

	uint uiFlag = 1;

	if ( !m_bEverAlive )
	{
		uiFlag |= PLAYER_UI_FLAG_OMITTED;
	}

	CvTaggedSaveFormatWrapper&	wrapper = CvTaggedSaveFormatWrapper::getSaveFormatWrapper();

	wrapper.AttachToStream(pStream);

	WRAPPER_WRITE_OBJECT_START(wrapper);

	WRAPPER_WRITE(wrapper, "CvPlayer", uiFlag);		// flag for expansion

	if ( m_bEverAlive )
	{
		// < M.A.D. Nukes Start >
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMADDeterrent);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMADIncoming);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMADOutgoing);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMADNukesCount);
		// < M.A.D. Nukes End   >
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStartingX);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStartingY);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTotalPopulation);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTotalLand);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTotalLandScored);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGold);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGoldPerTurn);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iAdvancedStartPoints);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGoldenAgeTurns);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumUnitGoldenAges);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStrikeTurns);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iAnarchyTurns);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMaxAnarchyTurns);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iAnarchyModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGoldenAgeModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGlobalHurryModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGreatPeopleCreated);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGreatGeneralsCreated);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGreatPeopleThresholdModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGreatGeneralsThresholdModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGreatPeopleRateModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGreatGeneralRateModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iDomesticGreatGeneralRateModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStateReligionGreatPeopleRateModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMaxGlobalBuildingProductionModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMaxTeamBuildingProductionModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMaxPlayerBuildingProductionModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iFreeExperience);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iFeatureProductionModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWorkerSpeedModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iImprovementUpgradeRateModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMilitaryProductionModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iSpaceProductionModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCityDefenseModifier);
	/************************************************************************************************/
	/* REVDCM                                 09/02/10                                phungus420    */
	/*                                                                                              */
	/* Player Functions                                                                             */
	/************************************************************************************************/
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNonStateReligionCommerceCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iUpgradeAnywhereCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iRevIdxLocal);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iRevIdxNational);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iRevIdxDistanceModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iRevIdxHolyCityGood);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iRevIdxHolyCityBad);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_fRevIdxNationalityMod);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_fRevIdxBadReligionMod);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_fRevIdxGoodReligionMod);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bInquisitionConditions);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iUnitUpgradePriceModifier);
	/************************************************************************************************/
	/* REVDCM                                  END                                                  */
	/************************************************************************************************/
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumNukeUnits);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumOutsideUnits);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iBaseFreeUnits);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iBaseFreeMilitaryUnits);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iFreeUnitsPopulationPercent);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iFreeMilitaryUnitsPopulationPercent);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGoldPerUnit);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iGoldPerMilitaryUnit);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iExtraUnitCost);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumMilitaryUnits);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iHappyPerMilitaryUnit);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMilitaryFoodProductionCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iConscriptCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMaxConscript);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iHighestUnitLevel);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iOverflowResearch);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNoUnhealthyPopulationCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iExpInBorderModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iBuildingOnlyHealthyCount);
		//DPII < Maintenance Modifiers >
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMaintenanceModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCoastalDistanceMaintenanceModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iConnectedCityMaintenanceModifier);
		//DPII < Maintenance Modifiers >
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iDistanceMaintenanceModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumCitiesMaintenanceModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCorporationMaintenanceModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTotalMaintenance);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iUpkeepModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iLevelExperienceModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iExtraHealth);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iBuildingGoodHealth);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iBuildingBadHealth);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iExtraHappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iBuildingHappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iLargestCityHappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWarWearinessPercentAnger);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWarWearinessModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iFreeSpecialist);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNoForeignTradeCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNoCorporationsCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNoForeignCorporationsCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCoastalTradeRoutes);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTradeRoutes);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iRevolutionTimer);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iConversionTimer);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStateReligionCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNoNonStateReligionSpreadCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStateReligionHappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNonStateReligionHappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStateReligionUnitProductionModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStateReligionBuildingProductionModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStateReligionFreeExperience);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCapitalCityID);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCitiesLost);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWinsVsBarbs);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iAssets);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iPower);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTechPower);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iUnitPower);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iPopulationScore);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iLandScore);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWondersScore);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTechScore);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCombatExperience);

		WRAPPER_WRITE(wrapper, "CvPlayer", m_bAlive);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bEverAlive);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bTurnActive);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bAutoMoves);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bEndTurn);
		WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", m_bPbemNewTurn && GC.getGameINLINE().isPbem(), "m_bPbemNewTurn");
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bExtendedGame);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bFoundedFirstCity);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bStrike);
		//TB Nukefix (Reversal) Should NOT comment out the following line
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bNukesValid);

	/************************************************************************************************/
	/* AI_AUTO_PLAY                           07/09/08                                jdog5000      */
	/*                                                                                              */
	/*                                                                                              */
	/************************************************************************************************/
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bDisableHuman);
	/************************************************************************************************/
	/* AI_AUTO_PLAY                            END                                                  */
	/************************************************************************************************/
	/************************************************************************************************/
	/* REVOLUTION_MOD                         06/11/08                                jdog5000      */
	/*                                                                                              */
	/*                                                                                              */
	/************************************************************************************************/
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iFreeUnitCountdown);
		
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStabilityIndex);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iStabilityIndexAverage);
		
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bRebel);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iMotherPlayer);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_bDoNotBotherStatus);

		// Used for DynamicCivNames
		WRAPPER_WRITE_STRING(wrapper, "CvPlayer", m_szName);
		WRAPPER_WRITE_STRING(wrapper, "CvPlayer", m_szCivDesc);
		WRAPPER_WRITE_STRING(wrapper, "CvPlayer", m_szCivShort);
		WRAPPER_WRITE_STRING(wrapper, "CvPlayer", m_szCivAdj);
	/************************************************************************************************/
	/* REVOLUTION_MOD                          END                                                  */
	/************************************************************************************************/
		WRAPPER_WRITE(wrapper, "CvPlayer", m_eID);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_ePersonalityType);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_eCurrentEra);
		WRAPPER_WRITE_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_RELIGIONS, m_eLastStateReligion);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_eParent);
		//m_eTeamType not saved

		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiSeaPlotYield);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiYieldRateModifier);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiCapitalYieldRateModifier);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiExtraYieldThreshold);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiTradeYieldModifier);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiFreeCityCommerce);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCommercePercent);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCommerceRate);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCommerceRateModifier);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCapitalCommerceRateModifier);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiStateReligionBuildingCommerce);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiSpecialistExtraCommerce);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_aiCommerceFlexibleCount);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", MAX_PLAYERS, m_aiGoldPerTurnByPlayer);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", MAX_TEAMS, m_aiEspionageSpendingWeightAgainstTeam);

		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_FEAT_TYPES, m_abFeatAccomplished);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_PLAYEROPTION_TYPES, m_abOptions);

		WRAPPER_WRITE_STRING(wrapper, "CvPlayer", m_szScriptData);

		FAssertMsg((0 < GC.getNumBonusInfos()), "GC.getNumBonusInfos() is not greater than zero but an array is being allocated in CvPlayer::write");
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, GC.getNumBonusInfos(), m_paiBonusExport);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, GC.getNumBonusInfos(), m_paiBonusImport);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_IMPROVEMENTS, GC.getNumImprovementInfos(), m_paiImprovementCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDINGS, GC.getNumBuildingInfos(), m_paiFreeBuildingCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDINGS, GC.getNumBuildingInfos(), m_paiExtraBuildingHappiness);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDINGS, GC.getNumBuildingInfos(), m_paiExtraBuildingHealth);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_FEATURES, GC.getNumFeatureInfos(), m_paiFeatureHappiness);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, GC.getNumUnitClassInfos(), m_paiUnitClassCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, GC.getNumUnitClassInfos(), m_paiUnitClassMaking);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDING_CLASSES, GC.getNumBuildingClassInfos(), m_paiBuildingClassCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDING_CLASSES, GC.getNumBuildingClassInfos(), m_paiBuildingClassMaking);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_HURRIES, GC.getNumHurryInfos(), m_paiHurryCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_SPECIAL_BUILDINGS, GC.getNumSpecialBuildingInfos(), m_paiSpecialBuildingNotRequiredCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVIC_OPTIONS, GC.getNumCivicOptionInfos(), m_paiHasCivicOptionCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVIC_OPTIONS, GC.getNumCivicOptionInfos(), m_paiNoCivicUpkeepCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_RELIGIONS, GC.getNumReligionInfos(), m_paiHasReligionCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CORPORATIONS, GC.getNumCorporationInfos(), m_paiHasCorporationCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UPKEEPS, GC.getNumUpkeepInfos(), m_paiUpkeepCount);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_SPECIALISTS, GC.getNumSpecialistInfos(), m_paiSpecialistValidCount);
		
	/************************************************************************************************/
	/* Afforess	                  Start		 12/9/09                                                */
	/*                                                                                              */
	/*                                                                                              */
	/************************************************************************************************/
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iForeignTradeRouteModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTaxRateUnhappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_fPopulationgrowthratepercentageLog);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iReligionSpreadRate);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCivicHappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iDistantUnitSupportCostModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iExtraCityDefense);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iEnslavementChance);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNoCapitalUnhappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTaxationAnger);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iLastTurnTaxRate);

		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiLandmarkYield);
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", MAX_PLAYERS, m_aiCeaseContactCounter);
		
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWorldHealth);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWorldHappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iProjectHealth);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iProjectHappiness);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iForceAllTradeRoutes);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWorldTradeRoutes);
		
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCivilizationHealth);
		
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iBuildingInflation);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iProjectInflation);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iTechInflation);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCivicInflation);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_accruedCostRatioTimes10000);
		
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iHurryCostModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iHurryInflationModifier);
		
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iHurryCount);
			
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNoLandmarkAngerCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iLandmarkHappiness);

		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCorporationSpreadModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCorporateTaxIncome);
		
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCityLimit);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCityOverLimitUnhappy);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iForeignUnhappyPercent);

		WRAPPER_WRITE(wrapper, "CvPlayer", m_iCulture);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_eCurrentCulturalAge);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_eCurrentAgeSegment);

		//	Subdue and construct-by-unit stats
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumAnimalsSubdued);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumAnarchyTurns);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumCivicSwitches);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNumCivicsSwitched);

		int iNumBuildingTypes = m_unitConstructionCounts.size();
		WRAPPER_WRITE(wrapper, "CvPlayer", iNumBuildingTypes);
		for(std::map<BuildingTypes,int>::const_iterator itr = m_unitConstructionCounts.begin(); itr != m_unitConstructionCounts.end(); ++itr)
		{
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", (itr->first), "eBuilding");
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", (itr->second), "iCount");
		}
		
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDS, GC.getNumBuildInfos(), m_pabAutomatedCanBuild);
		
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, GC.getNumBonusInfos(), m_paiBonusMintedPercent);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_COMBATINFOS, GC.getNumUnitCombatInfos(), m_paiUnitCombatProductionModifier);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BUILDING_CLASSES, GC.getNumBuildingClassInfos(), m_paiBuildingClassProductionModifier);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, GC.getNumUnitClassInfos(), m_paiUnitClassProductionModifier);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_BONUSES, GC.getNumBonusInfos(), m_paiResourceConsumption);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_SPECIALISTS, GC.getNumSpecialistInfos(), m_paiFreeSpecialistCount);

		WRAPPER_WRITE(wrapper, "CvPlayer", m_ePledgedVote);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_eSecretaryGeneralVote);

		for(iI = 0; iI < (int)m_civicSwitchHistory.size(); iI++)
		{
			civcSwitchInstance switchInstance = m_civicSwitchHistory[iI];

			WRAPPER_WRITE(wrapper, "CvPlayer", switchInstance.iTurn);
			WRAPPER_WRITE_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVICS, switchInstance.eFromCivic);
			WRAPPER_WRITE_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVICS, switchInstance.eToCivic);
			WRAPPER_WRITE(wrapper, "CvPlayer", switchInstance.bNoAnarchy);
		}

		m_Properties.writeWrapper(pStream);

		for (iI=0;iI<GC.getNumTerrainInfos();iI++)
		{
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_ppaaiTerrainYieldChange[iI]);
		}
		for (int i = 0; i < GC.getNumBuildingInfos(); ++i)
		{
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppiBuildingCommerceModifier[i]);
		}
		for (int i = 0; i < GC.getNumBuildingClassInfos(); ++i)
		{
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppiBuildingClassCommerceChange[i]);
		}
		for (int i = 0; i < GC.getNumBonusInfos(); ++i)
		{
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppiBonusCommerceModifier[i]);
		}
		for (int i = 0; i < GC.getNumSpecialistInfos(); ++i)
		{
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_ppiSpecialistYieldPercentChanges[i]);
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppiSpecialistCommercePercentChanges[i]);
		}
	/************************************************************************************************/
	/* Afforess	                     END                                                            */
	/************************************************************************************************/

		FAssertMsg((0 < GC.getNumTechInfos()), "GC.getNumTechInfos() is not greater than zero but it is expected to be in CvPlayer::write");
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_TECHS, GC.getNumTechInfos(), m_pabResearchingTech);

		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_VOTE_SOURCES, GC.getNumVoteSourceInfos(), m_pabLoyalMember);

		for (iI=0;iI<GC.getNumCivicOptionInfos();iI++)
		{
			WRAPPER_WRITE_CLASS_ENUM(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_CIVICS, m_paeCivics[iI]);
		}

		for (iI=0;iI<GC.getNumSpecialistInfos();iI++)
		{
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_ppaaiSpecialistExtraYield[iI]);
		}

		for (iI=0;iI<GC.getNumImprovementInfos();iI++)
		{
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_ppaaiImprovementYieldChange[iI]);
		}

		m_groupCycle.Write(pStream);
		m_researchQueue.Write(pStream);

		{
			CLLNode<CvWString>* pNode;
			uint iSize = m_cityNames.getLength();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numCities");
			pNode = m_cityNames.head();
			while (pNode != NULL)
			{
				WRAPPER_WRITE_STRING_DECORATED(wrapper, "CvPlayer", pNode->m_data, "cityName");
				pNode = m_cityNames.next(pNode);
			}
		}

		WriteStreamableFFreeListTrashArray(m_plotGroups, pStream);

		//WriteStreamableFFreeListTrashArray(m_cities, pStream);
		int iCitySaveFormat = 1;
		WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iCitySaveFormat, "iCitySaveFormat");
		{
			int iSize = m_citiesList.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "m_citiesList::size");
			std::vector<CvCityAI*>::iterator it;
			for (it = m_citiesList.begin(); it != m_citiesList.end(); ++it)
			{
				CvCityAI* pCity = *it;
				pCity->write(pStream);
			}
		}
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iLastCityId);

		//WriteStreamableFFreeListTrashArray(m_units, pStream);
		int iUnitSaveFormat = 1;
		WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iUnitSaveFormat, "iUnitSaveFormat");
		{
			int iSize = m_unitsList.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "m_unitsList::size");
			std::vector<CvUnitAI*>::iterator it;
			for (it = m_unitsList.begin(); it != m_unitsList.end(); ++it)
			{
				CvUnitAI* pUnit = *it;
				pUnit->write(pStream);
			}
		}
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iLastUnitId);

		WriteStreamableFFreeListTrashArray(m_selectionGroups, pStream);
		WriteStreamableFFreeListTrashArray(m_eventsTriggered, pStream);

		{
			CvMessageQueue::_Alloc::size_type iSize = m_listGameMessages.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numListGameMessages");
			CvMessageQueue::iterator it;
			for (it = m_listGameMessages.begin(); it != m_listGameMessages.end(); ++it)
			{
				CvTalkingHeadMessage& message = *it;
				message.write(*pStream);
			}
		}

		{
			CvPopupQueue currentPopups;
			if (GC.getGameINLINE().isNetworkMultiPlayer())
			{
				// don't save open popups in MP to avoid having different state on different machines
				currentPopups.clear();
			}
			else
			{
				gDLL->getInterfaceIFace()->getDisplayedButtonPopups(currentPopups);
			}
			CvPopupQueue::_Alloc::size_type iSize = m_listPopups.size() + currentPopups.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numPopups");
			CvPopupQueue::iterator it;
			for (it = currentPopups.begin(); it != currentPopups.end(); ++it)
			{
				CvPopupInfo* pInfo = *it;
				if (NULL != pInfo)
				{
					pInfo->write(*pStream);
				}
			}
			for (it = m_listPopups.begin(); it != m_listPopups.end(); ++it)
			{
				CvPopupInfo* pInfo = *it;
				if (NULL != pInfo)
				{
					pInfo->write(*pStream);
				}
			}
		}

		{
			CvDiploQueue::_Alloc::size_type iSize = m_listDiplomacy.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numDiploParams");
			CvDiploQueue::iterator it;
			for (it = m_listDiplomacy.begin(); it != m_listDiplomacy.end(); ++it)
			{
				CvDiploParameters* pDiplo = *it;
				if (NULL != pDiplo)
				{
					pDiplo->write(*pStream);
				}
			}
		}

		{
			uint iSize = m_mapScoreHistory.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numScoreHistEntries");
			CvTurnScoreMap::iterator it;
			for (it = m_mapScoreHistory.begin(); it != m_mapScoreHistory.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "iTurn");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->second, "iScore");
			}
		}

		{
			uint iSize = m_mapEconomyHistory.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numEconHistEntries");
			CvTurnScoreMap::iterator it;
			for (it = m_mapEconomyHistory.begin(); it != m_mapEconomyHistory.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "iTurn");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->second, "iScore");
			}
		}

		{
			uint iSize = m_mapIndustryHistory.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numIndHistEntries");
			CvTurnScoreMap::iterator it;
			for (it = m_mapIndustryHistory.begin(); it != m_mapIndustryHistory.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "iTurn");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->second, "iScore");
			}
		}

		{
			uint iSize = m_mapAgricultureHistory.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numAgriHistEntries");
			CvTurnScoreMap::iterator it;
			for (it = m_mapAgricultureHistory.begin(); it != m_mapAgricultureHistory.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "iTurn");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->second, "iScore");
			}
		}

		{
			uint iSize = m_mapPowerHistory.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numPowerHistEntries");
			CvTurnScoreMap::iterator it;
			for (it = m_mapPowerHistory.begin(); it != m_mapPowerHistory.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "iTurn");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->second, "iScore");
			}
		}

		{
			uint iSize = m_mapCultureHistory.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numCultHistEntries");
			CvTurnScoreMap::iterator it;
			for (it = m_mapCultureHistory.begin(); it != m_mapCultureHistory.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "iTurn");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->second, "iScore");
			}
		}

		{
			uint iSize = m_mapEspionageHistory.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numEspHistEntries");
			CvTurnScoreMap::iterator it;
			for (it = m_mapEspionageHistory.begin(); it != m_mapEspionageHistory.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "iTurn");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->second, "iScore");
			}
		}

	/************************************************************************************************/
	/* REVOLUTIONDCM_MOD                         02/04/08                            Glider1        */
	/*                                                                                              */
	/*                                                                                              */
	/************************************************************************************************/
		// RevolutionDCM - save revolution stability history to disk
		{
			uint iSize = m_mapRevolutionStabilityHistory.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numRevHistEntries");
			CvTurnScoreMap::iterator it;
			for (it = m_mapRevolutionStabilityHistory.begin(); it != m_mapRevolutionStabilityHistory.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "iTurn");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->second, "iScore");
			}
		}
		// RevolutionDCM - end
	/************************************************************************************************/
	/* REVOLUTIONDCM_MOD                         END                                 Glider1        */
	/************************************************************************************************/

		{
			uint iSize = m_mapEventsOccured.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numEventsOcurred");
			CvEventMap::iterator it;
			for (it = m_mapEventsOccured.begin(); it != m_mapEventsOccured.end(); ++it)
			{
				WRAPPER_WRITE_CLASS_ENUM_DECORATED(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_EVENTS, it->first, "eEvent");
				it->second.write(pStream);
			}
		}

		{
			uint iSize = m_mapEventCountdown.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numCountdownEvents");
			CvEventMap::iterator it;
			for (it = m_mapEventCountdown.begin(); it != m_mapEventCountdown.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", it->first, "eEvent");
				it->second.write(pStream);
			}
		}

		{
			uint iSize = m_aFreeUnitCombatPromotions.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numFreeCombatPromotions");
			UnitCombatPromotionArray::iterator it;
			for (it = m_aFreeUnitCombatPromotions.begin(); it != m_aFreeUnitCombatPromotions.end(); ++it)
			{
				WRAPPER_WRITE_CLASS_ENUM_DECORATED(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_COMBATINFOS, (*it).first, "iUnitCombat");
				WRAPPER_WRITE_CLASS_ENUM_DECORATED(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_PROMOTIONS, (*it).second, "iPromotion");
			}
		}

		{
			uint iSize = m_aFreeUnitClassPromotions.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numFreeUnitClassPromotions");
			UnitClassPromotionArray::iterator it;
			for (it = m_aFreeUnitClassPromotions.begin(); it != m_aFreeUnitClassPromotions.end(); ++it)
			{
				WRAPPER_WRITE_CLASS_ENUM_DECORATED(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, (*it).first, "iUnitClass");
				WRAPPER_WRITE_CLASS_ENUM_DECORATED(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_PROMOTIONS, (*it).second, "iPromotion");
			}
		}

		{
			uint iSize = m_aVote.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numVotes");
			std::vector< std::pair<int, PlayerVoteTypes> >::iterator it;
			for (it = m_aVote.begin(); it != m_aVote.end(); ++it)
			{
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", (*it).first, "iId");
				WRAPPER_WRITE_CLASS_ENUM_DECORATED(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_VOTES, (*it).second, "eVote");
			}
		}

		{
			uint iSize = m_aUnitExtraCosts.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numUnitCosts");
			std::vector< std::pair<UnitClassTypes, int> >::iterator it;
			for (it = m_aUnitExtraCosts.begin(); it != m_aUnitExtraCosts.end(); ++it)
			{
				WRAPPER_WRITE_CLASS_ENUM_DECORATED(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_UNIT_CLASSES, (*it).first, "eUnit");
				WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", (*it).second, "iCost");
			}
		}

		{
			uint iSize = m_triggersFired.size();
			WRAPPER_WRITE_DECORATED(wrapper, "CvPlayer", iSize, "numEventTriggers");
			std::vector<EventTriggerTypes>::iterator it;
			for (it = m_triggersFired.begin(); it != m_triggersFired.end(); ++it)
			{
				WRAPPER_WRITE_CLASS_ENUM_DECORATED(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_EVENT_TRIGGERS, (*it), "iTrigger");
			}
		}

		WRAPPER_WRITE(wrapper, "CvPlayer", m_iPopRushHurryCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iInflationModifier);

		int	iTempUnitId = (m_pTempUnit == NULL ? -1 : m_pTempUnit->getID());
		WRAPPER_WRITE(wrapper, "CvPlayer", iTempUnitId);
		WRAPPER_WRITE_CLASS_ARRAY(wrapper, "CvPlayer", REMAPPED_CLASS_TYPE_IMPROVEMENTS, GC.getNumImprovementInfos(), m_paiImprovementUpgradeRateModifierSpecific);
		for (iI=0;iI<GC.getNumSpecialistInfos();iI++)
		{
			WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_COMMERCE_TYPES, m_ppaaiSpecialistExtraCommerce[iI]);
		}
		WRAPPER_WRITE_ARRAY(wrapper, "CvPlayer", NUM_YIELD_TYPES, m_aiSpecialistExtraYield);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNationalHurryAngerModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iNationalEnemyWarWearinessModifier);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iFixedBordersCount);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iWarMongerIndex);
		WRAPPER_WRITE(wrapper, "CvPlayer", m_iSeizedForeignConnectednessPercent);
	}

	WRAPPER_WRITE_OBJECT_END(wrapper);
}

void CvPlayer::resyncHashmap(bool bWrite, ByteBuffer* pBuffer, stdext::hash_map<int, int> map)
{
	if (bWrite)
	{
		uint iSize = map.size();
		pBuffer->putInt(iSize);
		stdext::hash_map<int, int>::iterator it;
		for (it = map.begin(); it != map.end(); ++it)
		{ 
			pBuffer->putInt(it->first);
			pBuffer->putInt(it->second);
		}
	}
	else
	{
		map.clear();
		uint iSize = pBuffer->getInt();
		for (uint i = 0; i < iSize; i++)
		{
			int first = pBuffer->getInt();
			int second = pBuffer->getInt();
			map[first] = second;
		}
	}
}

void CvPlayer::resyncHashmap(bool bWrite, ByteBuffer* pBuffer, stdext::hash_map<EventTypes, EventTriggeredData> map)
{
	if (bWrite)
	{
		uint iSize = map.size();
		pBuffer->putInt(iSize);
		stdext::hash_map<EventTypes, EventTriggeredData>::iterator it;
		for (it = map.begin(); it != map.end(); ++it)
		{
			pBuffer->putInt(it->first);
			it->second.resync(bWrite, pBuffer);
		}
	}
	else
	{
		map.clear();
		uint iSize = pBuffer->getInt();
		for (uint i = 0; i < iSize; i++)
		{
			EventTypes first = (EventTypes)pBuffer->getInt();
			EventTriggeredData data;
			data.resync(bWrite, pBuffer);
			map[first] = data;
		}
	}
}

void CvPlayer::resync(bool bWrite, ByteBuffer* pBuffer)
{
	RESYNC_INT(bWrite, pBuffer, m_iMADDeterrent);
	RESYNC_INT(bWrite, pBuffer, m_iMADIncoming);
	RESYNC_INT(bWrite, pBuffer, m_iMADOutgoing);
	RESYNC_INT(bWrite, pBuffer, m_iMADNukesCount);
	RESYNC_INT(bWrite, pBuffer, m_iStartingX);
	RESYNC_INT(bWrite, pBuffer, m_iStartingY);
	RESYNC_INT(bWrite, pBuffer, m_iTotalPopulation);
	RESYNC_INT(bWrite, pBuffer, m_iTotalLand);
	RESYNC_INT(bWrite, pBuffer, m_iTotalLandScored);
	RESYNC_INT(bWrite, pBuffer, m_iGold);
	RESYNC_INT(bWrite, pBuffer, m_iGoldPerTurn);
	RESYNC_INT(bWrite, pBuffer, m_iAdvancedStartPoints);
	RESYNC_INT(bWrite, pBuffer, m_iGoldenAgeTurns);
	RESYNC_INT(bWrite, pBuffer, m_iNumUnitGoldenAges);
	RESYNC_INT(bWrite, pBuffer, m_iStrikeTurns);
	RESYNC_INT(bWrite, pBuffer, m_iAnarchyTurns);
	RESYNC_INT(bWrite, pBuffer, m_iMaxAnarchyTurns);
	RESYNC_INT(bWrite, pBuffer, m_iAnarchyModifier);
	RESYNC_INT(bWrite, pBuffer, m_iGoldenAgeModifier);
	RESYNC_INT(bWrite, pBuffer, m_iGlobalHurryModifier);
	RESYNC_INT(bWrite, pBuffer, m_iGreatPeopleCreated);
	RESYNC_INT(bWrite, pBuffer, m_iGreatGeneralsCreated);
	RESYNC_INT(bWrite, pBuffer, m_iGreatPeopleThresholdModifier);
	RESYNC_INT(bWrite, pBuffer, m_iGreatGeneralsThresholdModifier);
	RESYNC_INT(bWrite, pBuffer, m_iGreatPeopleRateModifier);
	RESYNC_INT(bWrite, pBuffer, m_iGreatGeneralRateModifier);
	RESYNC_INT(bWrite, pBuffer, m_iDomesticGreatGeneralRateModifier);
	RESYNC_INT(bWrite, pBuffer, m_iStateReligionGreatPeopleRateModifier);
	RESYNC_INT(bWrite, pBuffer, m_iMaxGlobalBuildingProductionModifier);
	RESYNC_INT(bWrite, pBuffer, m_iMaxTeamBuildingProductionModifier);
	RESYNC_INT(bWrite, pBuffer, m_iMaxPlayerBuildingProductionModifier);
	RESYNC_INT(bWrite, pBuffer, m_iFreeExperience);
	RESYNC_INT(bWrite, pBuffer, m_iFeatureProductionModifier);
	RESYNC_INT(bWrite, pBuffer, m_iWorkerSpeedModifier);
	RESYNC_INT(bWrite, pBuffer, m_iImprovementUpgradeRateModifier);
	RESYNC_INT(bWrite, pBuffer, m_iMilitaryProductionModifier);
	RESYNC_INT(bWrite, pBuffer, m_iSpaceProductionModifier);
	RESYNC_INT(bWrite, pBuffer, m_iCityDefenseModifier);
	RESYNC_INT(bWrite, pBuffer, m_iNonStateReligionCommerceCount);
	RESYNC_INT(bWrite, pBuffer, m_iUpgradeAnywhereCount);
	RESYNC_INT(bWrite, pBuffer, m_iRevIdxLocal);
	RESYNC_INT(bWrite, pBuffer, m_iRevIdxNational);
	RESYNC_INT(bWrite, pBuffer, m_iRevIdxDistanceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iRevIdxHolyCityGood);
	RESYNC_INT(bWrite, pBuffer, m_iRevIdxHolyCityBad);
	RESYNC_FLOAT(bWrite, pBuffer, m_fRevIdxNationalityMod);
	RESYNC_FLOAT(bWrite, pBuffer, m_fRevIdxBadReligionMod);
	RESYNC_FLOAT(bWrite, pBuffer, m_fRevIdxGoodReligionMod);
	RESYNC_BOOL(bWrite, pBuffer, m_bInquisitionConditions);
	RESYNC_INT(bWrite, pBuffer, m_iUnitUpgradePriceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iNumNukeUnits);
	RESYNC_INT(bWrite, pBuffer, m_iNumOutsideUnits);
	RESYNC_INT(bWrite, pBuffer, m_iBaseFreeUnits);
	RESYNC_INT(bWrite, pBuffer, m_iBaseFreeMilitaryUnits);
	RESYNC_INT(bWrite, pBuffer, m_iFreeUnitsPopulationPercent);
	RESYNC_INT(bWrite, pBuffer, m_iFreeMilitaryUnitsPopulationPercent);
	RESYNC_INT(bWrite, pBuffer, m_iGoldPerUnit);
	RESYNC_INT(bWrite, pBuffer, m_iGoldPerMilitaryUnit);
	RESYNC_INT(bWrite, pBuffer, m_iExtraUnitCost);
	RESYNC_INT(bWrite, pBuffer, m_iNumMilitaryUnits);
	RESYNC_INT(bWrite, pBuffer, m_iHappyPerMilitaryUnit);
	RESYNC_INT(bWrite, pBuffer, m_iMilitaryFoodProductionCount);
	RESYNC_INT(bWrite, pBuffer, m_iConscriptCount);
	RESYNC_INT(bWrite, pBuffer, m_iMaxConscript);
	RESYNC_INT(bWrite, pBuffer, m_iHighestUnitLevel);
	RESYNC_INT(bWrite, pBuffer, m_iOverflowResearch);
	RESYNC_INT(bWrite, pBuffer, m_iNoUnhealthyPopulationCount);
	RESYNC_INT(bWrite, pBuffer, m_iExpInBorderModifier);
	RESYNC_INT(bWrite, pBuffer, m_iBuildingOnlyHealthyCount);
	RESYNC_INT(bWrite, pBuffer, m_iMaintenanceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iCoastalDistanceMaintenanceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iConnectedCityMaintenanceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iDistanceMaintenanceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iNumCitiesMaintenanceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iCorporationMaintenanceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iTotalMaintenance);
	RESYNC_INT(bWrite, pBuffer, m_iUpkeepModifier);
	RESYNC_INT(bWrite, pBuffer, m_iLevelExperienceModifier);
	RESYNC_INT(bWrite, pBuffer, m_iExtraHealth);
	RESYNC_INT(bWrite, pBuffer, m_iBuildingGoodHealth);
	RESYNC_INT(bWrite, pBuffer, m_iBuildingBadHealth);
	RESYNC_INT(bWrite, pBuffer, m_iExtraHappiness);
	RESYNC_INT(bWrite, pBuffer, m_iBuildingHappiness);
	RESYNC_INT(bWrite, pBuffer, m_iLargestCityHappiness);
	RESYNC_INT(bWrite, pBuffer, m_iWarWearinessPercentAnger);
	RESYNC_INT(bWrite, pBuffer, m_iWarWearinessModifier);
	RESYNC_INT(bWrite, pBuffer, m_iFreeSpecialist);
	RESYNC_INT(bWrite, pBuffer, m_iNoForeignTradeCount);
	RESYNC_INT(bWrite, pBuffer, m_iNoCorporationsCount);
	RESYNC_INT(bWrite, pBuffer, m_iNoForeignCorporationsCount);
	RESYNC_INT(bWrite, pBuffer, m_iCoastalTradeRoutes);
	RESYNC_INT(bWrite, pBuffer, m_iTradeRoutes);
	RESYNC_INT(bWrite, pBuffer, m_iRevolutionTimer);
	RESYNC_INT(bWrite, pBuffer, m_iConversionTimer);
	RESYNC_INT(bWrite, pBuffer, m_iStateReligionCount);
	RESYNC_INT(bWrite, pBuffer, m_iNoNonStateReligionSpreadCount);
	RESYNC_INT(bWrite, pBuffer, m_iStateReligionHappiness);
	RESYNC_INT(bWrite, pBuffer, m_iNonStateReligionHappiness);
	RESYNC_INT(bWrite, pBuffer, m_iStateReligionUnitProductionModifier);
	RESYNC_INT(bWrite, pBuffer, m_iStateReligionBuildingProductionModifier);
	RESYNC_INT(bWrite, pBuffer, m_iStateReligionFreeExperience);
	RESYNC_INT(bWrite, pBuffer, m_iCapitalCityID);
	RESYNC_INT(bWrite, pBuffer, m_iCitiesLost);
	RESYNC_INT(bWrite, pBuffer, m_iWinsVsBarbs);
	RESYNC_INT(bWrite, pBuffer, m_iAssets);
	RESYNC_INT(bWrite, pBuffer, m_iPower);
	RESYNC_INT(bWrite, pBuffer, m_iTechPower);
	RESYNC_INT(bWrite, pBuffer, m_iUnitPower);
	RESYNC_INT(bWrite, pBuffer, m_iPopulationScore);
	RESYNC_INT(bWrite, pBuffer, m_iLandScore);
	RESYNC_INT(bWrite, pBuffer, m_iWondersScore);
	RESYNC_INT(bWrite, pBuffer, m_iTechScore);
	RESYNC_INT(bWrite, pBuffer, m_iCombatExperience);

	RESYNC_BOOL(bWrite, pBuffer, m_bAlive);
	RESYNC_BOOL(bWrite, pBuffer, m_bEverAlive);
	RESYNC_BOOL(bWrite, pBuffer, m_bTurnActive);
	RESYNC_BOOL(bWrite, pBuffer, m_bAutoMoves);
	RESYNC_BOOL(bWrite, pBuffer, m_bEndTurn);

	if (bWrite) m_bPbemNewTurn &= GC.getGameINLINE().isPbem();

	RESYNC_BOOL(bWrite, pBuffer, m_bPbemNewTurn);
	RESYNC_BOOL(bWrite, pBuffer, m_bExtendedGame);
	RESYNC_BOOL(bWrite, pBuffer, m_bFoundedFirstCity);
	RESYNC_BOOL(bWrite, pBuffer, m_bStrike);
	RESYNC_BOOL(bWrite, pBuffer, m_bNukesValid);
	RESYNC_BOOL(bWrite, pBuffer, m_bDisableHuman);
	RESYNC_INT(bWrite, pBuffer, m_iFreeUnitCountdown);
	RESYNC_INT(bWrite, pBuffer, m_iStabilityIndex);
	RESYNC_INT(bWrite, pBuffer, m_iStabilityIndexAverage);
	RESYNC_BOOL(bWrite, pBuffer, m_bRebel);
	RESYNC_INT(bWrite, pBuffer, m_iMotherPlayer);
	RESYNC_INT(bWrite, pBuffer, m_bDoNotBotherStatus);
	RESYNC_STRING(bWrite, pBuffer, m_szName);
	RESYNC_STRING(bWrite, pBuffer, m_szCivDesc);
	RESYNC_STRING(bWrite, pBuffer, m_szCivShort);
	RESYNC_STRING(bWrite, pBuffer, m_szCivAdj);

	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_eID, PlayerTypes);
	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_ePersonalityType, LeaderHeadTypes);
	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_eCurrentEra, EraTypes);
	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_eLastStateReligion, ReligionTypes);
	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_eParent, PlayerTypes);

	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_aiSeaPlotYield);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_aiYieldRateModifier);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_aiCapitalYieldRateModifier);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_aiExtraYieldThreshold);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_aiTradeYieldModifier);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_aiFreeCityCommerce);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_aiCommercePercent);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_aiCommerceRate);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_aiCommerceRateModifier);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_aiCapitalCommerceRateModifier);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_aiStateReligionBuildingCommerce);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_aiSpecialistExtraCommerce);
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_aiCommerceFlexibleCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, MAX_PLAYERS, m_aiGoldPerTurnByPlayer);
	RESYNC_INT_ARRAY(bWrite, pBuffer, MAX_TEAMS, m_aiEspionageSpendingWeightAgainstTeam);

	RESYNC_BOOL_ARRAY(bWrite, pBuffer, NUM_FEAT_TYPES, m_abFeatAccomplished);
	RESYNC_BOOL_ARRAY(bWrite, pBuffer, NUM_PLAYEROPTION_TYPES, m_abOptions);

	RESYNC_STRING(bWrite, pBuffer, m_szScriptData);

	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBonusInfos(), m_paiBonusExport);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBonusInfos(), m_paiBonusImport);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumImprovementInfos(), m_paiImprovementCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBuildingInfos(), m_paiFreeBuildingCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBuildingInfos(), m_paiExtraBuildingHappiness);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBuildingInfos(), m_paiExtraBuildingHealth);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumFeatureInfos(), m_paiFeatureHappiness);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumUnitClassInfos(), m_paiUnitClassCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumUnitClassInfos(), m_paiUnitClassMaking);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBuildingClassInfos(), m_paiBuildingClassCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBuildingClassInfos(), m_paiBuildingClassMaking);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumHurryInfos(), m_paiHurryCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumSpecialBuildingInfos(), m_paiSpecialBuildingNotRequiredCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumCivicOptionInfos(), m_paiHasCivicOptionCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumCivicOptionInfos(), m_paiNoCivicUpkeepCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumReligionInfos(), m_paiHasReligionCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumCorporationInfos(), m_paiHasCorporationCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumUpkeepInfos(), m_paiUpkeepCount);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumSpecialistInfos(), m_paiSpecialistValidCount);

	RESYNC_INT(bWrite, pBuffer, m_iForeignTradeRouteModifier);
	RESYNC_INT(bWrite, pBuffer, m_iTaxRateUnhappiness);
	RESYNC_FLOAT(bWrite, pBuffer, m_fPopulationgrowthratepercentageLog);
	RESYNC_INT(bWrite, pBuffer, m_iReligionSpreadRate);
	RESYNC_INT(bWrite, pBuffer, m_iCivicHappiness);
	RESYNC_INT(bWrite, pBuffer, m_iDistantUnitSupportCostModifier);
	RESYNC_INT(bWrite, pBuffer, m_iExtraCityDefense);
	RESYNC_INT(bWrite, pBuffer, m_iEnslavementChance);
	RESYNC_INT(bWrite, pBuffer, m_iNoCapitalUnhappiness);
	RESYNC_INT(bWrite, pBuffer, m_iTaxationAnger);
	RESYNC_INT(bWrite, pBuffer, m_iLastTurnTaxRate);

	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_aiLandmarkYield);
	RESYNC_INT_ARRAY(bWrite, pBuffer, MAX_PLAYERS, m_aiCeaseContactCounter);

	RESYNC_INT(bWrite, pBuffer, m_iWorldHealth);
	RESYNC_INT(bWrite, pBuffer, m_iWorldHappiness);
	RESYNC_INT(bWrite, pBuffer, m_iProjectHealth);
	RESYNC_INT(bWrite, pBuffer, m_iProjectHappiness);
	RESYNC_INT(bWrite, pBuffer, m_iForceAllTradeRoutes);
	RESYNC_INT(bWrite, pBuffer, m_iWorldTradeRoutes);

	RESYNC_INT(bWrite, pBuffer, m_iCivilizationHealth);

	RESYNC_INT(bWrite, pBuffer, m_iBuildingInflation);
	RESYNC_INT(bWrite, pBuffer, m_iProjectInflation);
	RESYNC_INT(bWrite, pBuffer, m_iTechInflation);
	RESYNC_INT(bWrite, pBuffer, m_iCivicInflation);
	RESYNC_INT(bWrite, pBuffer, m_accruedCostRatioTimes10000);

	RESYNC_INT(bWrite, pBuffer, m_iHurryCostModifier);
	RESYNC_INT(bWrite, pBuffer, m_iHurryInflationModifier);

	RESYNC_INT(bWrite, pBuffer, m_iHurryCount);

	RESYNC_INT(bWrite, pBuffer, m_iNoLandmarkAngerCount);
	RESYNC_INT(bWrite, pBuffer, m_iLandmarkHappiness);

	RESYNC_INT(bWrite, pBuffer, m_iCorporationSpreadModifier);
	RESYNC_INT(bWrite, pBuffer, m_iCorporateTaxIncome);

	RESYNC_INT(bWrite, pBuffer, m_iCityLimit);
	RESYNC_INT(bWrite, pBuffer, m_iCityOverLimitUnhappy);
	RESYNC_INT(bWrite, pBuffer, m_iForeignUnhappyPercent);

	RESYNC_INT(bWrite, pBuffer, m_iCulture);
	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_eCurrentCulturalAge, CulturalAgeTypes);
	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_eCurrentAgeSegment, AgeSegments);

	RESYNC_INT(bWrite, pBuffer, m_iNumAnimalsSubdued);
	RESYNC_INT(bWrite, pBuffer, m_iNumAnarchyTurns);
	RESYNC_INT(bWrite, pBuffer, m_iNumCivicSwitches);
	RESYNC_INT(bWrite, pBuffer, m_iNumCivicsSwitched);

	if (bWrite)
	{
		pBuffer->putInt(m_unitConstructionCounts.size());
		for (std::map<BuildingTypes, int>::const_iterator itr = m_unitConstructionCounts.begin(); itr != m_unitConstructionCounts.end(); ++itr)
		{
			pBuffer->putInt(itr->first);
			pBuffer->putInt(itr->second);
		}
	}
	else
	{
		m_unitConstructionCounts.clear();
		int iSize = pBuffer->getInt();
		for (int iI = 0; iI < iSize; iI++)
		{
			BuildingTypes eBuilding = (BuildingTypes)pBuffer->getInt();
			int iCount = pBuffer->getInt();
			m_unitConstructionCounts[eBuilding] = iCount;
		}
	}

	RESYNC_BOOL_ARRAY(bWrite, pBuffer, GC.getNumBuildInfos(), m_pabAutomatedCanBuild);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBonusInfos(), m_paiBonusMintedPercent);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumUnitCombatInfos(), m_paiUnitCombatProductionModifier);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBuildingClassInfos(), m_paiBuildingClassProductionModifier);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumUnitClassInfos(), m_paiUnitClassProductionModifier);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumBonusInfos(), m_paiResourceConsumption);
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumSpecialistInfos(), m_paiFreeSpecialistCount);

	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_ePledgedVote, PlayerVoteTypes);
	RESYNC_INT_WITH_CAST(bWrite, pBuffer, m_eSecretaryGeneralVote, TeamTypes);

	if (bWrite)
	{
		pBuffer->putInt(m_civicSwitchHistory.size());
		for (int iI = 0; iI < (int)m_civicSwitchHistory.size(); iI++)
		{
			civcSwitchInstance switchInstance = m_civicSwitchHistory[iI];

			pBuffer->putInt(switchInstance.iTurn);
			pBuffer->putInt(switchInstance.eFromCivic);
			pBuffer->putInt(switchInstance.eToCivic);
			pBuffer->put((byte)(switchInstance.bNoAnarchy ? 1 : 0));
		}
	}
	else
	{
		m_civicSwitchHistory.clear();
		int iSize = pBuffer->getInt();
		for (int iI = 0; iI < iSize; iI++)
		{
			civcSwitchInstance switchInstance;

			switchInstance.iTurn = pBuffer->getInt();
			switchInstance.eFromCivic = (CivicTypes)pBuffer->getInt();
			switchInstance.eToCivic = (CivicTypes)pBuffer->getInt();
			switchInstance.bNoAnarchy = (pBuffer->get() != 0);
		}
	}

	for (int iI = 0; iI < GC.getNumTerrainInfos(); iI++)
	{
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_ppaaiTerrainYieldChange[iI]);
	}
	for (int i = 0; i < GC.getNumBuildingInfos(); ++i)
	{
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_ppiBuildingCommerceModifier[i]);
	}
	for (int i = 0; i < GC.getNumBuildingClassInfos(); ++i)
	{
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_ppiBuildingClassCommerceChange[i]);
	}
	for (int i = 0; i < GC.getNumBonusInfos(); ++i)
	{
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_ppiBonusCommerceModifier[i]);
	}
	for (int i = 0; i < GC.getNumSpecialistInfos(); ++i)
	{
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_ppiSpecialistYieldPercentChanges[i]);
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_ppiSpecialistCommercePercentChanges[i]);
	}

	RESYNC_BOOL_ARRAY(bWrite, pBuffer, GC.getNumTechInfos(), m_pabResearchingTech);
	RESYNC_BOOL_ARRAY(bWrite, pBuffer, GC.getNumVoteSourceInfos(), m_pabLoyalMember);

	RESYNC_INT_ARRAY_WITH_CAST(bWrite, pBuffer, GC.getNumCivicOptionInfos(), m_paeCivics, CivicTypes)

	for (int iI = 0; iI<GC.getNumSpecialistInfos(); iI++)
	{
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_ppaaiSpecialistExtraYield[iI]);
	}

	for (int iI = 0; iI<GC.getNumImprovementInfos(); iI++)
	{
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_ppaaiImprovementYieldChange[iI]);
	}

	if (bWrite)
	{
		FDataStreamBuffer fBuffer;

		m_groupCycle.WriteNonWrapper(&fBuffer);
		m_researchQueue.WriteNonWrapper(&fBuffer);

		pBuffer->putInt(fBuffer.m_pByteBuffer->size());
		for (int i = 0; i < (int)fBuffer.m_pByteBuffer->size(); i++)
		{
			pBuffer->put(fBuffer.m_pByteBuffer->get(i));
		}
	}
	else
	{
		FDataStreamBuffer fBuffer;
		int iSize = pBuffer->getInt();
		for (int i = 0; i < iSize; i++)
		{
			fBuffer.m_pByteBuffer->put(pBuffer->get());
		}
		m_groupCycle.ReadNonWrapper(&fBuffer);
		m_researchQueue.ReadNonWrapper(&fBuffer);
	}


	if (bWrite)
	{
		CLLNode<CvWString>* pNode;
		int iSize = m_cityNames.getLength();
		pBuffer->putInt(iSize);
		pNode = m_cityNames.head();
		while (pNode != NULL)
		{
			pBuffer->putString(pNode->m_data);
			pNode = m_cityNames.next(pNode);
		}
	}
	else
	{
		m_cityNames.clear();
		int iSize = pBuffer->getInt();
		for (int i = 0; i < iSize; i++)
		{
			CvWString szName;
			pBuffer->getString(szName);
			m_cityNames.insertAtEnd(szName);
		}
	}

	ResyncStreamableFFreeListTrashArray(bWrite, pBuffer, m_plotGroups);

	RESYNC_INT(bWrite, pBuffer, m_iLastCityId);
	//Merge Cities
	/*
	if (bWrite)
	{
		pBuffer->putInt(m_cities.getCount());
		for (int iI = 0; iI < m_cities.getIndexAfterLast(); iI++)
		{
			CvCityAI* pCity = m_cities[iI];
			if (pCity)
			{
				pCity->resync(true, pBuffer);
			}
		}
	}
	else
	{
		int iCount = pBuffer->getInt();
		int iCityCount = 0;
		for (int iI = 0; iI < m_cities.getIndexAfterLast(); iI++)
		{
			CvCityAI* pCity = m_cities[iI];
			if (pCity)
			{
				if (iCityCount >= iCount)
				{
					CvPlot* pPlot = pCity->plot();
					if (pCity->isCitySelected())
					{
						gDLL->getInterfaceIFace()->clearSelectedCities();
					}
					deleteCity(pCity->getID());
					pPlot->updateMinimapColor();

					if (GC.IsGraphicsInitialized())
					{
						gDLL->getInterfaceIFace()->setDirty(GlobeLayer_DIRTY_BIT, true);

						gDLL->getEngineIFace()->SetDirty(CultureBorders_DIRTY_BIT, true);
					}
				}
				else
				{
					pCity->resync(false, pBuffer);
					iCityCount++;
				}
			}
		}
		while (iCityCount < iCount)
		{
			CvCityAI* pCity = (CvCityAI*)addCity();
			pCity->resync(false, pBuffer);
			pCity->setupGraphical();
			iCityCount++;
		}
	}
	*/
	ResyncStreamableFFreeListTrashArray(bWrite, pBuffer, m_selectionGroups);

	//Merge Units
	//Units can only be resynced with units of the same id, because the id is used as the index to retrieve them from storage
	
	RESYNC_INT(bWrite, pBuffer, m_iLastUnitId);
	if (bWrite)
	{
		pBuffer->putInt(m_unitsList.size());
		std::vector<CvUnitAI*>::iterator it;
		for (it = m_unitsList.begin(); it != m_unitsList.end(); ++it)
		{
			CvUnitAI* pUnit = (*it);

			//Prefix with unit id for verification purposes later
			pBuffer->putInt(pUnit->getID());
			pUnit->resync(true, pBuffer);
		}
	}
	else
	{
		int iI;

		for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
		{
			GC.getMapINLINE().plotByIndexINLINE(iI)->enableCenterUnitRecalc(false);
		}

		stdext::hash_map<int, CvUnitAI*> unaccountedForUnits;
		//Units are removed from unaccountedForUnits as we find their id from the resync
		//At the end, units left in the map were not sent to us from the resync and should not exist
		std::vector<CvUnitAI*>::iterator it;
		for (it = m_unitsList.begin(); it != m_unitsList.end(); ++it)
		{
			CvUnitAI* pUnit = (*it);
			unaccountedForUnits[pUnit->getID()] = pUnit;
		}

		//Also keep track of the order of the ids sent to us by the host game, we need to re-organize our units list in this order when we are done
		std::vector<int> idOrder;

		int iCount = pBuffer->getInt();
		int iUnitCount = 0;
		for (int iI = 0; iI < iCount; iI++)
		{
			int iExpectedID = pBuffer->getInt();

			idOrder.push_back(iExpectedID);

			stdext::hash_map<int, CvUnitAI*>::iterator it = m_unitsMap.find(iExpectedID);
			//Found the unit in our game matching the sent id, resyncing it
			if (it != m_unitsMap.end())
			{
				unaccountedForUnits.erase(iExpectedID);

				CvUnitAI* pUnit = it->second;

				//Set the old tile dirty
				pUnit->plot()->setFlagDirty(true);

				pUnit->resync(false, pBuffer);

				//Set the new tile dirty
				pUnit->plot()->setFlagDirty(true);
				if (GC.IsGraphicsInitialized() && pUnit->isInViewport())
				{
					pUnit->SetPosition(pUnit->plot());
				}

				if (pUnit->plot() == gDLL->getInterfaceIFace()->getSelectionPlot())
				{
					gDLL->getInterfaceIFace()->verifyPlotListColumn();

					gDLL->getInterfaceIFace()->setDirty(PlotListButtons_DIRTY_BIT, true);
				}
				pUnit->setInfoBarDirty(true);

			}
			//We did not find the unit and need to create it!
			else
			{
				CvUnitAI* pUnit = new CvUnitAI();
				pUnit->setID(iExpectedID);
				m_unitsList.push_back(pUnit);
				m_unitsMap[iExpectedID] = pUnit;

				pUnit->resync(false, pBuffer);

				pUnit->plot()->setFlagDirty(true);
				if (GC.IsGraphicsInitialized() && pUnit->isInViewport())
				{
					pUnit->SetPosition(pUnit->plot());
				}

				if (pUnit->plot() == gDLL->getInterfaceIFace()->getSelectionPlot())
				{
					gDLL->getInterfaceIFace()->verifyPlotListColumn();

					gDLL->getInterfaceIFace()->setDirty(PlotListButtons_DIRTY_BIT, true);
				}
				pUnit->setInfoBarDirty(true);
			}
			
		}

		{
			//Left over units not sent as part of the resync - they must be removed
			stdext::hash_map<int, CvUnitAI*>::iterator it;
			for (it = unaccountedForUnits.begin(); it != unaccountedForUnits.end(); ++it)
			{
				CvUnitAI* pUnit = it->second;
				if (pUnit->IsSelected())
				{
					if (gDLL->getInterfaceIFace()->getLengthSelectionList() == 1)
					{
						if (!(gDLL->getInterfaceIFace()->isFocused()) && !(gDLL->getInterfaceIFace()->isCitySelection()) && !(gDLL->getInterfaceIFace()->isDiploOrPopupWaiting()))
						{
							GC.getGameINLINE().updateSelectionList();
						}

						if (pUnit->IsSelected())
						{
							gDLL->getInterfaceIFace()->setCycleSelectionCounter(1);
						}
						else
						{
							gDLL->getInterfaceIFace()->setDirty(SelectionCamera_DIRTY_BIT, true);
						}
					}
				}

				gDLL->getInterfaceIFace()->removeFromSelectionList(pUnit);

				// XXX this is NOT a hack, without it, the game crashes.
				if (!pUnit->isUsingDummyEntities() && pUnit->isInViewport())
				{
					gDLL->getEntityIFace()->RemoveUnitFromBattle(pUnit);
				}
				deleteUnit(pUnit->getID());
			}
		}

		//Reorder our unit list in the order of ids sent to us
		{
			m_unitsList.clear();

			std::vector<int>::iterator it;
			for (it = idOrder.begin(); it != idOrder.end(); ++it)
			{
				int id = (*it);
				stdext::hash_map<int, CvUnitAI*>::iterator search = m_unitsMap.find(id);
				//Found the unit in our game matching the sent id, resyncing it
				if (search != m_unitsMap.end())
				{
					m_unitsList.push_back(search->second);
				}
				else
				{
					//Should not happen!
					FAssert(false);
				}
			}
		}

	
		//setColor(GC.getInitCore().getColor(getID()));

		{
			int iLoop;
			CvUnit* pLoopUnit;
			CvPlot* pLoopPlot;
			for (pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
			{
				pLoopUnit->reloadEntity();
				pLoopPlot = pLoopUnit->plot();

				if (pLoopPlot != NULL)
				{
					CvFlagEntity* pFlag = pLoopPlot->getFlagSymbol();

					if (pFlag != NULL)
					{
						if (gDLL->getFlagEntityIFace()->getPlayer(pFlag) == getID())
						{
							gDLL->getFlagEntityIFace()->destroy(pFlag);
							CvFlagEntity* pNewFlag = gDLL->getFlagEntityIFace()->create(getID());
							if (pFlag != NULL)
							{
								gDLL->getFlagEntityIFace()->setPlot(pNewFlag, pLoopPlot, false);
							}

							gDLL->getFlagEntityIFace()->updateGraphicEra(pNewFlag);
						}
					}

					pLoopPlot->setFlagDirty(true);

					pLoopPlot->updateCenterUnit();
				}
			}

			gDLL->getInterfaceIFace()->setDirty(Flag_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->makeInterfaceDirty();
			gDLL->getInterfaceIFace()->setDirty(Waypoints_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(SelectionButtons_DIRTY_BIT, true);
			gDLL->getInterfaceIFace()->setDirty(InfoPane_DIRTY_BIT, true);
		}

		Commanders.clear();
		int iLoop;
		for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if (pLoopUnit->isCommander())	//search for GGs among loaded units and add them to Commanders array
			{
				Commanders.push_back(pLoopUnit);
			}
			if (pLoopUnit->isZoneOfControl())
			{
				GC.getGameINLINE().toggleAnyoneHasUnitZoneOfControl();
			}
		}
	}

	//ResyncStreamableFFreeListTrashArray(bWrite, pBuffer, m_cities);
	//ResyncStreamableFFreeListTrashArray(bWrite, pBuffer, m_units);

	ResyncStreamableFFreeListTrashArray(bWrite, pBuffer, m_eventsTriggered);

	if (bWrite)
	{
		FDataStreamBuffer *fBuffer = new FDataStreamBuffer();

		CvMessageQueue::_Alloc::size_type iSize = m_listGameMessages.size();
		pBuffer->putInt(iSize);
		CvMessageQueue::iterator it;
		for (it = m_listGameMessages.begin(); it != m_listGameMessages.end(); ++it)
		{
			CvTalkingHeadMessage& message = *it;
			message.write(*fBuffer);
		}

		pBuffer->putInt(fBuffer->m_pByteBuffer->size());
		for (int i = 0; i < (int)fBuffer->m_pByteBuffer->size(); i++)
		{
			pBuffer->put(fBuffer->m_pByteBuffer->get(i));
		}
		SAFE_DELETE(fBuffer);
	}
	else
	{
		int iSize = pBuffer->getInt();

		FDataStreamBuffer *fBuffer = new FDataStreamBuffer();
		int iBufferSize = pBuffer->getInt();
		for (int i = 0; i < iBufferSize; i++)
		{
			fBuffer->m_pByteBuffer->put(pBuffer->get());
		}

		for (int i = 0; i < iSize; i++)
		{
			CvTalkingHeadMessage message;
			message.read(*fBuffer);
			m_listGameMessages.push_back(message);
		}
		SAFE_DELETE(fBuffer);
	}

	if (bWrite)
	{
		FDataStreamBuffer *fBuffer = new FDataStreamBuffer();

		CvDiploQueue::_Alloc::size_type iSize = m_listDiplomacy.size();
		pBuffer->putInt(iSize);
		CvDiploQueue::iterator it;
		for (it = m_listDiplomacy.begin(); it != m_listDiplomacy.end(); ++it)
		{
			CvDiploParameters* pDiplo = *it;
			if (NULL != pDiplo)
			{
				pDiplo->write(*fBuffer);
			}
		}


		pBuffer->putInt(fBuffer->m_pByteBuffer->size());
		for (int i = 0; i < (int)fBuffer->m_pByteBuffer->size(); i++)
		{
			pBuffer->put(fBuffer->m_pByteBuffer->get(i));
		}
		SAFE_DELETE(fBuffer);
	}
	else
	{
		m_listDiplomacy.clear();
		int iSize = pBuffer->getInt();

		FDataStreamBuffer *fBuffer = new FDataStreamBuffer();
		int iBufferSize = pBuffer->getInt();
		for (int i = 0; i < iBufferSize; i++)
		{
			fBuffer->m_pByteBuffer->put(pBuffer->get());
		}

		for (int i = 0; i < iSize; i++)
		{
			CvDiploParameters* pDiplo = new CvDiploParameters(NO_PLAYER);
			pDiplo->read(*fBuffer);
			m_listDiplomacy.push_back(pDiplo);
		}
		SAFE_DELETE(fBuffer);
	}


	resyncHashmap(bWrite, pBuffer, m_mapScoreHistory);
	resyncHashmap(bWrite, pBuffer, m_mapEconomyHistory);
	resyncHashmap(bWrite, pBuffer, m_mapIndustryHistory);
	resyncHashmap(bWrite, pBuffer, m_mapAgricultureHistory);
	resyncHashmap(bWrite, pBuffer, m_mapPowerHistory);
	resyncHashmap(bWrite, pBuffer, m_mapCultureHistory);
	resyncHashmap(bWrite, pBuffer, m_mapEspionageHistory);
	resyncHashmap(bWrite, pBuffer, m_mapRevolutionStabilityHistory);

	resyncHashmap(bWrite, pBuffer, m_mapEventsOccured);
	resyncHashmap(bWrite, pBuffer, m_mapEventCountdown);

	if (bWrite)
	{
		uint iSize = m_aFreeUnitCombatPromotions.size();
		pBuffer->putInt(iSize);
		UnitCombatPromotionArray::iterator it;
		for (it = m_aFreeUnitCombatPromotions.begin(); it != m_aFreeUnitCombatPromotions.end(); ++it)
		{
			pBuffer->putInt((*it).first);
			pBuffer->putInt((*it).second);
		}
	}
	else
	{
		m_aFreeUnitCombatPromotions.clear();
		uint iSize = pBuffer->getInt();
		for (uint i = 0; i < iSize; i++)
		{
			UnitCombatTypes first = (UnitCombatTypes)pBuffer->getInt();
			PromotionTypes second = (PromotionTypes)pBuffer->getInt();
			m_aFreeUnitCombatPromotions.push_back(std::make_pair(first, second));
		}
	}

	if (bWrite)
	{
		uint iSize = m_aFreeUnitClassPromotions.size();
		pBuffer->putInt(iSize);
		UnitClassPromotionArray::iterator it;
		for (it = m_aFreeUnitClassPromotions.begin(); it != m_aFreeUnitClassPromotions.end(); ++it)
		{
			pBuffer->putInt((*it).first);
			pBuffer->putInt((*it).second);
		}
	}
	else
	{
		m_aFreeUnitClassPromotions.clear();
		uint iSize = pBuffer->getInt();
		for (uint i = 0; i < iSize; i++)
		{
			UnitClassTypes first = (UnitClassTypes)pBuffer->getInt();
			PromotionTypes second = (PromotionTypes)pBuffer->getInt();
			m_aFreeUnitClassPromotions.push_back(std::make_pair(first, second));
		}
	}

	if (bWrite)
	{
		uint iSize = m_aVote.size();
		pBuffer->putInt(iSize);
		std::vector< std::pair<int, PlayerVoteTypes> >::iterator it;
		for (it = m_aVote.begin(); it != m_aVote.end(); ++it)
		{
			pBuffer->putInt((*it).first);
			pBuffer->putInt((*it).second);
		}
	}
	else
	{
		m_aVote.clear();
		uint iSize = pBuffer->getInt();
		for (uint i = 0; i < iSize; i++)
		{
			int first = pBuffer->getInt();
			PlayerVoteTypes second = (PlayerVoteTypes)pBuffer->getInt();
			m_aVote.push_back(std::make_pair(first, second));
		}
	}

	if (bWrite)
	{
		uint iSize = m_aUnitExtraCosts.size();
		pBuffer->putInt(iSize);
		std::vector< std::pair<UnitClassTypes, int> >::iterator it;
		for (it = m_aUnitExtraCosts.begin(); it != m_aUnitExtraCosts.end(); ++it)
		{
			pBuffer->putInt((*it).first);
			pBuffer->putInt((*it).second);
		}
	}
	else
	{
		m_aUnitExtraCosts.clear();
		uint iSize = pBuffer->getInt();
		for (uint i = 0; i < iSize; i++)
		{
			UnitClassTypes first = (UnitClassTypes) pBuffer->getInt();
			int second = pBuffer->getInt();
			m_aUnitExtraCosts.push_back(std::make_pair(first, second));
		}
	}

	if (bWrite)
	{
		uint iSize = m_triggersFired.size();
		pBuffer->putInt(iSize);
		std::vector<EventTriggerTypes>::iterator it;
		for (it = m_triggersFired.begin(); it != m_triggersFired.end(); ++it)
		{
			pBuffer->putInt(*it);
		}
	}
	else
	{
		m_triggersFired.clear();
		uint iSize = pBuffer->getInt();
		for (uint i = 0; i < iSize; i++)
		{
			EventTriggerTypes first = (EventTriggerTypes)pBuffer->getInt();
			m_triggersFired.push_back(first);
		}
	}

	RESYNC_INT(bWrite, pBuffer, m_iPopRushHurryCount);
	RESYNC_INT(bWrite, pBuffer, m_iInflationModifier);

	if (bWrite)
	{
		pBuffer->putInt(m_pTempUnit == NULL ? -1 : m_pTempUnit->getID());
	}
	else
	{
		int iTempUnitId = pBuffer->getInt();
		if (iTempUnitId != -1)
		{
			m_pTempUnit = getUnit(iTempUnitId);
		}
		else
		{
			m_pTempUnit = NULL;
		}
	}
	RESYNC_INT_ARRAY(bWrite, pBuffer, GC.getNumImprovementInfos(), m_paiImprovementUpgradeRateModifierSpecific);
	for (int iI = 0; iI<GC.getNumSpecialistInfos(); iI++)
	{
		RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_COMMERCE_TYPES, m_ppaaiSpecialistExtraCommerce[iI]);
	}
	RESYNC_INT_ARRAY(bWrite, pBuffer, NUM_YIELD_TYPES, m_aiSpecialistExtraYield);
	RESYNC_INT(bWrite, pBuffer, m_iNationalHurryAngerModifier);
	RESYNC_INT(bWrite, pBuffer, m_iNationalEnemyWarWearinessModifier);
	RESYNC_INT(bWrite, pBuffer, m_iFixedBordersCount);
	RESYNC_INT(bWrite, pBuffer, m_iWarMongerIndex);
	RESYNC_INT(bWrite, pBuffer, m_iSeizedForeignConnectednessPercent);
}

void CvPlayer::createGreatPeople(UnitTypes eGreatPersonUnit, bool bIncrementThreshold, bool bIncrementExperience, int iX, int iY)
{
	CvUnit* pGreatPeopleUnit = initUnit(eGreatPersonUnit, iX, iY, NO_UNITAI, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
	if (NULL == pGreatPeopleUnit)
	{
		FAssert(false);
		return;
	}

	if (bIncrementThreshold)
	{
		incrementGreatPeopleCreated();

		changeGreatPeopleThresholdModifier(GC.getDefineINT("GREAT_PEOPLE_THRESHOLD_INCREASE") * ((getGreatPeopleCreated() / 10) + 1));

		for (int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam())
			{
				GET_PLAYER((PlayerTypes)iI).changeGreatPeopleThresholdModifier(GC.getDefineINT("GREAT_PEOPLE_THRESHOLD_INCREASE_TEAM") * ((getGreatPeopleCreated() / 10) + 1));
			}
		}
	}

	if (bIncrementExperience)
	{
		incrementGreatGeneralsCreated();

		changeGreatGeneralsThresholdModifier(GC.getDefineINT("GREAT_GENERALS_THRESHOLD_INCREASE") * ((getGreatGeneralsCreated() / 10) + 1));

		for (int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam())
			{
				GET_PLAYER((PlayerTypes)iI).changeGreatGeneralsThresholdModifier(GC.getDefineINT("GREAT_GENERALS_THRESHOLD_INCREASE_TEAM") * ((getGreatGeneralsCreated() / 10) + 1));
			}
		}
	}


	CvPlot* pPlot = GC.getMapINLINE().plot(iX, iY);
	CvCity* pCity = NULL;
	CvWString szReplayMessage;

	if (pPlot)
	{
		pCity = pPlot->getPlotCity();
		if (pCity)
		{
			CvWString szCity;
			szCity.Format(L"%s (%s)", pCity->getName().GetCString(), GET_PLAYER(pCity->getOwnerINLINE()).getName());
			szReplayMessage = gDLL->getText("TXT_KEY_MISC_GP_BORN", pGreatPeopleUnit->getName().GetCString(), szCity.GetCString());
		}
		else
		{
			szReplayMessage = gDLL->getText("TXT_KEY_MISC_GP_BORN_FIELD", pGreatPeopleUnit->getName().GetCString());
		}
		GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szReplayMessage, iX, iY, (ColorTypes)GC.getInfoTypeForString("COLOR_UNIT_TEXT"));
	}

	for (int iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			MEMORY_TRACK_EXEMPT();

			if (pPlot->isRevealed(GET_PLAYER((PlayerTypes)iI).getTeam(), false))
			{
				AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szReplayMessage, "AS2D_UNIT_GREATPEOPLE", MESSAGE_TYPE_MAJOR_EVENT, pGreatPeopleUnit->getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_UNIT_TEXT"), iX, iY, true, true);
			}
			else
			{
				CvWString szMessage = gDLL->getText("TXT_KEY_MISC_GP_BORN_SOMEWHERE", pGreatPeopleUnit->getName().GetCString());
				AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szMessage, "AS2D_UNIT_GREATPEOPLE", MESSAGE_TYPE_MAJOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_UNIT_TEXT"));
			}
		}
	}

	// Python Event
	if (pCity)
	{
		CvEventReporter::getInstance().greatPersonBorn(pGreatPeopleUnit, getID(), pCity);
	}

}


const EventTriggeredData* CvPlayer::getEventOccured(EventTypes eEvent, bool bIncludeExpiredEvents) const
{
	FAssert(eEvent >= 0 && eEvent < GC.getNumEventInfos());

	CvEventMap::const_iterator it = m_mapEventsOccured.find(eEvent);

	if (it == m_mapEventsOccured.end() || ((it->second).m_bExpired && !bIncludeExpiredEvents) )
	{
		return NULL;
	}

	return &(it->second);
}

bool CvPlayer::isTriggerFired(EventTriggerTypes eEventTrigger) const
{
	return (std::find(m_triggersFired.begin(), m_triggersFired.end(), eEventTrigger) != m_triggersFired.end());
}

void CvPlayer::resetEventOccured(EventTypes eEvent, bool bAnnounce)
{
	FAssert(eEvent >= 0 && eEvent < GC.getNumEventInfos());

	CvEventMap::iterator it = m_mapEventsOccured.find(eEvent);

	if (it != m_mapEventsOccured.end())
	{
		expireEvent(it->first, it->second, bAnnounce);
		m_mapEventsOccured.erase(it);
	}
}

void CvPlayer::setEventOccured(EventTypes eEvent, const EventTriggeredData& kEventTriggered, bool bOthers)
{
	FAssert(eEvent >= 0 && eEvent < GC.getNumEventInfos());

	m_mapEventsOccured[eEvent] = kEventTriggered;

	if (GC.getEventInfo(eEvent).isQuest())
	{
		CvWStringBuffer szMessageBuffer;
		szMessageBuffer.append(GC.getEventInfo(eEvent).getDescription());
		GAMETEXT.setEventHelp(szMessageBuffer, eEvent, kEventTriggered.getID(), getID());
		gDLL->getInterfaceIFace()->addQuestMessage(getID(), szMessageBuffer.getCString(), kEventTriggered.getID());
	}

	if (bOthers)
	{
		if (GC.getEventInfo(eEvent).isGlobal())
		{
			for (int i = 0; i < MAX_CIV_PLAYERS; i++)
			{
				if (i != getID())
				{
					GET_PLAYER((PlayerTypes)i).setEventOccured(eEvent, kEventTriggered, false);
				}
			}
		}
		else if (GC.getEventInfo(eEvent).isTeam())
		{
			for (int i = 0; i < MAX_CIV_PLAYERS; i++)
			{
				if (i != getID() && getTeam() == GET_PLAYER((PlayerTypes)i).getTeam())
				{
					GET_PLAYER((PlayerTypes)i).setEventOccured(eEvent, kEventTriggered, false);
				}
			}
		}
	}
}


const EventTriggeredData* CvPlayer::getEventCountdown(EventTypes eEvent) const
{
	FAssert(eEvent >= 0 && eEvent < GC.getNumEventInfos());

	CvEventMap::const_iterator it = m_mapEventCountdown.find(eEvent);

	if (it == m_mapEventCountdown.end())
	{
		return NULL;
	}

	return &(it->second);
}

void CvPlayer::setEventCountdown(EventTypes eEvent, const EventTriggeredData& kEventTriggered)
{
	FAssert(eEvent >= 0 && eEvent < GC.getNumEventInfos());

	m_mapEventCountdown[eEvent] = kEventTriggered;
}

void CvPlayer::resetEventCountdown(EventTypes eEvent)
{
	FAssert(eEvent >= 0 && eEvent < GC.getNumEventInfos());

	CvEventMap::iterator it = m_mapEventCountdown.find(eEvent);

	if (it != m_mapEventCountdown.end())
	{
		m_mapEventCountdown.erase(it);
	}
}


void CvPlayer::resetTriggerFired(EventTriggerTypes eTrigger)
{
	std::vector<EventTriggerTypes>::iterator it = std::find(m_triggersFired.begin(), m_triggersFired.end(), eTrigger);

	if (it != m_triggersFired.end())
	{
		m_triggersFired.erase(it);
	}
}

void CvPlayer::setTriggerFired(const EventTriggeredData& kTriggeredData, bool bOthers, bool bAnnounce)
{
	FAssert(kTriggeredData.m_eTrigger >= 0 && kTriggeredData.m_eTrigger < GC.getNumEventTriggerInfos());

	CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(kTriggeredData.m_eTrigger);

	if (!isTriggerFired(kTriggeredData.m_eTrigger))
	{
		m_triggersFired.push_back(kTriggeredData.m_eTrigger);

		if (bOthers)
		{
			if (kTrigger.isGlobal())
			{
				for (int i = 0; i < MAX_CIV_PLAYERS; i++)
				{
					if (i != getID())
					{
						GET_PLAYER((PlayerTypes)i).setTriggerFired(kTriggeredData, false, false);
					}
				}
			}
			else if (kTrigger.isTeam())
			{
				for (int i = 0; i < MAX_CIV_PLAYERS; i++)
				{
					if (i != getID() && getTeam() == GET_PLAYER((PlayerTypes)i).getTeam())
					{
						GET_PLAYER((PlayerTypes)i).setTriggerFired(kTriggeredData, false, false);
					}
				}
			}
		}
	}

	if (!CvString(kTrigger.getPythonCallback()).empty())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		long lResult;

		CyArgsList argsList;
		argsList.add(gDLL->getPythonIFace()->makePythonObject(&kTriggeredData));

		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYRandomEventModule, kTrigger.getPythonCallback(), argsList.makeFunctionArgs(), &lResult);
	}

	if (bAnnounce)
	{
		CvPlot* pPlot = GC.getMapINLINE().plot(kTriggeredData.m_iPlotX, kTriggeredData.m_iPlotY);

		if (!kTriggeredData.m_szGlobalText.empty())
		{
			for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
			{
				CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);

				if (kLoopPlayer.isAlive())
				{
					if (GET_TEAM(kLoopPlayer.getTeam()).isHasMet(getTeam()) && (NO_PLAYER == kTriggeredData.m_eOtherPlayer || GET_TEAM(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()).isHasMet(getTeam())))
					{
						bool bShowPlot = kTrigger.isShowPlot();

						if (bShowPlot)
						{
							if (kLoopPlayer.getTeam() != getTeam())
							{
								if (NULL == pPlot ||
									!pPlot->isRevealed(kLoopPlayer.getTeam(), false) ||
									!pPlot->isInViewport())
								{
									bShowPlot = false;
								}
							}
						}

						MEMORY_TRACK_EXEMPT();

						if (bShowPlot)
						{
							AddDLLMessage((PlayerTypes)iPlayer, false, GC.getEVENT_MESSAGE_TIME(), kTriggeredData.m_szGlobalText, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), kTriggeredData.m_iPlotX, kTriggeredData.m_iPlotY, true, true);
						}
						else
						{
							AddDLLMessage((PlayerTypes)iPlayer, false, GC.getEVENT_MESSAGE_TIME(), kTriggeredData.m_szGlobalText, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT);
						}
					}
				}
			}

/************************************************************************************************/
/* REVOLUTION_MOD                         02/01/08                                jdog5000      */
/*                                                                                              */
/* Silence replay messages for events ... too crowded by late game                              */
/************************************************************************************************/
/* original code
			GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), kTriggeredData.m_szGlobalText, kTriggeredData.m_iPlotX, kTriggeredData.m_iPlotY, (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));
*/
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
		}
		else if (!kTriggeredData.m_szText.empty())
		{
			MEMORY_TRACK_EXEMPT();

			if (kTrigger.isShowPlot() && NULL != pPlot && pPlot->isRevealed(getTeam(), false))
			{
				AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), kTriggeredData.m_szText, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), kTriggeredData.m_iPlotX, kTriggeredData.m_iPlotY, true, true);
			}
			else
			{
				AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), kTriggeredData.m_szText, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"));
			}
		}
	}
}

EventTriggeredData* CvPlayer::initTriggeredData(EventTriggerTypes eEventTrigger, bool bFire, int iCityId, int iPlotX, int iPlotY, PlayerTypes eOtherPlayer, int iOtherPlayerCityId, ReligionTypes eReligion, CorporationTypes eCorporation, int iUnitId, BuildingTypes eBuilding)
{

	CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(eEventTrigger);

	CvCity* pCity = getCity(iCityId);
	CvCity* pOtherPlayerCity = NULL;
	if (NO_PLAYER != eOtherPlayer)
	{
		pOtherPlayerCity = GET_PLAYER(eOtherPlayer).getCity(iOtherPlayerCityId);
	}
	CvPlot* pPlot = GC.getMapINLINE().plot(iPlotX, iPlotY);
	CvUnit* pUnit = getUnit(iUnitId);

	std::vector<CvPlot*> apPlots;
	bool bPickPlot = ::isPlotEventTrigger(eEventTrigger);
	if (kTrigger.isPickCity())
	{
		if (NULL == pCity)
		{
			pCity = pickTriggerCity(eEventTrigger);
		}

		if (NULL != pCity)
		{
			if (bPickPlot)
			{
				for (int iPlot = 0; iPlot < NUM_CITY_PLOTS; ++iPlot)
				{
					if (CITY_HOME_PLOT != iPlot)
					{
						CvPlot* pLoopPlot = pCity->getCityIndexPlot(iPlot);

						if (NULL != pLoopPlot)
						{
							if (pLoopPlot->canTrigger(eEventTrigger, getID()))
							{
								apPlots.push_back(pLoopPlot);
							}
						}
					}
				}
			}
		}
		else
		{
			return NULL;
		}
	}
	else 
	{
		if (kTrigger.getNumBuildings() > 0 && kTrigger.getNumBuildingsRequired() > 0)
		{
			int iFoundValid = 0;

			for (int i = 0; i < kTrigger.getNumBuildingsRequired(); ++i)
			{
				if (kTrigger.getBuildingRequired(i) != NO_BUILDINGCLASS)
				{
					iFoundValid += getBuildingClassCount((BuildingClassTypes)kTrigger.getBuildingRequired(i));
				}
			}

			if (iFoundValid < kTrigger.getNumBuildings())
			{
				return NULL;
			}
		}

		if (kTrigger.getNumReligions() > 0)
		{
			int iFoundValid = 0;

			if (kTrigger.getNumReligionsRequired() > 0)
			{
				for (int i = 0; i < kTrigger.getNumReligionsRequired(); ++i)
				{
					if (kTrigger.getReligionRequired(i) != NO_RELIGION)
					{
						if (getHasReligionCount((ReligionTypes)kTrigger.getReligionRequired(i)) > 0)
						{
							++iFoundValid;
						}
					}
				}
			}
			else
			{
				for (int i = 0; i < GC.getNumReligionInfos(); ++i)
				{
					if (getHasReligionCount((ReligionTypes)i) > 0)
					{
						++iFoundValid;
					}
				}
			}

			if (iFoundValid < kTrigger.getNumReligions())
			{
				return NULL;
			}
		}

		if (kTrigger.getNumCorporations() > 0)
		{
			int iFoundValid = 0;

			if (kTrigger.getNumCorporationsRequired() > 0)
			{
				for (int i = 0; i < kTrigger.getNumCorporationsRequired(); ++i)
				{
					if (kTrigger.getCorporationRequired(i) != NO_CORPORATION)
					{
						if (getHasCorporationCount((CorporationTypes)kTrigger.getCorporationRequired(i)) > 0)
						{
							++iFoundValid;
						}
					}
				}
			}
			else
			{
				for (int i = 0; i < GC.getNumCorporationInfos(); ++i)
				{
					if (getHasCorporationCount((CorporationTypes)i) > 0)
					{
						++iFoundValid;
					}
				}
			}

			if (iFoundValid < kTrigger.getNumCorporations())
			{
				return NULL;
			}
		}

		if (kTrigger.getMinPopulation() > 0)
		{
			if (getTotalPopulation() < kTrigger.getMinPopulation())
			{
				return NULL;
			}
		}

		if (kTrigger.getMaxPopulation() > 0)
		{
			if (getTotalPopulation() > kTrigger.getMaxPopulation())
			{
				return NULL;
			}
		}

		if (bPickPlot)
		{
			for (int iPlot = 0; iPlot < GC.getMapINLINE().numPlotsINLINE(); ++iPlot)
			{
				CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);

				if (pLoopPlot->canTrigger(eEventTrigger, getID()))
				{
					apPlots.push_back(pLoopPlot);
				}
			}
		}
	}

	if (kTrigger.isPickReligion())
	{
		if (NO_RELIGION == eReligion)
		{
			if (kTrigger.isStateReligion())
			{
				ReligionTypes eStateReligion = getStateReligion();
				if (NO_RELIGION != eStateReligion && isValidTriggerReligion(kTrigger, pCity, eStateReligion))
				{
					eReligion = getStateReligion();
				}
			}
			else
			{
				int iOffset = GC.getGameINLINE().getSorenRandNum(GC.getNumReligionInfos(), "Event pick religion");

				for (int i = 0; i < GC.getNumReligionInfos(); ++i)
				{
					int iReligion = (i + iOffset) % GC.getNumReligionInfos();

					if (isValidTriggerReligion(kTrigger, pCity, (ReligionTypes)iReligion))
					{
						eReligion = (ReligionTypes)iReligion;
						break;
					}
				}
			}
		}

		if (NO_RELIGION == eReligion)
		{
			return NULL;
		}
	}

	if (kTrigger.isPickCorporation())
	{
		if (NO_CORPORATION == eCorporation)
		{
			int iOffset = GC.getGameINLINE().getSorenRandNum(GC.getNumCorporationInfos(), "Event pick corporation");

			for (int i = 0; i < GC.getNumCorporationInfos(); ++i)
			{
				int iCorporation = (i + iOffset) % GC.getNumCorporationInfos();

				if (isValidTriggerCorporation(kTrigger, pCity, (CorporationTypes)iCorporation))
				{
					eCorporation = (CorporationTypes)iCorporation;
					break;
				}
			}
		}

		if (NO_CORPORATION == eCorporation)
		{
			return NULL;
		}
	}

	if (NULL == pPlot)
	{
		if (!apPlots.empty())
		{
			int iChosen = GC.getGameINLINE().getSorenRandNum(apPlots.size(), "Event pick plot");
			pPlot = apPlots[iChosen];

			if (NULL == pCity)
			{
				pCity = GC.getMapINLINE().findCity(pPlot->getX_INLINE(), pPlot->getY_INLINE(), getID(), NO_TEAM, false);
			}
		}
		else 
		{
			if (bPickPlot)
			{
				return NULL;
			}

			if (NULL != pCity)
			{
				pPlot = pCity->plot();
			}
		}
	}

	if (kTrigger.getNumBuildings() > 0)
	{
		if (NULL != pCity && NO_BUILDING == eBuilding)
		{
			std::vector<BuildingTypes> aeBuildings;
			for (int i = 0; i < kTrigger.getNumBuildingsRequired(); ++i)
			{
				if (kTrigger.getBuildingRequired(i) != NO_BUILDINGCLASS)
				{
					BuildingTypes eTestBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(kTrigger.getBuildingRequired(i));
					if (NO_BUILDING != eTestBuilding && pCity->getNumRealBuilding(eTestBuilding) > 0)
					{
						aeBuildings.push_back(eTestBuilding);
					}
				}
			}

			if (!aeBuildings.empty())
			{
				int iChosen = GC.getGameINLINE().getSorenRandNum(aeBuildings.size(), "Event pick building");
				eBuilding = aeBuildings[iChosen];
			}
			else
			{
				return NULL;
			}
		}
	}	

	if (NULL == pUnit)
	{
		pUnit = pickTriggerUnit(eEventTrigger, pPlot, bPickPlot);
	}

	if (NULL == pUnit && kTrigger.getNumUnits() > 0)
	{
		return NULL;
	}

	if (NULL == pPlot && NULL != pUnit)
	{
		pPlot = pUnit->plot();
	}

	if (NULL == pPlot && bPickPlot)
	{
		return NULL;
	}

	if (kTrigger.getNumUnitsGlobal() > 0)
	{
		int iNumUnits = 0;
		for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
		{
			CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);

			if (kLoopPlayer.isAlive())
			{
				int iLoop;
				for (CvUnit* pLoopUnit = kLoopPlayer.firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = kLoopPlayer.nextUnit(&iLoop))
				{
					if (MIN_INT != pLoopUnit->getTriggerValue(eEventTrigger, pPlot, true))
					{
						++iNumUnits;
					}
				}
			}
		}

		if (iNumUnits < kTrigger.getNumUnitsGlobal())
		{
			return NULL;
		}
	}

	if (kTrigger.getNumBuildingsGlobal() > 0)
	{
		int iNumBuildings = 0;
		for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
		{
			CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);

			if (kLoopPlayer.isAlive())
			{
				for (int i = 0; i < kTrigger.getNumBuildingsRequired(); ++i)
				{
					if (kTrigger.getBuildingRequired(i) != NO_BUILDINGCLASS)
					{
						iNumBuildings += getBuildingClassCount((BuildingClassTypes)kTrigger.getBuildingRequired(i));
					}
				}
			}
		}

		if (iNumBuildings < kTrigger.getNumBuildingsGlobal())
		{
			return NULL;
		}
	}

	if (kTrigger.isPickPlayer())
	{
		std::vector<PlayerTypes> aePlayers;
		std::vector<CvCity*> apCities;

		if (NO_PLAYER == eOtherPlayer)
		{
			for (int i = 0; i < MAX_CIV_PLAYERS; i++)
			{
				if (GET_PLAYER((PlayerTypes)i).canTrigger(eEventTrigger, getID(), eReligion))
				{
					if (kTrigger.isPickOtherPlayerCity())
					{
						CvCity* pBestCity = NULL;

						if (NULL != pCity)
						{
							pBestCity = GC.getMapINLINE().findCity(pCity->getX_INLINE(), pCity->getY_INLINE(), (PlayerTypes)i);
						}
						else
						{
							pBestCity = GET_PLAYER((PlayerTypes)i).pickTriggerCity(eEventTrigger);
						}

						if (NULL != pBestCity)
						{
							apCities.push_back(pBestCity);
							aePlayers.push_back((PlayerTypes)i);
						}
					}
					else
					{
						apCities.push_back(NULL);
						aePlayers.push_back((PlayerTypes)i);
					}
				}
			}

			if (!aePlayers.empty())
			{
				int iChosen = GC.getGameINLINE().getSorenRandNum(aePlayers.size(), "Event pick player");
				eOtherPlayer = aePlayers[iChosen];
				pOtherPlayerCity = apCities[iChosen];
			}
			else
			{
				return NULL;
			}
		}
	}	

	EventTriggeredData* pTriggerData = addEventTriggered();

	if (NULL != pTriggerData)
	{
		pTriggerData->m_eTrigger = eEventTrigger;
		pTriggerData->m_ePlayer = getID();
		pTriggerData->m_iTurn = GC.getGameINLINE().getGameTurn();
		pTriggerData->m_iCityId = (NULL != pCity) ? pCity->getID() : -1;
		pTriggerData->m_iPlotX = (NULL != pPlot) ? pPlot->getX_INLINE() : INVALID_PLOT_COORD;
		pTriggerData->m_iPlotY = (NULL != pPlot) ? pPlot->getY_INLINE() : INVALID_PLOT_COORD;
		pTriggerData->m_eOtherPlayer = eOtherPlayer;
		pTriggerData->m_iOtherPlayerCityId = (NULL != pOtherPlayerCity) ? pOtherPlayerCity->getID() : -1;
		pTriggerData->m_eReligion = eReligion;
		pTriggerData->m_eCorporation = eCorporation;
		pTriggerData->m_iUnitId = (NULL != pUnit) ? pUnit->getID() : -1;
		pTriggerData->m_eBuilding = eBuilding;
		pTriggerData->m_bExpired = false;
	}
	else
	{
		return NULL;
	}

	if (!CvString(kTrigger.getPythonCanDo()).empty())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		long lResult;

		CyArgsList argsList;
		argsList.add(gDLL->getPythonIFace()->makePythonObject(pTriggerData));

		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYRandomEventModule, kTrigger.getPythonCanDo(), argsList.makeFunctionArgs(), &lResult);

		if (0 == lResult)
		{
			deleteEventTriggered(pTriggerData->getID());
			return NULL;
		}

		// python may change pTriggerData
		pCity = getCity(pTriggerData->m_iCityId);
		pPlot = GC.getMapINLINE().plot(pTriggerData->m_iPlotX, pTriggerData->m_iPlotY);
		pUnit = getUnit(pTriggerData->m_iUnitId);
		eOtherPlayer = pTriggerData->m_eOtherPlayer;
		if (NO_PLAYER != eOtherPlayer)
		{
			pOtherPlayerCity = GET_PLAYER(eOtherPlayer).getCity(pTriggerData->m_iOtherPlayerCityId);
		}
		eReligion = pTriggerData->m_eReligion;
		eCorporation = pTriggerData->m_eCorporation;
		eBuilding = pTriggerData->m_eBuilding;
	}

	std::vector<CvWString> aszTexts;
	for (int i = 0; i < kTrigger.getNumTexts(); ++i)
	{
		if (NO_ERA == kTrigger.getTextEra(i) || kTrigger.getTextEra(i) == getCurrentEra())
		{
			aszTexts.push_back(kTrigger.getText(i));
		}
	}

	if (!aszTexts.empty())
	{
		int iText = GC.getGameINLINE().getSorenRandNum(aszTexts.size(), "Event Text choice");

		pTriggerData->m_szText = gDLL->getText(aszTexts[iText].GetCString(), 
			eOtherPlayer != NO_PLAYER ? GET_PLAYER(eOtherPlayer).getCivilizationAdjectiveKey() : L"", 
			NULL != pCity ? pCity->getNameKey() : L"", 
			NULL != pUnit ? pUnit->getNameKey() : L"", 
			NO_RELIGION != eReligion ? GC.getReligionInfo(eReligion).getAdjectiveKey() : L"",
			NO_BUILDING != eBuilding ? GC.getBuildingInfo(eBuilding).getTextKeyWide() : L"",
			NULL != pOtherPlayerCity ? pOtherPlayerCity->getNameKey() : L"",
			NULL != pPlot && NO_TERRAIN != pPlot->getTerrainType() ? GC.getTerrainInfo(pPlot->getTerrainType()).getTextKeyWide() : L"",
			NULL != pPlot && NO_IMPROVEMENT != pPlot->getImprovementType() ? GC.getImprovementInfo(pPlot->getImprovementType()).getTextKeyWide() : L"",
			NULL != pPlot && NO_BONUS != pPlot->getBonusType() ? GC.getBonusInfo(pPlot->getBonusType()).getTextKeyWide() : L"",
			NULL != pPlot && NO_ROUTE != pPlot->getRouteType() ? GC.getRouteInfo(pPlot->getRouteType()).getTextKeyWide() : L"",
			NO_CORPORATION != eCorporation ? GC.getCorporationInfo(eCorporation).getTextKeyWide() : L""
			);
	}
	else
	{
		pTriggerData->m_szText = L"";
	}

	if (kTrigger.getNumWorldNews() > 0)
	{
		int iText = GC.getGameINLINE().getSorenRandNum(kTrigger.getNumWorldNews(), "Trigger World News choice");

		pTriggerData->m_szGlobalText = gDLL->getText(kTrigger.getWorldNews(iText).GetCString(),
			getCivilizationAdjectiveKey(),
			NULL != pCity ? pCity->getNameKey() : L"",
			pTriggerData->m_eReligion != NO_RELIGION ? GC.getReligionInfo(pTriggerData->m_eReligion).getAdjectiveKey() : L"",
			eOtherPlayer != NO_PLAYER ? GET_PLAYER(eOtherPlayer).getCivilizationAdjectiveKey() : L"",
			NULL != pOtherPlayerCity ? pOtherPlayerCity->getNameKey() : L"",
			pTriggerData->m_eCorporation != NO_CORPORATION ? GC.getCorporationInfo(pTriggerData->m_eCorporation).getTextKeyWide() : L""
			);
	}
	else
	{
		pTriggerData->m_szGlobalText.clear();
	}

	if (bFire)
	{
		trigger(*pTriggerData);
	}

	return pTriggerData;
}


bool CvPlayer::canDoEvent(EventTypes eEvent, const EventTriggeredData& kTriggeredData) const
{
	if (eEvent == NO_EVENT)
	{
		FAssert(false);
		return false;
	}

	CvEventInfo& kEvent = GC.getEventInfo(eEvent);
/************************************************************************************************/
/* Afforess	                  Start		 01/20/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (kEvent.getPrereqGameOption() != NO_GAMEOPTION)
	{
		if (!(GC.getGameINLINE().isOption((GameOptionTypes)kEvent.getPrereqGameOption())))
		{
			return false;
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	int iGold = std::min(getEventCost(eEvent, kTriggeredData.m_eOtherPlayer, false), getEventCost(eEvent, kTriggeredData.m_eOtherPlayer, true));

	if (iGold != 0)
	{
		if (iGold > 0 && NO_PLAYER != kTriggeredData.m_eOtherPlayer && kEvent.isGoldToPlayer())
		{
			if (GET_PLAYER(kTriggeredData.m_eOtherPlayer).getGold() < iGold)
			{
				return false;
			}
		}
		else if (iGold < 0)
		{
			if (getGold() < -iGold)
			{
				return false;
			}
		}
	}

	if (0 != kEvent.getSpaceProductionModifier())
	{
		bool bValid = false;
		for (int iProject = 0; iProject < GC.getNumProjectInfos(); ++iProject)
		{
			CvProjectInfo& kProject = GC.getProjectInfo((ProjectTypes)iProject);
			if (kProject.isSpaceship())
			{
				if (kProject.getVictoryPrereq() != NO_VICTORY)
				{
					if (GC.getGameINLINE().isVictoryValid((VictoryTypes)(kProject.getVictoryPrereq())))
					{
						bValid = true;
						break;
					}
				}
			}
		}

		if (!bValid)
		{
			return false;
		}
	}

	if (kEvent.getEspionagePoints() > 0 && GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
	{
		return false;
	}

	if (NO_PLAYER != kTriggeredData.m_eOtherPlayer)
	{
		if (kEvent.getEspionagePoints() + GET_TEAM(getTeam()).getEspionagePointsAgainstTeam(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()) < 0)
		{
			return false;
		}
	}

	if (0 != kEvent.getTechPercent() || 0 != kEvent.getTechCostPercent())
	{
		if (NO_TECH == getBestEventTech(eEvent, kTriggeredData.m_eOtherPlayer))
		{
			return false;
		}
	}

	if (NO_TECH != kEvent.getPrereqTech())
	{
		if (!GET_TEAM(getTeam()).isHasTech((TechTypes)kEvent.getPrereqTech()))
		{
			return false;
		}
	}

	if (NO_BONUS != kEvent.getBonusGift())
	{
		BonusTypes eBonus = (BonusTypes)kEvent.getBonusGift();
		if (NO_PLAYER == kTriggeredData.m_eOtherPlayer)
		{
			return false;
		}

		if (!canTradeNetworkWith(kTriggeredData.m_eOtherPlayer))
		{
			return false;
		}

		if (GET_PLAYER(kTriggeredData.m_eOtherPlayer).getNumAvailableBonuses(eBonus) > 0)
		{
			return false;
		}

		if (getNumTradeableBonuses(eBonus) <= 1)
		{
			return false;
		}
	}

	if (kEvent.getUnitClass() != NO_UNITCLASS)
	{
		UnitTypes eUnit = (UnitTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(kEvent.getUnitClass());
		if (eUnit == NO_UNIT)
		{
			return false;
		}
	}

	if (kEvent.isCityEffect())
	{
		CvCity* pCity =	getCity(kTriggeredData.m_iCityId);
		if (NULL == pCity || !pCity->canApplyEvent(eEvent, kTriggeredData))
		{
			return false;
		}
	}
	else if (kEvent.isOtherPlayerCityEffect())
	{
		if (NO_PLAYER == kTriggeredData.m_eOtherPlayer)
		{
			return false;
		}

		CvCity* pCity = GET_PLAYER(kTriggeredData.m_eOtherPlayer).getCity(kTriggeredData.m_iOtherPlayerCityId);
		if (NULL == pCity || !pCity->canApplyEvent(eEvent, kTriggeredData))
		{
			return false;
		}
	}

	if (::isPlotEventTrigger(kTriggeredData.m_eTrigger))
	{
		CvPlot* pPlot = GC.getMapINLINE().plotINLINE(kTriggeredData.m_iPlotX, kTriggeredData.m_iPlotY);
		if (NULL != pPlot)
		{
			if (!pPlot->canApplyEvent(eEvent))
			{
				return false;
			}
		}
	}

	CvUnit* pUnit = getUnit(kTriggeredData.m_iUnitId);
	if (NULL != pUnit)
	{
		if (!pUnit->canApplyEvent(eEvent))
		{
			return false;
		}
	}

	if (NO_BONUS != kEvent.getBonusRevealed())
	{
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getBonusInfo((BonusTypes)kEvent.getBonusRevealed()).getTechReveal()))
		{
			return false;
		}

		if (GET_TEAM(getTeam()).isForceRevealedBonus((BonusTypes)kEvent.getBonusRevealed()))
		{
			return false;
		}
	}

	if (kEvent.getConvertOwnCities() > 0)
	{
		bool bFoundValid = false;

		if (NO_RELIGION != kTriggeredData.m_eReligion)
		{
			int iLoop;
			for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				if (!pLoopCity->isHasReligion(kTriggeredData.m_eReligion))
				{
					if (-1 == kEvent.getMaxNumReligions() || pLoopCity->getReligionCount() <= kEvent.getMaxNumReligions())
					{
						bFoundValid = true;
						break;
					}
				}
			}
		}

		if (!bFoundValid)
		{
			return false;
		}
	}

	if (kEvent.getConvertOtherCities() > 0)
	{
		bool bFoundValid = false;

		if (NO_RELIGION != kTriggeredData.m_eReligion)
		{
			if (NO_PLAYER != kTriggeredData.m_eOtherPlayer)
			{
				int iLoop;
				for (CvCity* pLoopCity = GET_PLAYER(kTriggeredData.m_eOtherPlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(kTriggeredData.m_eOtherPlayer).nextCity(&iLoop))
				{
					if (!pLoopCity->isHasReligion(kTriggeredData.m_eReligion))
					{
						if (-1 == kEvent.getMaxNumReligions() || pLoopCity->getReligionCount() <= kEvent.getMaxNumReligions())
						{
							bFoundValid = true;
							break;
						}
					}
				}
			}
		}

		if (!bFoundValid)
		{
			return false;
		}
	}

	if (0 != kEvent.getAttitudeModifier())
	{
		if (NO_PLAYER == kTriggeredData.m_eOtherPlayer)
		{
			return false;
		}

		if (GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam() == getTeam())
		{
			return false;
		}

		if (GET_PLAYER(kTriggeredData.m_eOtherPlayer).isHuman())
		{
			if (0 == kEvent.getOurAttitudeModifier())
			{
				return false;
			}
		}
	}

	if (0 != kEvent.getTheirEnemyAttitudeModifier())
	{
		if (NO_PLAYER == kTriggeredData.m_eOtherPlayer)
		{
			return false;
		}

		TeamTypes eWorstEnemy = GET_TEAM(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()).AI_getWorstEnemy();
		if (NO_TEAM == eWorstEnemy || eWorstEnemy == getTeam())
		{
			return false;
		}

		if (!GET_TEAM(eWorstEnemy).isAlive())
		{
			return false;
		}

		if (eWorstEnemy == getTeam())
		{
			return false;
		}
	}

	if (kEvent.isDeclareWar())
	{
		if (NO_PLAYER == kTriggeredData.m_eOtherPlayer)
		{
			return false;
		}

		if (!GET_TEAM(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()).canDeclareWar(getTeam()) || !GET_TEAM(getTeam()).canDeclareWar(GET_PLAYER(kTriggeredData.m_eOtherPlayer).getTeam()))
		{
			return false;
		}
	}

	if (kEvent.isQuest())
	{
		for (int iTrigger = 0; iTrigger < GC.getNumEventTriggerInfos(); ++iTrigger)
		{
			CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo((EventTriggerTypes)iTrigger);
			if (!kTrigger.isRecurring())
			{
				for (int i = 0; i < kTrigger.getNumPrereqEvents(); ++i)
				{
					if (kTrigger.getPrereqEvent(i) == eEvent)
					{
						if (isTriggerFired((EventTriggerTypes)iTrigger))
						{
							return false;
						}
					}
				}
			}
		}
	}

	if (!CvString(kEvent.getPythonCanDo()).empty())
	{
		PYTHON_ACCESS_LOCK_SCOPE

		long lResult;

		CyArgsList argsList;
		argsList.add(eEvent);
		argsList.add(gDLL->getPythonIFace()->makePythonObject(&kTriggeredData));

		PYTHON_CALL_FUNCTION4(__FUNCTION__, PYRandomEventModule, kEvent.getPythonCanDo(), argsList.makeFunctionArgs(), &lResult);

		if (0 == lResult)
		{
			return false;
		}
	}

	return true;
}


void CvPlayer::applyEvent(EventTypes eEvent, int iEventTriggeredId, bool bUpdateTrigger)
{
	PROFILE_FUNC();

	EventTriggeredData* pTriggeredData = NULL;

	FAssert(eEvent != NO_EVENT);

	//	-1 iEventTriggeredId implies a replay after a reset of modifiers and only modifier effects
	//	should be applied
	bool	adjustModifiersOnly = (iEventTriggeredId == -1);

	if ( !adjustModifiersOnly )
	{
		pTriggeredData = getEventTriggered(iEventTriggeredId);

		if (NULL == pTriggeredData)
		{
			deleteEventTriggered(iEventTriggeredId);
			return;
		}

		if (bUpdateTrigger)
		{
			setTriggerFired(*pTriggeredData, true);
		}

		if (!canDoEvent(eEvent, *pTriggeredData))
		{
			if (bUpdateTrigger)
			{
				deleteEventTriggered(iEventTriggeredId);
			}
			return;
		}

		setEventOccured(eEvent, *pTriggeredData);
	}

	CvEventInfo& kEvent = GC.getEventInfo(eEvent);
	CvCity* pCity =	(pTriggeredData == NULL ? NULL : getCity(pTriggeredData->m_iCityId));
	CvCity* pOtherPlayerCity = NULL;

	if (pTriggeredData != NULL && NO_PLAYER != pTriggeredData->m_eOtherPlayer)
	{
		pOtherPlayerCity = GET_PLAYER(pTriggeredData->m_eOtherPlayer).getCity(pTriggeredData->m_iOtherPlayerCityId);
	}

	if ( !adjustModifiersOnly )
	{
		int iGold = getEventCost(eEvent, pTriggeredData->m_eOtherPlayer, false);
		int iRandomGold = getEventCost(eEvent, pTriggeredData->m_eOtherPlayer, true);
	/************************************************************************************************/
	/* Afforess	                  Start		 07/15/10                                               */
	/*                                                                                              */
	/*                                                                                              */
	/************************************************************************************************/
	/*
		iGold += GC.getGameINLINE().getSorenRandNum(iRandomGold - iGold + 1, "Event random gold");
	*/
		if (iGold > 0)
			iGold += GC.getGameINLINE().getSorenRandNum(iRandomGold - iGold + 1, "Event random gold");
		else if (iGold < 0)
			iGold -= GC.getGameINLINE().getSorenRandNum(abs(iRandomGold - iGold - 1), "Event random gold");
	/************************************************************************************************/
	/* Afforess	                     END                                                            */
	/************************************************************************************************/

		if (iGold != 0)
		{
			changeGold(iGold);

			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer && kEvent.isGoldToPlayer())
			{
				GET_PLAYER(pTriggeredData->m_eOtherPlayer).changeGold(-iGold);
			}
		}

		if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
		{
			if (kEvent.getEspionagePoints() != 0)
			{
				GET_TEAM(getTeam()).changeEspionagePointsAgainstTeam(GET_PLAYER(pTriggeredData->m_eOtherPlayer).getTeam(), kEvent.getEspionagePoints());
			}
		}

		if (0 != kEvent.getTechPercent())
		{
			TechTypes eBestTech = getBestEventTech(eEvent, pTriggeredData->m_eOtherPlayer);

			if (eBestTech != NO_TECH)
			{
				int iBeakers  = GET_TEAM(getTeam()).changeResearchProgressPercent(eBestTech, kEvent.getTechPercent(), getID());

				if (iBeakers > 0)
				{
					for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
					{
						if (GET_PLAYER((PlayerTypes)iI).isAlive())
						{
							if (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam())
							{
								MEMORY_TRACK_EXEMPT();

								CvWString szBuffer = gDLL->getText("TXT_KEY_MISC_PROGRESS_TOWARDS_TECH", iBeakers, GC.getTechInfo(eBestTech).getTextKeyWide());

								AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, NULL, MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_TECH_TEXT"));
							}
						}
					}
				}
			}
		}

		if (kEvent.isGoldenAge())
		{
			changeGoldenAgeTurns(getGoldenAgeLength());
		}

		if (kEvent.isDeclareWar())
		{
			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
	/************************************************************************************************/
	/* BETTER_BTS_AI_MOD                      10/02/09                                jdog5000      */
	/*                                                                                              */
	/* AI logging                                                                                   */
	/************************************************************************************************/
			if( gTeamLogLevel >= 2 )
			{
				logBBAI("    Team %d (%S) declares war on team %d due to event", GET_PLAYER(pTriggeredData->m_eOtherPlayer).getTeam(), GET_PLAYER(pTriggeredData->m_eOtherPlayer).getCivilizationDescription(0), getTeam() );
			}
	/************************************************************************************************/
	/* BETTER_BTS_AI_MOD                       END                                                  */
	/************************************************************************************************/
				GET_TEAM(GET_PLAYER(pTriggeredData->m_eOtherPlayer).getTeam()).declareWar(getTeam(), false, WARPLAN_LIMITED);
			}
		}

		if (NO_BONUS != kEvent.getBonusGift())
		{
			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
				CLinkList<TradeData> ourList;
				CLinkList<TradeData> theirList;
				TradeData kTradeData;
				setTradeItem(&kTradeData, TRADE_RESOURCES, kEvent.getBonusGift());
				ourList.insertAtEnd(kTradeData);
				GC.getGameINLINE().implementDeal(getID(), pTriggeredData->m_eOtherPlayer, &ourList, &theirList);			
			}
		}

		for (int iEvent = 0; iEvent < GC.getNumEventInfos(); ++iEvent)
		{
			if (kEvent.getClearEventChance(iEvent) > 0)
			{
				bool bClear = GC.getGameINLINE().getSorenRandNum(100, "Event Clear") < kEvent.getClearEventChance(iEvent);
				if (bClear)
				{
					if (kEvent.isGlobal())
					{
						for (int j = 0; j < MAX_CIV_PLAYERS; j++)
						{
							GET_PLAYER((PlayerTypes)j).resetEventOccured((EventTypes)iEvent, j != getID());
						}
					}
					else if (kEvent.isTeam())
					{
						for (int j = 0; j < MAX_CIV_PLAYERS; j++)
						{
							if (getTeam() == GET_PLAYER((PlayerTypes)j).getTeam())
							{
								GET_PLAYER((PlayerTypes)j).resetEventOccured((EventTypes)iEvent, j != getID());
							}
						}
					}
					else
					{
						resetEventOccured((EventTypes)iEvent, false);
					}

					if (NULL != pCity && kEvent.isCityEffect())
					{
						pCity->setEventOccured((EventTypes)iEvent, false);
					}
					else if (NULL != pOtherPlayerCity && kEvent.isOtherPlayerCityEffect())
					{
						pOtherPlayerCity->setEventOccured((EventTypes)iEvent, false);
					}
				}
			}
		}

		CvPlot* pPlot = GC.getMapINLINE().plotINLINE(pTriggeredData->m_iPlotX, pTriggeredData->m_iPlotY);
		if (NULL != pPlot)
		{
			if (::isPlotEventTrigger(pTriggeredData->m_eTrigger))
			{
				FAssert(pPlot->canApplyEvent(eEvent));
				pPlot->applyEvent(eEvent);
			}
		}

		CvUnit* pUnit = getUnit(pTriggeredData->m_iUnitId);
		if (NULL != pUnit)
		{
			FAssert(pUnit->canApplyEvent(eEvent));
			pUnit->applyEvent(eEvent);   // might kill the unit
		}
		if (NO_BONUS != kEvent.getBonusRevealed())
		{
			GET_TEAM(getTeam()).setForceRevealedBonus((BonusTypes)kEvent.getBonusRevealed(), true);
		}

		std::vector<CvCity*> apSpreadReligionCities;

		if (kEvent.getConvertOwnCities() > 0)
		{
			if (NO_RELIGION != pTriggeredData->m_eReligion)
			{
				int iLoop;
				for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
				{
					if (!pLoopCity->isHasReligion(pTriggeredData->m_eReligion))
					{
						if (-1 == kEvent.getMaxNumReligions() || pLoopCity->getReligionCount() <= kEvent.getMaxNumReligions())
						{
							apSpreadReligionCities.push_back(pLoopCity);
						}
					}
				}
			}
		}

		while ((int)apSpreadReligionCities.size() > kEvent.getConvertOwnCities())
		{
			int iChosen = GC.getGameINLINE().getSorenRandNum(apSpreadReligionCities.size(), "Even Spread Religion (own)");

			int i = 0;
			for (std::vector<CvCity*>::iterator it = apSpreadReligionCities.begin(); it != apSpreadReligionCities.end(); ++it)
			{
				if (i == iChosen)
				{
					apSpreadReligionCities.erase(it);
					break;
				}
				++i;
			}
		}

		for (std::vector<CvCity*>::iterator it = apSpreadReligionCities.begin(); it != apSpreadReligionCities.end(); ++it)
		{
			(*it)->setHasReligion(pTriggeredData->m_eReligion, true, true, false);
		}

		apSpreadReligionCities.clear();

		if (kEvent.getConvertOtherCities() > 0)
		{
			if (NO_RELIGION != pTriggeredData->m_eReligion)
			{
				if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
				{
					//std::vector<CvCity*> apCities;
					int iLoop;
					for (CvCity* pLoopCity = GET_PLAYER(pTriggeredData->m_eOtherPlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(pTriggeredData->m_eOtherPlayer).nextCity(&iLoop))
					{
						if (!pLoopCity->isHasReligion(pTriggeredData->m_eReligion))
						{
							if (-1 == kEvent.getMaxNumReligions() || pLoopCity->getReligionCount() <= kEvent.getMaxNumReligions())
							{
								apSpreadReligionCities.push_back(pLoopCity);
							}
						}
					}
				}
			}
		}

		while ((int)apSpreadReligionCities.size() > kEvent.getConvertOtherCities())
		{
			int iChosen = GC.getGameINLINE().getSorenRandNum(apSpreadReligionCities.size(), "Even Spread Religion (other)");

			int i = 0;
			for (std::vector<CvCity*>::iterator it = apSpreadReligionCities.begin(); it != apSpreadReligionCities.end(); ++it)
			{
				if (i == iChosen)
				{
					apSpreadReligionCities.erase(it);
					break;
				}
				++i;
			}
		}

		for (std::vector<CvCity*>::iterator it = apSpreadReligionCities.begin(); it != apSpreadReligionCities.end(); ++it)
		{
			(*it)->setHasReligion(pTriggeredData->m_eReligion, true, true, false);
		}

		if (0 != kEvent.getOurAttitudeModifier())
		{
			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
				if (kEvent.getOurAttitudeModifier() > 0)
				{
					AI_changeMemoryCount(pTriggeredData->m_eOtherPlayer, MEMORY_EVENT_GOOD_TO_US, kEvent.getOurAttitudeModifier());
				}
				else
				{
					AI_changeMemoryCount(pTriggeredData->m_eOtherPlayer, MEMORY_EVENT_BAD_TO_US, -kEvent.getOurAttitudeModifier());
				}
			}
		}

		if (0 != kEvent.getAttitudeModifier())
		{
			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
				if (kEvent.getAttitudeModifier() > 0)
				{
					GET_PLAYER(pTriggeredData->m_eOtherPlayer).AI_changeMemoryCount(getID(), MEMORY_EVENT_GOOD_TO_US, kEvent.getAttitudeModifier());
				}
				else
				{
					GET_PLAYER(pTriggeredData->m_eOtherPlayer).AI_changeMemoryCount(getID(), MEMORY_EVENT_BAD_TO_US, -kEvent.getAttitudeModifier());
				}
			}
		}

		if (0 != kEvent.getTheirEnemyAttitudeModifier())
		{
			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
				TeamTypes eWorstEnemy = GET_TEAM(GET_PLAYER(pTriggeredData->m_eOtherPlayer).getTeam()).AI_getWorstEnemy();
				if (NO_TEAM != eWorstEnemy)
				{
					for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
					{
						CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);
						if (kLoopPlayer.isAlive() && kLoopPlayer.getTeam() == eWorstEnemy)
						{
							if (kEvent.getTheirEnemyAttitudeModifier() > 0)
							{
								kLoopPlayer.AI_changeMemoryCount(getID(), MEMORY_EVENT_GOOD_TO_US, kEvent.getTheirEnemyAttitudeModifier());
								AI_changeMemoryCount((PlayerTypes)iPlayer, MEMORY_EVENT_GOOD_TO_US, kEvent.getTheirEnemyAttitudeModifier());
							}
							else
							{
								kLoopPlayer.AI_changeMemoryCount(getID(), MEMORY_EVENT_BAD_TO_US, -kEvent.getTheirEnemyAttitudeModifier());
								AI_changeMemoryCount((PlayerTypes)iPlayer, MEMORY_EVENT_BAD_TO_US, -kEvent.getTheirEnemyAttitudeModifier());
							}
						}
					}
				}
			}
		}

		if (NULL != pCity && kEvent.isCityEffect())
		{
			pCity->applyEvent(eEvent, pTriggeredData);
		}
		else if (NULL != pOtherPlayerCity && kEvent.isOtherPlayerCityEffect())
		{
			pOtherPlayerCity->applyEvent(eEvent, pTriggeredData);
		}

		if (!CvString(kEvent.getPythonCallback()).empty())
		{
			PYTHON_ACCESS_LOCK_SCOPE

			long lResult;

			CyArgsList argsList;
			argsList.add(eEvent);
			argsList.add(gDLL->getPythonIFace()->makePythonObject(pTriggeredData));

			PYTHON_CALL_FUNCTION4(__FUNCTION__, PYRandomEventModule, kEvent.getPythonCallback(), argsList.makeFunctionArgs(), &lResult);
		}

		if (kEvent.getNumWorldNews() > 0)
		{
			int iText = GC.getGameINLINE().getSorenRandNum(kEvent.getNumWorldNews(), "Event World News choice");

			CvWString szGlobalText;

			TeamTypes eTheirWorstEnemy = NO_TEAM;
			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
				eTheirWorstEnemy = GET_TEAM(GET_PLAYER(pTriggeredData->m_eOtherPlayer).getTeam()).AI_getWorstEnemy();
			}

			szGlobalText = gDLL->getText(kEvent.getWorldNews(iText).GetCString(),
				getCivilizationAdjectiveKey(),
				NULL != pCity ? pCity->getNameKey() : L"", 
				pTriggeredData->m_eOtherPlayer != NO_PLAYER ? GET_PLAYER(pTriggeredData->m_eOtherPlayer).getCivilizationAdjectiveKey() : L"", 
				NULL != pOtherPlayerCity ? pOtherPlayerCity->getNameKey() : L"",
				NO_RELIGION != pTriggeredData->m_eReligion ? GC.getReligionInfo(pTriggeredData->m_eReligion).getAdjectiveKey() : L"",
				NO_TEAM != eTheirWorstEnemy ? GET_TEAM(eTheirWorstEnemy).getName().GetCString() : L"",
				NO_CORPORATION != pTriggeredData->m_eCorporation ? GC.getCorporationInfo(pTriggeredData->m_eCorporation).getTextKeyWide() : L""
				);

			for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
			{
				CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);

				if (kLoopPlayer.isAlive())
				{
					if (GET_TEAM(kLoopPlayer.getTeam()).isHasMet(getTeam()) && (NO_PLAYER == pTriggeredData->m_eOtherPlayer || GET_TEAM(GET_PLAYER(pTriggeredData->m_eOtherPlayer).getTeam()).isHasMet(getTeam())))
					{
						bool bShowPlot = GC.getEventTriggerInfo(pTriggeredData->m_eTrigger).isShowPlot();

						if (bShowPlot)
						{
							if (kLoopPlayer.getTeam() != getTeam())
							{
								if (NULL == pPlot || !pPlot->isRevealed(kLoopPlayer.getTeam(), false))
								{
									bShowPlot = false;
								}
							}
						}

						MEMORY_TRACK_EXEMPT();

						if (bShowPlot)
						{
							AddDLLMessage((PlayerTypes)iPlayer, false, GC.getEVENT_MESSAGE_TIME(), szGlobalText, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), pTriggeredData->m_iPlotX, pTriggeredData->m_iPlotY, true, true);
						}
						else
						{
							AddDLLMessage((PlayerTypes)iPlayer, false, GC.getEVENT_MESSAGE_TIME(), szGlobalText, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT);
						}
					}
				}
			}

	/************************************************************************************************/
	/* REVOLUTION_MOD                         02/01/08                                jdog5000      */
	/*                                                                                              */
	/* Silence replay messages for events ... too crowded by late game                              */
	/************************************************************************************************/
	/*
			GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szGlobalText, pTriggeredData->m_iPlotX, pTriggeredData->m_iPlotY, (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));
	*/
	/************************************************************************************************/
	/* REVOLUTION_MOD                          END                                                  */
	/************************************************************************************************/
		}

		if (!CvWString(kEvent.getLocalInfoTextKey()).empty())
		{
			CvWString szLocalText;

			TeamTypes eTheirWorstEnemy = NO_TEAM;
			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
				eTheirWorstEnemy = GET_TEAM(GET_PLAYER(pTriggeredData->m_eOtherPlayer).getTeam()).AI_getWorstEnemy();
			}

			szLocalText = gDLL->getText(kEvent.getLocalInfoTextKey(),
			getCivilizationAdjectiveKey(),
			NULL != pCity ? pCity->getNameKey() : L"", 
			pTriggeredData->m_eOtherPlayer != NO_PLAYER ? GET_PLAYER(pTriggeredData->m_eOtherPlayer).getCivilizationAdjectiveKey() : L"", 
			NULL != pOtherPlayerCity ? pOtherPlayerCity->getNameKey() : L"",
			NO_RELIGION != pTriggeredData->m_eReligion ? GC.getReligionInfo(pTriggeredData->m_eReligion).getAdjectiveKey() : L"",
			NO_TEAM != eTheirWorstEnemy ? GET_TEAM(eTheirWorstEnemy).getName().GetCString() : L"",
			NO_CORPORATION != pTriggeredData->m_eCorporation ? GC.getCorporationInfo(pTriggeredData->m_eCorporation).getTextKeyWide() : L""
			);

			MEMORY_TRACK_EXEMPT();

			if (GC.getEventTriggerInfo(pTriggeredData->m_eTrigger).isShowPlot())
			{
				AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), szLocalText, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), pTriggeredData->m_iPlotX, pTriggeredData->m_iPlotY, true, true);
			}
			else
			{
				AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), szLocalText, "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"));
			}
		}

		if (!CvWString(kEvent.getOtherPlayerPopup()).empty())
		{
			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
				CvWString szText = gDLL->getText(kEvent.getOtherPlayerPopup(),
					getCivilizationAdjectiveKey(),
					NULL != pCity ? pCity->getNameKey() : L"", 
					pTriggeredData->m_eOtherPlayer != NO_PLAYER ? GET_PLAYER(pTriggeredData->m_eOtherPlayer).getCivilizationAdjectiveKey() : L"", 
					NULL != pOtherPlayerCity ? pOtherPlayerCity->getNameKey() : L"",
					NO_RELIGION != pTriggeredData->m_eReligion ? GC.getReligionInfo(pTriggeredData->m_eReligion).getAdjectiveKey() : L"",
					NO_CORPORATION != pTriggeredData->m_eCorporation ? GC.getCorporationInfo(pTriggeredData->m_eCorporation).getTextKeyWide() : L""
					);

				CvPopupInfo* pInfo = new CvPopupInfo();

				if (NULL != pInfo)
				{
					pInfo->setText(szText);

					GET_PLAYER(pTriggeredData->m_eOtherPlayer).addPopup(pInfo);
				}
			}
		}

		bool bDeleteTrigger = bUpdateTrigger;

		for (int iEvent = 0; iEvent < GC.getNumEventInfos(); ++iEvent)
		{
			if (0 == kEvent.getAdditionalEventTime(iEvent))
			{
				if (kEvent.getAdditionalEventChance(iEvent) > 0)
				{
					if (canDoEvent((EventTypes)iEvent, *pTriggeredData))
					{
						if (GC.getGameINLINE().getSorenRandNum(100, "Additional Event") < kEvent.getAdditionalEventChance(iEvent))
						{
							applyEvent((EventTypes)iEvent, iEventTriggeredId, false);
						}
					}
				}
			}
			else
			{
				bool bSetTimer = true;
				if (kEvent.getAdditionalEventChance(iEvent) > 0)
				{
					if (GC.getGameINLINE().getSorenRandNum(100, "Additional Event 2") >= kEvent.getAdditionalEventChance(iEvent))
					{
						bSetTimer = false;
					}
				}

				if (bSetTimer)
				{
					EventTriggeredData kTriggered = *pTriggeredData;
					kTriggered.m_iTurn = (GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent() * kEvent.getAdditionalEventTime((EventTypes)iEvent)) / 100 + GC.getGameINLINE().getGameTurn();

					const EventTriggeredData* pExistingTriggered = getEventCountdown((EventTypes)iEvent);

					if (NULL != pExistingTriggered)
					{
						kTriggered.m_iTurn = std::min(kTriggered.m_iTurn, pExistingTriggered->m_iTurn); 
					}

					setEventCountdown((EventTypes)iEvent, kTriggered);
					bDeleteTrigger = false;
				}
			}
		}

		if (bDeleteTrigger)
		{
			deleteEventTriggered(iEventTriggeredId);
		}
	}

	if (!kEvent.isCityEffect() && !kEvent.isOtherPlayerCityEffect())
	{
		for (int i = 0; i < NUM_COMMERCE_TYPES; ++i)
		{
			if (kEvent.getCommerceModifier(i) != 0)
			{
				changeCommerceRateModifier((CommerceTypes)i, kEvent.getCommerceModifier(i));
			}
			if (kEvent.getNumBuildingCommerceModifiers() > 0)
			{
				for( int j = 0; j < GC.getNumBuildingInfos(); j++)
				{
					BuildingClassTypes eBuildingClass = (BuildingClassTypes)GC.getBuildingInfo((BuildingTypes)j).getBuildingClassType();

					if ( kEvent.getBuildingCommerceModifier(eBuildingClass, i) != 0 )
					{
						changeBuildingCommerceModifier((BuildingTypes)j, (CommerceTypes)i, kEvent.getBuildingCommerceModifier(eBuildingClass, i));
					}
				}
			}
		}
		for (int i = 0; i < NUM_YIELD_TYPES; ++i)
		{
			if (kEvent.getYieldModifier(i) != 0)
			{
				changeYieldRateModifier((YieldTypes)i, kEvent.getYieldModifier(i));
			}
		}
	}

	if (0 != kEvent.getInflationModifier())
	{
		m_iInflationModifier += kEvent.getInflationModifier();
	}

	if (0 != kEvent.getSpaceProductionModifier())
	{
		changeSpaceProductionModifier(kEvent.getSpaceProductionModifier());
	}

	if (0 != kEvent.getFreeUnitSupport())
	{
		changeBaseFreeUnits(kEvent.getFreeUnitSupport());
	}

	CvProperties* pProp = kEvent.getPropertiesAllCities();
	if (!pProp->isEmpty())
	{
		addPropertiesAllCities(pProp);
	}

	if (!kEvent.isCityEffect() && !kEvent.isOtherPlayerCityEffect())
	{
		if (kEvent.getHappy() != 0)
		{
			changeExtraHappiness(kEvent.getHappy());
		}

		if (kEvent.getHealth() != 0)
		{
			changeExtraHealth(kEvent.getHealth());
		}

		if (kEvent.getNumBuildingYieldChanges() > 0)
		{
			int iLoop;
			for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
			{
				for (int iYield = 0; iYield < NUM_YIELD_TYPES; ++iYield)
				{
					for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
					{
						pLoopCity->changeBuildingYieldChange((BuildingClassTypes)iBuildingClass, (YieldTypes)iYield, kEvent.getBuildingYieldChange(iBuildingClass, iYield));
					}					
				}
			}
		}

		if (kEvent.getNumBuildingCommerceChanges() > 0)
		{
			int iLoop;
			for (int iBuildingClass = 0; iBuildingClass < GC.getNumBuildingClassInfos(); ++iBuildingClass)
			{
				for (int iCommerce = 0; iCommerce < NUM_COMMERCE_TYPES; ++iCommerce)
				{
					for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
					{
						pLoopCity->changeBuildingCommerceChange((BuildingClassTypes)iBuildingClass, (CommerceTypes)iCommerce, kEvent.getBuildingCommerceChange(iBuildingClass, iCommerce));
					}					
				}
			}
		}

		if (kEvent.getNumBuildingHappyChanges() > 0)
		{
			for (int i = 0; i < GC.getNumBuildingClassInfos(); ++i)
			{
				if (0 != kEvent.getBuildingHappyChange(i))
				{
					BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(i);
					if (NO_BUILDING != eBuilding)
					{
						changeExtraBuildingHappiness(eBuilding, kEvent.getBuildingHappyChange(i));
					}
				}
			}
		}

		if (kEvent.getNumBuildingHealthChanges() > 0)
		{
			for (int i = 0; i < GC.getNumBuildingClassInfos(); ++i)
			{
				if (0 != kEvent.getBuildingHealthChange(i))
				{
					BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(i);
					if (NO_BUILDING != eBuilding)
					{
						changeExtraBuildingHealth(eBuilding, kEvent.getBuildingHealthChange(i));
					}
				}
			}
		}

		if (kEvent.getHurryAnger() != 0 && !adjustModifiersOnly)
		{
			int iLoop;

			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->changeHurryAngerTimer(kEvent.getHurryAnger() * pLoopCity->flatHurryAngerLength());
			}
		}

		if (kEvent.getHappyTurns() > 0 && !adjustModifiersOnly)
		{
			int iLoop;

			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->changeHappinessTimer(kEvent.getHappyTurns());
			}
		}

		if (kEvent.getMaxPillage() > 0 && !adjustModifiersOnly)
		{
			FAssert(kEvent.getMaxPillage() >= kEvent.getMinPillage());
			int iNumPillage = kEvent.getMinPillage() + GC.getGameINLINE().getSorenRandNum(kEvent.getMaxPillage() - kEvent.getMinPillage(), "Pick number of event pillaged plots");

			int iNumPillaged = 0;
			for (int i = 0; i < iNumPillage; ++i)
			{
				int iRandOffset = GC.getGameINLINE().getSorenRandNum(GC.getMapINLINE().numPlotsINLINE(), "Pick event pillage plot (any city)");
				for (int j = 0; j < GC.getMapINLINE().numPlotsINLINE(); ++j)
				{
					int iPlot = (j + iRandOffset) % GC.getMapINLINE().numPlotsINLINE();
					CvPlot* pPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);
					if (NULL != pPlot && pPlot->getOwnerINLINE() == getID() && pPlot->isCity())
					{
						if (NO_IMPROVEMENT != pPlot->getImprovementType() && !GC.getImprovementInfo(pPlot->getImprovementType()).isPermanent())
						{
							MEMORY_TRACK_EXEMPT();

							CvWString szBuffer = gDLL->getText("TXT_KEY_EVENT_CITY_IMPROVEMENT_DESTROYED", GC.getImprovementInfo(pPlot->getImprovementType()).getTextKeyWide());
							AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGED", MESSAGE_TYPE_INFO, GC.getImprovementInfo(pPlot->getImprovementType()).getButton(), (ColorTypes)GC.getInfoTypeForString("COLOR_RED"), pPlot->getX_INLINE(), pPlot->getY_INLINE(), true, true);
							pPlot->setImprovementType(NO_IMPROVEMENT);
							++iNumPillaged;
							break;
						}
					}
				}
			}

			if (NO_PLAYER != pTriggeredData->m_eOtherPlayer)
			{
				MEMORY_TRACK_EXEMPT();

				CvWString szBuffer = gDLL->getText("TXT_KEY_EVENT_NUM_CITY_IMPROVEMENTS_DESTROYED", iNumPillaged, getCivilizationAdjectiveKey());
				AddDLLMessage(pTriggeredData->m_eOtherPlayer, false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_PILLAGED", MESSAGE_TYPE_INFO);
			}
		}

		if (kEvent.getFood() != 0 && !adjustModifiersOnly)
		{
			int iLoop;

			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->changeFood(kEvent.getFood());
			}
		}

		if (kEvent.getFoodPercent() != 0 && !adjustModifiersOnly)
		{
			int iLoop;

			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->changeFood((pLoopCity->getFood() * kEvent.getFoodPercent()) / 100);
			}
		}

		if (kEvent.getPopulationChange() != 0 && !adjustModifiersOnly)
		{
			int iLoop;

			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				if (pLoopCity->getPopulation() + kEvent.getPopulationChange() > 0)
				{
					pLoopCity->changePopulation(kEvent.getPopulationChange());
				}
			}
		}

		if (kEvent.getCulture() != 0 && !adjustModifiersOnly)
		{
			int iLoop;

			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				if (pLoopCity->getCultureTimes100(pLoopCity->getOwnerINLINE()) + 100 * kEvent.getCulture() > 0)
				{
					pLoopCity->changeCulture(pLoopCity->getOwnerINLINE(), kEvent.getCulture(), true, true);
				}
			}
		}
		
/************************************************************************************************/
/* Afforess	                  Start		 01/20/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		if (kEvent.getRevolutionIndexChange() != 0 && !adjustModifiersOnly)
		{
			int iLoop;
			for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
			{
				if (kEvent.getRevolutionIndexChange() > 0)
				{
					pLoopCity->changeLocalRevIndex(kEvent.getRevolutionIndexChange());
				}
				else if (kEvent.getRevolutionIndexChange() < 0)
				{
					pLoopCity->changeLocalRevIndex(std::max(-(pLoopCity->getLocalRevIndex()), kEvent.getRevolutionIndexChange()));
				}	
			}
		}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/


		if (kEvent.getUnitClass() != NO_UNITCLASS && !adjustModifiersOnly)
		{
			UnitTypes eUnit = (UnitTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(kEvent.getUnitClass());
			if (eUnit != NO_UNIT)
			{
				CvCity* pUnitCity = pCity;

				if (NULL == pUnitCity)
				{
					pUnitCity = getCapitalCity();
				}

				if (NULL != pUnitCity)
				{
					for (int i = 0; i < kEvent.getNumUnits(); ++i)
					{
						initUnit(eUnit, pUnitCity->getX_INLINE(), pUnitCity->getY_INLINE(), NO_UNITAI, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
					}
				}
			}
		}
	}

	for (int i = 0; i < GC.getNumUnitCombatInfos(); ++i)
	{
		if (NO_PROMOTION != kEvent.getUnitCombatPromotion(i))
		{
			int iLoop;
			for (CvUnit* pLoopUnit = firstUnit(&iLoop); NULL != pLoopUnit; pLoopUnit = nextUnit(&iLoop))
			{
				//TB SubCombat Mod Begin
				if (pLoopUnit->hasCombatType((UnitCombatTypes)i))
				{
					pLoopUnit->setHasPromotion((PromotionTypes)kEvent.getUnitCombatPromotion(i), true);
				}
				//TB SubCombat Mod End
			}
			setFreePromotion((UnitCombatTypes)i, (PromotionTypes)kEvent.getUnitCombatPromotion(i), true);
		}
	}

	for (int i = 0; i < GC.getNumUnitClassInfos(); ++i)
	{
		if (NO_PROMOTION != kEvent.getUnitClassPromotion(i))
		{
			int iLoop;
			for (CvUnit* pLoopUnit = firstUnit(&iLoop); NULL != pLoopUnit; pLoopUnit = nextUnit(&iLoop))
			{
				if (pLoopUnit->getUnitClassType() == i)
				{
					pLoopUnit->setHasPromotion((PromotionTypes)kEvent.getUnitClassPromotion(i), true);
				}
			}

			setFreePromotion((UnitClassTypes)i, (PromotionTypes)kEvent.getUnitClassPromotion(i), true);
		}
	}

}

bool CvPlayer::isValidEventTech(TechTypes eTech, EventTypes eEvent, PlayerTypes eOtherPlayer) const
{
	CvEventInfo& kEvent = GC.getEventInfo(eEvent);

	if (0 == kEvent.getTechPercent() && 0 == kEvent.getTechCostPercent())
	{
		return false;
	}

	if (kEvent.getTechPercent() < 0 && GET_TEAM(getTeam()).getResearchProgress(eTech) <= 0)
	{
		return false;
	}

	if (!canResearch(eTech))
	{
		return false;
	}

	if (getResearchTurnsLeft(eTech, true) < kEvent.getTechMinTurnsLeft())
	{
		return false;
	}

	if (NO_PLAYER != eOtherPlayer && !GET_TEAM(GET_PLAYER(eOtherPlayer).getTeam()).isHasTech(eTech))
	{
		return false;
	}

	return true;
}


TechTypes CvPlayer::getBestEventTech(EventTypes eEvent, PlayerTypes eOtherPlayer) const
{
	TechTypes eBestTech = NO_TECH;
	CvEventInfo& kEvent = GC.getEventInfo(eEvent);

	if (0 == kEvent.getTechPercent() && 0 == kEvent.getTechCostPercent())
	{
		return NO_TECH;
	}

	if (NO_TECH != kEvent.getTech())
	{
		eBestTech = (TechTypes)kEvent.getTech();
	}
	else
	{
		bool bFoundFlavor = false;
		for (int i = 0; i < GC.getNumFlavorTypes(); ++i)
		{
			if (0 != kEvent.getTechFlavorValue(i))
			{
				bFoundFlavor = true;
				break;
			}
		}

		if (!bFoundFlavor)
		{
			eBestTech = getCurrentResearch();
		}
	}

	if (NO_TECH != eBestTech)
	{
		if (!isValidEventTech(eBestTech, eEvent, eOtherPlayer))
		{
			eBestTech = NO_TECH;
		}
	}
	else
	{
		int iBestValue = 0;
		for (int iTech = 0; iTech < GC.getNumTechInfos(); ++iTech)
		{
			if (isValidEventTech((TechTypes)iTech, eEvent, eOtherPlayer))
			{
				int iValue = 0;
				for (int i = 0; i < GC.getNumFlavorTypes(); ++i)
				{
					iValue += kEvent.getTechFlavorValue(i) * GC.getTechInfo((TechTypes)iTech).getFlavorValue(i);
				}

				if (iValue > iBestValue)
				{
					eBestTech = (TechTypes)iTech;
					iBestValue = iValue;
				}
			}
		}
	}

	return eBestTech;
}

int CvPlayer::getEventCost(EventTypes eEvent, PlayerTypes eOtherPlayer, bool bRandom) const
{
	CvEventInfo& kEvent = GC.getEventInfo(eEvent);

	int iGold = kEvent.getGold();
	if (bRandom)
	{
		iGold += kEvent.getRandomGold();
	}
	
	iGold *= std::max(0, calculateInflationRate() + 100);
	iGold /= 100;

	TechTypes eBestTech = getBestEventTech(eEvent, eOtherPlayer);

	if (NO_TECH != eBestTech)
	{
		iGold -= (kEvent.getTechCostPercent() * GET_TEAM(getTeam()).getResearchCost(eBestTech)) / 100;
	}

	return iGold;
}


void CvPlayer::doEvents()
{
	if (GC.getGameINLINE().isOption(GAMEOPTION_NO_EVENTS))
	{
		return;
	}

/************************************************************************************************/
/* REVOLUTION_MOD                         03/02/08                                jdog5000      */
/*                                                                                              */
/* For minor civs                                                                               */
/************************************************************************************************/
/* original code
	if (isBarbarian() || isMinorCiv())
*/
	// Allow events for minor civs
	if (isBarbarian())
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
	{
		return;
	}

	CvEventMap::iterator it = m_mapEventsOccured.begin();
	while (it != m_mapEventsOccured.end())
	{
		if (checkExpireEvent(it->first, it->second))
		{
			expireEvent(it->first, it->second, true);
		}

		++it;
	}

	bool bNewEventEligible = true;
	if (GC.getGameINLINE().getElapsedGameTurns() < GC.getDefineINT("FIRST_EVENT_DELAY_TURNS"))
	{
		bNewEventEligible = false;
	}

	if (bNewEventEligible)
	{
		if (GC.getGameINLINE().getSorenRandNum(GC.getDefineINT("EVENT_PROBABILITY_ROLL_SIDES"), "Global event check") >= GC.getEraInfo(getCurrentEra()).getEventChancePerTurn())
		{
			bNewEventEligible = false;
		}
	}

	std::vector< std::pair<EventTriggeredData*, int> > aePossibleEventTriggerWeights;
	int iTotalWeight = 0;
	for (int i = 0; i < GC.getNumEventTriggerInfos(); ++i)
	{
		int iWeight = getEventTriggerWeight((EventTriggerTypes)i);
		if (iWeight == -1)
		{
			trigger((EventTriggerTypes)i);
		}
		else if (iWeight > 0 && bNewEventEligible)
		{
			EventTriggeredData* pTriggerData = initTriggeredData((EventTriggerTypes)i);
			if (NULL != pTriggerData)
			{
				iTotalWeight += iWeight;
				aePossibleEventTriggerWeights.push_back(std::make_pair(pTriggerData, iTotalWeight));
			}
		}
	}

	if (iTotalWeight > 0)
	{
		bool bFired = false;
		int iValue = GC.getGameINLINE().getSorenRandNum(iTotalWeight, "Event trigger");
		for (std::vector< std::pair<EventTriggeredData*, int> >::iterator it = aePossibleEventTriggerWeights.begin(); it != aePossibleEventTriggerWeights.end(); ++it)
		{
			EventTriggeredData* pTriggerData = (*it).first;
			if (NULL != pTriggerData)
			{
				if (iValue < (*it).second && !bFired)
				{
					trigger(*pTriggerData);
					bFired = true;
				}
				else
				{
					deleteEventTriggered(pTriggerData->getID());
				}
			}
		}
	}

	std::vector<int> aCleanup;
	for (int i = 0; i < GC.getNumEventInfos(); ++i)
	{
		const EventTriggeredData* pTriggeredData = getEventCountdown((EventTypes)i);
		if (NULL != pTriggeredData)
		{
			if (GC.getGameINLINE().getGameTurn() >= pTriggeredData->m_iTurn)
			{
				applyEvent((EventTypes)i, pTriggeredData->m_iId);
				resetEventCountdown((EventTypes)i);
				aCleanup.push_back(pTriggeredData->m_iId);
			}
		}
	}

	for (std::vector<int>::iterator it = aCleanup.begin(); it != aCleanup.end(); ++it)
	{
		bool bDelete = true;

		for (int i = 0; i < GC.getNumEventInfos(); ++i)
		{
			const EventTriggeredData* pTriggeredData = getEventCountdown((EventTypes)i);
			if (NULL != pTriggeredData)
			{
				if (pTriggeredData->m_iId == *it)
				{
					bDelete = false;
					break;
				}
			}
		}

		if (bDelete)
		{
			deleteEventTriggered(*it);
		}
	}
}


void CvPlayer::expireEvent(EventTypes eEvent, EventTriggeredData& kTriggeredData, bool bFail)
{
	FAssert(getEventOccured(eEvent) == &kTriggeredData);
	FAssert(GC.getEventInfo(eEvent).isQuest() || GC.getGameINLINE().getGameTurn() - kTriggeredData.m_iTurn <= 4);

	if (GC.getEventInfo(eEvent).isQuest())
	{
		CvMessageQueue::iterator it;
		for (it = m_listGameMessages.begin(); it != m_listGameMessages.end(); ++it)
		{
			CvTalkingHeadMessage& message = *it;

			// the trigger ID is stored in the otherwise unused length field
			if (message.getLength() == kTriggeredData.getID()) 
			{
				m_listGameMessages.erase(it);
				gDLL->getInterfaceIFace()->dirtyTurnLog(getID());
				break;
			}
		}

		if (bFail)
		{
			MEMORY_TRACK_EXEMPT();

			AddDLLMessage(getID(), false, GC.getEVENT_MESSAGE_TIME(), gDLL->getText(GC.getEventInfo(eEvent).getQuestFailTextKey()), "AS2D_CIVIC_ADOPT", MESSAGE_TYPE_MINOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_RED"));
		}
	}

	kTriggeredData.m_bExpired = true;
}

bool CvPlayer::checkExpireEvent(EventTypes eEvent, const EventTriggeredData& kTriggeredData) const
{
	if ( !kTriggeredData.m_bExpired )
	{
		CvEventInfo& kEvent = GC.getEventInfo(eEvent);

		if (!CvString(kEvent.getPythonExpireCheck()).empty())
		{
			PYTHON_ACCESS_LOCK_SCOPE

			long lResult;

			CyArgsList argsList;
			argsList.add(eEvent);
			argsList.add(gDLL->getPythonIFace()->makePythonObject(&kTriggeredData));

			PYTHON_CALL_FUNCTION4(__FUNCTION__, PYRandomEventModule, kEvent.getPythonExpireCheck(), argsList.makeFunctionArgs(), &lResult);

			if (0 != lResult)
			{
				return true;
			}
		}

		if (!kEvent.isQuest())
		{
			if (GC.getGameINLINE().getGameTurn() - kTriggeredData.m_iTurn > 2)
			{
				return true;
			}

			return false;
		}

		CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(kTriggeredData.m_eTrigger);

		FAssert(kTriggeredData.m_ePlayer != NO_PLAYER);

		CvPlayer& kPlayer = GET_PLAYER(kTriggeredData.m_ePlayer);

		if (kTrigger.isStateReligion() & kTrigger.isPickReligion())
		{
			if (kPlayer.getStateReligion() != kTriggeredData.m_eReligion)
			{
				return true;
			}
		}

		if (NO_CIVIC != kTrigger.getCivic())
		{
			if (!kPlayer.isCivic((CivicTypes)kTrigger.getCivic()))
			{
				return true;
			}
		}

		if (kTriggeredData.m_iCityId != -1)
		{
			if (NULL == kPlayer.getCity(kTriggeredData.m_iCityId))
			{
				return true;
			}
		}

		if (kTriggeredData.m_iUnitId != -1)
		{
			if (NULL == kPlayer.getUnit(kTriggeredData.m_iUnitId))
			{
				return true;
			}
		}

		if (NO_PLAYER != kTriggeredData.m_eOtherPlayer)
		{
			if (!GET_PLAYER(kTriggeredData.m_eOtherPlayer).isAlive())
			{
				return true;
			}

			if (kTriggeredData.m_iOtherPlayerCityId != -1)
			{
				if (NULL == GET_PLAYER(kTriggeredData.m_eOtherPlayer).getCity(kTriggeredData.m_iOtherPlayerCityId))
				{
					return true;
				}
			}
		}

		if (kTrigger.getNumObsoleteTechs() > 0)
		{
			for (int iI = 0; iI < kTrigger.getNumObsoleteTechs(); iI++)
			{
				if (GET_TEAM(getTeam()).isHasTech((TechTypes)(kTrigger.getObsoleteTech(iI))))
				{
					return true;
				}
			}
		}
	}

	return false;
}


void CvPlayer::trigger(EventTriggerTypes eTrigger)
{
	initTriggeredData(eTrigger, true);
}

void CvPlayer::trigger(const EventTriggeredData& kData)
{
	if (isHuman())
	{
		CvPopupInfo* pInfo = new CvPopupInfo(BUTTONPOPUP_EVENT, kData.getID());
		addPopup(pInfo);
	}
	else
	{
		EventTypes eEvent = AI_chooseEvent(kData.getID());
		if (NO_EVENT != eEvent)
		{
			applyEvent(eEvent, kData.getID());
		}
	}
}

bool CvPlayer::canTrigger(EventTriggerTypes eTrigger, PlayerTypes ePlayer, ReligionTypes eReligion) const
{
	if (!isAlive())
	{
		return false;
	}

	if (getID() == ePlayer)
	{
		return false;
	}

	CvPlayer& kPlayer = GET_PLAYER(ePlayer);
	CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(eTrigger);

	if (getTeam() == kPlayer.getTeam())
	{
		return false;
	}

	if (!kTrigger.isPickPlayer())
	{
		return false;
	}

	if (!GET_TEAM(getTeam()).isHasMet(kPlayer.getTeam()))
	{
		return false;
	}

	if (isHuman() && kTrigger.isOtherPlayerAI())
	{
		return false;
	}

	if (GET_TEAM(getTeam()).isAtWar(kPlayer.getTeam()) != kTrigger.isOtherPlayerWar())
	{
		return false;
	}

	if (NO_TECH != kTrigger.getOtherPlayerHasTech())
	{
		if (!GET_TEAM(getTeam()).isHasTech((TechTypes)kTrigger.getOtherPlayerHasTech()))
		{
			return false;
		}
	}

	if (kTrigger.getOtherPlayerShareBorders() > 0)
	{
		int iCount = 0;

		for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); ++iI)
		{
			CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

			if (!pLoopPlot->isWater())
			{
				if ((pLoopPlot->getOwnerINLINE() == getID()) && pLoopPlot->isAdjacentPlayer(ePlayer, true))
				{
					++iCount;
				}
			}
		}

		if (iCount < kTrigger.getOtherPlayerShareBorders())
		{
			return false;
		}
	}

	if (NO_RELIGION != eReligion)
	{
		bool bHasReligion = kTrigger.isStateReligion() ? (getStateReligion() == eReligion) : (getHasReligionCount(eReligion) > 0);

		if (kTrigger.isOtherPlayerHasReligion())
		{
			if (!bHasReligion)
			{
				return false;
			}
		}

		if (kTrigger.isOtherPlayerHasOtherReligion())
		{
			if (bHasReligion)
			{
				return false;
			}

			if (kTrigger.isStateReligion() && getStateReligion() == NO_RELIGION)
			{
				return false;
			}

		}
	}

	return true;
}

CvCity* CvPlayer::pickTriggerCity(EventTriggerTypes eTrigger) const
{
	CvCity* pCity = NULL;
	std::vector<CvCity*> apCities;
	int iLoop;
	int iBestValue = MIN_INT;
	for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		int iValue = pLoopCity->getTriggerValue(eTrigger);

		if (iValue >= iBestValue && iValue != MIN_INT)
		{
			if (iValue > iBestValue)
			{
				apCities.clear();
				iBestValue = iValue;
			}

			apCities.push_back(pLoopCity);
		}
	}

	if (!apCities.empty())
	{
		int iChosen = GC.getGameINLINE().getSorenRandNum(apCities.size(), "Event pick city");
		pCity = apCities[iChosen];
	}

	return pCity;
}

CvUnit* CvPlayer::pickTriggerUnit(EventTriggerTypes eTrigger, CvPlot* pPlot, bool bPickPlot) const
{
	CvUnit* pUnit = NULL;
	std::vector<CvUnit*> apUnits;
	int iLoop;
	int iBestValue = MIN_INT;
	for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		int iValue = pLoopUnit->getTriggerValue(eTrigger, pPlot, bPickPlot);

		if (iValue >= iBestValue && iValue != MIN_INT)
		{
			if (iValue > iBestValue)
			{
				apUnits.clear();
				iBestValue = iValue;
			}
			apUnits.push_back(pLoopUnit);
		}
	}

	if (!apUnits.empty())
	{
		int iChosen = GC.getGameINLINE().getSorenRandNum(apUnits.size(), "Event pick unit");
		pUnit = apUnits[iChosen];
	}

	return pUnit;
}

bool CvPlayer::isEventTriggerPossible(EventTriggerTypes eTrigger, bool bIgnoreActive) const
{
	CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(eTrigger);
	if (NO_HANDICAP != kTrigger.getMinDifficulty())
	{
		if (GC.getGameINLINE().getHandicapType() < kTrigger.getMinDifficulty())
		{
			return false;
		}
	}

	if (kTrigger.isSinglePlayer() && GC.getGameINLINE().isGameMultiPlayer())
	{
		return false;
	}

	if (!bIgnoreActive && !GC.getGameINLINE().isEventActive(eTrigger))
	{
		return false;
	}

	if (kTrigger.getNumObsoleteTechs() > 0)
	{
		for (int iI = 0; iI < kTrigger.getNumObsoleteTechs(); iI++)
		{
			if (GET_TEAM(getTeam()).isHasTech((TechTypes)(kTrigger.getObsoleteTech(iI))))
			{
				return false;
			}
		}
	}

	if (!kTrigger.isRecurring())
	{
		if (isTriggerFired(eTrigger))
		{
			return false;
		}
	}

	if (kTrigger.getNumPrereqOrTechs() > 0)
	{
		bool bFoundValid = false;

		for (int iI = 0; iI < kTrigger.getNumPrereqOrTechs(); iI++)
		{
			if (GET_TEAM(getTeam()).isHasTech((TechTypes)(kTrigger.getPrereqOrTechs(iI))))
			{
				bFoundValid = true;
				break;
			}
		}

		if (!bFoundValid)
		{
			return false;
		}
	}


	if (kTrigger.getNumPrereqAndTechs() > 0)
	{
		bool bFoundValid = true;

		for (int iI = 0; iI < kTrigger.getNumPrereqAndTechs(); iI++)
		{
			if (!GET_TEAM(getTeam()).isHasTech((TechTypes)(kTrigger.getPrereqAndTechs(iI))))
			{
				bFoundValid = false;
				break;
			}
		}

		if (!bFoundValid)
		{
			return false;
		}
	}

	if (kTrigger.getNumPrereqEvents() > 0)
	{
		bool bFoundValid = true;
		for (int iI = 0; iI < kTrigger.getNumPrereqEvents(); iI++)
		{
			if (NULL == getEventOccured((EventTypes)kTrigger.getPrereqEvent(iI)))
			{
				bFoundValid = false;
				break;
			}
		}

		if (!bFoundValid)
		{
			return false;
		}
	}

	if (NO_CIVIC != kTrigger.getCivic())
	{
		bool bFoundValid = false;

		for (int iI = 0; iI < GC.getNumCivicOptionInfos(); ++iI)
		{
			if (getCivics((CivicOptionTypes)iI) == kTrigger.getCivic())
			{
				bFoundValid = true;
				break;
			}
		}

		if (!bFoundValid)
		{
			return false;
		}
	}

	if (kTrigger.getMinTreasury() > 0)
	{
		if (getGold() < kTrigger.getMinTreasury())
		{
			return false;
		}
	}

	if (!((*getPropertiesConst()) >= *kTrigger.getPrereqPlayerMinProperties()))
	{
		return false;
	}

	if (!((*getPropertiesConst()) <= *kTrigger.getPrereqPlayerMaxProperties()))
	{
		return false;
	}

	if (GC.getMapINLINE().getNumLandAreas() < kTrigger.getMinMapLandmass())
	{
		return false;
	}

	if (kTrigger.getMinOurLandmass() > 0 || kTrigger.getMaxOurLandmass() != -1)
	{
		int iNumLandmass = 0;

		int iLoop;
		for (CvArea* pArea = GC.getMapINLINE().firstArea(&iLoop); NULL != pArea; pArea = GC.getMapINLINE().nextArea(&iLoop))
		{
			if (!pArea->isWater())
			{
				if (pArea->getCitiesPerPlayer(getID()) > 0)
				{
					++iNumLandmass;
				}
			}
		}

		if (iNumLandmass < kTrigger.getMinOurLandmass())
		{
			return false;
		}

		if (kTrigger.getMaxOurLandmass() != -1 && iNumLandmass > kTrigger.getMaxOurLandmass())
		{
			return false;
		}
	}
	return true;
}

int CvPlayer::getEventTriggerWeight(EventTriggerTypes eTrigger) const
{
	if (!isEventTriggerPossible(eTrigger))
	{
		return 0;
	}

	CvEventTriggerInfo& kTrigger = GC.getEventTriggerInfo(eTrigger);

	if (kTrigger.getProbability() < 0)
	{
		return kTrigger.getProbability();
	}

	int iProbability = kTrigger.getProbability();

	if (kTrigger.isProbabilityUnitMultiply() && kTrigger.getNumUnits() > 0)
	{
		int iNumUnits = 0;
		int iLoop;
		for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if (MIN_INT != pLoopUnit->getTriggerValue(eTrigger, NULL, true))
			{
				++iNumUnits;
			}
		}

		iProbability *= iNumUnits;
	}

	if (kTrigger.isProbabilityBuildingMultiply() && kTrigger.getNumBuildings() > 0)
	{
		int iNumBuildings = 0;
		for (int i = 0; i < kTrigger.getNumBuildingsRequired(); ++i)
		{
			if (kTrigger.getBuildingRequired(i) != NO_BUILDINGCLASS)
			{
				iNumBuildings += getBuildingClassCount((BuildingClassTypes)kTrigger.getBuildingRequired(i));
			}
		}

		iProbability *= iNumBuildings;
	}

	return iProbability;
}


PlayerTypes CvPlayer::getSplitEmpirePlayer(int iAreaId) const
{
	// can't create different derivative civs on the same continent
	for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; ++iPlayer)
	{
		CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iPlayer);
		if (kLoopPlayer.isAlive() && kLoopPlayer.getParent() == getID())
		{
			CvCity* pLoopCapital = kLoopPlayer.getCapitalCity();
			if (NULL != pLoopCapital)
			{
				if (pLoopCapital->area()->getID() == iAreaId)
				{
					return NO_PLAYER;
				}
			}
		}
	}

	PlayerTypes eNewPlayer = NO_PLAYER;

	// Try to find a player who's never been in the game before
	for (int i = 0; i < MAX_CIV_PLAYERS; ++i)
	{
		if (!GET_PLAYER((PlayerTypes)i).isEverAlive())
		{
			eNewPlayer = (PlayerTypes)i;
			break;
		}
	}

	if (eNewPlayer == NO_PLAYER)
	{
		// Try to recycle a dead player
		for (int i = 0; i < MAX_CIV_PLAYERS; ++i)
		{
			if (!GET_PLAYER((PlayerTypes)i).isAlive())
			{
				eNewPlayer = (PlayerTypes)i;
				break;
			}
		}
	}

	return eNewPlayer;
}

bool CvPlayer::canSplitEmpire() const
{
	int iLoopArea;

	if (GC.getGameINLINE().isOption(GAMEOPTION_NO_VASSAL_STATES))
	{
		return false;
	}

	if (GET_TEAM(getTeam()).isAVassal())
	{
		return false;
	}

	CivLeaderArray aLeaders;
	if (!getSplitEmpireLeaders(aLeaders))
	{
		return false;
	}

	bool bFoundArea = false;

	for (CvArea* pLoopArea = GC.getMapINLINE().firstArea(&iLoopArea); pLoopArea != NULL; pLoopArea = GC.getMapINLINE().nextArea(&iLoopArea))
	{
		if (canSplitArea(pLoopArea->getID()))
		{
			bFoundArea = true;
			break;
		}
	}

	if (!bFoundArea)
	{
		return false;
	}

	return true;
}

bool CvPlayer::canSplitArea(int iAreaId) const
{
	CvArea* pArea = GC.getMapINLINE().getArea(iAreaId);
	CvCity* pCapital = getCapitalCity();

	if (NULL == pCapital)
	{
		return false;
	}

	if (NULL == pArea || pArea == pCapital->area())
	{
		return false;
	}

	if (0 == pArea->getCitiesPerPlayer(getID()))
	{
		return false;
	}

	PlayerTypes ePlayer = getSplitEmpirePlayer(pArea->getID());
	if (NO_PLAYER == ePlayer)
	{
		return false;
	}

	if (!GET_PLAYER(ePlayer).isAlive())
	{
		if (pArea->getCitiesPerPlayer(getID()) <= 1)
		{
			return false;
		}
	}

	return true;
}

bool CvPlayer::getSplitEmpireLeaders(CivLeaderArray& aLeaders) const
{
	aLeaders.clear();

	for (int i = 0; i < GC.getNumCivilizationInfos(); ++i)
	{
		bool bValid = true;

		if (getCivilizationType() == i)
		{
			bValid = false;
		}

		if (bValid)
		{
			if (!GC.getCivilizationInfo((CivilizationTypes)i).isPlayable() || !GC.getCivilizationInfo((CivilizationTypes)i).isAIPlayable())
			{
				bValid = false;
			}
		}

		if (bValid)
		{
			for (int j = 0; j < MAX_CIV_PLAYERS; ++j)
			{
				if (getID() != j && GET_PLAYER((PlayerTypes)j).isEverAlive() && GET_PLAYER((PlayerTypes)j).getCivilizationType() == i)
				{
					bValid = false;
					break;
				}
			}
		}

		if (bValid)
		{
			for (int j = 0; j < GC.getNumLeaderHeadInfos(); ++j)
			{
				bool bLeaderValid = true;
				if (!GC.getCivilizationInfo((CivilizationTypes)i).isLeaders(j) && !GC.getGameINLINE().isOption(GAMEOPTION_LEAD_ANY_CIV))
				{
					bLeaderValid = false;
				}

				if (bLeaderValid)
				{
					for (int k = 0; k < MAX_CIV_PLAYERS; ++k)
					{
						if (GET_PLAYER((PlayerTypes)k).isEverAlive() && GET_PLAYER((PlayerTypes)k).getPersonalityType() == j)
						{
							bLeaderValid = false;
						}
					}
				}

				if (bLeaderValid)
				{
					aLeaders.push_back(std::make_pair((CivilizationTypes)i, (LeaderHeadTypes)j));
				}
			}
		}
	}

	return (!aLeaders.empty());
}

bool CvPlayer::splitEmpire(int iAreaId)
{
	PROFILE_FUNC();

	if (!canSplitEmpire())
	{
		return false;
	}

	if (!canSplitArea(iAreaId))
	{
		return false;
	}

	CvArea* pArea = GC.getMapINLINE().getArea(iAreaId);
	if (NULL == pArea)
	{
		return false;
	}

	PlayerTypes eNewPlayer = getSplitEmpirePlayer(iAreaId);
	if (eNewPlayer == NO_PLAYER)
	{
		return false;
	}

	bool bPlayerExists = GET_TEAM(GET_PLAYER(eNewPlayer).getTeam()).isAlive();
	FAssert(!bPlayerExists);
	if (!bPlayerExists)
	{
		int iBestValue = -1;
		LeaderHeadTypes eBestLeader = NO_LEADER;
		CivilizationTypes eBestCiv = NO_CIVILIZATION;

		CivLeaderArray aLeaders;
		if (getSplitEmpireLeaders(aLeaders))
		{
			CivLeaderArray::iterator it;
			for (it = aLeaders.begin(); it != aLeaders.end(); ++it)
			{
				int iValue = (1 + GC.getGameINLINE().getSorenRandNum(100, "Choosing Split Personality"));

				if (GC.getCivilizationInfo(getCivilizationType()).getDerivativeCiv() == it->first)
				{
					iValue += 1000;
				}

				if (iValue > iBestValue)
				{
					iBestValue = iValue;
					eBestLeader = it->second;
					eBestCiv = it->first;
				}
			}
		}

		if (eBestLeader == NO_LEADER || eBestCiv == NO_CIVILIZATION)
		{
			return false;
		}

		CvWString szMessage = gDLL->getText("TXT_KEY_MISC_EMPIRE_SPLIT", getNameKey(), GC.getCivilizationInfo(eBestCiv).getShortDescriptionKey(), GC.getLeaderHeadInfo(eBestLeader).getTextKeyWide());
		for (int i = 0; i < MAX_CIV_PLAYERS; ++i)
		{
			if (GET_PLAYER((PlayerTypes)i).isAlive())
			{
				if (i == getID() || i == eNewPlayer || GET_TEAM(GET_PLAYER((PlayerTypes)i).getTeam()).isHasMet(getTeam()))
				{
					MEMORY_TRACK_EXEMPT();

					AddDLLMessage((PlayerTypes)i, false, GC.getEVENT_MESSAGE_TIME(), szMessage, "AS2D_REVOLTEND", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("INTERFACE_CITY_BAR_CAPITAL_TEXTURE")->getPath());
				}
			}
		}
		GC.getGameINLINE().addReplayMessage(REPLAY_MESSAGE_MAJOR_EVENT, getID(), szMessage, -1, -1, (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      12/30/08                                jdog5000      */
/*                                                                                              */
/* Bugfix                                                                                       */
/************************************************************************************************/
/*
		// remove leftover culture from old recycled player
		for (int iPlot = 0; iPlot < GC.getMapINLINE().numPlotsINLINE(); ++iPlot)
		{
			CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);

			pLoopPlot->setCulture(eNewPlayer, 0, false, false);
		}
*/
		// Clearing plot culture along with many other bits of data now handled by CvGame::addPlayer
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/

		GC.getGameINLINE().addPlayer(eNewPlayer, eBestLeader, eBestCiv);
		GET_PLAYER(eNewPlayer).setParent(getID());
		GC.getInitCore().setLeaderName(eNewPlayer, GC.getLeaderHeadInfo(eBestLeader).getTextKeyWide());

		CvTeam& kNewTeam = GET_TEAM(GET_PLAYER(eNewPlayer).getTeam());
		for (int iTeam = 0; iTeam < MAX_TEAMS; ++iTeam)
		{
			CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iTeam);

			if (kLoopTeam.isAlive())
			{
				kNewTeam.setEspionagePointsAgainstTeam((TeamTypes)iTeam, GET_TEAM(getTeam()).getEspionagePointsAgainstTeam((TeamTypes)iTeam));
				kLoopTeam.setEspionagePointsAgainstTeam(GET_PLAYER(eNewPlayer).getTeam(), kLoopTeam.getEspionagePointsAgainstTeam(getTeam()));
			}
		}
		kNewTeam.setEspionagePointsEver(GET_TEAM(getTeam()).getEspionagePointsEver());

		GET_TEAM(getTeam()).assignVassal(GET_PLAYER(eNewPlayer).getTeam(), false);

		AI_updateBonusValue();
	}

	std::vector< std::pair<int, int> > aCultures;
	for (int iPlot = 0; iPlot < GC.getMapINLINE().numPlotsINLINE(); ++iPlot)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);

		bool bTranferPlot = pLoopPlot->area() == pArea;

		if (!bTranferPlot)
		{
			CvCity* pWorkingCity = pLoopPlot->getWorkingCity();
			if (NULL != pWorkingCity && pWorkingCity->getOwnerINLINE() == getID() && pWorkingCity->area() == pArea)
			{
				bTranferPlot = true;
			}
		}

		if (!bTranferPlot && pLoopPlot->isWater() && pLoopPlot->isAdjacentToArea(pArea))
		{
			bTranferPlot = true;
		}

		if (bTranferPlot)
		{
			int iCulture = pLoopPlot->getCulture(getID());

			if (bPlayerExists)
			{
				iCulture = std::max(iCulture, pLoopPlot->getCulture(eNewPlayer));
			}

			aCultures.push_back(std::make_pair(iPlot, iCulture));
		}

		if (pLoopPlot->isRevealed(getTeam(), false))
		{
			pLoopPlot->setRevealed(GET_PLAYER(eNewPlayer).getTeam(), true, false, getTeam(), false);
		}
	}

	int iLoop;
	for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->area() == pArea)
		{
			int iCulture = pLoopCity->getCultureTimes100(getID());
			CvPlot* pPlot = pLoopCity->plot();

			GET_PLAYER(eNewPlayer).acquireCity(pLoopCity, false, true, false);

			if (NULL != pPlot)
			{
				CvCity* pCity = pPlot->getPlotCity();
				if (NULL != pCity)
				{
					pCity->setCultureTimes100(eNewPlayer, iCulture, false, false);
				}
			}
		}
	}

	for (uint i = 0; i < aCultures.size(); ++i)
	{
		CvPlot* pPlot = GC.getMapINLINE().plotByIndexINLINE(aCultures[i].first);
		pPlot->setCulture(eNewPlayer, aCultures[i].second, true, false);
		pPlot->setCulture(getID(), 0, true, false);

		for (int iTeam = 0; iTeam < MAX_TEAMS; ++iTeam)
		{
			if (pPlot->getRevealedOwner((TeamTypes)iTeam, false) == getID())
			{
				pPlot->setRevealedOwner((TeamTypes)iTeam, eNewPlayer);
			}
		}
	}

	for (int i = 0; i < GC.getNumTechInfos(); ++i)
	{
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)i))
		{
			CvTeam& kNewTeam = GET_TEAM(GET_PLAYER(eNewPlayer).getTeam());

			kNewTeam.setHasTech((TechTypes)i, true, eNewPlayer, false, false);
			if (GET_TEAM(getTeam()).isNoTradeTech((TechTypes)i) || GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_BROKERING))
			{
				kNewTeam.setNoTradeTech((TechTypes)i, true);
			}
		}
	}

	//	Don't initialise concripts until after the techs are set up else you'll get stone throwers!
	for (CvCity* pLoopCity = GET_PLAYER(eNewPlayer).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER(eNewPlayer).nextCity(&iLoop))
	{
		for (int i = 0; i < GC.getDefineINT("COLONY_NUM_FREE_DEFENDERS"); ++i)
		{
			pLoopCity->initConscriptedUnit();
		}
	}


	GC.getGameINLINE().updatePlotGroups();

	return true;
}

/************************************************************************************************/
/* REVOLUTION_MOD                         11/15/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
// Add ePlayer's cities, units, techs, etc to this player
bool CvPlayer::assimilatePlayer( PlayerTypes ePlayer )
{
	CvPlayer& kPlayer = GET_PLAYER(ePlayer);
	if( !kPlayer.isAlive() )
	{
		return false;
	}
	CvTeam& kTeam = GET_TEAM(kPlayer.getTeam());

	CvCity* pCapital = getCapitalCity();
	if( pCapital == NULL )
	{
		return false;
	}

	CvCity* pLoopCity = NULL;
	CvUnit* pLoopUnit = NULL;

	if( kTeam.isAtWar(getTeam()) )
	{
		kTeam.makePeace(getTeam(),false);
	}
	
	for(int iI = 0; iI < MAX_CIV_PLAYERS; iI++ )
	{
		if( kPlayer.canContact((PlayerTypes)iI) )
		{
			MEMORY_TRACK_EXEMPT();

			CvWString szBuffer = gDLL->getText("TXT_KEY_REV_MESS_ASSIMILATE", kPlayer.getCivilizationDescription(), getCivilizationDescription());
			AddDLLMessage(((PlayerTypes)iI), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, NULL, MESSAGE_TYPE_MAJOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"));
		}
	}

	// Convert units
	int iLoop;
	for (pLoopUnit = kPlayer.firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = kPlayer.nextUnit(&iLoop))
	{
		CvUnit* pNewUnit = initUnit(pLoopUnit->getUnitType(), pLoopUnit->getX_INLINE(), pLoopUnit->getY_INLINE(), NO_UNITAI, NO_DIRECTION, GC.getGameINLINE().getSorenRandNum(10000, "AI Unit Birthmark"));
		pNewUnit->convert(pLoopUnit);
	}

	// Convert cities
	for (pLoopCity = kPlayer.firstCity(&iLoop); pLoopCity != NULL; pLoopCity = kPlayer.nextCity(&iLoop))
	{
		CvPlot* pPlot = pLoopCity->plot();
		pPlot->setOwner(getID(), false, false);
		pLoopCity = pPlot->getPlotCity();

		pLoopCity->changeCultureTimes100(getID(), pLoopCity->getCultureTimes100(kPlayer.getID())/2, true, false);
		pPlot->changeCulture(getID(), pPlot->getCulture(kPlayer.getID())/2, false);
	}	

	// Add Techs
	for (int iI = 0; iI < GC.getNumTechInfos(); iI++)
	{
		if( kTeam.isHasTech((TechTypes)iI) && !(GET_TEAM(getTeam()).isHasTech((TechTypes)iI)) )
		{
			GET_TEAM(getTeam()).setHasTech((TechTypes)iI, true, getID(), false, false);
		}
	}

	// Share map
	for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);

		if (pLoopPlot->isRevealed(kTeam.getID(), false))
		{
			pLoopPlot->setRevealed(getTeam(), true, false, kTeam.getID(), false);
		}
	}

	// Diplomacy
	for (int iI = 0; iI < MAX_TEAMS; iI++)
	{
		if ((iI != getTeam()) && (iI != kTeam.getID()))
		{
			if (GET_TEAM((TeamTypes)iI).isAlive())
			{
				if (kTeam.isHasMet((TeamTypes)iI))
				{
					GET_TEAM(getTeam()).meet(((TeamTypes)iI), false);
				}
			}
		}
	}

	// Make sure assimilated player is dead
	kPlayer.killUnits();
	kPlayer.killCities();

	for (int i = 0; i < GC.getMapINLINE().numPlotsINLINE(); ++i)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(i);
		if (pLoopPlot && (pLoopPlot->getTeam() == getTeam() || pLoopPlot->getTeam() == kTeam.getID()))
		{
			pLoopPlot->updateCulture(true, false);
		}
	}

	GC.getGameINLINE().updatePlotGroups();
	GC.getMapINLINE().verifyUnitValidPlot();

	GET_TEAM(getTeam()).AI_updateWorstEnemy();
	GET_TEAM(getTeam()).AI_updateAreaStragies();

	GC.getGameINLINE().updateScore(true);

	return true;
}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/

bool CvPlayer::isValidTriggerReligion(const CvEventTriggerInfo& kTrigger, CvCity* pCity, ReligionTypes eReligion) const
{
	if (kTrigger.getNumReligionsRequired() > 0)
	{
		bool bFound = false;

		for (int i = 0; i < kTrigger.getNumReligionsRequired(); ++i)
		{
			if (eReligion == kTrigger.getReligionRequired(i))
			{
				bFound = true;
				break;
			}
		}

		if (!bFound)
		{
			return false;
		}
	}

	if (NULL != pCity)
	{
		if (!pCity->isHasReligion(eReligion))
		{
			return false;
		}

		if (kTrigger.isHolyCity())
		{
			if (!pCity->isHolyCity(eReligion))
			{
				return false;
			}
		}
	}
	else
	{
		if (0 == getHasReligionCount(eReligion))
		{
			return false;
		}

		if (kTrigger.isHolyCity())
		{
			CvCity* pHolyCity = GC.getGameINLINE().getHolyCity(eReligion);
			if (NULL == pHolyCity || pHolyCity->getOwnerINLINE() != getID())
			{
				return false;
			}
		}
	}

	return true;
}

bool CvPlayer::isValidTriggerCorporation(const CvEventTriggerInfo& kTrigger, CvCity* pCity, CorporationTypes eCorporation) const
{
	if (kTrigger.getNumCorporationsRequired() > 0)
	{
		bool bFound = false;

		for (int i = 0; i < kTrigger.getNumCorporationsRequired(); ++i)
		{
			if (eCorporation == kTrigger.getCorporationRequired(i))
			{
				bFound = true;
				break;
			}
		}

		if (!bFound)
		{
			return false;
		}
	}

	if (NULL != pCity)
	{
		if (!pCity->isHasCorporation(eCorporation))
		{
			return false;
		}

		if (kTrigger.isHeadquarters())
		{
			if (!pCity->isHeadquarters(eCorporation))
			{
				return false;
			}
		}
	}
	else
	{
		if (getHasCorporationCount(eCorporation) > 0)
		{
			return true;
		}

		if (kTrigger.isHeadquarters())
		{
			CvCity* pHeadquarters = GC.getGameINLINE().getHeadquarters(eCorporation);
			if (NULL == pHeadquarters || pHeadquarters->getOwnerINLINE() != getID())
			{
				return false;
			}
		}
	}

	return false;
}

void CvPlayer::launch(VictoryTypes eVictory)
{
	CvTeam& kTeam = GET_TEAM(getTeam());

	if (!kTeam.canLaunch(eVictory))
	{
		return;
	}

	kTeam.finalizeProjectArtTypes();
	kTeam.setVictoryCountdown(eVictory, kTeam.getVictoryDelay(eVictory));

	//gDLL->getEngineIFace()->AddLaunch(getID());
	// K-Mod. The spaceship launch causes pitboss to crash
	if (!gDLL->IsPitbossHost())
		gDLL->getEngineIFace()->AddLaunch(getID());
	// K-Mod end.

	kTeam.setCanLaunch(eVictory, false);

	CvCity *capital = getCapitalCity();

	//message
	CvWString szBuffer;
	for(int i = 0; i < MAX_PLAYERS; ++i)
	{
		if (GET_PLAYER((PlayerTypes)i).isAlive())
		{
			int plotX = -1;
			int plotY = -1;
			if((capital != NULL) && capital->isRevealed(GET_PLAYER((PlayerTypes) i).getTeam(), false))
			{
				plotX = capital->getX();
				plotY = capital->getY();
			}

			if (GET_PLAYER((PlayerTypes)i).getTeam() == getTeam())
			{
				szBuffer = gDLL->getText("TXT_KEY_VICTORY_YOU_HAVE_LAUNCHED");
			}
			else
			{
				szBuffer = gDLL->getText("TXT_KEY_VICTORY_TEAM_HAS_LAUNCHED", GET_TEAM(getTeam()).getName().GetCString());
			}

			MEMORY_TRACK_EXEMPT();

			AddDLLMessage(((PlayerTypes)i), true, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_CULTURELEVEL", MESSAGE_TYPE_MAJOR_EVENT, ARTFILEMGR.getMiscArtInfo("SPACE_SHIP_BUTTON")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_HIGHLIGHT_TEXT"), plotX, plotY, true, true);
		}
	}
}

bool CvPlayer::isFreePromotion(UnitCombatTypes eUnitCombat, PromotionTypes ePromotion) const
{
	for (UnitCombatPromotionArray::const_iterator it = m_aFreeUnitCombatPromotions.begin(); it != m_aFreeUnitCombatPromotions.end(); ++it)
	{
		if ((*it).first == eUnitCombat && (*it).second == ePromotion)
		{
			return true;
		}
	}

	return false;
}

void CvPlayer::setFreePromotion(UnitCombatTypes eUnitCombat, PromotionTypes ePromotion, bool bFree)
{
	for (UnitCombatPromotionArray::iterator it = m_aFreeUnitCombatPromotions.begin(); it != m_aFreeUnitCombatPromotions.end(); ++it)
	{
		if ((*it).first == eUnitCombat && (*it).second == ePromotion)
		{
			if (!bFree)
			{
				m_aFreeUnitCombatPromotions.erase(it);
			}
			return;
		}
	}

	if (bFree)
	{
		m_aFreeUnitCombatPromotions.push_back(std::make_pair(eUnitCombat, ePromotion));
	}
}

bool CvPlayer::isFreePromotion(UnitClassTypes eUnitClass, PromotionTypes ePromotion) const
{
	for (UnitClassPromotionArray::const_iterator it = m_aFreeUnitClassPromotions.begin(); it != m_aFreeUnitClassPromotions.end(); ++it)
	{
		if ((*it).first == eUnitClass && (*it).second == ePromotion)
		{
			return true;
		}
	}

	return false;
}

void CvPlayer::setFreePromotion(UnitClassTypes eUnitClass, PromotionTypes ePromotion, bool bFree)
{
	for (UnitClassPromotionArray::iterator it = m_aFreeUnitClassPromotions.begin(); it != m_aFreeUnitClassPromotions.end(); ++it)
	{
		if ((*it).first == eUnitClass && (*it).second == ePromotion)
		{
			if (!bFree)
			{
				m_aFreeUnitClassPromotions.erase(it);
			}
			return;
		}
	}

	if (bFree)
	{
		m_aFreeUnitClassPromotions.push_back(std::make_pair(eUnitClass, ePromotion));
	}
}

PlayerVoteTypes CvPlayer::getVote(int iId) const
{
	for (std::vector< std::pair<int, PlayerVoteTypes> >::const_iterator it = m_aVote.begin(); it != m_aVote.end(); ++it)
	{
		if ((*it).first == iId)
		{
			return ((*it).second);
		}
	}

	return NO_PLAYER_VOTE;
}

void CvPlayer::setVote(int iId, PlayerVoteTypes ePlayerVote)
{
	for (std::vector< std::pair<int, PlayerVoteTypes> >::iterator it = m_aVote.begin(); it != m_aVote.end(); ++it)
	{
		if ((*it).first == iId)
		{
			if (ePlayerVote == NO_PLAYER_VOTE)
			{
				m_aVote.erase(it);
			}
			else
			{
				(*it).second = ePlayerVote;
			}
			return;
		}
	}

	if (ePlayerVote != NO_PLAYER_VOTE)
	{
		m_aVote.push_back(std::make_pair(iId, ePlayerVote));
	}
}

int CvPlayer::getUnitExtraCost(UnitClassTypes eUnitClass) const
{
	for (std::vector< std::pair<UnitClassTypes, int> >::const_iterator it = m_aUnitExtraCosts.begin(); it != m_aUnitExtraCosts.end(); ++it)
	{
		if ((*it).first == eUnitClass)
		{
			return ((*it).second);
		}
	}

	return 0;
}

void CvPlayer::setUnitExtraCost(UnitClassTypes eUnitClass, int iCost)
{
	for (std::vector< std::pair<UnitClassTypes, int> >::iterator it = m_aUnitExtraCosts.begin(); it != m_aUnitExtraCosts.end(); ++it)
	{
		if ((*it).first == eUnitClass)
		{
			if (0 == iCost)
			{
				m_aUnitExtraCosts.erase(it);
			}
			else
			{
				(*it).second = iCost;
			}
			return;
		}
	}

	if (0 != iCost)
	{
		m_aUnitExtraCosts.push_back(std::make_pair(eUnitClass, iCost));
	}
}

// CACHE: cache frequently used values
///////////////////////////////////////
bool CvPlayer::hasShrine(ReligionTypes eReligion)
{
	bool bHasShrine = false;
	
	if (eReligion != NO_RELIGION)
	{
		CvCity* pHolyCity = GC.getGameINLINE().getHolyCity(eReligion);
		
		// if the holy city exists, and we own it
		if (pHolyCity != NULL && pHolyCity->getOwnerINLINE() == getID())
			bHasShrine = pHolyCity->hasShrine(eReligion);
	}
	return bHasShrine;
}

void CvPlayer::invalidatePopulationRankCache()
{
	int iLoop;
	CvCity* pLoopCity;
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->invalidatePopulationRankCache();
	}
}

void CvPlayer::invalidateYieldRankCache(YieldTypes eYield)
{
	int iLoop;
	CvCity* pLoopCity;
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->invalidateYieldRankCache();
	}
}

void CvPlayer::invalidateCommerceRankCache(CommerceTypes eCommerce)
{
	int iLoop;
	CvCity* pLoopCity;
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->invalidateCommerceRankCache();
	}
}


void CvPlayer::doUpdateCacheOnTurn()
{
	// add this back, after testing without it
	// invalidateYieldRankCache();

	clearCanConstructCacheForClass(NO_BUILDINGCLASS);
}

void CvPlayer::processVoteSourceBonus(VoteSourceTypes eVoteSource, bool bActive)
{
	int iLoop;
	for (CvCity* pCity = firstCity(&iLoop); NULL != pCity; pCity = nextCity(&iLoop))
	{
		pCity->processVoteSourceBonus(eVoteSource, bActive);
	}
}

int CvPlayer::getVotes(VoteTypes eVote, VoteSourceTypes eVoteSource) const
{
	int iVotes = 0;

	ReligionTypes eReligion = GC.getGameINLINE().getVoteSourceReligion(eVoteSource);

	if (NO_VOTE == eVote)
	{
		if (NO_RELIGION != eReligion)
		{
			iVotes = getReligionPopulation(eReligion);
		}
		else
		{
			iVotes = getTotalPopulation();
		}
	}
	else
	{
		if (!GC.getVoteInfo(eVote).isVoteSourceType(eVoteSource))
		{
			return 0;
		}

		if (GC.getVoteInfo(eVote).isCivVoting())
		{
			if (NO_RELIGION == eReligion || getHasReligionCount(eReligion) > 0)
			{
				iVotes = 1;
			}
		}
		else if (GC.getVoteInfo(eVote).isCityVoting())
		{
			if (NO_RELIGION != eReligion)
			{
				iVotes = getHasReligionCount(eReligion);
			}
			else
			{
				iVotes = getNumCities();
			}
		}
		else
		{
			if (NO_RELIGION == eReligion)
			{
				iVotes = getTotalPopulation();
			}
			else
			{
				iVotes = getReligionPopulation(eReligion);
			}
		}

		if (NO_RELIGION != eReligion && getStateReligion() == eReligion)
		{
			iVotes *= (100 + GC.getVoteInfo(eVote).getStateReligionVotePercent());
			iVotes /= 100;
		}
	}

	return iVotes;
}

bool CvPlayer::canDoResolution(VoteSourceTypes eVoteSource, const VoteSelectionSubData& kData) const
{
	CvTeam& kOurTeam = GET_TEAM(getTeam());

	if (NO_PLAYER != kData.ePlayer)
	{
		if (!kOurTeam.isHasMet(GET_PLAYER(kData.ePlayer).getTeam()))
		{
			return false;
		}
	}

	if (GC.getVoteInfo(kData.eVote).isOpenBorders())
	{
		for (int iTeam2 = 0; iTeam2 < MAX_CIV_TEAMS; ++iTeam2)
		{
			if (GET_TEAM((TeamTypes)iTeam2).isVotingMember(eVoteSource))
			{
				if (!kOurTeam.isOpenBordersTrading() && !GET_TEAM((TeamTypes)iTeam2).isOpenBordersTrading())
				{
					return false;
				}

				if (kOurTeam.isAtWar((TeamTypes)iTeam2))
				{
					return false;
				}
			}
		}
	}
	else if (GC.getVoteInfo(kData.eVote).isDefensivePact())
	{
		for (int iTeam2 = 0; iTeam2 < MAX_CIV_TEAMS; ++iTeam2)
		{
			if (GET_TEAM((TeamTypes)iTeam2).isVotingMember(eVoteSource))
			{
				if (!kOurTeam.isDefensivePactTrading() && !GET_TEAM((TeamTypes)iTeam2).isDefensivePactTrading())
				{
					return false;
				}

				if (kOurTeam.getAtWarCount(true) > 0 || GET_TEAM((TeamTypes)iTeam2).getAtWarCount(true) > 0)
				{
					return false;
				}

				if (!kOurTeam.canSignDefensivePact((TeamTypes)iTeam2))
				{
					return false;
				}
			}
		}
	}
	else if (GC.getVoteInfo(kData.eVote).isForcePeace())
	{
		FAssert(NO_PLAYER != kData.ePlayer);
		CvPlayer& kPlayer = GET_PLAYER(kData.ePlayer);

		if (kPlayer.getTeam() != getTeam())
		{
			if (kOurTeam.isAtWar(kPlayer.getTeam()))
			{
				TeamTypes eMaster = getTeam();
				for (int iMaster = 0; iMaster < MAX_CIV_TEAMS; ++iMaster)
				{
					if (iMaster != getID() && kOurTeam.isVassal((TeamTypes)iMaster))
					{
						if (GET_TEAM((TeamTypes)iMaster).isVotingMember(eVoteSource))
						{
							eMaster = (TeamTypes)iMaster;
							break;
						}
					}
				}

				if (!GET_TEAM(eMaster).canContact(kPlayer.getTeam()))
				{
					return false;
				}
			}
		}
	}
	else if (GC.getVoteInfo(kData.eVote).isForceWar())
	{
		FAssert(NO_PLAYER != kData.ePlayer);
		CvPlayer& kPlayer = GET_PLAYER(kData.ePlayer);

		if (!kOurTeam.isAtWar(kPlayer.getTeam()))
		{
			TeamTypes eMaster = getTeam();
			for (int iMaster = 0; iMaster < MAX_CIV_TEAMS; ++iMaster)
			{
				if (iMaster != getID() && kOurTeam.isVassal((TeamTypes)iMaster))
				{
					if (GET_TEAM((TeamTypes)iMaster).isVotingMember(eVoteSource))
					{
						eMaster = (TeamTypes)iMaster;
						break;
					}
				}
			}

			if (!GET_TEAM(eMaster).canDeclareWar(kPlayer.getTeam()))
			{
				return false;
			}
		}
	}
	else if (GC.getVoteInfo(kData.eVote).isForceNoTrade())
	{
		FAssert(NO_PLAYER != kData.ePlayer);
		CvPlayer& kPlayer = GET_PLAYER(kData.ePlayer);

		if (!canStopTradingWithTeam(kPlayer.getTeam(), true))
		{
			return false;
		}

	}
	else if (GC.getVoteInfo(kData.eVote).isAssignCity())
	{
		if (GET_TEAM(GET_PLAYER(kData.eOtherPlayer).getTeam()).isVassal(GET_PLAYER(kData.ePlayer).getTeam()))
		{
			return false;
		}
	}

	return true;
}

bool CvPlayer::canDefyResolution(VoteSourceTypes eVoteSource, const VoteSelectionSubData& kData) const
{
	if (GC.getGameINLINE().getSecretaryGeneral(eVoteSource) == getTeam())
	{
		return false;
	}

	if (GC.getVoteInfo(kData.eVote).isOpenBorders())
	{
		for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; ++iTeam)
		{
			CvTeam& kTeam = GET_TEAM((TeamTypes)iTeam);
			if ((TeamTypes)iTeam != getTeam())
			{
				if (kTeam.isVotingMember(eVoteSource))
				{
					if (!kTeam.isOpenBorders(getTeam()))
					{
						return true;
					}
				}
			}
		}
	}
	else if (GC.getVoteInfo(kData.eVote).isDefensivePact())
	{
		for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; ++iTeam)
		{
			CvTeam& kTeam = GET_TEAM((TeamTypes)iTeam);
			if ((TeamTypes)iTeam != getTeam())
			{
				if (kTeam.isVotingMember(eVoteSource))
				{
					if (!kTeam.isDefensivePact(getTeam()))
					{
						return true;
					}
				}
			}
		}
	}
	else if (GC.getVoteInfo(kData.eVote).isForceNoTrade())
	{
		return true;
	}
	else if (GC.getVoteInfo(kData.eVote).isForceWar())
	{
		if (!::atWar(getTeam(), GET_PLAYER(kData.ePlayer).getTeam()))
		{
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      12/31/08                                jdog5000      */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
			// Vassals can't defy declarations of war
			if( !GET_TEAM(getTeam()).isAVassal() )
			{
				return true;
			}
/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
		}
	}
	else if (GC.getVoteInfo(kData.eVote).isForcePeace())
	{
		if (GET_PLAYER(kData.ePlayer).getTeam() == getTeam())
		{
			return true;
		}

		if (::atWar(getTeam(), GET_PLAYER(kData.ePlayer).getTeam()))
		{
			return true;
		}
	}
	else if (GC.getVoteInfo(kData.eVote).isAssignCity())
	{
		if (kData.ePlayer == getID())
		{
			return true;
		}
	}
	else if (!GC.getGameINLINE().isTeamVote(kData.eVote))
	{
		return true;
	}

	return false;
}


void CvPlayer::setDefiedResolution(VoteSourceTypes eVoteSource, const VoteSelectionSubData& kData)
{
	FAssert(canDefyResolution(eVoteSource, kData));

	// cities get unhappiness
	int iLoop;
	for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
	{
		ReligionTypes eReligion = GC.getGameINLINE().getVoteSourceReligion(eVoteSource);

		if (NO_RELIGION == eReligion || pLoopCity->isHasReligion(eReligion))
		{
			int iAngerLength = pLoopCity->flatDefyResolutionAngerLength();
			if (NO_RELIGION != eReligion && pLoopCity->isHasReligion(eReligion))
			{
				iAngerLength /= std::max(1, pLoopCity->getReligionCount());
			}

			pLoopCity->changeDefyResolutionAngerTimer(iAngerLength);
		}
	}

	setLoyalMember(eVoteSource, false);
}


void CvPlayer::setEndorsedResolution(VoteSourceTypes eVoteSource, const VoteSelectionSubData& kData)
{
	setLoyalMember(eVoteSource, true);
}

bool CvPlayer::isFullMember(VoteSourceTypes eVoteSource) const
{
	if (NO_RELIGION != GC.getGameINLINE().getVoteSourceReligion(eVoteSource))
	{
		if (getStateReligion() != GC.getGameINLINE().getVoteSourceReligion(eVoteSource))
		{
			return false;
		}
	}

	if (NO_CIVIC != GC.getVoteSourceInfo(eVoteSource).getCivic())
	{
		if (!isCivic((CivicTypes)GC.getVoteSourceInfo(eVoteSource).getCivic()))
		{
			return false;
		}
	}

	if (!isLoyalMember(eVoteSource))
	{
		return false;
	}

	return isVotingMember(eVoteSource);
}

bool CvPlayer::isVotingMember(VoteSourceTypes eVoteSource) const
{
	return (getVotes(NO_VOTE, eVoteSource) > 0);
}

PlayerTypes CvPlayer::pickConqueredCityOwner(const CvCity& kCity) const
{
	PlayerTypes eBestPlayer = kCity.getLiberationPlayer(true);

	if (NO_PLAYER != eBestPlayer)
	{
		if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(eBestPlayer).getTeam()))
		{
			return eBestPlayer;
		}
	}

	return getID();
}

bool CvPlayer::canHaveTradeRoutesWith(PlayerTypes ePlayer) const
{
	CvPlayer& kOtherPlayer = GET_PLAYER(ePlayer);

	if (!kOtherPlayer.isAlive())
	{
		return false;
	}

	if (getTeam() == kOtherPlayer.getTeam())
	{
		return true;
	}

	if (GET_TEAM(getTeam()).isFreeTrade(kOtherPlayer.getTeam()))
	{
		if (GET_TEAM(getTeam()).isVassal(kOtherPlayer.getTeam()))
		{
			return true;
		}

		if (GET_TEAM(kOtherPlayer.getTeam()).isVassal(getTeam()))
		{
			return true;
		}

		if (!isNoForeignTrade() && !kOtherPlayer.isNoForeignTrade())
		{
			return true;
		}
	}
	//Afforess: civics
	if (GC.getGameINLINE().getPlayerRank(getID()) < GC.getGameINLINE().getPlayerRank(ePlayer))
	{
		for (int iCivicOption = 0; iCivicOption < GC.getNumCivicOptionInfos(); iCivicOption++)
		{
			CivicTypes eCivic = getCivics((CivicOptionTypes)iCivicOption);
			if (eCivic != NO_CIVIC && GC.getCivicInfo(eCivic).isForcesOpenTradeWithWeakerPlayers())
			{
				int iWeakestThreshold = GC.getDefineINT("WEAKEST_PLAYER_THRESHOLD", 33);
				int iAliveCount = 0;
				for (int iI = 0; iI < MAX_PLAYERS; iI++)
				{
					if (GET_PLAYER((PlayerTypes)iI).isAlive())
					{
						iAliveCount++;
					}
				}
				int iRank = GC.getGameINLINE().getPlayerRank(ePlayer);
				int iBottomPlayers = std::max(1, iAliveCount * iWeakestThreshold / 100);
				if (iAliveCount - iRank < iBottomPlayers)
				{
					return true;
				}
				//If we can't force it on the first pass
				break;
			}
		}
	}
	//Afforess end

	return false;
}

bool CvPlayer::canStealTech(PlayerTypes eTarget, TechTypes eTech) const
{
	if (GET_TEAM(GET_PLAYER(eTarget).getTeam()).isHasTech(eTech))
	{
		if (canResearch(eTech))
		{
			return true;
		}
	}

	return false;
}

bool CvPlayer::canForceCivics(PlayerTypes eTarget, CivicTypes eCivic) const
{
	return (GET_PLAYER(eTarget).canDoCivics(eCivic) && !GET_PLAYER(eTarget).isCivic(eCivic) && isCivic(eCivic));
}

bool CvPlayer::canForceReligion(PlayerTypes eTarget, ReligionTypes eReligion) const
{
	return (GET_PLAYER(eTarget).canDoReligion(eReligion) && GET_PLAYER(eTarget).getStateReligion() != eReligion && getStateReligion() == eReligion);
}

bool CvPlayer::canSpyDestroyUnit(PlayerTypes eTarget, CvUnit& kUnit) const
{
	if (kUnit.getTeam() == getTeam())
	{
		return false;
	}

	if (kUnit.getUnitInfo().getProductionCost() <= 0)
	{
		return false;
	}

	if (!kUnit.plot()->isVisible(getTeam(), false))
	{
		return false;
	}

	return true;
}

bool CvPlayer::canSpyBribeUnit(PlayerTypes eTarget, CvUnit& kUnit) const
{
	if (!canSpyDestroyUnit(eTarget, kUnit))
	{
		return false;
	}

	// Can't buy units when at war
	if (kUnit.isEnemy(getTeam()))
	{
		return false;
	}

	// Can't buy units if they are not in a legal plot
	if (!GET_TEAM(getTeam()).isFriendlyTerritory(GET_PLAYER(eTarget).getTeam()) && !GET_TEAM(getTeam()).isOpenBorders(GET_PLAYER(eTarget).getTeam()))
	{
		return false;
	}

	CLLNode<IDInfo>* pUnitNode = kUnit.plot()->headUnitNode();

	while (pUnitNode != NULL)
	{
		CvUnit* pLoopUnit = ::getUnit(pUnitNode->m_data);
		pUnitNode = kUnit.plot()->nextUnitNode(pUnitNode);

		if (NULL != pLoopUnit && pLoopUnit != &kUnit)
		{
			if (pLoopUnit->isEnemy(getTeam()))
			{
				// If we buy the unit, we will be on the same plot as an enemy unit! Not good.
				return false;
			}
		}
	}

	return true;
}

bool CvPlayer::canSpyDestroyBuilding(PlayerTypes eTarget, BuildingTypes eBuilding) const
{
	CvBuildingInfo& kBuilding = GC.getBuildingInfo(eBuilding);
	if (kBuilding.getProductionCost() <= 0)
	{
		return false;
	}
	
	if (::isLimitedWonderClass((BuildingClassTypes)kBuilding.getBuildingClassType()))
	{
		return false;
	}

	return true;
}

bool CvPlayer::canSpyDestroyProject(PlayerTypes eTarget, ProjectTypes eProject) const
{
	CvProjectInfo& kProject = GC.getProjectInfo(eProject);
	if (kProject.getProductionCost() <= 0)
	{
		return false;
	}

	if (GET_TEAM(GET_PLAYER(eTarget).getTeam()).getProjectCount(eProject) <= 0)
	{
		return false;
	}

	if (::isWorldProject(eProject))
	{
		return false;
	}

	if (!kProject.isSpaceship())
	{
		return false;
	}
	else
	{
		VictoryTypes eVicotry = (VictoryTypes)kProject.getVictoryPrereq();
		if (NO_VICTORY != eVicotry)
		{
			// Can't destroy spaceship components if we have already launched
			if (GET_TEAM(GET_PLAYER(eTarget).getTeam()).getVictoryCountdown(eVicotry) >= 0)
			{
				return false;
			}
		}
	}	

	return true;
}

void CvPlayer::forcePeace(PlayerTypes ePlayer)
{
	if (!GET_TEAM(getTeam()).isAVassal())
	{
		FAssert(GET_TEAM(getTeam()).canChangeWarPeace(GET_PLAYER(ePlayer).getTeam()));

		CLinkList<TradeData> playerList;
		CLinkList<TradeData> loopPlayerList;
		TradeData kTradeData;
		setTradeItem(&kTradeData, TRADE_PEACE_TREATY);
		playerList.insertAtEnd(kTradeData);
		loopPlayerList.insertAtEnd(kTradeData);

		GC.getGameINLINE().implementDeal(getID(), ePlayer, &playerList, &loopPlayerList);
	}
}

bool CvPlayer::canSpiesEnterBorders(PlayerTypes ePlayer) const
{
	for (int iMission = 0; iMission < GC.getNumEspionageMissionInfos(); ++iMission)
	{
		if (GC.getEspionageMissionInfo((EspionageMissionTypes)iMission).isNoActiveMissions() && GC.getEspionageMissionInfo((EspionageMissionTypes)iMission).isPassive())
		{
			if (GET_PLAYER(ePlayer).canDoEspionageMission((EspionageMissionTypes)iMission, getID(), NULL, -1, NULL))
			{
				return false;
			}
		}
	}

	return true;
}

int CvPlayer::getReligionPopulation(ReligionTypes eReligion) const
{
	int iPopulation = 0;
	int iLoop;
	for (CvCity* pCity = firstCity(&iLoop); NULL != pCity; pCity = nextCity(&iLoop))
	{
		if (pCity->isHasReligion(eReligion))
		{
			iPopulation += pCity->getPopulation();
		}
	}

	return iPopulation;
}

int CvPlayer::getNewCityProductionValue() const
{
	int iValue = 0;
	for (int iJ = 0; iJ < GC.getNumBuildingClassInfos(); iJ++)
	{
		BuildingTypes eBuilding = ((BuildingTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iJ)));

		if (NO_BUILDING != eBuilding)
		{
			if (GC.getBuildingInfo(eBuilding).getFreeStartEra() != NO_ERA)
			{
				if (GC.getGameINLINE().getStartEra() >= GC.getBuildingInfo(eBuilding).getFreeStartEra())
				{
					iValue += (100 * getProductionNeeded(eBuilding)) / std::max(1, 100 + getProductionModifier(eBuilding));
				}
			}
		}
	}

	iValue *= 100 + GC.getDefineINT("NEW_CITY_BUILDING_VALUE_MODIFIER");
	iValue /= 100;

	iValue += (GC.getDefineINT("ADVANCED_START_CITY_COST") * GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent()) / 100;

	int iPopulation = GC.getDefineINT("INITIAL_CITY_POPULATION") + GC.getEraInfo(GC.getGameINLINE().getStartEra()).getFreePopulation();
	for (int i = 1; i <= iPopulation; ++i)
	{
		iValue += (getGrowthThreshold(i) * GC.getDefineINT("ADVANCED_START_POPULATION_COST")) / 100;
	}

	return iValue;
}

int CvPlayer::getGrowthThreshold(int iPopulation) const
{
	int iThreshold;
	iThreshold = (GC.getDefineINT("BASE_CITY_GROWTH_THRESHOLD") + (iPopulation * GC.getDefineINT("CITY_GROWTH_MULTIPLIER")));

	iThreshold *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGrowthPercent();
	iThreshold /= 100;
	
/************************************************************************************************/
/* Afforess	                  Start		 06/14/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
/*
	iThreshold *= GC.getEraInfo(GC.getGameINLINE().getStartEra()).getGrowthPercent();
*/
	iThreshold *= GC.getEraInfo(getCurrentEra()).getGrowthPercent();
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	iThreshold /= 100;

	if (!isHuman() && !isBarbarian())
	{
		iThreshold *= GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIGrowthPercent();
		iThreshold /= 100;

		iThreshold *= std::max(0, ((GC.getHandicapInfo(GC.getGameINLINE().getHandicapType()).getAIPerEraModifier() * getCurrentEra()) + 100));
		iThreshold /= 100;
	}
	
/************************************************************************************************/
/* Afforess	                  Start		 02/02/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	if (isGoldenAge())
	{
		iThreshold *= (100 + GC.getDefineINT("GOlDEN_AGE_PERCENT_LESS_FOOD_FOR_GROWTH"));
		iThreshold /= 100;
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

	return std::max(1, iThreshold);
}

void CvPlayer::verifyUnitStacksValid()
{
	int iLoop;
	for(CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		pLoopUnit->verifyStackValid();
	}
}

UnitTypes CvPlayer::getTechFreeUnit(TechTypes eTech) const
{
	UnitClassTypes eUnitClass = (UnitClassTypes) GC.getTechInfo(eTech).getFirstFreeUnitClass();
	if (eUnitClass == NO_UNITCLASS)
	{
		return NO_UNIT;
	}

	UnitTypes eUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(eUnitClass)));
	if (eUnit == NO_UNIT)
	{
		return NO_UNIT;
	}

	if (GC.getUnitInfo(eUnit).getEspionagePoints() > 0 && GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE))
	{
		return NO_UNIT;
	}

	return eUnit;
}

// BUG - Trade Totals - start
/*
 * Adds the yield and count for each trade route with eWithPlayer.
 *
 * The yield and counts are not reset to zero.
 * If Fractional Trade Routes is enabled and bRound is false, the yield values are left times 100.
 */
void CvPlayer::calculateTradeTotals(YieldTypes eIndex, int& iDomesticYield, int& iDomesticRoutes, int& iForeignYield, int& iForeignRoutes, PlayerTypes eWithPlayer, bool bRound, bool bBase) const
{
	int iIter;

	for (CvCity* pCity = firstCity(&iIter); NULL != pCity; pCity = nextCity(&iIter))
	{
		pCity->calculateTradeTotals(eIndex, iDomesticYield, iDomesticRoutes, iForeignYield, iForeignRoutes, eWithPlayer, bRound, bBase);
	}
}

/*
 * Returns the total trade yield with eWithPlayer.
 *
 * If Fractional Trade Routes is enabled, the yield value is left times 100.
 * UNUSED
 */
int CvPlayer::calculateTotalTradeYield(YieldTypes eIndex, PlayerTypes eWithPlayer, bool bRound, bool bBase) const
{
	int iDomesticYield = 0;
	int iDomesticRoutes = 0;
	int iForeignYield = 0;
	int iForeignRoutes = 0;
	
	calculateTradeTotals(eIndex, iDomesticYield, iDomesticRoutes, iForeignYield, iForeignRoutes, eWithPlayer, bRound, bBase);
	return iDomesticYield + iForeignRoutes;
}
// BUG - Trade Totals - end


void CvPlayer::buildTradeTable(PlayerTypes eOtherPlayer, CLinkList<TradeData>& ourList) const
{
	TradeData item;
	int iLoop;

	//	Put the gold and maps into the table
	setTradeItem(&item, TRADE_GOLD);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}

	//	Gold per turn
	setTradeItem(&item, TRADE_GOLD_PER_TURN);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}

	//	Maps
	setTradeItem(&item, TRADE_MAPS, 0);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}

	//	Vassal
	setTradeItem(&item, TRADE_VASSAL, 0);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}
/************************************************************************************************/
/* Afforess	                  Start		 06/16/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
     //Embassy
    setTradeItem(&item, TRADE_EMBASSY);
    if (canTradeItem(eOtherPlayer, item))
    {
        ourList.insertAtEnd(item);
    }
	
	//Free Trade
	setTradeItem(&item, TRADE_FREE_TRADE_ZONE);
    if (canTradeItem(eOtherPlayer, item))
    {
        ourList.insertAtEnd(item);
    }

	//Right of Passage
	setTradeItem(&item, TRADE_RITE_OF_PASSAGE);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}

	//War Reparations
	setTradeItem(&item, TRADE_WAR_REPARATIONS);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}

/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	//	Open Borders
	setTradeItem(&item, TRADE_OPEN_BORDERS);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}

	//	Defensive Pact
	setTradeItem(&item, TRADE_DEFENSIVE_PACT);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}

	//	Permanent Alliance
	setTradeItem(&item, TRADE_PERMANENT_ALLIANCE);
	if (canTradeItem(eOtherPlayer, item))
	{
		ourList.insertAtEnd(item);
	}

	if (::atWar(getTeam(), GET_PLAYER(eOtherPlayer).getTeam()))
	{
		//	We are at war, allow a peace treaty option
		setTradeItem(&item, TRADE_PEACE_TREATY);
		ourList.insertAtEnd(item);

		//	Capitulation
		setTradeItem(&item, TRADE_SURRENDER, 0);
		if (canTradeItem(eOtherPlayer, item))
		{
			ourList.insertAtEnd(item);
		}
	}

	//	Initial build of the inventory lists and buttons.
	//	Go through all the possible headings
	for (int i = NUM_BASIC_ITEMS; i < NUM_TRADEABLE_HEADINGS; i++)
	{
		//bool bFoundItemUs = false;

		//	Build what we need to build for this item
		switch (i)
		{
		case TRADE_TECHNOLOGIES:
			for (int j = 0; j < GC.getNumTechInfos(); j++)
			{
				setTradeItem(&item, TRADE_TECHNOLOGIES, j);
				if (canTradeItem(eOtherPlayer, item))
				{
					//bFoundItemUs = true;
					ourList.insertAtEnd(item);
				}
			}
			break;

		case TRADE_RESOURCES:
			for (int j = 0; j < GC.getNumBonusInfos(); j++)
			{
				setTradeItem(&item, TRADE_RESOURCES, j);
				if (canTradeItem(eOtherPlayer, item))
				{
					//bFoundItemUs = true;
					ourList.insertAtEnd(item);
				}
			}
			break;

		case TRADE_CITIES:
			for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				setTradeItem(&item, TRADE_CITIES, pLoopCity->getID());
				if (canTradeItem(eOtherPlayer, item))
				{
					//bFoundItemUs = true;
					ourList.insertAtEnd(item);
				}
			}
			break;

		case TRADE_PEACE:
			if (!isHuman())
			{
				for (int j = 0; j < MAX_CIV_TEAMS; j++)
				{
					if (GET_TEAM((TeamTypes)j).isAlive())
					{
						if (j != getTeam() && j != GET_PLAYER(eOtherPlayer).getTeam())
						{
							setTradeItem(&item, TRADE_PEACE, j);
							if (canTradeItem(eOtherPlayer, item))
							{
								ourList.insertAtEnd(item);
								//bFoundItemUs = true;
							}
						}
					}
				}
			}
			break;

		case TRADE_WAR:
			if (!isHuman())
			{
				for (int j = 0; j < MAX_CIV_TEAMS; j++)
				{
					if (GET_TEAM((TeamTypes)j).isAlive())
					{
						if (j != getTeam() && j != GET_PLAYER(eOtherPlayer).getTeam())
						{
							setTradeItem(&item, TRADE_WAR, j);
							if (canTradeItem(eOtherPlayer, item))
							{
								ourList.insertAtEnd(item);
								//bFoundItemUs = true;
							}
						}
					}
				}
			}
			break;

		case TRADE_EMBARGO:
			if (!isHuman())
			{
				for (int j = 0; j < MAX_CIV_TEAMS; j++)
				{
					if (GET_TEAM((TeamTypes)j).isAlive())
					{
						if (j != getTeam() && j != GET_PLAYER(eOtherPlayer).getTeam())
						{
							setTradeItem(&item, TRADE_EMBARGO, j);
							if (canTradeItem(eOtherPlayer, item))
							{
								ourList.insertAtEnd(item);
								//bFoundItemUs = true;
							}
						}
					}
				}
			}
			break;

		case TRADE_CIVIC:
			for (int j = 0; j < GC.getNumCivicInfos(); j++)
			{
				setTradeItem(&item, TRADE_CIVIC, j);
				if (canTradeItem(eOtherPlayer, item))
				{
					//bFoundItemUs = true;
					ourList.insertAtEnd(item);
				}
			}
			break;

		case TRADE_RELIGION:
			for (int j = 0; j < GC.getNumReligionInfos(); j++)
			{
				setTradeItem(&item, TRADE_RELIGION, j);
				if (canTradeItem(eOtherPlayer, item))
				{
					//bFoundItemUs = true;
					ourList.insertAtEnd(item);
				}
			}
			break;
/************************************************************************************************/
/* Afforess	                  Start		 06/16/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
        case TRADE_CORPORATION:
            for (int j = 0; j < GC.getNumCorporationInfos(); j++)
            {
                setTradeItem(&item, TRADE_CORPORATION, j);
                if (canTradeItem(eOtherPlayer, item))
                {
                    //bFoundItemUs = true;
                    ourList.insertAtEnd(item);
                }
            }
            break;

		case TRADE_SECRETARY_GENERAL_VOTE:
			for (int j = 0; j < GC.getNumVoteSourceInfos(); j++)
			{
				setTradeItem(&item, TRADE_SECRETARY_GENERAL_VOTE, j);
				if (canTradeItem(eOtherPlayer, item))
				{
					//bFoundItemUs = true;
					ourList.insertAtEnd(item);
				}
			}
			break;

        case TRADE_PLEDGE_VOTE:
            setTradeItem(&item, TRADE_PLEDGE_VOTE, PLAYER_VOTE_YES);
            if (canTradeItem(eOtherPlayer, item))
            {
                //bFoundItemUs = true;
                ourList.insertAtEnd(item);
            }

            setTradeItem(&item, TRADE_PLEDGE_VOTE, PLAYER_VOTE_NO);
            if (canTradeItem(eOtherPlayer, item))
            {
                //bFoundItemUs = true;
                ourList.insertAtEnd(item);
            }

            setTradeItem(&item, TRADE_PLEDGE_VOTE, PLAYER_VOTE_ABSTAIN);
            if (canTradeItem(eOtherPlayer, item))
            {
                //bFoundItemUs = true;
                ourList.insertAtEnd(item);
            }
            break;
		case TRADE_WORKER:
            for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
            {
                setTradeItem(&item, TRADE_WORKER, pLoopUnit->getID());
                if (canTradeItem(eOtherPlayer, item))
                {
                    //bFoundItemUs = true;
                    ourList.insertAtEnd(item);
                }
            }
            break;

        case TRADE_MILITARY_UNIT:
            for (CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
            {
                setTradeItem(&item, TRADE_MILITARY_UNIT, pLoopUnit->getID());
                if (canTradeItem(eOtherPlayer, item))
                {
                    //bFoundItemUs = true;
                    ourList.insertAtEnd(item);
                }
            }
            break;
        case TRADE_CONTACT:
            for (int j = 0; j < MAX_CIV_TEAMS; j++)
            {
                if (GET_TEAM((TeamTypes)j).isAlive())
                {
                    if (j != getTeam() && j != GET_PLAYER(eOtherPlayer).getTeam())
                    {
                        setTradeItem(&item, TRADE_CONTACT, j);
                        if (canTradeItem(eOtherPlayer, item))
                        {
                            ourList.insertAtEnd(item);
                            //bFoundItemUs = true;
                        }
                    }
                }
            }
            break;
		case TRADE_CEASE_RELATIONS:
			for (int j = 0; j < MAX_CIV_PLAYERS; j++)
			{
				if (GET_PLAYER((PlayerTypes)j).isAlive())
				{
					if (j != getID() && j != GET_PLAYER(eOtherPlayer).getID())
					{
						setTradeItem(&item, TRADE_CEASE_RELATIONS, j);
						if (canTradeItem(eOtherPlayer, item))
						{
							ourList.insertAtEnd(item);
							//bFoundItemUs = true;
						}
					}
				}
			}
			break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		}
	}
}

bool CvPlayer::getHeadingTradeString(PlayerTypes eOtherPlayer, TradeableItems eItem, CvWString& szString, CvString& szIcon) const
{
	szIcon.clear();

	switch ( eItem )
	{
	case TRADE_TECHNOLOGIES:
		szString = gDLL->getText("TXT_KEY_CONCEPT_TECHNOLOGY");
		break;

	case TRADE_RESOURCES:
		szString = gDLL->getText("TXT_KEY_TRADE_RESOURCES");
		break;

	case TRADE_CITIES:
		szString = gDLL->getText("TXT_KEY_TRADE_CITIES");
		break;

/************************************************************************************************/
/* Afforess	                  Start		 07/29/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
    case TRADE_WORKER:
        szString = gDLL->getText("TXT_KEY_TRADE_WORKERS");
        break;

    case TRADE_MILITARY_UNIT:
        szString = gDLL->getText("TXT_KEY_TRADE_MILITARY_UNIT");
        break;
    case TRADE_CONTACT:
		szString =  gDLL->getText("TXT_KEY_TRADE_MAKE_CONTACT_WITH");
		break;
	case TRADE_CEASE_RELATIONS:
		szString = gDLL->getText("TXT_KEY_TRADE_CEASE_RELATIONS_WITH");
		break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	case TRADE_PEACE:
		szString = gDLL->getText("TXT_KEY_TRADE_MAKE_PEACE_WITH");
		break;

	case TRADE_WAR:
		szString = gDLL->getText("TXT_KEY_TRADE_DECLARE_WAR_ON");
		break;

	case TRADE_EMBARGO:
		szString = gDLL->getText("TXT_KEY_TRADE_STOP_TRADING_WITH");
		break;

	case TRADE_CIVIC:
		szString = gDLL->getText("TXT_KEY_TRADE_ADOPT");
		break;

	case TRADE_RELIGION:
		szString = gDLL->getText("TXT_KEY_TRADE_CONVERT");
		break;
/************************************************************************************************/
/* Afforess	                  Start		 07/29/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
    case TRADE_CORPORATION:
        szString = gDLL->getText("TXT_KEY_TRADE_BUY_CORPORATION");
        break;
    case TRADE_PLEDGE_VOTE:
        szString = gDLL->getText("TXT_KEY_TRADE_PLEDGE_VOTE");
        break;
	case TRADE_SECRETARY_GENERAL_VOTE:
		szString = gDLL->getText("TXT_KEY_TRADE_SECRETARY_GENERAL_VOTE");
		break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	default:
		szString.clear();
		return false;
		break;
	}

	return true;
}


bool CvPlayer::getItemTradeString(PlayerTypes eOtherPlayer, bool bOffer, bool bShowingCurrent, const TradeData& zTradeData, CvWString& szString, CvString& szIcon) const
{
	szIcon.clear();

	switch (zTradeData.m_eItemType)
	{
	case TRADE_GOLD:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_GOLD_NUM", zTradeData.m_iData);
		}
		else
		{
			szString = gDLL->getText("TXT_KEY_TRADE_GOLD_NUM", AI_maxGoldTrade(eOtherPlayer));
		}
		break;
	case TRADE_GOLD_PER_TURN:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_GOLD_PER_TURN_NUM", zTradeData.m_iData);
		}
		else
		{
			szString = gDLL->getText("TXT_KEY_TRADE_GOLD_PER_TURN_NUM", AI_maxGoldPerTurnTrade(eOtherPlayer));
		}
		break;
	case TRADE_MAPS:
		szString = gDLL->getText("TXT_KEY_TRADE_WORLD_MAP_STRING");
		break;
	case TRADE_VASSAL:
		szString = gDLL->getText("TXT_KEY_TRADE_VASSAL_STRING");
		break;
	case TRADE_SURRENDER:
		szString = gDLL->getText("TXT_KEY_TRADE_CAPITULATE_STRING");
		break;
	case TRADE_OPEN_BORDERS:
		szString = gDLL->getText("TXT_KEY_TRADE_OPEN_BORDERS_STRING");
		break;
	case TRADE_DEFENSIVE_PACT:
		szString = gDLL->getText("TXT_KEY_TRADE_DEFENSIVE_PACT_STRING");
		break;
	case TRADE_PERMANENT_ALLIANCE:
		szString = gDLL->getText("TXT_KEY_TRADE_PERMANENT_ALLIANCE_STRING");
		break;
	case TRADE_PEACE_TREATY:
		szString = gDLL->getText("TXT_KEY_TRADE_PEACE_TREATY_STRING", getTreatyLength());
		break;
	case TRADE_TECHNOLOGIES:
		szString = GC.getTechInfo((TechTypes)zTradeData.m_iData).getDescription();
		szIcon = GC.getTechInfo((TechTypes)zTradeData.m_iData).getButton();
		break;
	case TRADE_RESOURCES:
		if (bOffer)
		{
			int iNumResources = GET_PLAYER(eOtherPlayer).getNumTradeableBonuses((BonusTypes)zTradeData.m_iData);
			if (bShowingCurrent)
			{
				++iNumResources;
			}
			szString = gDLL->getText("TXT_KEY_TRADE_RESOURCE", GC.getBonusInfo((BonusTypes)zTradeData.m_iData).getDescription(), iNumResources);

		}
		else
		{
			szString.Format( L"%s (%d)", GC.getBonusInfo((BonusTypes)zTradeData.m_iData).getDescription(), getNumTradeableBonuses((BonusTypes)zTradeData.m_iData));
		}
		szIcon = GC.getBonusInfo((BonusTypes)zTradeData.m_iData).getButton();
		break;
	case TRADE_CITIES:
		{
			CvCity* pCity = NULL;
			if (bOffer)
			{
				pCity = GET_PLAYER(eOtherPlayer).getCity(zTradeData.m_iData);
			}
			else
			{
				pCity = getCity(zTradeData.m_iData);
			}
			if (NULL != pCity)
			{
				if (pCity->getLiberationPlayer(false) == eOtherPlayer)
				{
					szString.Format(L"%s (%s)", pCity->getName().GetCString(), gDLL->getText("TXT_KEY_LIBERATE_CITY").GetCString());
				}
				else
				{
					szString = gDLL->getText("TXT_KEY_CITY_OF", pCity->getNameKey());
				}
			}
		}
		break;
		
	case TRADE_PEACE:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_PEACE_WITH");
			szString += GET_TEAM((TeamTypes)zTradeData.m_iData).getName();
		}
		else
		{
			szString = GET_TEAM((TeamTypes)zTradeData.m_iData).getName();
		}
		break;
	case TRADE_WAR:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_WAR_WITH");
			szString += GET_TEAM((TeamTypes)zTradeData.m_iData).getName();
		}
		else
		{
			szString = GET_TEAM((TeamTypes)zTradeData.m_iData).getName();
		}
		break;
	case TRADE_EMBARGO:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_STOP_TRADING_WITH");
			szString += L" " + GET_TEAM((TeamTypes)zTradeData.m_iData).getName();
		}
		else
		{
			szString = GET_TEAM((TeamTypes)zTradeData.m_iData).getName();
		}
		break;
	case TRADE_CIVIC:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_ADOPT");
			szString += GC.getCivicInfo((CivicTypes)zTradeData.m_iData).getDescription();
		}
		else
		{
			szString = GC.getCivicInfo((CivicTypes)zTradeData.m_iData).getDescription();
		}
		szIcon = GC.getCivicInfo((CivicTypes)zTradeData.m_iData).getButton();
		break;
	case TRADE_RELIGION:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_CONVERT");
			szString += GC.getReligionInfo((ReligionTypes)zTradeData.m_iData).getDescription();
		}
		else
		{
			szString = GC.getReligionInfo((ReligionTypes)zTradeData.m_iData).getDescription();
		}
		szIcon = GC.getReligionInfo((ReligionTypes)zTradeData.m_iData).getButton();
		break;
/************************************************************************************************/
/* Afforess	                  Start		 06/16/10                                               */
/*                                                                                              */
/* Advanced Diplomacy                                                                           */
/************************************************************************************************/
    case TRADE_WORKER:
        {
            CvUnit* pUnit = NULL;
            if (bOffer)
            {
                pUnit = GET_PLAYER(eOtherPlayer).getUnit(zTradeData.m_iData);
            }
            else
            {
                pUnit = getUnit(zTradeData.m_iData);
            }
            if (pUnit != NULL)
            {
                szString.Format(L"%s", pUnit->getName().GetCString());
				szIcon = GC.getUnitInfo((UnitTypes)pUnit->getUnitType()).getButton();
            }
        }
        break;

    case TRADE_MILITARY_UNIT:
        {
            CvUnit* pUnit = NULL;
            if (bOffer)
            {
                pUnit = GET_PLAYER(eOtherPlayer).getUnit(zTradeData.m_iData);
            }
            else
            {
                pUnit = getUnit(zTradeData.m_iData);
            }
            if (pUnit != NULL)
            {
                CvWStringBuffer szTemp;
                //GAMETEXT.setUnitHelp(szTemp, pUnit, true);
                //szString = CvWString(szTemp.getCString());
				szString.Format(L"%s", pUnit->getName().GetCString());
				szIcon = GC.getUnitInfo((UnitTypes)pUnit->getUnitType()).getButton();
            }
        }
        break;
    case TRADE_CONTACT:
        if (bOffer)
        {
            szString = gDLL->getText("TXT_KEY_TRADE_CONTACT_WITH");
			szString += gDLL->getText(" ");
            szString += GET_TEAM((TeamTypes)zTradeData.m_iData).getName();
        }
        else
        {
			szString = gDLL->getText(" ");
            szString += GET_TEAM((TeamTypes)zTradeData.m_iData).getName();
        }
        break;
	case TRADE_CEASE_RELATIONS:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_CEASE_RELATIONS_WITH");
			szString += gDLL->getText(" ");
			szString += GET_PLAYER((PlayerTypes)zTradeData.m_iData).getName();
		}
		else
		{
			szString = GET_PLAYER((PlayerTypes)zTradeData.m_iData).getName();
		}
		break;
	case TRADE_CORPORATION:
        if (bOffer)
        {
            szString = gDLL->getText("TXT_KEY_TRADE_BUY");
			szString += gDLL->getText(" ");
            szString += GC.getCorporationInfo((CorporationTypes)zTradeData.m_iData).getDescription();
        }
        else
        {
			szString = gDLL->getText(" ");
            szString += GC.getCorporationInfo((CorporationTypes)zTradeData.m_iData).getDescription();
        }
        szIcon = GC.getCorporationInfo((CorporationTypes)zTradeData.m_iData).getButton();
        break;
    case TRADE_PLEDGE_VOTE:
        szString = gDLL->getText("TXT_KEY_TRADE_VOTE");
        if ((PlayerVoteTypes)zTradeData.m_iData == PLAYER_VOTE_YES)
        {
            szString = gDLL->getText("TXT_KEY_POPUP_YES");
        }
        else if ((PlayerVoteTypes)zTradeData.m_iData == PLAYER_VOTE_NO)
        {
            szString = gDLL->getText("TXT_KEY_POPUP_NO");
        }
        else if ((PlayerVoteTypes)zTradeData.m_iData == PLAYER_VOTE_ABSTAIN)
        {
            szString = gDLL->getText("TXT_KEY_POPUP_ABSTAIN");
        }
        break;
	case TRADE_SECRETARY_GENERAL_VOTE:
		if (bOffer)
		{
			szString = gDLL->getText("TXT_KEY_TRADE_SEC_GEN_VOTE", GET_PLAYER(eOtherPlayer).getNameKey(), GC.getVoteSourceInfo((VoteSourceTypes)zTradeData.m_iData).getDescription());
		}
		else
		{
			szString = GC.getVoteSourceInfo((VoteSourceTypes)zTradeData.m_iData).getDescription();
		}
		break;
	case TRADE_RITE_OF_PASSAGE:
		szString = gDLL->getText("TXT_KEY_TRADE_LIMITED_BORDERS_STRING");
		break;
	case TRADE_FREE_TRADE_ZONE:
		szString = gDLL->getText("TXT_KEY_MISC_FREE_TRADE_ZONE");
		break;
	case TRADE_EMBASSY:
        szString = gDLL->getText("TXT_KEY_TRADE_EMBASSY_STRING");
        break;
	case TRADE_WAR_REPARATIONS:
		szString = gDLL->getText("TXT_KEY_TRADE_WAR_REPARATIONS_STRING");
		break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/

/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	default:
		szString.clear();
		return false;
	}

	return true;
}

void CvPlayer::updateTradeList(PlayerTypes eOtherPlayer, CLinkList<TradeData>& ourInventory, const CLinkList<TradeData>& ourOffer, const CLinkList<TradeData>& theirOffer) const
{
	for (CLLNode<TradeData>* pNode = ourInventory.head(); pNode != NULL; pNode = ourInventory.next(pNode))
	{
		pNode->m_data.m_bHidden = false;

		// Don't show peace treaties when not at war
		if (!::atWar(getTeam(), GET_PLAYER(eOtherPlayer).getTeam()))
		{
			if (pNode->m_data.m_eItemType == TRADE_PEACE_TREATY || pNode->m_data.m_eItemType == TRADE_SURRENDER)
			{
				pNode->m_data.m_bHidden = true;
			}
		}
		// Afforess: Don't show war reparations when at war
		else
		{
			if (pNode->m_data.m_eItemType == TRADE_WAR_REPARATIONS)
			{
				pNode->m_data.m_bHidden = true;
			}
		}

		// Don't show technologies with no tech trading game option 
		if (GC.getGame().isOption(GAMEOPTION_NO_TECH_TRADING) && pNode->m_data.m_eItemType == TRADE_TECHNOLOGIES)
		{
			pNode->m_data.m_bHidden = true;
		}
	}

	for (CLLNode<TradeData>* pNode = ourInventory.head(); pNode != NULL; pNode = ourInventory.next(pNode))
	{
		switch (pNode->m_data.m_eItemType)
		{
		case TRADE_PEACE_TREATY:
			for (CLLNode<TradeData>* pOfferNode = ourOffer.head(); pOfferNode != NULL; pOfferNode = ourOffer.next(pOfferNode))
			{
				// Don't show vassal deals if peace treaty is already on the table
				if (CvDeal::isVassal(pOfferNode->m_data.m_eItemType))
				{
					pNode->m_data.m_bHidden = true;
					break;
				}
			}
			break;
		case TRADE_VASSAL:
		case TRADE_SURRENDER:
			for (CLLNode<TradeData>* pOfferNode = theirOffer.head(); pOfferNode != NULL; pOfferNode = theirOffer.next(pOfferNode))
			{
				// Don't show vassal deals if another type of vassal deal is on the table
				if (CvDeal::isVassal(pOfferNode->m_data.m_eItemType))
				{
					pNode->m_data.m_bHidden = true;
					break;
				}
			}

			if (!pNode->m_data.m_bHidden)
			{
				for (CLLNode<TradeData>* pOfferNode = ourOffer.head(); pOfferNode != NULL; pOfferNode = ourOffer.next(pOfferNode))
				{
					// Don't show peace deals if the other player is offering to be a vassal
					if (CvDeal::isEndWar(pOfferNode->m_data.m_eItemType))
					{
						pNode->m_data.m_bHidden = true;
						break;
					}
				}
			}
			break;
/************************************************************************************************/
/* Afforess	                  Start		 12/9/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
        case TRADE_PLEDGE_VOTE:
			for (CLLNode<TradeData>* pOfferNode = theirOffer.head(); pOfferNode != NULL; pOfferNode = theirOffer.next(pOfferNode))
			{
				// Don't show other trade items of the same category if it's a single option
				if (CvDeal::isSingleOption(pOfferNode->m_data.m_eItemType) && (pOfferNode->m_data.m_eItemType == pNode->m_data.m_eItemType))
				{
					pNode->m_data.m_bHidden = true;
					break;
				}
			}
			break;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
		default:
			break;
		}
	}
	/************************************************************************************************/
	/* Afforess	                  Start		5/29/11                                                 */
	/*                                                                                              */
	/* Allow city trades for other items                                                            */
	/************************************************************************************************/
	/*if (!isHuman() || !GET_PLAYER(eOtherPlayer).isHuman())  // everything allowed in human-human trades
	{
		CLLNode<TradeData>* pFirstOffer = ourOffer.head();
		if (pFirstOffer == NULL)
		{
			pFirstOffer = theirOffer.head();
		}

		if (pFirstOffer != NULL)
		{
			if (!CvDeal::isEndWar(pFirstOffer->m_data.m_eItemType) || !::atWar(getTeam(), GET_PLAYER(eOtherPlayer).getTeam()))
			{
				for (CLLNode<TradeData>* pNode = ourInventory.head(); pNode != NULL; pNode = ourInventory.next(pNode))
				{
					if (pFirstOffer->m_data.m_eItemType == TRADE_CITIES || pNode->m_data.m_eItemType == TRADE_CITIES)
					{
						pNode->m_data.m_bHidden = true;
					}
					else if (CvDeal::isAnnual(pFirstOffer->m_data.m_eItemType) != CvDeal::isAnnual(pNode->m_data.m_eItemType))
					{
						pNode->m_data.m_bHidden = true;
					}
				}
			}
		}
	}*/
	/************************************************************************************************/
	/* Afforess	                     END                                                            */
	/************************************************************************************************/
}

int CvPlayer::getIntroMusicScriptId(PlayerTypes eForPlayer) const
{
	CvPlayer& kForPlayer = GET_PLAYER(eForPlayer);
	EraTypes eEra = kForPlayer.getCurrentEra();
	CvLeaderHeadInfo& kLeader = GC.getLeaderHeadInfo(getLeaderType());
	if (GET_TEAM(kForPlayer.getTeam()).isAtWar(getTeam()))
	{
		return kLeader.getDiploWarIntroMusicScriptIds(eEra);
	}
	else
	{
		return kLeader.getDiploPeaceIntroMusicScriptIds(eEra);
	}
}

int CvPlayer::getMusicScriptId(PlayerTypes eForPlayer) const
{
	CvPlayer& kForPlayer = GET_PLAYER(eForPlayer);
	EraTypes eEra = kForPlayer.getCurrentEra();
	CvLeaderHeadInfo& kLeader = GC.getLeaderHeadInfo(getLeaderType());
	if (GET_TEAM(kForPlayer.getTeam()).isAtWar(getTeam()))
	{
		return kLeader.getDiploWarMusicScriptIds(eEra);
	}
	else
	{
		return kLeader.getDiploPeaceMusicScriptIds(eEra);
	}
}


void CvPlayer::getGlobeLayerColors(GlobeLayerTypes eGlobeLayerType, int iOption, std::vector<NiColorA>& aColors, std::vector<CvPlotIndicatorData>& aIndicators) const
{
	switch (eGlobeLayerType)
	{
	case GLOBE_LAYER_TRADE:
		getTradeLayerColors(aColors, aIndicators);
		break;
	case GLOBE_LAYER_UNIT:
		getUnitLayerColors((GlobeLayerUnitOptionTypes) iOption, aColors, aIndicators);
		break;
	case GLOBE_LAYER_RESOURCE:
		getResourceLayerColors((GlobeLayerResourceOptionTypes) iOption, aColors, aIndicators);
		break;
	case GLOBE_LAYER_RELIGION:
		getReligionLayerColors((ReligionTypes) iOption, aColors, aIndicators);
		break;
	case GLOBE_LAYER_CULTURE:
		getCultureLayerColors(aColors, aIndicators);
		break;
	default:
		FAssertMsg(false, "Unknown globe layer type");
		break;
	}
}

void CvPlayer::getTradeLayerColors(std::vector<NiColorA>& aColors, std::vector<CvPlotIndicatorData>& aIndicators) const
{
	aColors.resize(GC.getCurrentViewport()->numPlots(), NiColorA(0, 0, 0, 0));
	aIndicators.clear();

	typedef std::map< int, std::vector<int> > PlotGroupMap;
	PlotGroupMap mapPlotGroups;
	for (int iI = 0; iI < GC.getCurrentViewport()->numPlots(); ++iI)
	{
		CvPlot* pLoopPlot = GC.getCurrentViewport()->plotByIndex(iI);
		CvPlotGroup* pPlotGroup = pLoopPlot->getPlotGroup(getID());
		if (pPlotGroup != NULL && pLoopPlot->isRevealed(getTeam(), true) && pLoopPlot->getTeam() == getTeam())
		{
			mapPlotGroups[pPlotGroup->getID()].push_back(iI);
		}
	}

	CvRandom kRandom;
	kRandom.init(42);
	for (PlotGroupMap::iterator it = mapPlotGroups.begin(); it != mapPlotGroups.end(); ++it)
	{
		NiColorA kColor(kRandom.getFloat(), kRandom.getFloat(), kRandom.getFloat(), 0.8f);
		std::vector<int>& aPlots = it->second;
		for (size_t i = 0; i < aPlots.size(); ++i)
		{
			aColors[aPlots[i]] = kColor;
		}
	}
}

void CvPlayer::getUnitLayerColors(GlobeLayerUnitOptionTypes eOption, std::vector<NiColorA>& aColors, std::vector<CvPlotIndicatorData>& aIndicators) const
{
	aColors.resize(GC.getCurrentViewport()->numPlots(), NiColorA(0, 0, 0, 0));
	aIndicators.clear();

	std::vector< std::vector<float> > aafPlayerPlotStrength(MAX_PLAYERS);
	for (int i = 0; i < MAX_PLAYERS; i++)
	{
		if (GET_PLAYER((PlayerTypes)i).isAlive())
		{
			aafPlayerPlotStrength[i].resize(GC.getCurrentViewport()->numPlots());
		}
	}

	float fMaxPlotStrength = 0.0f;

	// create unit plot indicators...
	// build the trade group texture
	//typedef std::map<int, NiColor> GroupMap;
	//GroupMap mapColors;

	// Loop through all the players
	CvWStringBuffer szBuffer;
	for (int iPlayer = 0; iPlayer < MAX_PLAYERS; iPlayer++)
	{
		if (GET_PLAYER((PlayerTypes)iPlayer).isAlive())
		{
			for (int iI = 0; iI < GC.getCurrentViewport()->numPlots(); ++iI)
			{
				CvPlot* pLoopPlot = GC.getCurrentViewport()->plotByIndex(iI);
				int iNumUnits = pLoopPlot->getNumUnits();
				float fPlotStrength = 0.0f;

				if (iNumUnits > 0 && pLoopPlot->isVisible(getTeam(), true))
				{
					bool bShowIndicator = false;

					CLLNode<IDInfo>* pUnitNode = pLoopPlot->headUnitNode();
					while (pUnitNode != NULL)
					{
						CvUnit* pUnit = ::getUnit(pUnitNode->m_data);
						pUnitNode = pLoopPlot->nextUnitNode(pUnitNode);

						if (pUnit->getVisualOwner() == iPlayer && !pUnit->isInvisible(getTeam(), GC.getGameINLINE().isDebugMode()))
						{
							// now, is this unit of interest?
							bool bIsMilitary = pUnit->baseCombatStr() > 0;
							bool bIsEnemy = pUnit->isEnemy(getTeam());
							bool bIsOnOurTeam = pUnit->getTeam() == getTeam();
							bool bOfInterest = false;

							switch (eOption)
							{
							case SHOW_ALL_MILITARY:
								{
									bOfInterest = bIsMilitary;
									if (bOfInterest)
									{
										fPlotStrength += ((float) pUnit->currHitPoints() / (float) pUnit->maxHitPoints() * (float) pUnit->baseCombatStr());
									}
									break;
								}
							case SHOW_TEAM_MILITARY:
								{
									bOfInterest = bIsMilitary && bIsOnOurTeam;
									if (bOfInterest)
										fPlotStrength += ((float) pUnit->currHitPoints() / (float) pUnit->maxHitPoints() * (float) pUnit->baseCombatStr());
									break;
								}
							case SHOW_ENEMIES:
								{
									bOfInterest = bIsMilitary && bIsEnemy;
									if (bOfInterest)
										fPlotStrength += ((float) pUnit->currHitPoints() / (float) pUnit->maxHitPoints() * (float) pUnit->baseCombatStr());
									break;
								}

							case SHOW_ENEMIES_IN_TERRITORY:
								{
									bOfInterest = bIsMilitary;
									break;
								}

							case SHOW_PLAYER_DOMESTICS:
								{
									bOfInterest = !bIsMilitary;// && (pUnit->getVisualOwner() == eCurPlayer);
									break;
								}
							default:
								bOfInterest = false; 
								break;
							}

							// create the indicator
							if (bOfInterest)
							{
								bShowIndicator = true;
							}

							fMaxPlotStrength = std::max(fPlotStrength, fMaxPlotStrength);
							aafPlayerPlotStrength[iPlayer][iI] = fPlotStrength;
						}
					}

					if (bShowIndicator)
					{
						CvUnit* pUnit = pLoopPlot->getBestDefender(NO_PLAYER);
						if (pUnit != NULL)
						{
							PlayerColorTypes eUnitColor = GET_PLAYER(pUnit->getVisualOwner()).getPlayerColor();
							const NiColorA& kColor = GC.getColorInfo((ColorTypes) GC.getPlayerColorInfo(eUnitColor).getColorTypePrimary()).getColor();

							szBuffer.clear();
							GAMETEXT.setPlotListHelp(szBuffer, pLoopPlot, true, true);

							CvPlotIndicatorData kIndicator;
							kIndicator.m_pUnit = pUnit;
							kIndicator.m_strLabel = "UNITS";
							kIndicator.m_strIcon = pUnit->getButton();

							if (eOption == SHOW_ENEMIES_IN_TERRITORY)
							{
								kIndicator.m_kColor.r = 1;
								kIndicator.m_kColor.g = 0;
								kIndicator.m_kColor.b = 0;
							}
							else
							{
								kIndicator.m_kColor.r = kColor.r;
								kIndicator.m_kColor.g = kColor.g;
								kIndicator.m_kColor.b = kColor.b;
							}
							kIndicator.m_strHelpText = szBuffer.getCString();

							//setup visibility
							switch (eOption)
							{
							case SHOW_ENEMIES_IN_TERRITORY:
								kIndicator.m_bTestEnemyVisibility = true;
								kIndicator.m_eVisibility = PLOT_INDICATOR_VISIBLE_ALWAYS;
								break;
							case SHOW_ENEMIES:
								kIndicator.m_eVisibility = PLOT_INDICATOR_VISIBLE_ALWAYS;
								break;
							default:
								kIndicator.m_eVisibility = PLOT_INDICATOR_VISIBLE_ONSCREEN_ONLY;
								break;
							}
							aIndicators.push_back(kIndicator);
						}
					}
				}
			}
		}
	}

	if (fMaxPlotStrength > 0)
	{
		for (int iPlayer = 0; iPlayer < MAX_PLAYERS; iPlayer++)
		{
			if (GET_PLAYER((PlayerTypes)iPlayer).isAlive())
			{
				PlayerColorTypes eCurPlayerColor = GET_PLAYER((PlayerTypes) iPlayer).getPlayerColor();
				const NiColorA& kColor = GC.getColorInfo((ColorTypes) GC.getPlayerColorInfo(eCurPlayerColor).getColorTypePrimary()).getColor();

				for (int iI = 0; iI < GC.getCurrentViewport()->numPlots(); iI++)
				{
					CvPlot* pLoopPlot = GC.getCurrentViewport()->plotByIndex(iI);
					if (pLoopPlot->isVisible(getTeam(), true))
					{
						float fPlotStrength = aafPlayerPlotStrength[iPlayer][iI];
						if (fPlotStrength > 0)
						{
							float fAlpha = (fPlotStrength / fMaxPlotStrength * 0.75f + 0.25f) * 0.8f;
							if (fAlpha > aColors[iI].a)
							{
								aColors[iI] = kColor;
								aColors[iI].a = fAlpha;
							}
						}
					}
				}
			}
		}
	}
}

void CvPlayer::getResourceLayerColors(GlobeLayerResourceOptionTypes eOption, std::vector<NiColorA>& aColors, std::vector<CvPlotIndicatorData>& aIndicators) const
{
	aColors.clear();
	aIndicators.clear();

	//PlayerColorTypes ePlayerColor = getPlayerColor();

	CvWStringBuffer szBuffer;
	for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
		PlayerTypes eOwner = pLoopPlot->getRevealedOwner(getTeam(), true); 

		if (pLoopPlot->isRevealed(getTeam(), true) && pLoopPlot->isInViewport())
		{
			BonusTypes eCurType = pLoopPlot->getBonusType((GC.getGame().isDebugMode()) ? NO_TEAM : getTeam());
			if (eCurType != NO_BONUS)
			{
				CvBonusInfo& kBonusInfo = GC.getBonusInfo(eCurType);

				bool bOfInterest = false;
				switch (eOption)
				{
				case SHOW_ALL_RESOURCES:
					bOfInterest = true;
					break;
				case SHOW_STRATEGIC_RESOURCES:
					bOfInterest = (kBonusInfo.getHappiness() == 0) && (kBonusInfo.getHealth() == 0);
					break;
				case SHOW_HAPPY_RESOURCES:
					bOfInterest = (kBonusInfo.getHappiness() != 0 ) && (kBonusInfo.getHealth() == 0);
					break;
				case SHOW_HEALTH_RESOURCES:
					bOfInterest = (kBonusInfo.getHappiness() == 0) && (kBonusInfo.getHealth() != 0);
					break;

				}

				if (bOfInterest)
				{
					CvPlotIndicatorData kData;
					kData.m_strLabel = "RESOURCES";
					kData.m_eVisibility = PLOT_INDICATOR_VISIBLE_ONSCREEN_ONLY;
					kData.m_strIcon = GC.getBonusInfo(eCurType).getButton();

					int x = pLoopPlot->getViewportX();
					int y = pLoopPlot->getViewportY();
					kData.m_Target = NiPoint2(GC.getCurrentViewport()->plotXToPointX(x), GC.getCurrentViewport()->plotYToPointY(y));

					if (eOwner == NO_PLAYER)
					{
						kData.m_kColor.r = 0.8f;
						kData.m_kColor.g = 0.8f;
						kData.m_kColor.b = 0.8f;
					}
					else
					{
						PlayerColorTypes eCurPlayerColor = GET_PLAYER(eOwner).getPlayerColor();
						const NiColorA& kColor = GC.getColorInfo((ColorTypes) GC.getPlayerColorInfo(eCurPlayerColor).getColorTypePrimary()).getColor();
						kData.m_kColor.r = kColor.r;
						kData.m_kColor.g = kColor.g;
						kData.m_kColor.b = kColor.b;
					}

					szBuffer.clear();
					GAMETEXT.setBonusHelp(szBuffer, eCurType, false);
					kData.m_strHelpText = szBuffer.getCString();

					aIndicators.push_back(kData);
				}
			}
		}
	}
}

void CvPlayer::getReligionLayerColors(ReligionTypes eSelectedReligion, std::vector<NiColorA>& aColors, std::vector<CvPlotIndicatorData>& aIndicators) const
{
	aColors.resize(GC.getCurrentViewport()->numPlots(), NiColorA(0, 0, 0, 0));
	aIndicators.clear();

	CvRandom kRandom;
	kRandom.init(42 * eSelectedReligion);
	const NiColorA kBaseColor(kRandom.getFloat(), kRandom.getFloat(), kRandom.getFloat(), 1.0f);

	for (int iI = 0; iI  < MAX_PLAYERS; iI ++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			int iLoop;
			for (CvCity* pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
			{
				if (pLoopCity->isRevealed(getTeam(), true))
				{
					if (pLoopCity->isHasReligion(eSelectedReligion))
					{
						float fAlpha = 0.8f;
						if (!pLoopCity->isHolyCity(eSelectedReligion))
						{
							fAlpha *= 0.5f;
						}

						// loop through the city's plots
						for (int iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
						{
							CvPlot* pLoopPlot = plotCity(pLoopCity->getX(), pLoopCity->getY(), iJ);
							if (pLoopPlot != NULL)
							{
								// visibility query
								if (pLoopPlot->isRevealed(getTeam(), true) && pLoopPlot->isInViewport())
								{
									int iIndex = GC.getCurrentViewport()->plotNum(pLoopPlot->getViewportX(), pLoopPlot->getViewportY());
									if (fAlpha > aColors[iIndex].a)
									{
										aColors[iIndex] = kBaseColor;
										aColors[iIndex].a = fAlpha;
									}
								}
							}
						}
					}
				}
			}
		}
	}
}

void CvPlayer::getCultureLayerColors(std::vector<NiColorA>& aColors, std::vector<CvPlotIndicatorData>& aIndicators) const
{
	const int iColorsPerPlot = 4;
	aColors.resize(GC.getCurrentViewport()->numPlots() * iColorsPerPlot, NiColorA(0, 0, 0, 0));
	aIndicators.clear();

	// find maximum total culture
	int iMaxTotalCulture = INT_MIN;
	int iMinTotalCulture = INT_MAX;
	for (int iI = 0; iI < GC.getCurrentViewport()->numPlots(); iI++)
	{
		CvPlot* pLoopPlot = GC.getCurrentViewport()->plotByIndex(iI);
		int iTotalCulture = pLoopPlot->countTotalCulture();
		if (iTotalCulture > iMaxTotalCulture)
		{
			iMaxTotalCulture = iTotalCulture;
		}
		if (iTotalCulture < iMinTotalCulture && iTotalCulture > 0)
		{
			iMinTotalCulture = iTotalCulture;
		}
	}
	iMinTotalCulture = 0;

	// find culture percentages
	for (int iI = 0; iI < GC.getCurrentViewport()->numPlots(); iI++)
	{
		CvPlot* pLoopPlot = GC.getCurrentViewport()->plotByIndex(iI);
		//PlayerTypes eOwner = pLoopPlot->getRevealedOwner(getTeam(), true); 

		// how many people own this plot?
		std::vector < std::pair<int,int> > plot_owners;
		int iNumNonzeroOwners = 0;
		for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; iPlayer++)
		{
			if (GET_PLAYER((PlayerTypes)iPlayer).isAlive())
			{
				int iCurCultureAmount = pLoopPlot->getCulture((PlayerTypes)iPlayer);
				if (iCurCultureAmount != 0)
				{
					iNumNonzeroOwners ++;
					plot_owners.push_back(std::pair<int,int>(iCurCultureAmount, iPlayer));
				}
			}
		}

		// ensure that it is revealed
		if (!plot_owners.empty() && pLoopPlot->getRevealedOwner(getTeam(), true) != NO_PLAYER)
		{
			for (int i = 0; i < iColorsPerPlot; ++i)
			{
				int iCurOwnerIdx = i % plot_owners.size();
				PlayerTypes eCurOwnerID = (PlayerTypes) plot_owners[iCurOwnerIdx].second;
				int iCurCulture = plot_owners[iCurOwnerIdx].first;
				const NiColorA& kCurColor = GC.getColorInfo((ColorTypes) GC.getPlayerColorInfo(GET_PLAYER(eCurOwnerID).getPlayerColor()).getColorTypePrimary()).getColor();

				// damp the color by the value...
				aColors[iI * iColorsPerPlot + i] = kCurColor;
				float blend_factor = 0.5f * std::min(1.0f, std::max(0.0f, (float)(iCurCulture - iMinTotalCulture) / iMaxTotalCulture));
				aColors[iI * iColorsPerPlot + i].a = std::min(0.8f * blend_factor + 0.5f, 1.0f);
			}
		}
	}
}

void CvPlayer::cheat(bool bCtrl, bool bAlt, bool bShift)
{
	if (gDLL->getChtLvl() > 0)
	{
		GET_TEAM(getTeam()).setHasTech(getCurrentResearch(), true, getID(), true, false);
	}
}

const CvArtInfoUnit* CvPlayer::getUnitArtInfo(UnitTypes eUnit, int iMeshGroup) const
{
	CivilizationTypes eCivilization = getCivilizationType();
	if (eCivilization == NO_CIVILIZATION)
	{
		eCivilization = (CivilizationTypes) GC.getDefineINT("BARBARIAN_CIVILIZATION");
	}
	UnitArtStyleTypes eStyle = (UnitArtStyleTypes) GC.getCivilizationInfo(eCivilization).getUnitArtStyleType();
	EraTypes eEra = getCurrentEra();
	if (eEra == NO_ERA)
	{
		eEra = (EraTypes) 0;
	}
	return GC.getUnitInfo(eUnit).getArtInfo(iMeshGroup, eEra, eStyle);
}

bool CvPlayer::hasSpaceshipArrived() const
{
	VictoryTypes eSpaceVictory = GC.getGameINLINE().getSpaceVictory();
	if (eSpaceVictory != NO_VICTORY)
	{
		int iVictoryCountdown = GET_TEAM(getTeam()).getVictoryCountdown(eSpaceVictory);
		if (((GC.getGameINLINE().getGameState() == GAMESTATE_EXTENDED) && (iVictoryCountdown > 0)) || (iVictoryCountdown == 0))
		{
			return true;
		}
	}

	return false;
}

/************************************************************************************************/
/* Afforess	                  Start		 12/9/09                                                */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
void CvPlayer::doCheckForTaxationAnger()
{
	PROFILE_FUNC()

	int iOldTaxRate, iCurrentTaxRate, iDifference, iAnarchyTurns, iModifier;
	iOldTaxRate = getLastTurnTaxRate();
	iCurrentTaxRate = getCommercePercent(COMMERCE_GOLD);
	
	iModifier = GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getAnarchyPercent();
	iModifier += GC.getEraInfo(GC.getGameINLINE().getStartEra()).getAnarchyPercent();
	iModifier += getNumCities() * GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getNumCitiesAnarchyPercent();
	iModifier /= 300;
	iModifier = std::max(1, iModifier);
	
	if (iOldTaxRate != iCurrentTaxRate)
	{
		if (getTaxationAnger() > 0 && !isGoldenAge() && (getAnarchyTurns() <= 0))
		{
			iDifference = iCurrentTaxRate - iOldTaxRate;
			//Lowering Taxes will not cause anger
			if (iDifference > 0)
			{
				iAnarchyTurns = iDifference / 10;
				//Even if you only raised taxes by 5%, it's still bad.
				if (!GC.getDefineINT("TAXATION_ANGER_ROUND_DOWN"))
				{
					if (iDifference % 10 > 0)
						iAnarchyTurns++;
				}
				
				iAnarchyTurns *= iModifier;
				
				changeAnarchyTurns((iAnarchyTurns), true);
				//Inform the player of the situation
				MEMORY_TRACK_EXEMPT();

				AddDLLMessage(getID(), true, GC.getEVENT_MESSAGE_TIME(), gDLL->getText("TXT_KEY_MISC_TAXATION_ANGER").GetCString(), "AS2D_REVOLTSTART", MESSAGE_TYPE_MAJOR_EVENT, NULL, (ColorTypes)GC.getInfoTypeForString("COLOR_WARNING_TEXT"));
			}
		}
		//Our Current Tax Rate is Now the Last Turns
		m_iLastTurnTaxRate = 0;
		changeLastTurnTaxRate(iCurrentTaxRate);
	}
}

int CvPlayer::getEnslavementChance() const
{
    return m_iEnslavementChance;
}

void CvPlayer::changeEnslavementChance(int iChange)
{
	if (iChange != 0)
	{
		m_iEnslavementChance = (m_iEnslavementChance + iChange);
	}
}

bool CvPlayer::isTradingMilitaryBonus(PlayerTypes ePlayer) const
{
	for (int iI = 0; iI < GC.getNumBonusInfos(); iI++)
	{
		if (GET_PLAYER(ePlayer).AI_militaryBonusVal((BonusTypes)iI) > 0)
		{
			if (getNumTradeImportsByBonus(ePlayer, ((BonusTypes)iI)) > 0)
			{
				return true;
			}
		}
	}
	return false;
}

int CvPlayer::getNumTradeImportsByBonus(PlayerTypes ePlayer, BonusTypes eBonus) const
{
	CLLNode<TradeData>* pNode;
	CvDeal* pLoopDeal;
	int iCount;
	int iLoop;

	FAssert(ePlayer != getID());

	iCount = 0;

	for(pLoopDeal = GC.getGameINLINE().firstDeal(&iLoop); pLoopDeal != NULL; pLoopDeal = GC.getGameINLINE().nextDeal(&iLoop))
	{
		if ((pLoopDeal->getFirstPlayer() == getID()) && (pLoopDeal->getSecondPlayer() == ePlayer))
		{
			for (pNode = pLoopDeal->headSecondTradesNode(); (pNode != NULL); pNode = pLoopDeal->nextSecondTradesNode(pNode))
			{
				if (pNode->m_data.m_eItemType == TRADE_RESOURCES)
				{
					if (pNode->m_data.m_iData == eBonus)
					{
						iCount++;
					}
				}
			}
		}

		if ((pLoopDeal->getFirstPlayer() == ePlayer) && (pLoopDeal->getSecondPlayer() == getID()))
		{
			for (pNode = pLoopDeal->headFirstTradesNode(); (pNode != NULL); pNode = pLoopDeal->nextFirstTradesNode(pNode))
			{
				if (pNode->m_data.m_eItemType == TRADE_RESOURCES)
				{
					if (pNode->m_data.m_iData == eBonus)
					{
						iCount++;
					}
				}
			}
		}
	}

	return iCount;
}

CvCity* CvPlayer::getBestHQCity(CorporationTypes eCorporation) const
{
    CvCity* pCurrentHQ = GC.getGameINLINE().getHeadquarters(eCorporation);
	CvCity* pLoopCity;
	CvCity* pBestCity = NULL;
	int iValue;
	int iBestValue = 0;

	if (GC.getCorporationInfo(eCorporation).getObsoleteTech() != NO_TECH)
	{
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getCorporationInfo(eCorporation).getObsoleteTech()))
			return NULL;
	}
	int iLoop;
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
	    iValue = 0;
		//If we find no best city, the capital will do.
		if (pLoopCity->isCapital())
			pBestCity = pLoopCity;
	    if (!pLoopCity->isHasCorporation(eCorporation))
	    {
            if (pLoopCity->isConnectedTo(pCurrentHQ))
            {
                for (int iCorporation = 0; iCorporation < GC.getNumCorporationInfos(); ++iCorporation)
                {
                    if (pLoopCity->isHeadquarters((CorporationTypes)iCorporation))
                    {
                        if (GC.getGameINLINE().isCompetingCorporation((CorporationTypes)iCorporation, eCorporation))
                        {
                            continue;
                        }
                        iValue -= 25;
                    }
                }

                bool bFoundBonus = false;
                for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
                {
                    BonusTypes eBonus = (BonusTypes)GC.getCorporationInfo(eCorporation).getPrereqBonus(i);
                    if (NO_BONUS != eBonus)
                    {
                        if (pLoopCity->hasBonus(eBonus))
                        {
                            bFoundBonus = true;
                            iValue += 50;
                        }
                    }
                }

                if (!bFoundBonus)
                {
                    continue;
                }

                iValue += 100;
            }
	    }
	    else
	    {
	        iValue = 300;

	        if (pLoopCity->isConnectedTo(pCurrentHQ))
	        {
	            iValue += 100;
	        }

            for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
            {
                BonusTypes eBonus = (BonusTypes)GC.getCorporationInfo(eCorporation).getPrereqBonus(i);
                if (NO_BONUS != eBonus)
                {
                    if (pLoopCity->hasBonus(eBonus))
                    {
                        iValue += 50;
                    }
                }
            }

            for (int iCorporation = 0; iCorporation < GC.getNumCorporationInfos(); ++iCorporation)
            {
                if (pLoopCity->isHeadquarters((CorporationTypes)iCorporation))
                {
                    iValue -= 25;
                }
            }
	    }

	    if (iValue > iBestValue)
	    {
	        iBestValue = iValue;
	        pBestCity = pLoopCity;
	    }
	}

	return pBestCity;
}


PlayerVoteTypes CvPlayer::getPledgedVote() const
{
    return (PlayerVoteTypes)m_ePledgedVote;
}

void CvPlayer::setPledgedVote(PlayerVoteTypes eIndex)
{
    m_ePledgedVote = eIndex;
}

TeamTypes CvPlayer::getPledgedSecretaryGeneralVote() const
{
	return (TeamTypes)m_eSecretaryGeneralVote;
}

void CvPlayer::setPledgedSecretaryGeneralVote(TeamTypes eIndex)
{
	m_eSecretaryGeneralVote = eIndex;
}

DenialTypes CvPlayer::AI_pledgeVoteTrade(VoteTriggeredData* kData, PlayerVoteTypes ePlayerVote, PlayerTypes ePlayer) const
{
	if (GET_TEAM(getTeam()).AI_getWorstEnemy() == GET_PLAYER(ePlayer).getTeam())
	{
		return DENIAL_WORST_ENEMY;
	}

    return NO_DENIAL;
}

DenialTypes CvPlayer::AI_corporationTrade(CorporationTypes eCorporation, PlayerTypes ePlayer) const
{

	if (isNoCorporations())
	{
		return DENIAL_NO_GAIN;
	}
	
	CvCity* pLoopCity;
	int iLoop;
	bool bValid = false;
	bool bRequiresBonus = false;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		//If we don't have the corporation
		if (!(pLoopCity->isHasCorporation(eCorporation)))
		{
			for (int i = 0; i < GC.getNUM_CORPORATION_PREREQ_BONUSES(); ++i)
			{
				BonusTypes eBonus = (BonusTypes)GC.getCorporationInfo(eCorporation).getPrereqBonus(i);
				if (NO_BONUS != eBonus)
				{
					bRequiresBonus = true;
					//if the city can have the corporation
					if (pLoopCity->hasBonus(eBonus))
					{
						bValid = true;
					}
				}
			}
		}
	}
	
	if (!bValid && bRequiresBonus)
	{
		return DENIAL_NO_GAIN;
	}

	if (GET_PLAYER(ePlayer).getTeam() == getTeam())
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAtWar(getTeam()))
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
	{
		return NO_DENIAL;
	}
	
	if (isHuman())
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(getTeam()).AI_getWorstEnemy() == GET_PLAYER(ePlayer).getTeam())
	{
		return DENIAL_WORST_ENEMY;
	}

	if ((getHasCorporationCount(eCorporation) * 2) > getNumCities())
	{
		return DENIAL_NO_GAIN;
	}
	
	if (GET_PLAYER(ePlayer).isNoCorporations())
	{
		return DENIAL_NO_GAIN;
	}
	
	AttitudeTypes eAttitude = GET_PLAYER(getID()).AI_getAttitude(ePlayer);

	if (eAttitude <= GC.getLeaderHeadInfo(getPersonalityType()).getCorporationRefuseAttitudeThreshold())
	{
		return DENIAL_ATTITUDE;
	}
	


    return NO_DENIAL;
}

DenialTypes CvPlayer::AI_secretaryGeneralTrade(VoteSourceTypes eVoteSource, PlayerTypes ePlayer) const
{

	if (GET_PLAYER(ePlayer).getTeam() == getTeam())
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAtWar(getTeam()))
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(getTeam()).AI_getWorstEnemy() == GET_PLAYER(ePlayer).getTeam())
	{
		return DENIAL_WORST_ENEMY;
	}

	if (GC.getGameINLINE().isTeamVoteEligible(getTeam(), eVoteSource))
	{
		return DENIAL_JOKING;
	}

	AttitudeTypes eAttitude = GET_PLAYER(getID()).AI_getAttitude(ePlayer);

	if (eAttitude <= GC.getLeaderHeadInfo(getPersonalityType()).getSecretaryGeneralVoteRefuseAttitudeThreshold())
	{
		return DENIAL_ATTITUDE;
	}

	return NO_DENIAL;
}

DenialTypes CvPlayer::AI_workerTrade(CvUnit* pUnit, PlayerTypes ePlayer) const
{

	if (isHuman())
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAtWar(getTeam()))
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
	{
		return NO_DENIAL;
	}
	
	if (GET_PLAYER(ePlayer).getTeam() == getTeam())
	{
		return NO_DENIAL;
	}
	
	if (GET_PLAYER(pUnit->getOriginalOwner()).getID() == GET_PLAYER(ePlayer).getID())
	{
		return DENIAL_JOKING;
	}
	
	if (GET_TEAM(getTeam()).AI_getWorstEnemy() == GET_PLAYER(ePlayer).getTeam())
	{
		return DENIAL_WORST_ENEMY;
	}

	if (GET_TEAM(getTeam()).AI_isSneakAttackPreparing(GET_PLAYER(ePlayer).getTeam()))
	{
		return DENIAL_NO_GAIN;
	}

	if (GET_PLAYER(ePlayer).AI_totalUnitAIs(UNITAI_WORKER) > GET_PLAYER(ePlayer).getNumCities())
	{
		if (GET_PLAYER(ePlayer).calculateUnitCost() > 0)
		{
			return DENIAL_NO_GAIN;
		}
	}

	AttitudeTypes eAttitude = AI_getAttitude(ePlayer);

	if (eAttitude <= GC.getLeaderHeadInfo(getPersonalityType()).getWorkerRefuseAttitudeThreshold())
	{
		return DENIAL_ATTITUDE;
	}

	return NO_DENIAL;
}

DenialTypes CvPlayer::AI_militaryUnitTrade(CvUnit* pUnit, PlayerTypes ePlayer) const
{
	
	if (isHuman())
	{
		return NO_DENIAL;
	}

	if (GET_PLAYER(ePlayer).getTeam() == getTeam())
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isAtWar(getTeam()))
	{
		return NO_DENIAL;
	}
	
	if (GET_TEAM(getTeam()).AI_isSneakAttackPreparing(GET_PLAYER(ePlayer).getTeam()))
	{
		return DENIAL_NO_GAIN;
	}

	if (GET_PLAYER(pUnit->getOriginalOwner()).getID() == GET_PLAYER(ePlayer).getID())
	{
		return DENIAL_JOKING;
	}
	
	if (GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0 && !GET_TEAM(getTeam()).AI_shareWar(GET_PLAYER(ePlayer).getTeam()))
	{
		return DENIAL_NO_GAIN;
	}

	if (GET_PLAYER(ePlayer).AI_isFinancialTrouble() && (GET_PLAYER(ePlayer).calculateUnitCost() > 0))
	{
		if (GET_TEAM(GET_PLAYER(ePlayer).getTeam()).getAtWarCount(true) == 0)
		{
			return DENIAL_NO_GAIN;
		}
	}

	AttitudeTypes eAttitude = GET_PLAYER(getID()).AI_getAttitude(ePlayer);

	if (pUnit->nukeRange() > 0 && GET_PLAYER(ePlayer).getNumNukeUnits() == 0)
	{
		return DENIAL_JOKING;
	}

	if (eAttitude <= GC.getLeaderHeadInfo(getPersonalityType()).getMilitaryUnitRefuseAttitudeThreshold())
	{
		return DENIAL_ATTITUDE;
	}

	return NO_DENIAL;
}

bool CvPlayer::hasValidCivics(BuildingTypes eBuilding) const
{
	int iI;
	bool bValidOrCivic = false;
	bool bNoReqOrCivic = true;
	bool bValidAndCivic = true;
	bool bReqAndCivic = true;
	for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
	{
		if (GC.getBuildingInfo(eBuilding).isPrereqOrCivics(iI))
		{
			bNoReqOrCivic = false;
			if (isCivic(CivicTypes(iI)))
			{
				bValidOrCivic = true;
			}
		}
		
		if (GC.getBuildingInfo(eBuilding).isPrereqAndCivics(iI))
		{
			bReqAndCivic = true;
			if (!isCivic(CivicTypes(iI)))
			{
				bValidAndCivic = false;
			}
		}
	}
	
	if (!bNoReqOrCivic && !bValidOrCivic)
	{
		return false;
	}

	if (bReqAndCivic && !bValidAndCivic)
	{
		return false;
	}
	
	return true;
}

int CvPlayer::getBonusMintedPercent(BonusTypes eIndex) const
{
	return m_paiBonusMintedPercent[eIndex];
}

void CvPlayer::changeBonusMintedPercent(BonusTypes eIndex, int iChange)
{
	if (iChange != 0)
	{
		CvCity* pLoopCity;
		int iLoop;
		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			if (pLoopCity->getNumBonuses(eIndex) > 0)
			{
				pLoopCity->processBonus(eIndex, -1);
			}
		}

		m_paiBonusMintedPercent[eIndex] += iChange;

		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			if (pLoopCity->getNumBonuses(eIndex) > 0)
			{
				pLoopCity->processBonus(eIndex, 1);
			}

			pLoopCity->updateCorporation();

			pLoopCity->AI_setAssignWorkDirty(true);

			pLoopCity->setInfoDirty(true);
		}
	}

}

int CvPlayer::getUnitCombatProductionModifier(UnitCombatTypes eIndex) const
{
	return m_paiUnitCombatProductionModifier[eIndex];
}

void CvPlayer::changeUnitCombatProductionModifier(UnitCombatTypes eIndex, int iChange)
{
	if (iChange != 0)
	{
		m_paiUnitCombatProductionModifier[eIndex] = (m_paiUnitCombatProductionModifier[eIndex] + iChange);
	}
}

int CvPlayer::getBuildingClassProductionModifier(BuildingClassTypes eIndex) const
{
	return m_paiBuildingClassProductionModifier[eIndex];
}

void CvPlayer::changeBuildingClassProductionModifier(BuildingClassTypes eIndex, int iChange)
{
	if (iChange != 0)
	{
		m_paiBuildingClassProductionModifier[eIndex] = (m_paiBuildingClassProductionModifier[eIndex] + iChange);
	}
}

int CvPlayer::getUnitClassProductionModifier(UnitClassTypes eIndex) const
{
	return m_paiUnitClassProductionModifier[eIndex];
}

void CvPlayer::changeUnitClassProductionModifier(UnitClassTypes eIndex, int iChange)
{
	if (iChange != 0)
	{
		m_paiUnitClassProductionModifier[eIndex] = (m_paiUnitClassProductionModifier[eIndex] + iChange);
	}
}

bool CvPlayer::isAutomatedCanBuild(BuildTypes eBuild) const
{
	return m_pabAutomatedCanBuild[eBuild];
}

void CvPlayer::setAutomatedCanBuild(BuildTypes eBuild, bool bNewValue)
{
	m_pabAutomatedCanBuild[eBuild] = bNewValue;
}

bool CvPlayer::hasEnemyDefenderUnit(CvPlot* pPlot)
{
	std::vector<CvUnit *> plotUnits;
	CvUnit *pLoopUnit;
	
	GC.getGame().getPlotUnits(pPlot, plotUnits);
	
	for (int iI = 0; iI < (int) plotUnits.size(); ++iI)
	{
		pLoopUnit = plotUnits[iI];
		if (atWar(getTeam(), GET_PLAYER(pLoopUnit->getOwner()).getTeam()))
		{
			return true;
		}
	}
	
	return false;	
}

int CvPlayer::getCivicHappiness() const
{
	return m_iCivicHappiness;
}

void CvPlayer::changeCivicHappiness(int iChange)
{
	if (iChange != 0)
	{
		m_iCivicHappiness = (m_iCivicHappiness + iChange);

		AI_makeAssignWorkDirty();
	}
}

//TB Bugfix: left this here for reference if any problems arise from the new method.
//bool CvPlayer::hasFixedBorders()
//{
//	int iI;
//	if (isBarbarian() || GC.getGameINLINE().isOption(GAMEOPTION_NO_FIXED_BORDERS) )
//	{
//		return false;
//	}
//
//	for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
//	{
//		CivicTypes eCivic = getCivics((CivicOptionTypes)iI);
//
//		if ( eCivic != NO_CIVIC && GC.getCivicInfo(eCivic).IsFixedBorders())
//		{
//			return true;
//		}
//	}
//	
//	return false;
//}

int CvPlayer::getForeignTradeRouteModifier() const
{
	return m_iForeignTradeRouteModifier;
}

void CvPlayer::changeForeignTradeRouteModifier(int iChange)
{
	if (iChange != 0)
	{
		m_iForeignTradeRouteModifier = (m_iForeignTradeRouteModifier + iChange);

		updateTradeRoutes();
	}
}

int CvPlayer::getTaxRateUnhappiness() const
{
	return m_iTaxRateUnhappiness;
}

void CvPlayer::changeTaxRateUnhappiness(int iChange)
{
	if (iChange != 0)
	{
		m_iTaxRateUnhappiness = (m_iTaxRateUnhappiness + iChange);
	}
}

int CvPlayer::calculateTaxRateUnhappiness() const
{
	return (getCommercePercent(COMMERCE_GOLD) * getTaxRateUnhappiness() / 100);
}

#if defined QC_MASTERY_VICTORY
//Sevo Begin -VCM
/*  getSevoWonderScore
This function returns the number of wonders BUILT by the playerID (not OWNED!)

If Mode == 1, it will return the total number of Wonders BUILT in the world.
If Mode == 2, it will return the total number of Wonders available to build in the game.

Sort of an ugly overload, but it works.

I don't plan to run this code except: 1) When the score screen is accessed; and 2) at the end of the game.
Thus I'm not worrying overly about running speed.  I wouldn't recommend putting this into the game loop.
*/

int CvPlayer::getSevoWondersScore(int mode)
{
	int iI, iLoopBuilding;
	CvCity* pLoopCity;
	int iLoop;
		
	int numWonders = 0;
	int numWondersPossible = 0;	
	int numWondersBuiltByPlayer = 0;
	// iI is the loop player ID.
	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if  ((GET_PLAYER((PlayerTypes)iI).isAlive()) && (!(GET_PLAYER((PlayerTypes)iI).isMinorCiv())))
		{
			for (pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
			{
				// All the code above is basically in place to loop through every city on earth.  There might be an easier way, but I didn't see one readily.
				// Note that I'm not sure, but this might also loop through cities that HAVE been destroyed, thus civs will get credit for building wonders even if they get taken out.  have to check on that.
				// Now we'll cycle through all the buildings IN THE GAME (not just this city).  Ugh.  This is PAINFULLY inefficient.  I hate ugly code, but I need this to work...
				numWondersPossible = 0;
				for (iLoopBuilding = 0; iLoopBuilding < GC.getNumBuildingInfos(); iLoopBuilding++)
				{
					BuildingClassTypes eBuildingClass = (BuildingClassTypes)GC.getBuildingInfo((BuildingTypes)iLoopBuilding).getBuildingClassType();
					if (::isWorldWonderClass(eBuildingClass))
					{
						numWondersPossible++;
						//This building class is a world wonder
						if (pLoopCity->getNumRealBuilding((BuildingTypes)iLoopBuilding)>0)
						{
							// This city contains this wonder
							// Increment the wonder counter
							
							numWonders ++;
											
							if (((pLoopCity->getBuildingOriginalOwner((BuildingTypes)iLoopBuilding)) == getID()) ||
								(mode == 1))
							{
								//The original owner (builder) is the same as the loop player.
								numWondersBuiltByPlayer++;
							}						
						}
					}
				}				
			}
		}
	}
	if (mode == 1)
	{
		return numWonders;
	}
	else if (mode == 2)
	{
		return numWondersPossible;
	}
	else
	{
		return numWondersBuiltByPlayer;
	}
}
	//Sevo End VCM
#endif

void CvPlayer::recalculatePopulationgrowthratepercentage()
{
	PROFILE_FUNC();

	m_fPopulationgrowthratepercentageLog = 0;

	//	Game has been restored from an old save format so we have to calculate
	//	from first principles
	BuildingTypes eLoopBuilding;
	for (int iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		eLoopBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(iI);
		if (eLoopBuilding != NO_BUILDING)
		{
			if ( GC.getBuildingInfo(eLoopBuilding).getGlobalPopulationgrowthratepercentage() != 0 )
			{
				int iLoop;
				for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
				{
					if (pLoopCity->getNumBuilding(eLoopBuilding) > 0)
					{
						changePopulationgrowthratepercentage(GC.getBuildingInfo(eLoopBuilding).getGlobalPopulationgrowthratepercentage(),true);
					}
				}
			}
		}
	}

	for(int iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		CivicTypes eCivic = getCivics((CivicOptionTypes)iI);

		if ( eCivic != NO_CIVIC )
		{
			if ( GC.getCivicInfo(eCivic).getPopulationgrowthratepercentage() != 0 )
			{
				changePopulationgrowthratepercentage(GC.getCivicInfo(eCivic).getPopulationgrowthratepercentage(),true);
			}
		}
	}
}

int CvPlayer::getPopulationgrowthratepercentage() const
{
	if ( m_fPopulationgrowthratepercentageLog == INVALID_GROWTH_PERCENT_LOG )
	{
		((CvPlayer*)this)->recalculatePopulationgrowthratepercentage();
	}

	float fMultiplier = exp(m_fPopulationgrowthratepercentageLog);

	return (int)(fMultiplier*100 - 100);
}

void CvPlayer::setPopulationgrowthratepercentage(int iNewValue)
{
	m_fPopulationgrowthratepercentageLog = log((100+(float)iNewValue)/100);
}

void CvPlayer::changePopulationgrowthratepercentage(int iChange, bool bAdd)
{
	if ( m_fPopulationgrowthratepercentageLog == INVALID_GROWTH_PERCENT_LOG )
	{
		recalculatePopulationgrowthratepercentage();
	}

	float logdiff = (bAdd ? 1 : -1)*log((100+(float)iChange)/100);
	
	m_fPopulationgrowthratepercentageLog += logdiff;
}

int CvPlayer::getReligionSpreadRate() const
{
	return m_iReligionSpreadRate;
}	

void CvPlayer::setReligionSpreadRate(int iValue)
{
    FAssertMsg(iValue >= 0, "iValue cannot be less than 0");
    m_iReligionSpreadRate = iValue;
}

void CvPlayer::changeReligionSpreadRate(int iChange)
{
    setReligionSpreadRate(getReligionSpreadRate() + iChange);
}

int CvPlayer::getDistantUnitSupportCostModifier() const
{
	return m_iDistantUnitSupportCostModifier;
}	

void CvPlayer::setDistantUnitSupportCostModifier(int iValue)
{
    m_iDistantUnitSupportCostModifier = iValue;
}

void CvPlayer::changeDistantUnitSupportCostModifier(int iChange)
{
    setDistantUnitSupportCostModifier(getDistantUnitSupportCostModifier() + iChange);
}

int CvPlayer::getExtraCityDefense() const
{
	return m_iExtraCityDefense;
}	

void CvPlayer::setExtraCityDefense(int iValue)
{
    m_iExtraCityDefense = iValue;
}

void CvPlayer::changeExtraCityDefense(int iChange)
{
    setExtraCityDefense(getExtraCityDefense() + iChange);
}

int CvPlayer::getWorldHappiness() const
{
	return m_iWorldHappiness;
}	

void CvPlayer::changeWorldHappiness(int iChange)
{
    m_iWorldHappiness += iChange;
}

int CvPlayer::getWorldHealth() const
{
	return m_iWorldHealth;
}	

void CvPlayer::changeWorldHealth(int iChange)
{
    m_iWorldHealth += iChange;
}

int CvPlayer::getProjectHappiness() const
{
	return m_iProjectHappiness;
}

void CvPlayer::changeProjectHappiness(int iChange)
{
    m_iProjectHappiness += iChange;
}

int CvPlayer::getProjectHealth() const
{
	return m_iProjectHealth;
}	

void CvPlayer::changeProjectHealth(int iChange)
{
    m_iProjectHealth += iChange;
}

int CvPlayer::getForceAllTradeRoutes() const
{
	return m_iForceAllTradeRoutes;
}	

void CvPlayer::changeForceAllTradeRoutes(int iChange)
{
	if (iChange != 0)
	{
		m_iForceAllTradeRoutes += iChange;
		
		updateTradeRoutes();
	}
}

int CvPlayer::getWorldTradeRoutes() const
{
	return m_iWorldTradeRoutes;
}	

void CvPlayer::changeWorldTradeRoutes(int iChange)
{
    if (iChange != 0)
	{
		m_iWorldTradeRoutes = (m_iWorldTradeRoutes + iChange);
		FAssert(getWorldTradeRoutes() >= 0);

		for (int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			GET_PLAYER((PlayerTypes)iI).updateTradeRoutes();
		}
	}
}

void CvPlayer::changeNoCapitalUnhappiness(int iChange)
{
	if (iChange != 0)
	{
		m_iNoCapitalUnhappiness += iChange;
		CvCity* pCapitalCity = getCapitalCity();

		if (pCapitalCity != NULL)
		{
			pCapitalCity->AI_setAssignWorkDirty(true);

			if (pCapitalCity->getTeam() == GC.getGameINLINE().getActiveTeam())
			{
				pCapitalCity->setInfoDirty(true);
			}
		}
	}
}

int CvPlayer::getNoCapitalUnhappiness() const
{
	return m_iNoCapitalUnhappiness;
}

void CvPlayer::changeTaxationAnger(int iChange)
{
	if (iChange != 0)
	{
		m_iTaxationAnger += iChange;
	}
}

int CvPlayer::getTaxationAnger() const
{
	return m_iTaxationAnger;
}	

void CvPlayer::changeLastTurnTaxRate(int iChange)
{
	if (iChange != 0)
	{
		m_iLastTurnTaxRate += iChange;
	}
}

int CvPlayer::getLastTurnTaxRate() const
{
	return m_iLastTurnTaxRate;
}

int CvPlayer::getFreeSpecialistCount(SpecialistTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < GC.getNumSpecialistInfos(), "eIndex expected to be < GC.getNumSpecialistInfos()");
	return m_paiFreeSpecialistCount[eIndex];
}

void CvPlayer::setFreeSpecialistCount(SpecialistTypes eIndex, int iNewValue)
{
	int iOldValue;

	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < GC.getNumSpecialistInfos(), "eIndex expected to be < GC.getNumSpecialistInfos()");

	iOldValue = getFreeSpecialistCount(eIndex);

	if (iOldValue != iNewValue)
	{
		m_paiFreeSpecialistCount[eIndex] = iNewValue;
		FAssert(getFreeSpecialistCount(eIndex) >= 0);
		
		int iLoop;
		for (CvCity* pLoopCity = firstCity(&iLoop); NULL != pLoopCity; pLoopCity = nextCity(&iLoop))
		{
			pLoopCity->changeFreeSpecialistCount(eIndex, (iNewValue - iOldValue));
		}
	}
}

void CvPlayer::changeFreeSpecialistCount(SpecialistTypes eIndex, int iChange)
{
	setFreeSpecialistCount(eIndex, (getFreeSpecialistCount(eIndex) + iChange));
}

int CvPlayer::getTerrainYieldChange(TerrainTypes eIndex1, YieldTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumTerrainInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_YIELD_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_ppaaiTerrainYieldChange[eIndex1][eIndex2];
}


void CvPlayer::changeTerrainYieldChange(TerrainTypes eIndex1, YieldTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumTerrainInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_YIELD_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_ppaaiTerrainYieldChange[eIndex1][eIndex2] = (m_ppaaiTerrainYieldChange[eIndex1][eIndex2] + iChange);

		updateYield();
	}
}

int CvPlayer::doMultipleResearch(int iOverflow)
{
	TechTypes eCurrentTech;
	eCurrentTech = getCurrentResearch();
	
	FAssertMsg(eCurrentTech < GC.getNumTechInfos(), "eCurrentTech is expected to be within maximum bounds (invalid Index)");

	if (!GC.getGameINLINE().isOption(GAMEOPTION_MULTIPLE_RESEARCH))
	{
		return iOverflow;
	}
	
	if ( eCurrentTech == NO_TECH || GET_TEAM(getTeam()).isHasTech(eCurrentTech) )
	{
		if ( !isHuman() )
		{
			AI_chooseResearch();
			eCurrentTech = getCurrentResearch();
		}
		else
		{
			//	This shouldn't really happen but it's  safety precaution
			clearResearchQueue();
		}
	}

	while (eCurrentTech != NO_TECH && ((100 * (GET_TEAM(getTeam()).getResearchCost(eCurrentTech) - GET_TEAM(getTeam()).getResearchProgress(eCurrentTech))) / std::max(1, calculateResearchModifier(eCurrentTech)) <= iOverflow))
	{
		//The Future Tech can cause strange infinite loops
		if (GC.getTechInfo(eCurrentTech).isRepeat())
			break;

		iOverflow -= (100 * (GET_TEAM(getTeam()).getResearchCost(eCurrentTech) - GET_TEAM(getTeam()).getResearchProgress(eCurrentTech))) / std::max(1, calculateResearchModifier(eCurrentTech));
		GET_TEAM(getTeam()).setHasTech(eCurrentTech, true, getID(), true, true);
		if (!GC.getGameINLINE().isMPOption(MPOPTION_SIMULTANEOUS_TURNS) && !GC.getGameINLINE().isOption(GAMEOPTION_NO_TECH_BROKERING))
		{
			GET_TEAM(getTeam()).setNoTradeTech(eCurrentTech, true);
		}
		if ( !isHuman() )
		{
			AI_chooseResearch();
		}

		eCurrentTech = getCurrentResearch();
	}
	
	return std::max(0, iOverflow);
}

int CvPlayer::getCivilizationHealth() const
{
	return m_iCivilizationHealth;
}


void CvPlayer::changeCivilizationHealth(int iChange)
{
	if (iChange != 0)
	{
		m_iCivilizationHealth = (m_iCivilizationHealth + iChange);

		AI_makeAssignWorkDirty();
	}
}

int CvPlayer::getNoLandmarkAngerCount() const
{
	return m_iNoLandmarkAngerCount;
}

bool CvPlayer::isNoLandmarkAnger() const
{
	return getNoLandmarkAngerCount() > 0;
}

void CvPlayer::changeNoLandmarkAngerCount(int iChange)
{
	if (iChange != 0)
	{
		m_iNoLandmarkAngerCount = (m_iNoLandmarkAngerCount + iChange);

		AI_makeAssignWorkDirty();
	}
}

int CvPlayer::getLandmarkHappiness() const
{
	return m_iLandmarkHappiness;
}

void CvPlayer::changeLandmarkHappiness(int iChange)
{
	if (iChange != 0)
	{
		m_iLandmarkHappiness = (m_iLandmarkHappiness + iChange);

		AI_makeAssignWorkDirty();
	}
}

bool CvPlayer::isShowLandmarks() const
{
	return m_bShowLandmarks && GC.getGameINLINE().isOption(GAMEOPTION_PERSONALIZED_MAP);
}

void CvPlayer::setShowLandmarks(bool bNewVal)
{
	bool bOldVal = m_bShowLandmarks;
	if (bOldVal && !bNewVal)
	{
		for (int iPlot = 0; iPlot < GC.getMapINLINE().numPlotsINLINE(); iPlot++)
		{
			CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);
			if (pLoopPlot->getLandmarkType() != NO_LANDMARK)
			{
				PYTHON_ACCESS_LOCK_SCOPE

				CyArgsList argsList;
				CyPlot* pyPlot = new CyPlot(pLoopPlot);
				argsList.add(gDLL->getPythonIFace()->makePythonObject(pyPlot));
				argsList.add(getID());
				argsList.add("");
				PYTHON_CALL_FUNCTION(__FUNCTION__, PYCivModule, "AddSign", argsList.makeFunctionArgs());
				delete pyPlot;
			}
		}
	}
	else
	{
		for (int iPlot = 0; iPlot < GC.getMapINLINE().numPlotsINLINE(); iPlot++)
		{
			CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iPlot);
			if (pLoopPlot->getLandmarkType() != NO_LANDMARK)
			{
				PYTHON_ACCESS_LOCK_SCOPE

				CyArgsList argsList;
				CyPlot* pyPlot = new CyPlot(pLoopPlot);
				argsList.add(gDLL->getPythonIFace()->makePythonObject(pyPlot));
				argsList.add(getID());
				argsList.add(pLoopPlot->getLandmarkMessage().GetCString());
				PYTHON_CALL_FUNCTION(__FUNCTION__, PYCivModule, "AddSign", argsList.makeFunctionArgs());
				delete pyPlot;
			}
		}
	}
	m_bShowLandmarks = bNewVal;
}


int CvPlayer::processedNationalCulture() const
{
	int iCulture;
	if (countTotalCulture() < MAX_INT)
	{
		iCulture = (int)countTotalCulture();
	}
	else
	{
		iCulture = MAX_INT;
	}
	return iCulture;
}

void CvPlayer::acquireFort(CvPlot* pPlot)
{
	CvPlot* pLoopPlot;
	int iI;

//	logMsg("%S acquiring fort from %S at (%d, %d)", getCivilizationShortDescription(), pPlot->getOwnerINLINE() == NO_PLAYER ? L"no one" : GET_PLAYER(pPlot->getOwnerINLINE()).getCivilizationShortDescription(), pPlot->getX(), pPlot->getY());
	
	ImprovementTypes eOldFortImprovement = pPlot->getImprovementType();
	
	for (iI = 0; iI < NUM_DIRECTION_TYPES; iI++)
	{
		pLoopPlot = plotDirection(pPlot->getX_INLINE(), pPlot->getY_INLINE(), ((DirectionTypes)iI));

		if (pLoopPlot != NULL)
		{
			if (!pLoopPlot->isCity())	
			{
				if ((pLoopPlot->getOwnerINLINE() == pPlot->getOwnerINLINE()) || (pLoopPlot->getOwnerINLINE() == NO_PLAYER))
				{
					int iNumCitiesForRange = pLoopPlot->getCultureRangeCities(pPlot->getOwnerINLINE(), 1);
					
					if (iNumCitiesForRange == 1 && pLoopPlot->calculateCulturalOwner() == getID())
					{
						//	This captures surrounding tiles that are culturally owned by the
						//	captor even if the previous owner has fixed borders
						pLoopPlot->setOwner(getID(), true, false);
					}
				}
			}
		}
	}

	pPlot->setImprovementType(NO_IMPROVEMENT);

	pPlot->setOwner(getID(), true, false);

	pPlot->setImprovementType(eOldFortImprovement);
}

int CvPlayer::getResourceConsumption(BonusTypes eBonus) const
{
	return m_paiResourceConsumption[eBonus];
}

//recalculate resource consumption only measures how much we are using
//the resource at this very moment, not the past. It ignores existing buildings
//units, etc... UNLESS they are generating income from the resource.
void CvPlayer::recalculateResourceConsumption(BonusTypes eBonus)
{
	PROFILE_FUNC()

	int iLoop;
	CvCity* pLoopCity;
	int iConsumption = 0;
	int iI, iJ;
	int iTempValue;
	int iTradingPartnerCount;
	
	if (!hasBonus(eBonus))
	{
		m_paiResourceConsumption[eBonus] = 0;
		return;
	}
	
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		int aiBaseCommerceRate[NUM_COMMERCE_TYPES];
		for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
		{
			aiBaseCommerceRate[iI] = pLoopCity->getBaseCommerceRate((CommerceTypes)iI);
		}

		//See if we are constructing something that uses the resource
		if (pLoopCity->getProductionBuilding() != NO_BUILDING)
		{
			CvBuildingInfo& kBuilding = GC.getBuildingInfo(pLoopCity->getProductionBuilding());
			
			if ((kBuilding.getPrereqAndBonus() == eBonus) || (kBuilding.getPrereqVicinityBonus() == eBonus))
				iConsumption += kBuilding.getProductionCost();
				
			for (iI = 0; iI < GC.getNUM_BUILDING_PREREQ_OR_BONUSES(); iI++)
			{
				if ((kBuilding.getPrereqOrBonuses(iI) == eBonus) || (kBuilding.getPrereqOrVicinityBonuses(iI) == eBonus))
				{
					iConsumption += kBuilding.getProductionCost();
				}
			}
				
			if (kBuilding.getBonusProductionModifier(eBonus) != 0)
			{
				iTempValue = kBuilding.getBonusProductionModifier(eBonus);
				iTempValue *= kBuilding.getProductionCost();
				iTempValue /= 100;
				iConsumption += iTempValue;
			}
		}
		else if (pLoopCity->getProductionUnit() != NO_UNIT)
		{
			CvUnitInfo& kUnit = GC.getUnitInfo(pLoopCity->getProductionUnit());
			
			if ((kUnit.getPrereqAndBonus() == eBonus) || (kUnit.getPrereqVicinityBonus() == eBonus))
				iConsumption += kUnit.getProductionCost();
				
			for (iI = 0; iI < GC.getNUM_UNIT_PREREQ_OR_BONUSES(); iI++)
			{
				if ((kUnit.getPrereqOrBonuses(iI) == eBonus) || (kUnit.getPrereqOrVicinityBonuses(iI) == eBonus))
				{
					iConsumption += kUnit.getProductionCost();
				}
			}
				
			if (kUnit.getBonusProductionModifier(eBonus) != 0)
			{
				iTempValue = kUnit.getBonusProductionModifier(eBonus);
				iTempValue *= kUnit.getProductionCost();
				iTempValue /= 100;
				iConsumption += iTempValue;
			}
		}
		else if (pLoopCity->getProductionProject() != NO_PROJECT)
		{
			iTempValue = GC.getProjectInfo(pLoopCity->getProductionProject()).getBonusProductionModifier(eBonus);
			iTempValue *= GC.getProjectInfo(pLoopCity->getProductionProject()).getProductionCost();
			iTempValue /= 100;
			iConsumption += iTempValue;
		}
			
		//loop through all possible buildings and check if they generating us income or defense because of this bonus
		for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
		{
			iTempValue = 0;
			BuildingTypes eLoopBuilding = (BuildingTypes)GC.getCivilizationInfo(pLoopCity->getCivilizationType()).getCivilizationBuildings(iI);
			if (eLoopBuilding != NO_BUILDING)
			{
				CvBuildingInfo& kLoopBuilding = GC.getBuildingInfo(eLoopBuilding);
				
				if (pLoopCity->getNumRealBuilding(eLoopBuilding) > 0)
				{
					iTempValue += kLoopBuilding.getBonusHappinessChanges(eBonus) * 12;
					iTempValue += kLoopBuilding.getBonusHealthChanges(eBonus) * 8;
					iTempValue += kLoopBuilding.getBonusDefenseChanges(eBonus);
					for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
					{
						iTempValue += kLoopBuilding.getBonusYieldChanges(eBonus, iJ) * 3;
						iTempValue += kLoopBuilding.getBonusYieldModifier(eBonus, iJ) * pLoopCity->getBaseYieldRate((YieldTypes)iJ) / 33;
					}
					for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
					{
						iTempValue += kLoopBuilding.getBonusCommerceModifier(eBonus, iJ) * aiBaseCommerceRate[iJ] / 33;
					}
					iTempValue *= pLoopCity->getNumRealBuilding(eLoopBuilding);
				}
			}
			iConsumption += iTempValue;
		}

		//if we are selling this resource, count the other players use too
		//Note: There is no way to tell who we are selling the resource to.
		//Just counting who we have met and is importing the resource seems to be
		//the best approx. Then, we divide by total trading partners to get an average.
		if (getBonusExport(eBonus) > 0)
		{
			iTempValue = 0;
			iTradingPartnerCount = 0;
			for (iI = 0; iI < MAX_PLAYERS; iI++)
			{
				if (GET_PLAYER((PlayerTypes)iI).isAlive())
				{
					if (GET_TEAM(getTeam()).isHasMet(GET_PLAYER((PlayerTypes)iI).getTeam()))
					{
						if (GET_PLAYER((PlayerTypes)iI).getBonusImport(eBonus) > 0)
						{
							iTempValue += GET_PLAYER((PlayerTypes)iI).getResourceConsumption(eBonus);
							iTradingPartnerCount++;
						}
					}
				}
			}
			iTempValue /= std::max(1, iTradingPartnerCount);
			iTempValue *= getBonusExport(eBonus);
			iConsumption += iTempValue;
		}
	}
	m_paiResourceConsumption[eBonus] = iConsumption;
}

void CvPlayer::recalculateAllResourceConsumption()
{
	for (int iI = 0; iI < GC.getNumBonusInfos(); iI++)
	{
		recalculateResourceConsumption((BonusTypes)iI);
	}
}

int CvPlayer::getBuildingInflation() const
{
	return m_iBuildingInflation;
}

void CvPlayer::changeBuildingInflation(int iChange)
{
	m_iBuildingInflation += iChange;
}

int CvPlayer::getProjectInflation() const
{
	return m_iProjectInflation;
}

void CvPlayer::changeProjectInflation(int iChange)
{
	m_iProjectInflation += iChange;
}

int CvPlayer::getTechInflation() const
{
	return m_iTechInflation;
}

void CvPlayer::changeTechInflation(int iChange)
{
	m_iTechInflation += iChange;
}

int CvPlayer::getCivicInflation() const
{
	return m_iCivicInflation;
}

void CvPlayer::changeCivicInflation(int iChange)
{
	m_iCivicInflation += iChange;
}

int CvPlayer::getHurryCostModifier() const
{
	return m_iHurryCostModifier;
}

void CvPlayer::changeHurryCostModifier(int iChange)
{
	m_iHurryCostModifier += iChange;
}

int CvPlayer::getHurryInflationModifier() const
{
	return m_iHurryInflationModifier;
}

void CvPlayer::changeHurryInflationModifier(int iChange)
{
	m_iHurryInflationModifier += iChange;
}

int CvPlayer::getHurriedCount() const
{
	return m_iHurryCount;
}

void CvPlayer::changeHurriedCount(int iChange)
{
	m_iHurryCount += iChange;
}

bool CvPlayer::hasValidBuildings(TechTypes eTech) const
{
	int iI;
	bool bRequiresOrBuilding = false;
	bool bHasOneOrBuilding = false;
	//CvCivilizationInfo &civilizationInfo = GC.getCivilizationInfo(getCivilizationType());
	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		int iRequired = GC.getTechInfo(eTech).getPrereqBuildingClass(iI);
		if (iRequired > 0 )
		{
			if (getBuildingClassCount((BuildingClassTypes)iI) < iRequired)
			{
				return false;
			}
		}
		if (!bHasOneOrBuilding)
		{
			int iRequiredOr = GC.getTechInfo(eTech).getPrereqOrBuildingClass(iI);
			if (iRequiredOr > 0 )
			{
				bRequiresOrBuilding = true;
				if (getBuildingClassCount((BuildingClassTypes)iI) >= iRequiredOr)
				{
					bHasOneOrBuilding = true;
				}
			}
		}
	}
	if (!bHasOneOrBuilding && bRequiresOrBuilding)
	{
		return false;
	}
	return true;
}

void CvPlayer::checkAIStrategy()
{
	bool bValidStrategy = (
	(GC.getLeaderHeadInfo(getPersonalityType()).getCultureVictoryWeight() != 0) 	||
	(GC.getLeaderHeadInfo(getPersonalityType()).getSpaceVictoryWeight() != 0) 		||
	(GC.getLeaderHeadInfo(getPersonalityType()).getConquestVictoryWeight() != 0)	||
	(GC.getLeaderHeadInfo(getPersonalityType()).getDominationVictoryWeight() != 0)	||
	(GC.getLeaderHeadInfo(getPersonalityType()).getDiplomacyVictoryWeight() != 0)
	);
	
	//The XML for this leader's strategies are empty, we need to create some
	if (!bValidStrategy)
	{
		//TODO: Make this based off of leaders traits
		GC.getLeaderHeadInfo(getPersonalityType()).setCultureVictoryWeight(GC.getGameINLINE().getSorenRandNum(100, "AI Strategy"));
		GC.getLeaderHeadInfo(getPersonalityType()).setSpaceVictoryWeight(GC.getGameINLINE().getSorenRandNum(100, "AI Strategy"));
		GC.getLeaderHeadInfo(getPersonalityType()).setConquestVictoryWeight(GC.getGameINLINE().getSorenRandNum(100, "AI Strategy"));
		GC.getLeaderHeadInfo(getPersonalityType()).setDominationVictoryWeight(GC.getGameINLINE().getSorenRandNum(100, "AI Strategy"));
		GC.getLeaderHeadInfo(getPersonalityType()).setDiplomacyVictoryWeight(GC.getGameINLINE().getSorenRandNum(100, "AI Strategy"));
	}
}

int CvPlayer::getBuildingClassCommerceChange(BuildingClassTypes eIndex1, CommerceTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumBuildingClassInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_ppiBuildingClassCommerceChange[eIndex1][eIndex2];
}

void CvPlayer::changeBuildingClassCommerceChange(BuildingClassTypes eIndex1, CommerceTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumBuildingClassInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		//int iOldValue = getBuildingClassCommerceChange(eIndex1, eIndex2);
		//int iExistingValue;
		int iOldValue;

		//	Do this in a thread-safe manner
		do
		{
			iOldValue = m_ppiBuildingClassCommerceChange[eIndex1][eIndex2];
		} while( InterlockedCompareExchange((volatile LONG*)&m_ppiBuildingClassCommerceChange[eIndex1][eIndex2], iOldValue + iChange, iOldValue) != iOldValue );
		//m_ppiBuildingClassCommerceChange[eIndex1][eIndex2] += iChange;

		CvCity* pLoopCity;
		int iLoop;

		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			//iExistingValue = pLoopCity->getBuildingCommerceChange(eIndex1, eIndex2);
			pLoopCity->changeBuildingCommerceChange(eIndex1, eIndex2, iChange);
		}

		setCommerceDirty();
	}
}

int CvPlayer::getBuildingCommerceModifier(BuildingTypes eIndex1, CommerceTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumBuildingInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_ppiBuildingCommerceModifier[eIndex1][eIndex2];
}

void CvPlayer::changeBuildingCommerceModifier(BuildingTypes eIndex1, CommerceTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumBuildingInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		//int iOldValue = getBuildingCommerceModifier(eIndex1, eIndex2);
		m_ppiBuildingCommerceModifier[eIndex1][eIndex2] += iChange;		
		
		CvCity* pLoopCity;
		int iLoop;

		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			int iExistingValue = pLoopCity->getBuildingCommerceModifier((BuildingClassTypes)GC.getBuildingInfo(eIndex1).getBuildingClassType(), eIndex2);
			// set the new
			//pLoopCity->updateCommerceModifierByBuilding(eIndex1, eIndex2, (iExistingValue - iOldValue + getBuildingCommerceModifier(eIndex1, eIndex2)));
			pLoopCity->updateCommerceModifierByBuilding(eIndex1, eIndex2, iExistingValue + iChange);
		}

		setCommerceDirty();
	}
}

int CvPlayer::getBonusCommerceModifier(BonusTypes eIndex1, CommerceTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumBonusInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_ppiBonusCommerceModifier[eIndex1][eIndex2];
}

void CvPlayer::changeBonusCommerceModifier(BonusTypes eIndex1, CommerceTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumBonusInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		//int iOldValue = getBonusCommerceModifier(eIndex1, eIndex2);

		m_ppiBonusCommerceModifier[eIndex1][eIndex2] += iChange;
		setCityCommerceModifierDirty(eIndex2);
		setCommerceDirty();
	}
}

void CvPlayer::setCityCommerceModifierDirty(CommerceTypes eCommerce)
{
	int iLoop;
	CvCity* pLoopCity;
	// dirty all of this player's cities...
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->setCommerceModifierDirty(eCommerce);
	}
}

int CvPlayer::getLandmarkYield(YieldTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiLandmarkYield[eIndex];
}


void CvPlayer::changeLandmarkYield(YieldTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiLandmarkYield[eIndex] = (m_aiLandmarkYield[eIndex] + iChange);

		updateYield();
	}
}

int CvPlayer::getBuildingClassCount(BuildingClassTypes eBuildingClass, bool bUpgrades) const
{
	if (bUpgrades)
	{
		return getBuildingClassCountWithUpgrades(eBuildingClass);
	}
	return getBuildingClassCount(eBuildingClass);
}

int CvPlayer::getBuildingClassCountWithUpgrades(BuildingClassTypes eBuildingClass) const
{
	int iCount;
	iCount = getBuildingClassCount(eBuildingClass);
	BuildingTypes eBuilding = (BuildingTypes)GC.getCivilizationInfo(getCivilizationType()).getCivilizationBuildings(eBuildingClass);
	if (eBuilding != NO_BUILDING)
	{
		CvBuildingInfo& kBuilding = GC.getBuildingInfo(eBuilding);
		if (kBuilding.isReplaceBuildingClass(NO_BUILDINGCLASS))
		{
			int numNumBuildingClassInfos = GC.getNumBuildingClassInfos();
			for (int iI = 0; iI < numNumBuildingClassInfos; iI++)
			{
				if (kBuilding.isReplaceBuildingClass(iI))
				{
					iCount += getBuildingClassCount((BuildingClassTypes)iI);
				}
			}
		}
	}
	return iCount;
}

void CvPlayer::setColor(PlayerColorTypes eColor)
{
	GC.getInitCore().setColor( getID(), eColor );
	gDLL->getInterfaceIFace()->makeInterfaceDirty();
	int iLoop;
	CvCity* pLoopCity;
	// dirty all of this player's cities...
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if (pLoopCity->getOwnerINLINE() == getID())
		{
			pLoopCity->setLayoutDirty(true);
		}
	}
// Forces update of units flags
	EraTypes eEra = getCurrentEra();
	//Suppresses Era popups
	bool bHuman = m_bHuman;
	m_bHuman = false;
	setCurrentEra((EraTypes)0);
	setCurrentEra((EraTypes)(GC.getNumEraInfos() - 1));
	setCurrentEra(eEra);
	m_bHuman = bHuman;
	gDLL->getInterfaceIFace()->makeInterfaceDirty();
	
	// Need to force redraw
	gDLL->getEngineIFace()->SetDirty(CultureBorders_DIRTY_BIT, true);
	gDLL->getEngineIFace()->SetDirty(MinimapTexture_DIRTY_BIT, true);
	gDLL->getEngineIFace()->SetDirty(GlobeTexture_DIRTY_BIT, true);
	gDLL->getEngineIFace()->SetDirty(GlobePartialTexture_DIRTY_BIT, true);

	gDLL->getInterfaceIFace()->setDirty(ColoredPlots_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(HighlightPlot_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(CityInfo_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(UnitInfo_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(InfoPane_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(GlobeLayer_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(MinimapSection_DIRTY_BIT, true);
	gDLL->getEngineIFace()->SetDirty(MinimapTexture_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(Score_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(Foreign_Screen_DIRTY_BIT, true);
	gDLL->getInterfaceIFace()->setDirty(GlobeInfo_DIRTY_BIT, true);

	setupGraphical();
}

void CvPlayer::setHandicap(int iNewVal)
{
	GC.getInitCore().setHandicap(getID(), (HandicapTypes)iNewVal);

	//	Arkatakor: Updates the handicap info of all players in the CvGame class
	GC.getGameINLINE().averageHandicaps();

	AI_makeAssignWorkDirty();
}

bool CvPlayer::canBuild(const CvPlot* pPlot, ImprovementTypes eImprovement, bool bTestEra, bool bTestVisible) const
{
	for (int iI = 0; iI < GC.getNumBuildInfos(); iI++)
	{
		if (GC.getBuildInfo((BuildTypes)iI).getImprovement() == eImprovement)
		{
			if (canBuild(pPlot, (BuildTypes)iI, bTestEra, bTestVisible))
			{
				return true;
			}
		}
	}
	return false;
}

bool CvPlayer::isModderOption(ModderOptionTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_MODDEROPTION_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiModderOptions[eIndex] != 0;
}

int CvPlayer::getModderOption(ModderOptionTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_MODDEROPTION_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiModderOptions[eIndex];
}

void CvPlayer::setModderOption(ModderOptionTypes eIndex, int iNewValue)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_MODDEROPTION_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	m_aiModderOptions[eIndex] = iNewValue;
}

void CvPlayer::setModderOption(ModderOptionTypes eIndex, bool bNewValue)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_MODDEROPTION_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	m_aiModderOptions[eIndex] = bNewValue;
}

int CvPlayer::getCorporationSpreadModifier() const
{
	return m_iCorporationSpreadModifier;
}	

void CvPlayer::changeCorporationSpreadModifier(int iChange)
{
   m_iCorporationSpreadModifier += iChange;
   FAssertMsg(getCorporationSpreadModifier() >= -100, "Corporation Spread Rate is Below Zero!");
}

int CvPlayer::getCorporateTaxIncome() const
{
	return m_iCorporateTaxIncome;
}	

void CvPlayer::changeCorporateTaxIncome(int iChange)
{
   m_iCorporateTaxIncome += iChange;
   FAssertMsg(getCorporateTaxIncome() >= 0, "Corporation Taxes Are Negative!");
}

int CvPlayer::getCorporationInfluence(CorporationTypes eIndex) const
{
	int iInfluence = 100;
	
	//Government Subsidizes Corporations
	if (getCorporationMaintenanceModifier() > -100)
	{
		iInfluence += (getCorporationMaintenanceModifier() + 100);
	}
	//Government Taxes Corporations
	else if (getCorporationMaintenanceModifier() < -100)
	{
		//50% tax rate would kill any corporation
		iInfluence += (getCorporationMaintenanceModifier() + 100);
	}
	
	iInfluence += GET_TEAM(getTeam()).getCorporationRevenueModifier() / 2;
	
	
	TechTypes ePrereqTech = (TechTypes)GC.getCorporationInfo(eIndex).getTechPrereq();
	//Find the prereq tech for corporate HQ
	if (ePrereqTech == NO_TECH)
	{
		for (int i = 0; i < GC.getNumBuildingInfos(); i++)
		{
			if ((CorporationTypes)GC.getBuildingInfo((BuildingTypes)i).getGlobalCorporationCommerce() == eIndex)
			{
				ePrereqTech = (TechTypes)GC.getBuildingInfo((BuildingTypes)i).getPrereqAndTech();
				if (ePrereqTech != NO_TECH)
				{
					//Found a tech, exit the loop, else keep looking
					break;
				}
			}
		}
	}
	if (ePrereqTech != NO_TECH)
	{
		if (!GET_TEAM(getTeam()).isHasTech(ePrereqTech))
		{
			iInfluence *= 2;
			iInfluence /= 3;
		}
	}
	if (GC.getCorporationInfo(eIndex).getObsoleteTech() != NO_TECH)
	{
		if (GET_TEAM(getTeam()).isHasTech((TechTypes)GC.getCorporationInfo(eIndex).getObsoleteTech()))
		{
			return 0;
		}
	}
	
	//Compare Technological Advancement to the owner of the corporation
	if (GC.getGameINLINE().getHeadquarters(eIndex) != NULL)
	{
		PlayerTypes eCorpOwner = GC.getGameINLINE().getHeadquarters(eIndex)->getOwner();
		if (eCorpOwner != getID())
		{
			int iExtraTechs = 0;
			for (int iI = 0; iI < GC.getNumTechInfos(); iI++)
			{
				if (GET_TEAM(getTeam()).isHasTech((TechTypes)iI) && !GET_TEAM(GET_PLAYER(eCorpOwner).getTeam()).isHasTech((TechTypes)iI))
				{
					iExtraTechs++;
				}
				else if (!GET_TEAM(getTeam()).isHasTech((TechTypes)iI) && GET_TEAM(GET_PLAYER(eCorpOwner).getTeam()).isHasTech((TechTypes)iI))
				{
					iExtraTechs--;
				}
			}
			iInfluence += iExtraTechs;
			
			if (GET_TEAM(getTeam()).isAtWar(GET_PLAYER(eCorpOwner).getTeam()))
			{
				iInfluence /= 3;
			}
		}
	}
	
	iInfluence *= 100 + (-getEnvironmentalProtection() * 5);
	iInfluence /= 100;
	
	iInfluence *= 100 + (-getLaborFreedom() * 2);
	iInfluence /= 100;
	
	logBBAI("  Player %d (%S) Has a Corporation Infleunce of %d for Corporation %s", getID(), getCivilizationDescription(0), iInfluence, GC.getCorporationInfo(eIndex).getDescription());
	
	return iInfluence;
}
		
int CvPlayer::getEnvironmentalProtection() const
{
	int iValue = 0;
	for (int iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		if (getCivics((CivicOptionTypes)iI) != NO_CIVIC)
		{
			iValue += GC.getCivicInfo(getCivics((CivicOptionTypes)iI)).getRevEnvironmentalProtection();
		}
	}
	return iValue;
}

int CvPlayer::getLaborFreedom() const
{
	int iValue = 0;
	for (int iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		if (getCivics((CivicOptionTypes)iI) != NO_CIVIC)
		{
			iValue += GC.getCivicInfo(getCivics((CivicOptionTypes)iI)).getRevLaborFreedom();
		}
	}
	return iValue;
}

void CvPlayer::doTaxes()
{
	PROFILE_FUNC()

	int iOldTaxes = getCorporateTaxIncome();
	changeCorporateTaxIncome(-iOldTaxes);
	
	if (!GC.getGameINLINE().isOption(GAMEOPTION_REALISTIC_CORPORATIONS))
	{
		return;
	}
	
	int iLoop;
	int iNewTaxes = 0;
	for (CvCity* pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		iNewTaxes += pLoopCity->calculateCorporateTaxes();
	}
	
	changeCorporateTaxIncome(iNewTaxes);
}

		
int CvPlayer::getScoreComponent(int iRawScore, int iInitial, int iMax, int iFactor, bool bExponential, bool bFinal, bool bVictory) const
{
	if (GC.getGameINLINE().getEstimateEndTurn() == 0)
	{
		return 0;
	}

	if (bFinal && bVictory)
	{
		float fTurnRatio = float(GC.getGameINLINE().getGameTurn()) / float(GC.getGameINLINE().getEstimateEndTurn());
		if (bExponential && (iInitial != 0))
		{
			float fRatio = float(iMax) / float(iInitial);
			iMax = iInitial * int(pow(fRatio, fTurnRatio));
		}
		else
		{
			iMax = iInitial + int((fTurnRatio * float(iMax - iInitial)));
		}
	}
	int iScore;
	int iFree = (GC.getSCORE_FREE_PERCENT() * iMax) / 100;
	if ((iFree + iMax) != 0)
	{
		iScore = (iFactor * (iRawScore + iFree)) / (iFree + iMax);
	}
	else
	{
		iScore = iFactor;
	}
		
	if (bVictory)
	{
		iScore = ((100 + GC.getDefineINT("SCORE_VICTORY_PERCENT")) * iScore) / 100;
	}

	if (bFinal)
	{
		iScore = ((100 + GC.getDefineINT("SCORE_HANDICAP_PERCENT_OFFSET") + (GC.getGameINLINE().getHandicapType() * GC.getDefineINT("SCORE_HANDICAP_PERCENT_PER"))) * iScore) / 100;
	}

	return iScore;
}

	
void CvPlayer::doAdvancedEconomy()
{
	PROFILE_FUNC()

	if (getHurriedCount() > 0)
	{
		int iTurnIncrement = GC.getDefineINT("HURRY_INFLATION_DECAY_RATE");
		iTurnIncrement *= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getTrainPercent();
		iTurnIncrement /= 100;
		iTurnIncrement *= std::max(0, 100 + getHurryInflationModifier());
		iTurnIncrement /= 100;
		if (GC.getGameINLINE().getElapsedGameTurns() % std::max(1, iTurnIncrement) == 0)
		{
			changeHurriedCount(-1);
		}
	}
}

int CvPlayer::getWonderConstructRand() const
{
	int iNumBTSWonders = 62;
	int iNumModWonders = GC.getGameINLINE().getNumWonders();
	int iWonderConstructRand = GC.getLeaderHeadInfo(getPersonalityType()).getWonderConstructRand();
	iWonderConstructRand *= iNumModWonders;
	iWonderConstructRand /= iNumBTSWonders;
	return iWonderConstructRand;
}

int CvPlayer::getSpecialistCommercePercentChanges(SpecialistTypes eIndex1, CommerceTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumSpecialistInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_ppiSpecialistCommercePercentChanges[eIndex1][eIndex2];
}

void CvPlayer::changeSpecialistCommercePercentChanges(SpecialistTypes eIndex1, CommerceTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumSpecialistInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		int iOldValue = getSpecialistCommercePercentChanges(eIndex1, eIndex2);
		int iExistingValue;
		m_ppiSpecialistCommercePercentChanges[eIndex1][eIndex2] += iChange;		
		
		CvCity* pLoopCity;
		int iLoop;

		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			iExistingValue = (pLoopCity->getFreeSpecialistCount(eIndex1) + pLoopCity->getSpecialistCount(eIndex1)) * (getSpecialistCommercePercentChanges(eIndex1, eIndex2) - iOldValue);
			// set the new
			pLoopCity->changeSpecialistCommerceTimes100(eIndex2, iExistingValue);
		}
	}
}

int CvPlayer::getSpecialistYieldPercentChanges(SpecialistTypes eIndex1, YieldTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumSpecialistInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_YIELD_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");
	return m_ppiSpecialistYieldPercentChanges[eIndex1][eIndex2];
}

void CvPlayer::changeSpecialistYieldPercentChanges(SpecialistTypes eIndex1, YieldTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex1 < GC.getNumSpecialistInfos(), "eIndex1 is expected to be within maximum bounds (invalid Index)");
	FAssertMsg(eIndex2 >= 0, "eIndex2 is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex2 < NUM_YIELD_TYPES, "eIndex2 is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		int iOldValue = getSpecialistYieldPercentChanges(eIndex1, eIndex2);
		int iExistingValue;
		m_ppiSpecialistYieldPercentChanges[eIndex1][eIndex2] += iChange;		
		
		CvCity* pLoopCity;
		int iLoop;

		for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
		{
			iExistingValue = (pLoopCity->getSpecialistCount(eIndex1) * (getSpecialistYieldPercentChanges(eIndex1, eIndex2)) - iOldValue) / 100;
			// set the new
			pLoopCity->changeBaseYieldRate(eIndex2, iExistingValue);
		}
	}
}

int CvPlayer::getFractionalCombatExperience() const
{
	return m_iFractionalCombatExperience;
}

void CvPlayer::changeFractionalCombatExperience(int iChange)
{
	m_iFractionalCombatExperience += iChange;
	int iNewXP = m_iFractionalCombatExperience / 100;
	changeCombatExperience(iNewXP);
	m_iFractionalCombatExperience -= iNewXP * 100;
}

void CvPlayer::updateCache()
{
	/*int iI, iJ;
	for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		if (getCivics((CivicOptionTypes)iI) != NO_CIVIC)
		{
			for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
			{
				changeLandmarkYield((YieldTypes)iJ, GC.getCivicInfo(getCivics((CivicOptionTypes)iI)).getLandmarkYieldChanges(iJ));
			}
		}
	}*/
	
}

void CvPlayer::clearTileCulture()
{
	int iI;
	CvPlot* pLoopPlot;
	for (iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
	{
		pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
		pLoopPlot->setCulture(getID(), 0, true, true);
	}
}

void CvPlayer::clearCityCulture()
{
	int iI, iLoop;
	CvCity* pLoopCity;
	for (iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			for (pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
			{
				pLoopCity->setCulture(getID(), 0, true, true);
			}
		}
	}
}

int CvPlayer::getCityOverLimitUnhappy() const {
	// AIAndy: No unhappiness for barbarians from number of cities
	if (isBarbarian())
		return 0;
	return m_iCityOverLimitUnhappy;
}

void CvPlayer::changeCityOverLimitUnhappy(int iChange)
{
	m_iCityOverLimitUnhappy += iChange;
}

int CvPlayer::getCityLimit() const {
	return m_iCityLimit;
}

void CvPlayer::changeCityLimit(int iChange)
{
	m_iCityLimit += iChange;
}

int CvPlayer::getForeignUnhappyPercent() const {
	return m_iForeignUnhappyPercent;
}

void CvPlayer::changeForeignUnhappyPercent(int iChange) {
	if (iChange != 0)
	{
		m_iForeignUnhappyPercent += iChange;
	}
}
/************************************************************************************************/
/* Afforess                                                END                                  */
/************************************************************************************************/
// < M.A.D. Nukes Start >
int CvPlayer::getMADIncoming() const
{
	if (m_iMADIncoming < 0)
	{
		return 0;	// added by 45° to prevent negative nuke count that sometimes happen in MAD Nuke Manager
	}
	else
	{	
		return m_iMADIncoming;
	}	
}

void CvPlayer::setMADIncoming(int iValue)
{
	m_iMADIncoming = iValue;
}

void CvPlayer::changeMADIncoming(int iValue)
{
	m_iMADIncoming += iValue;
}

int CvPlayer::getMADOutgoing() const
{
	return m_iMADOutgoing;
}

void CvPlayer::setMADOutgoing(int iValue)
{
	m_iMADOutgoing = iValue;
}

void CvPlayer::changeMADOutgoing(int iValue)
{
	m_iMADOutgoing += iValue;
}

int CvPlayer::getMADDeterrent() const
{
	return m_iMADDeterrent;
}

void CvPlayer::setMADDeterrent(int iValue)
{
	m_iMADDeterrent = iValue;
}

void CvPlayer::changeMADDeterrent(int iValue)
{
	m_iMADDeterrent += iValue;
}

bool CvPlayer::getMADTrigger(int iValue) const
{
	return m_bMADTrigger[iValue];
}

void CvPlayer::setMADTrigger(int iValue, bool bValue)
{
	m_bMADTrigger[iValue] = bValue;
}

int CvPlayer::getMADNukesCount() const
{
	return m_iMADNukesCount;
}

bool CvPlayer::isEnabledMAD() const
{
	return getMADNukesCount() > 0;
}

void CvPlayer::changeMADNukesCount(int iChange)
{
	if (iChange != 0)
	{
		m_iMADNukesCount += iChange;
		gDLL->getInterfaceIFace()->setDirty(MiscButtons_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(SelectionButtons_DIRTY_BIT, true);
		gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
		if (!isEnabledMAD())
		{
			CvUnit* pLoopUnit;
			int iLoop;
			for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
			{
				if (pLoopUnit->isMADEnabled())
				{
					pLoopUnit->setMADEnabled(false);
					pLoopUnit->setMoves(0);
				}
			}
		}
	}
}

// < M.A.D. Nukes End   >


// BUG - Reminder Mod - start
#include "CvMessageControl.h"
void CvPlayer::addReminder(int iGameTurn, CvWString szMessage) const
{
	CvMessageControl::getInstance().sendAddReminder(getID(), iGameTurn, szMessage);
}
// BUG - Reminder Mod - end

CvContractBroker&	CvPlayer::getContractBroker(void)
{
	return m_contractBroker;
}

// Cultural Age
AgeSegments CvPlayer::getCurrentAgeSegment() const
{
	return m_eCurrentAgeSegment;
}

void CvPlayer::setCurrentAgeSegment(AgeSegments eNewValue)
{
	m_eCurrentAgeSegment = eNewValue;
}

CulturalAgeTypes CvPlayer::getCurrentCulturalAge() const
{
	return m_eCurrentCulturalAge;
}

void CvPlayer::setCurrentCulturalAge(CulturalAgeTypes eNewValue)
{
	m_eCurrentCulturalAge = eNewValue;
}

int CvPlayer::getCulture() const
{
	return m_iCulture;
}

void CvPlayer::setCulture(int iNewValue)
{
	m_iCulture = iNewValue;
}

void CvPlayer::changeCulture(int iAddValue)
{
	if (m_iCulture == -1) //saved game loaded which does not contain that information
	{
		m_iCulture = processedNationalCulture();
	}
	m_iCulture += iAddValue;
}


void CvPlayer::clearCanConstructCacheForClass(BuildingClassTypes eBuildingClass) const
{
	for(int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		BuildingClassTypes	eLoopBuildingClass = NO_BUILDINGCLASS;

		if ( eBuildingClass != NO_BUILDINGCLASS )
		{
			CvBuildingInfo&	kBuilding = GC.getBuildingInfo((BuildingTypes)iI);

			eLoopBuildingClass = (BuildingClassTypes)kBuilding.getBuildingClassType();

			int iLoop;
			CvCity* pLoopCity;
			for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
			{
				pLoopCity->FlushCanConstructCache((BuildingTypes)iI);
				pLoopCity->setBuildingListInvalid();
			}		
		}

		if ( eBuildingClass == eLoopBuildingClass )
		{
			m_bCanConstructCached[iI] = false;
			m_bCanConstructCachedDefaultParam[iI] = false;
		}
	}
}

void CvPlayer::clearModifierTotals()
{
	int iI, iJ;

	//	Clear city-sourced modifiers
	int	iLoop;
	CvCity*	pLoopCity;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->clearModifierTotals();
	}
	
	//	Project stuff
	m_iWorldHappiness = 0;
	m_iProjectHappiness = 0;
	m_iWorldHealth = 0;
	m_iProjectHealth = 0;
	m_iWorldTradeRoutes = 0;

	m_iForceAllTradeRoutes = 0;
	m_iNoCapitalUnhappiness = 0;
	m_iTaxationAnger = 0;
	m_iCivilizationHealth = 0;

	m_iForeignTradeRouteModifier = 0;
	m_iTaxRateUnhappiness = 0;
	m_iCivicHappiness = 0;
	m_iUnitUpgradePriceModifier = 0;
	m_iAnarchyModifier = 0;
	m_iGoldenAgeModifier = 0;
	m_iGlobalHurryModifier = 0;
	m_iGreatPeopleRateModifier = 0;
	m_iGreatGeneralRateModifier = 0;
	m_iDomesticGreatGeneralRateModifier = 0;
	m_iStateReligionGreatPeopleRateModifier = 0;
	m_iMaxGlobalBuildingProductionModifier = 0;
	m_iMaxTeamBuildingProductionModifier = 0;
	m_iMaxPlayerBuildingProductionModifier = 0;
	m_iFreeExperience = 0;
	m_iFeatureProductionModifier = 0;
	m_iWorkerSpeedModifier = 0;
	m_iImprovementUpgradeRateModifier = 0;
	m_iMilitaryProductionModifier = 0;
	m_iSpaceProductionModifier = 0;
	m_iCityDefenseModifier = 0;
/************************************************************************************************/
/* REVDCM                                 09/02/10                                phungus420    */
/*                                                                                              */
/* Player Functions                                                                             */
/************************************************************************************************/
	m_iNonStateReligionCommerceCount = 0;
	m_iUpgradeAnywhereCount = 0;
	m_iRevIdxDistanceModifier = 0;
	m_iRevIdxHolyCityGood = 0;
	m_iRevIdxHolyCityBad = 0;
	m_fRevIdxNationalityMod = 0;
	m_fRevIdxBadReligionMod = 0;
	m_fRevIdxGoodReligionMod = 0;
	m_iCityLimit = 0;
	m_iCityOverLimitUnhappy = 0;
	m_iForeignUnhappyPercent = 0;
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/
	m_iBaseFreeUnits = 0;
	m_iBaseFreeMilitaryUnits = 0;
	m_iFreeUnitsPopulationPercent = 0;
	m_iFreeMilitaryUnitsPopulationPercent = 0;
	m_iGoldPerUnit = 0;
	m_iGoldPerMilitaryUnit = 0;
	m_iHappyPerMilitaryUnit = 0;
	m_iMilitaryFoodProductionCount = 0;
	m_iNoUnhealthyPopulationCount = 0;
	m_iExpInBorderModifier = 0;
	m_iBuildingOnlyHealthyCount = 0;
	//DPII < Maintenance Modifier >
	m_iMaintenanceModifier = 0;
	m_iCoastalDistanceMaintenanceModifier = 0;
	m_iConnectedCityMaintenanceModifier = 0;
	//DPII < Maintenance Modifier >
	m_iDistanceMaintenanceModifier = 0;
	m_iNumCitiesMaintenanceModifier = 0;
	m_iCorporationMaintenanceModifier = 0;
	m_iUpkeepModifier = 0;
	m_iLevelExperienceModifier = 0;
	m_iExtraHealth = 0;
	m_iBuildingGoodHealth = 0;
	m_iBuildingBadHealth = 0;
	m_iExtraHappiness = 0;
	m_iBuildingHappiness = 0;
	m_iLargestCityHappiness = 0;
	m_iWarWearinessModifier = 0;
	m_iFreeSpecialist = 0;
	m_iNoForeignTradeCount = 0;
	m_iNoCorporationsCount = 0;
	m_iNoForeignCorporationsCount = 0;
	m_iCoastalTradeRoutes = 0;
	m_iTradeRoutes = 0;
	m_iStateReligionCount = 0;
	m_iNoNonStateReligionSpreadCount = 0;
	m_iStateReligionHappiness = 0;
	m_iNonStateReligionHappiness = 0;
	m_iStateReligionUnitProductionModifier = 0;
	m_iStateReligionBuildingProductionModifier = 0;
	m_iStateReligionFreeExperience = 0;
	
	m_iBuildingInflation = 0;
	m_iCivicInflation = 0;
	m_iProjectInflation = 0;
	m_iTechInflation = 0;
	
	m_iHurryCostModifier = 0;
	m_iHurryInflationModifier = 0;

	m_iTechScore = 0;
	m_iWondersScore = 0;

	m_iNationalHurryAngerModifier = 0;
	m_iNationalEnemyWarWearinessModifier = 0;
	m_iFixedBordersCount = 0;
	m_iSeizedForeignConnectednessPercent = 0;
	//m_Properties.clear();

	setPopulationgrowthratepercentage(0);
	setReligionSpreadRate(0);
	setDistantUnitSupportCostModifier(0);
	setExtraCityDefense(0);

	for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		m_paiFreeBuildingCount[iI] = 0;
		m_paiExtraBuildingHappiness[iI] = 0;
		m_paiExtraBuildingHealth[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumFeatureInfos(); iI++)
	{
		m_paiFeatureHappiness[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); iI++)
	{
		m_paiSpecialBuildingNotRequiredCount[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumHurryInfos(); iI++)
	{
		m_paiHurryCount[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		m_paiHasCivicOptionCount[iI] = 0;
		m_paiNoCivicUpkeepCount[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
	{
		m_paiSpecialistValidCount[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
	{
		for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
		{
			m_ppaaiSpecialistExtraYield[iI][iJ] = 0;
		}

		m_paiFreeSpecialistCount[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
	{
		for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
		{
			m_ppaaiSpecialistExtraYield[iI][iJ] = 0;
		}
		//TB Traits begin
		for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
		{
			m_ppaaiSpecialistExtraCommerce[iI][iJ] = 0;
		}
		//TB Traits end

		m_paiFreeSpecialistCount[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumImprovementInfos(); iI++)
	{
		for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
		{
			m_ppaaiImprovementYieldChange[iI][iJ] = 0;
		}
		m_paiImprovementUpgradeRateModifierSpecific[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumUnitCombatInfos(); iI++)
	{
		m_paiUnitCombatProductionModifier[iI] = 0;
	}
	
	for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
	{
		m_paiBonusMintedPercent[iI] = 0;
	}

	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		m_paiBuildingClassProductionModifier[iI] = 0;
	}
	
	for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
	{
		m_paiUnitClassProductionModifier[iI] = 0;
	}
	
	for (iI = 0; iI < GC.getNumTerrainInfos(); iI++)
	{
		for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
		{
			m_ppaaiTerrainYieldChange[iI][iJ] = 0;
		}
	}

	for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
		{
			m_ppiBuildingCommerceModifier[iI][iJ] = 0;
		}
	}

	for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
	{
		m_paiBuildingClassCount[iI] = 0;

		for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
		{
			m_ppiBuildingClassCommerceChange[iI][iJ] = 0;
		}
	}

	for (iI = 0; iI < GC.getNumBonusInfos(); iI++)
	{
		for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
		{
			m_ppiBonusCommerceModifier[iI][iJ] = 0;
		}
	}
	
	for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
	{
		for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
		{
			m_ppiSpecialistCommercePercentChanges[iI][iJ] = 0;
		}
		for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
		{
			m_ppiSpecialistYieldPercentChanges[iI][iJ] = 0;
		}
	}
	for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
	{
		m_aiSeaPlotYield[iI] = 0;
		m_aiYieldRateModifier[iI] = 0;
		m_aiCapitalYieldRateModifier[iI] = 0;
		m_aiExtraYieldThreshold[iI] = 0;
		m_aiTradeYieldModifier[iI] = 0;
/************************************************************************************************/
/* Afforess	                  Start		 04/15/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
		m_aiLandmarkYield[iI] = 0;
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/		
		//TB Traits begin
		m_aiSpecialistExtraYield[iI] = 0;
		//TB Traits end
	}

	for (iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
	{
		m_aiFreeCityCommerce[iI] = 0;
		m_aiCommerceRate[iI] = 0;
		m_abCommerceDirty[iI] = false;
		m_aiCommerceRateModifier[iI] = 0;
		m_aiCapitalCommerceRateModifier[iI] = 0;
		m_aiStateReligionBuildingCommerce[iI] = 0;
		m_aiSpecialistExtraCommerce[iI] = 0;
		m_aiCommerceFlexibleCount[iI] = 0;
	}

	//	Reset power to just that due to pop.  Other contributions will be re-added during the
	//	recalc
	m_iPower = getPopulationPower(getTotalPopulation());
	m_iUnitPower = 0;
	m_iTechPower = 0;

	//	Similarly assets for pop, land, and units
	m_iAssets = getPopulationAsset(getTotalPopulation());
	m_iAssets += getLandPlotsAsset(getTotalLandScored());

	for(CvUnit* pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
	{
		m_iAssets += GC.getUnitInfo(pLoopUnit->getUnitType()).getAssetValue();
		m_iUnitPower += GC.getUnitInfo(pLoopUnit->getUnitType()).getPowerValue();
	}
}

void CvPlayer::processTrait(TraitTypes eTrait, int iChange)
{
	int iJ;

/************************************************************************************************/
/* REVDCM                                 09/02/10                                phungus420    */
/*                                                                                              */
/* RevTrait Effects                                                                             */
/************************************************************************************************/
	changeNonStateReligionCommerce(iChange*((GC.getTraitInfo(eTrait).isNonStateReligionCommerce())? 1 : 0));
	changeUpgradeAnywhere(iChange*((GC.getTraitInfo(eTrait).isUpgradeAnywhere())? 1 : 0));
	changeRevIdxLocal(iChange*GC.getTraitInfo(eTrait).getRevIdxLocal());
	changeRevIdxNational(iChange*GC.getTraitInfo(eTrait).getRevIdxNational());
	changeRevIdxDistanceModifier(iChange*GC.getTraitInfo(eTrait).getRevIdxDistanceModifier());
	changeRevIdxHolyCityGood(iChange*GC.getTraitInfo(eTrait).getRevIdxHolyCityGood());
	changeRevIdxHolyCityBad(iChange*GC.getTraitInfo(eTrait).getRevIdxHolyCityBad());
	changeRevIdxNationalityMod(iChange*GC.getTraitInfo(eTrait).getRevIdxNationalityMod());
	changeRevIdxBadReligionMod(iChange*GC.getTraitInfo(eTrait).getRevIdxBadReligionMod());
	changeRevIdxGoodReligionMod(iChange*GC.getTraitInfo(eTrait).getRevIdxGoodReligionMod());
/************************************************************************************************/
/* REVDCM                                  END                                                  */
/************************************************************************************************/

/************************************************************************************************/
/* Afforess	                  Start		 01/31/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	changeCivilizationHealth(iChange*GC.getTraitInfo(eTrait).getHealth());
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
	changeExtraHappiness(iChange*GC.getTraitInfo(eTrait).getHappiness());

	for (iJ = 0; iJ < GC.getNumBuildingInfos(); iJ++)
	{
		changeExtraBuildingHappiness((BuildingTypes)iJ, iChange*GC.getBuildingInfo((BuildingTypes)iJ).getHappinessTraits(eTrait));
	}

	changeUpkeepModifier(iChange*GC.getTraitInfo(eTrait).getUpkeepModifier());
	changeLevelExperienceModifier(iChange*GC.getTraitInfo(eTrait).getLevelExperienceModifier());
	changeGreatPeopleRateModifier(iChange*GC.getTraitInfo(eTrait).getGreatPeopleRateModifier());
	changeGreatGeneralRateModifier(iChange*GC.getTraitInfo(eTrait).getGreatGeneralRateModifier());
	changeDomesticGreatGeneralRateModifier(iChange*GC.getTraitInfo(eTrait).getDomesticGreatGeneralRateModifier());

	changeMaxGlobalBuildingProductionModifier(iChange*GC.getTraitInfo(eTrait).getMaxGlobalBuildingProductionModifier());
	changeMaxTeamBuildingProductionModifier(iChange*GC.getTraitInfo(eTrait).getMaxTeamBuildingProductionModifier());
	changeMaxPlayerBuildingProductionModifier(iChange*GC.getTraitInfo(eTrait).getMaxPlayerBuildingProductionModifier());

	for (iJ = 0; iJ < NUM_YIELD_TYPES; iJ++)
	{
		changeTradeYieldModifier(((YieldTypes)iJ), iChange*GC.getTraitInfo(eTrait).getTradeYieldModifier(iJ));
	}

	for (iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
	{
		changeFreeCityCommerce(((CommerceTypes)iJ), iChange*GC.getTraitInfo(eTrait).getCommerceChange(iJ));
		changeCommerceRateModifier(((CommerceTypes)iJ), iChange*GC.getTraitInfo(eTrait).getCommerceModifier(iJ));
	}

	for (iJ = 0; iJ < GC.getNumCivicOptionInfos(); iJ++)
	{
		if (GC.getCivicOptionInfo((CivicOptionTypes) iJ).getTraitNoUpkeep(eTrait))
		{
			changeNoCivicUpkeepCount(((CivicOptionTypes)iJ), iChange);
		}
	}
/************************************************************************************************/
/* Afforess	                  Start		 08/26/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
	for (iJ = 0; iJ < GC.getNumImprovementInfos(); iJ++)
	{
		for (int iK = 0; iK < NUM_YIELD_TYPES; iK++)
		{
			changeImprovementYieldChange((ImprovementTypes)iJ, (YieldTypes)iK, iChange*GC.getImprovementInfo((ImprovementTypes)iJ).getTraitYieldChanges(eTrait, iK));
		}
	}
/************************************************************************************************/
/* Afforess	                     END                                                            */
/************************************************************************************************/
}

void CvPlayer::recalculateModifiers()
{
	OutputDebugString("\nStarting recalculateModifiers...");

	int iI;

	//	Put back starting defaults
	changeBaseFreeUnits(GC.getDefineINT("INITIAL_BASE_FREE_UNITS"));
	changeBaseFreeMilitaryUnits(GC.getDefineINT("INITIAL_BASE_FREE_MILITARY_UNITS"));
	changeFreeUnitsPopulationPercent(GC.getDefineINT("INITIAL_FREE_UNITS_POPULATION_PERCENT"));
	changeFreeMilitaryUnitsPopulationPercent(GC.getDefineINT("INITIAL_FREE_MILITARY_UNITS_POPULATION_PERCENT"));
	changeGoldPerUnit(GC.getDefineINT("INITIAL_GOLD_PER_UNIT"));
	changeTradeRoutes(GC.getDefineINT("INITIAL_TRADE_ROUTES"));
	changeStateReligionHappiness(GC.getDefineINT("INITIAL_STATE_RELIGION_HAPPINESS"));
	changeNonStateReligionHappiness(GC.getDefineINT("INITIAL_NON_STATE_RELIGION_HAPPINESS"));

	for (iI = 0; iI < NUM_YIELD_TYPES; iI++)
	{
		changeTradeYieldModifier(((YieldTypes)iI), GC.getYieldInfo((YieldTypes)iI).getTradeModifier() - getTradeYieldModifier((YieldTypes)iI));
	}

	//	Put back trait-sourced modifiers
	addTraitBonuses();

	//	Owing to an old bug the home area may not know it is our home area
	//	so set that up now if needed as well
	if ( getCapitalCity() != NULL )
	{
		CvArea*	homeArea = getCapitalCity()->area();

		if ( !homeArea->isHomeArea(getID()) )
		{
			homeArea->setHomeArea(getID(),NULL);
		}
	}

	//	Put back city-sourced modifiers
	int	iLoop;
	CvCity*	pLoopCity;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->recalculateModifiers();
	}

	//	Put back civic-sourced modifiers
	for(int iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		CivicTypes eCivic = getCivics((CivicOptionTypes)iI);

		if ( eCivic != NO_CIVIC )
		{
			processCivics(eCivic, 1);
		}
	}
// TB Nukefix
//	m_bNukesValid = false;

	//	Replay events in so far as they effect modifiers
	CvEventMap::iterator it;
	for (it = m_mapEventsOccured.begin(); it != m_mapEventsOccured.end(); ++it)
	{
		applyEvent((*it).first, -1, false);
	}

	//	Recalculate unitAI counts
	//	Note - would ideally have this be a virtual to avoid the cast but adding virtuals to this
	//	class screws up the core engine which accessing it via the DLL interafce
	((CvPlayerAI*)this)->AI_recalculateUnitCounts();
	recalculateUnitClassCounts();

	bool bresetInflation = false;
	if ( GC.getLoadedInitCore().getGameSaveSvnRev() <= 3484 ) //SVN 3484 is the first with the Inflation fix.
	{
		bresetInflation = true;
	}
	doInflation(bresetInflation); //true was only set during two week, to 'clean' the messed savegames due to inflation calculation bugs.

	setMaintenanceDirty(true);
    
	AI_updateBonusValue();
	AI_updateFoundValues(true);
	//	Re-establish blockades
	updatePlunder(1, false);
}

bool CvPlayer::upgradeAvailable(UnitTypes eFromUnit, UnitClassTypes eToUnitClass) const
{
	if ( NULL == m_upgradeCache )
	{
		m_upgradeCache = new CvUpgradeCache(getID());
	}
	return m_upgradeCache->upgradeAvailable(eFromUnit, eToUnitClass);
}

CvProperties* CvPlayer::getProperties()
{
	return &m_Properties;
}

const CvProperties* CvPlayer::getPropertiesConst() const
{
	return &m_Properties;
}

void CvPlayer::addPropertiesAllCities(CvProperties *pProp)
{
	CvCity* pLoopCity;
	int iLoop;

	EnterCriticalSection(&c_allCitiesPropertySection);

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->getProperties()->addProperties(pProp);
		//getProperties()->addProperties(pProp);
	}

	LeaveCriticalSection(&c_allCitiesPropertySection);
}

void CvPlayer::subtractPropertiesAllCities(CvProperties *pProp)
{
	CvCity* pLoopCity;
	int iLoop;

	EnterCriticalSection(&c_allCitiesPropertySection);

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->getProperties()->subtractProperties(pProp);
		//getProperties()->subtractProperties(pProp);
	}

	LeaveCriticalSection(&c_allCitiesPropertySection);
}


void CvPlayer::setBuildingListInvalid()
{
	m_BuildingList.setInvalid();
}

bool CvPlayer::getBuildingListFilterActive(BuildingFilterTypes eFilter)
{
	return m_BuildingList.getFilterActive(eFilter);
}

void CvPlayer::setBuildingListFilterActive(BuildingFilterTypes eFilter, bool bActive)
{
	m_BuildingList.setFilterActive(eFilter, bActive);
}

BuildingGroupingTypes CvPlayer::getBuildingListGrouping()
{
	return m_BuildingList.getGroupingActive();
}

void CvPlayer::setBuildingListGrouping(BuildingGroupingTypes eGrouping)
{
	m_BuildingList.setGroupingActive(eGrouping);
}

BuildingSortTypes CvPlayer::getBuildingListSorting()
{
	return m_BuildingList.getSortingActive();
}

void CvPlayer::setBuildingListSorting(BuildingSortTypes eSorting)
{
	m_BuildingList.setSortingActive(eSorting);
}

int CvPlayer::getBuildingListGroupNum()
{
	return m_BuildingList.getGroupNum();
}

int CvPlayer::getBuildingListNumInGroup(int iGroup)
{
	return m_BuildingList.getNumInGroup(iGroup);
}

BuildingTypes CvPlayer::getBuildingListType(int iGroup, int iPos)
{
	return m_BuildingList.getBuildingType(iGroup, iPos);
}

int CvPlayer::getBuildingListSelectedBuildingRow()
{
	return m_BuildingList.getBuildingSelectionRow();
}

int CvPlayer::getBuildingListSelectedWonderRow()
{
	return m_BuildingList.getWonderSelectionRow();
}

BuildingTypes CvPlayer::getBuildingListSelectedBuilding()
{
	return m_BuildingList.getSelectedBuilding();
}

BuildingTypes CvPlayer::getBuildingListSelectedWonder()
{
	return m_BuildingList.getSelectedWonder();
}

void CvPlayer::setBuildingListSelectedBuilding(BuildingTypes eBuilding)
{
	m_BuildingList.setSelectedBuilding(eBuilding);
}

void CvPlayer::setBuildingListSelectedWonder(BuildingTypes eWonder)
{
	m_BuildingList.setSelectedWonder(eWonder);
}


void CvPlayer::setUnitListInvalid()
{
	m_UnitList.setInvalid();
}

bool CvPlayer::getUnitListFilterActive(UnitFilterTypes eFilter)
{
	return m_UnitList.getFilterActive(eFilter);
}

void CvPlayer::setUnitListFilterActive(UnitFilterTypes eFilter, bool bActive)
{
	m_UnitList.setFilterActive(eFilter, bActive);
}

UnitGroupingTypes CvPlayer::getUnitListGrouping()
{
	return m_UnitList.getGroupingActive();
}

void CvPlayer::setUnitListGrouping(UnitGroupingTypes eGrouping)
{
	m_UnitList.setGroupingActive(eGrouping);
}

UnitSortTypes CvPlayer::getUnitListSorting()
{
	return m_UnitList.getSortingActive();
}

void CvPlayer::setUnitListSorting(UnitSortTypes eSorting)
{
	m_UnitList.setSortingActive(eSorting);
}

int CvPlayer::getUnitListGroupNum()
{
	return m_UnitList.getGroupNum();
}

int CvPlayer::getUnitListNumInGroup(int iGroup)
{
	return m_UnitList.getNumInGroup(iGroup);
}

UnitTypes CvPlayer::getUnitListType(int iGroup, int iPos)
{
	return m_UnitList.getUnitType(iGroup, iPos);
}

int CvPlayer::getUnitListSelectedRow()
{
	return m_UnitList.getSelectionRow();
}

UnitTypes CvPlayer::getUnitListSelected()
{
	return m_UnitList.getSelectedUnit();
}

void CvPlayer::setUnitListSelected(UnitTypes eUnit)
{
	m_UnitList.setSelectedUnit(eUnit);
}

void CvPlayer::processNewRoutes(void)
{
	//	Invalidate best route cache
	m_eBestRoute = NO_ROUTE;

	//	Process auto-upgrade of city tile routes
	int		iLoop;
	CvCity*	pLoopCity;
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->plot()->updateCityRoute(true);
	}
}

bool CvPlayer::canHaveBuilder(BuildTypes eBuild) const
{
	std::map<int,bool>::const_iterator itr = m_canHaveBuilder.find(eBuild);

	if ( itr == m_canHaveBuilder.end() )
	{
		CvUnit*	pLoopUnit;
		int iLoop;
		bool hasSuitableUnit = false;

		for(pLoopUnit = firstUnit(&iLoop); pLoopUnit != NULL; pLoopUnit = nextUnit(&iLoop))
		{
			if ( pLoopUnit->getUnitInfo().getBuilds(eBuild) )
			{
				hasSuitableUnit = true;
				break;
			}
		}

		if ( !hasSuitableUnit )
		{
			//	Could we build one?
			for(int iI = 0; iI < GC.getNumUnitInfos(); iI++)
			{
				if ( GC.getUnitInfo((UnitTypes)iI).getBuilds(eBuild) && canTrain((UnitTypes)iI) )
				{
					hasSuitableUnit = true;
				}
			}

			MEMORY_TRACK_EXEMPT();

			m_canHaveBuilder[eBuild] = hasSuitableUnit;
		}

		return hasSuitableUnit;
	}
	else
	{
		return itr->second;
	}
}


//TB Nukefix
bool CvPlayer::isNukesValid() const
{
	if (GC.getGameINLINE().isOption(GAMEOPTION_NO_NUKES))
	{
		return false;
	}
	return m_bNukesValid;
}


void CvPlayer::makeNukesValid(bool bValid)
{
	m_bNukesValid = bValid;
}

#ifdef _DEBUG
void CvPlayer::ValidatePlotGroup(CvPlot* plot, CvPlotGroup* group)
{
#if 0
	CvPlotGroup* pLoopPlotGroup;
	int iLoop;

	for(pLoopPlotGroup = firstPlotGroup(&iLoop); pLoopPlotGroup != NULL; pLoopPlotGroup = nextPlotGroup(&iLoop))
	{
		if ( pLoopPlotGroup != group )
		{
			CLLNode<XYCoords>* pPlotNode;

			pPlotNode = pLoopPlotGroup->headPlotsNode();
			while (pPlotNode != NULL)
			{
				FAssert(pPlotNode->m_data.iX != plot->getX_INLINE() || pPlotNode->m_data.iY != plot->getY_INLINE());

				pPlotNode = pLoopPlotGroup->nextPlotsNode(pPlotNode);
			}
		}
	}
#endif
}
#endif

typedef struct buildingCommerceStruct
{
	int				iMultiplier;
	int				iGlobalMultiplier;
	int				iCount;
	float			fContribution;
} buildingCommerceStruct;

void CvPlayer::validateCommerce() const
{
	std::vector<buildingCommerceStruct> multipliers;

	for(int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		CvBuildingInfo&	kBuilding = GC.getBuildingInfo((BuildingTypes)iI);
		buildingCommerceStruct	commerceStruct;

		commerceStruct.iMultiplier = kBuilding.getCommerceModifier(COMMERCE_GOLD);
		commerceStruct.iGlobalMultiplier = kBuilding.getGlobalCommerceModifier(COMMERCE_GOLD);
		commerceStruct.iCount = 0;
		commerceStruct.fContribution = 0;

		multipliers.push_back(commerceStruct);
	}

	float fBuildings = 0;
	float fHeadquarters = 0;
	float fShrines = 0;
	float fCorporations = 0;
	float fSpecialists = 0;
	float fWealth = 0;
	float fUnmodifiedTotal = 0;
	float fPlayerGoldModifierEffect = 0;
	float fBonusGoldModifierEffect = 0;
	int iLoop;
	CvCity* pLoopCity;
	// dirty all of this player's cities...
	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		if ( !pLoopCity->isDisorder() )
		{
			float fCityBuildings = 0;
			float fCityHeadquarters = 0;
			float fCityShrines = 0;

			for(int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
			{
				int iCount = pLoopCity->getNumActiveBuilding((BuildingTypes)iI);
				if ( iCount > 0 )
				{
					int	iBuildingGold = pLoopCity->getBuildingCommerceByBuilding(COMMERCE_GOLD, (BuildingTypes)iI);
					if ( iBuildingGold != 0)
					{
						CvBuildingInfo&	kBuilding = GC.getBuildingInfo((BuildingTypes)iI);
						if ( kBuilding.getFoundsCorporation() != NO_CORPORATION )
						{
							fCityHeadquarters += (float)iBuildingGold;
						}
						else if ( kBuilding.getGlobalReligionCommerce() != NO_RELIGION )
						{
							fCityShrines += (float)iBuildingGold;
						}
						else
						{
							fCityBuildings += (float)iBuildingGold;
						}
					}
				}
			}

			fBuildings += fCityBuildings;
			fHeadquarters += fCityHeadquarters;
			fShrines += fCityShrines;

			float fCityCorporations = (float)pLoopCity->getCorporationCommerce(COMMERCE_GOLD);
			fCorporations += fCityCorporations;

			float fTaxRate = (float)pLoopCity->calculateCorporateTaxes();
			if (fTaxRate > 0)
				fCorporations += fTaxRate;

			float fCitySpecialists = (float)pLoopCity->getSpecialistCommerce(COMMERCE_GOLD);
			fSpecialists += fCitySpecialists;
			
			fSpecialists += (float)(pLoopCity->getSpecialistPopulation() + pLoopCity->getNumGreatPeople()) * getSpecialistExtraCommerce(COMMERCE_GOLD);
			
			float fCityWealth = 0;
			if (pLoopCity->isProductionProcess() && pLoopCity->getProductionProcess() == (ProcessTypes)GC.getInfoTypeForString("PROCESS_WEALTH"))
			{
				float fCityWealth = (float)(pLoopCity->getProductionToCommerceModifier(COMMERCE_GOLD) * pLoopCity->getYieldRate(YIELD_PRODUCTION)) / 100;
				fWealth += fCityWealth;
			}

			float fCityTotal = /*fCityTaxes + */ fCityBuildings + fCityHeadquarters + fCityShrines + fCityCorporations + fCitySpecialists;
			fUnmodifiedTotal += fCityTotal;
			
			if (pLoopCity->isCapital())
				fPlayerGoldModifierEffect += fCityTotal * (float)(getCommerceRateModifier(COMMERCE_GOLD) + getCapitalCommerceRateModifier(COMMERCE_GOLD)) / 100;
			else
				fPlayerGoldModifierEffect += fCityTotal * (float)getCommerceRateModifier(COMMERCE_GOLD) / 100;

			fBonusGoldModifierEffect += fCityTotal * (float)pLoopCity->getBonusCommerceRateModifier(COMMERCE_GOLD) / 100;
			
			int iBuildingMod = 0;
			for(int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
			{
				int iCount = pLoopCity->getNumActiveBuilding((BuildingTypes)iI);
				if ( iCount > 0 && multipliers[iI].iMultiplier != 0 )
				{
					iBuildingMod += multipliers[iI].iMultiplier;
					multipliers[iI].iCount += iCount;
					multipliers[iI].fContribution += (float)iCount * fCityTotal * (float)multipliers[iI].iMultiplier / 100;
				}
			}
		}
	}
				
	int iTotalMinusTaxes = (int)fBuildings + (int)fCorporations + (int)fShrines + (int)fSpecialists + (int)fWealth + (int)fPlayerGoldModifierEffect + (int)fBonusGoldModifierEffect;
	
	for(int iI = 0; iI < GC.getNumBuildingInfos(); iI++)
	{
		iTotalMinusTaxes += (int)multipliers[iI].fContribution;
		if (multipliers[iI].iGlobalMultiplier != 0)
		{
			float fAdjust = fUnmodifiedTotal * (float)multipliers[iI].iGlobalMultiplier / 100;
			multipliers[iI].fContribution += fAdjust;
			fPlayerGoldModifierEffect -= fAdjust;
		}
	}

	int iGoldCommerce = getCommerceRate(COMMERCE_GOLD);

	//calvitix 20120828 : WARNING for the moment, It appers a lot of Mismatched during AI turn, causing slowdown
	// NEED TO BE FIXED
	if ( iGoldCommerce != iTotalMinusTaxes )
	{
		OutputDebugString("Mismatched commerce");
		updateCommerce();
	}
}

CvCity*	CvPlayer::findClosestCity(CvPlot* pPlot) const
{
	int iLoop;
	CvCity* pLoopCity;
	int	iClosest = MAX_INT;
	CvCity*	pResult = NULL;

	if ( pPlot == NULL )
	{
		return firstCity(&iLoop);
	}

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		int iDistance = plotDistance(pLoopCity->getX_INLINE(), pLoopCity->getY_INLINE(), pPlot->getX_INLINE(), pPlot->getY_INLINE());

		if ( iDistance < iClosest )
		{
			iClosest = iDistance;
			pResult = pLoopCity;
		}
	}

	return pResult;
}
int CvPlayer::getImprovementUpgradeRateModifierSpecific(ImprovementTypes eImprovement) const
{
	return m_paiImprovementUpgradeRateModifierSpecific[eImprovement];
}

void CvPlayer::changeImprovementUpgradeRateModifierSpecific(ImprovementTypes eImprovement, int iChange)
{
	m_paiImprovementUpgradeRateModifierSpecific[eImprovement] = (m_paiImprovementUpgradeRateModifierSpecific[eImprovement] + iChange);
}
int CvPlayer::getExtraSpecialistCommerce(SpecialistTypes eIndex1, CommerceTypes eIndex2) const
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 expected to be >= 0");
	FAssertMsg(eIndex1 < GC.getNumSpecialistInfos(), "eIndex1 expected to be < GC.getNumSpecialistInfos()");
	FAssertMsg(eIndex2 >= 0, "eIndex2 expected to be >= 0");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 expected to be < NUM_COMMERCE_TYPES");
	return m_ppaaiSpecialistExtraCommerce[eIndex1][eIndex2];
}


void CvPlayer::changeExtraSpecialistCommerce(SpecialistTypes eIndex1, CommerceTypes eIndex2, int iChange)
{
	FAssertMsg(eIndex1 >= 0, "eIndex1 expected to be >= 0");
	FAssertMsg(eIndex1 < GC.getNumSpecialistInfos(), "eIndex1 expected to be < GC.getNumSpecialistInfos()");
	FAssertMsg(eIndex2 >= 0, "eIndex2 expected to be >= 0");
	FAssertMsg(eIndex2 < NUM_COMMERCE_TYPES, "eIndex2 expected to be < NUM_COMMERCE_TYPES");

	if (iChange != 0)
	{
		m_ppaaiSpecialistExtraCommerce[eIndex1][eIndex2] = (m_ppaaiSpecialistExtraCommerce[eIndex1][eIndex2] + iChange);
		//TB Note: should be allowed to be negative.
		//FAssert(getExtraSpecialistCommerce(eIndex1, eIndex2) >= 0);

		updateExtraSpecialistCommerce();

		AI_makeAssignWorkDirty();
	}
}

void CvPlayer::updateExtraSpecialistCommerce()
{
	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->updateExtraSpecialistCommerce();
	}
}

int CvPlayer::getSpecialistExtraYield(YieldTypes eIndex) const
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");
	return m_aiSpecialistExtraYield[eIndex];
}

void CvPlayer::changeSpecialistExtraYield(YieldTypes eIndex, int iChange)
{
	FAssertMsg(eIndex >= 0, "eIndex is expected to be non-negative (invalid Index)");
	FAssertMsg(eIndex < NUM_YIELD_TYPES, "eIndex is expected to be within maximum bounds (invalid Index)");

	if (iChange != 0)
	{
		m_aiSpecialistExtraYield[eIndex] = (m_aiSpecialistExtraYield[eIndex] + iChange);
		FAssert(getSpecialistExtraYield(eIndex) >= 0);

		updateYield();

		AI_makeAssignWorkDirty();
	}
}
int CvPlayer::getNationalHurryAngerModifier() const
{
	return m_iNationalHurryAngerModifier;
}	

void CvPlayer::setNationalHurryAngerModifier(int iValue)
{
    m_iNationalHurryAngerModifier = iValue;
}

void CvPlayer::changeNationalHurryAngerModifier(int iChange)
{
    setNationalHurryAngerModifier(getNationalHurryAngerModifier() + iChange);
}

int CvPlayer::getNationalEnemyWarWearinessModifier() const
{
	return m_iNationalEnemyWarWearinessModifier;
}	

void CvPlayer::setNationalEnemyWarWearinessModifier(int iValue)
{
    m_iNationalEnemyWarWearinessModifier = iValue;
}

void CvPlayer::changeNationalEnemyWarWearinessModifier(int iChange)
{
    setNationalEnemyWarWearinessModifier(getNationalEnemyWarWearinessModifier() + iChange);
}
void CvPlayer::startDeferredPlotGroupBonusCalculation(void)
{
	PROFILE_FUNC();

	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->startDeferredBonusProcessing();
	}
}

void CvPlayer::endDeferredPlotGroupBonusCalculation(void)
{
	PROFILE_FUNC();

	CvCity* pLoopCity;
	int iLoop;

	for (pLoopCity = firstCity(&iLoop); pLoopCity != NULL; pLoopCity = nextCity(&iLoop))
	{
		pLoopCity->endDeferredBonusProcessing();
	}
}

bool CvPlayer::hasFixedBorders() const
{
	if (isBarbarian() || GC.getGameINLINE().isOption(GAMEOPTION_NO_FIXED_BORDERS) )
	{
		return false;
	}

	return (m_iFixedBordersCount > 0);
}	

void CvPlayer::setFixedBordersCount(int iValue)
{
    m_iFixedBordersCount = iValue;
}

void CvPlayer::changeFixedBordersCount(int iChange)
{
    m_iFixedBordersCount += iChange;
}

// K-Mod
int CvPlayer::getTypicalUnitValue(UnitAITypes eUnitAI) const
{
	//UnitTypes eBestUnit = NO_UNIT;
	int iHighestValue = 0;

	for (int iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
	{
		UnitTypes eLoopUnit = ((UnitTypes)(GC.getCivilizationInfo(getCivilizationType()).getCivilizationUnits(iI)));

		if (eLoopUnit != NO_UNIT && GC.getUnitInfo(eLoopUnit).getUnitAIType(eUnitAI) && canTrain(eLoopUnit))
		{
			int iValue = GC.getGameINLINE().AI_combatValue(eLoopUnit);
			if (iValue > iHighestValue)
			{
				iHighestValue = iValue;
				//eBestUnit = eLoopUnit;
			}
		}
	}

	return iHighestValue;
}

/**
	This index changes based on how often this player incites conflicts between other civs
*/
int CvPlayer::getWarMongererIndex() const
{
	return m_iWarMongerIndex;
}

void CvPlayer::changeWarMongererIndex(int iChange)
{
	m_iWarMongerIndex += iChange;
}

void CvPlayer::decayWarMongererIndex()
{
	if (m_iWarMongerIndex > 0)
	{
		int iOldValue = m_iWarMongerIndex;
		int iDecayRate = GC.getDefineINT("WARMONGERER_INDEX_DECAY_RATE", 20);
		if (!isHuman()) {
			iDecayRate *= 3;
		}
		iDecayRate *= 100;
		iDecayRate /= GC.getGameSpeedInfo(GC.getGameINLINE().getGameSpeedType()).getGoldenAgePercent();
		iDecayRate = std::max(1, iDecayRate);
		//Don't allow negatives
		m_iWarMongerIndex = std::max(0, m_iWarMongerIndex - iDecayRate);
		GC.getGameINLINE().logMsg("War Mongerer Index decreasing from %d to %d for Player %d", iOldValue, m_iWarMongerIndex, getID());
	}
}

bool CvPlayer::canTradeWarReparations(PlayerTypes ePlayer) const
{
	return AI_getMemoryCount(ePlayer, MEMORY_DECLARED_WAR) > 0 || AI_getMemoryCount(ePlayer, MEMORY_HIRED_WAR_ALLY) > 0 ||
		AI_getMemoryCount(ePlayer, MEMORY_NUKED_US) > 0 || AI_getMemoryCount(ePlayer, MEMORY_RAZED_CITY) > 0 ||
		AI_getMemoryCount(ePlayer, MEMORY_RAZED_HOLY_CITY) > 0 || AI_getMemoryCount(ePlayer, MEMORY_BACKSTAB) > 0;
}

DenialTypes CvPlayer::AI_tradeWarReparations(PlayerTypes ePlayer) const
{
	if (isHuman())
	{
		return NO_DENIAL;
	}

	return DENIAL_JOKING;
}

DenialTypes CvPlayer::AI_tradeCeaseRelations(PlayerTypes ePlayer, PlayerTypes eRequestFrom) const
{
	if (isHuman())
	{
		return NO_DENIAL;
	}

	if (AI_getAttitude(ePlayer) > ATTITUDE_PLEASED)
	{
		return DENIAL_JOKING;
	}

	if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(eRequestFrom).getTeam()))
	{
		return NO_DENIAL;
	}

	if (GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()))
	{
		return DENIAL_POWER_THEM;
	}

	AttitudeTypes eAttitudeThem = GET_TEAM(getTeam()).AI_getAttitude(GET_PLAYER(ePlayer).getTeam());

	for (int iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isAlive())
		{
			if (GET_PLAYER((PlayerTypes)iI).getTeam() == getTeam())
			{
				if (eAttitudeThem > GC.getLeaderHeadInfo(GET_PLAYER((PlayerTypes)iI).getPersonalityType()).getStopTradingThemRefuseAttitudeThreshold())
				{
					return DENIAL_ATTITUDE_THEM;
				}
			}
		}
	}

	if (GET_TEAM(getTeam()).isOpenBorders(GET_PLAYER(ePlayer).getTeam()))
	{
		if (GET_TEAM(getTeam()).getAnyWarPlanCount(true) > 0 && GET_TEAM(getTeam()).AI_getWarPlan(GET_PLAYER(ePlayer).getTeam()) == NO_WARPLAN)
		{
			return DENIAL_MYSTERY;
		}
	}

	return NO_DENIAL;
}

int CvPlayer::getCeaseContactCounter(PlayerTypes ePlayer) const
{
	return m_aiCeaseContactCounter[ePlayer];
}

void CvPlayer::setCeaseContactCounter(PlayerTypes ePlayer, int iValue)
{
	m_aiCeaseContactCounter[ePlayer] = iValue;
}

int CvPlayer::getFractionalXPEarnedInCity() const
{
	return m_iFractionalXPEarnedInCity;
}

void CvPlayer::changeFractionalXPEarnedInCity(int iChange)
{
	m_iFractionalXPEarnedInCity = std::max(0, m_iFractionalXPEarnedInCity + iChange);
}

//Calculates the tribute percent paid out to the strongest players
int CvPlayer::getStrongestTributePercent() const
{
	int iTributePercent = 0;
	for (int iCivicOption = 0; iCivicOption < GC.getNumCivicOptionInfos(); iCivicOption++)
	{
		CivicTypes eCivic = getCivics((CivicOptionTypes)iCivicOption);
		if (eCivic != NO_CIVIC)
		{
			iTributePercent += std::max(0, GC.getCivicInfo(eCivic).getTributePercent());
		}
	}
	return iTributePercent;
}

//Calculates the tributes paid out to the weakest players
int CvPlayer::getWeakestTributePercent() const
{
	int iTributePercent = 0;
	for (int iCivicOption = 0; iCivicOption < GC.getNumCivicOptionInfos(); iCivicOption++)
	{
		CivicTypes eCivic = getCivics((CivicOptionTypes)iCivicOption);
		if (eCivic != NO_CIVIC)
		{
			//I am lazy so negative tribute counts as tribute to the weakest players (instead of the strongest)
			iTributePercent -= std::min(0, GC.getCivicInfo(eCivic).getTributePercent());
		}
	}
	return iTributePercent;
}

//Calculates the gold per turn you should receive as a result of *other* players appeasements
int CvPlayer::calculateTributeReceived() const
{
	int iTribute = 0;
	bool bWeakest = GC.getGameINLINE().isInWeakestPlayerThreshold(getID());
	bool bStrongest = GC.getGameINLINE().isInStrongestPlayerThreshold(getID());
	if (!bWeakest && !bStrongest)
	{
		return 0;
	}

	for (int iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (iI != getID() && GET_PLAYER((PlayerTypes)iI).isAlive() && GET_TEAM(getTeam()).isHasMet(GET_PLAYER((PlayerTypes)iI).getTeam()) && !GET_TEAM(getTeam()).isAtWar(GET_PLAYER((PlayerTypes)iI).getTeam()))
		{
			if (bStrongest)
			{
				int iTributePercent = GET_PLAYER((PlayerTypes)iI).getStrongestTributePercent();
				if (iTributePercent > 0)
				{
					int iCommerce = 0;
					for (int iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
					{
						iCommerce += GET_PLAYER((PlayerTypes)iI).getCommerceRate((CommerceTypes)iJ);
					}
					iTribute += (iCommerce * iTributePercent / GC.getGameINLINE().getNumStrongestPlayers((PlayerTypes)iI));
				}
			}
			else if (bWeakest)
			{
				int iTributePercent = GET_PLAYER((PlayerTypes)iI).getWeakestTributePercent();
				if (iTributePercent > 0)
				{
					int iCommerce = 0;
					for (int iJ = 0; iJ < NUM_COMMERCE_TYPES; iJ++)
					{
						iCommerce += GET_PLAYER((PlayerTypes)iI).getCommerceRate((CommerceTypes)iJ);
					}
					iTribute += (iCommerce * iTributePercent) / GC.getGameINLINE().getNumWeakestPlayers((PlayerTypes)iI);
				}
			}
		}
	}
	iTribute /= 100;
	return iTribute;
}

int CvPlayer::calculateTributeReceived(PlayerTypes ePlayer) const
{
	int iTribute = 0;
	bool bWeakest = GC.getGameINLINE().isInWeakestPlayerThreshold(getID());
	bool bStrongest = GC.getGameINLINE().isInStrongestPlayerThreshold(getID());
	if (!bWeakest && !bStrongest)
	{
		return 0;
	}

	if (ePlayer != getID() && GET_PLAYER(ePlayer).isAlive() && GET_TEAM(getTeam()).isHasMet(GET_PLAYER(ePlayer).getTeam()) && !GET_TEAM(getTeam()).isAtWar(GET_PLAYER(ePlayer).getTeam()))
	{
		if (bStrongest)
		{
			int iTributePercent = GET_PLAYER(ePlayer).getStrongestTributePercent();
			if (iTributePercent > 0)
			{
				int iCommerce = 0;
				for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
				{
					iCommerce += GET_PLAYER(ePlayer).getCommerceRate((CommerceTypes)iI);
				}
				iTribute += (iCommerce * iTributePercent / GC.getGameINLINE().getNumStrongestPlayers(ePlayer));
			}
		}
		else if (bWeakest)
		{
			int iTributePercent = GET_PLAYER(ePlayer).getWeakestTributePercent();
			if (iTributePercent > 0)
			{
				int iCommerce = 0;
				for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
				{
					iCommerce += GET_PLAYER(ePlayer).getCommerceRate((CommerceTypes)iI);
				}
				iTribute += (iCommerce * iTributePercent) / GC.getGameINLINE().getNumWeakestPlayers(ePlayer);
			}
		}
	}
	iTribute /= 100;
	return iTribute;
}

//Calculates the gold per turn you should pay out to other civs as a result of your tribute
int CvPlayer::calculateTributePayment() const
{
	if (!isAnarchy())
	{
		int iCommerce = 0;
		for (int iI = 0; iI < NUM_COMMERCE_TYPES; iI++)
		{
			iCommerce += getCommerceRate((CommerceTypes)iI);
		}
		iCommerce *= (getStrongestTributePercent() + getWeakestTributePercent());
		iCommerce /= 100;
		return iCommerce;
	}
	return 0;
}

int CvPlayer::getSeizedForeignConnectednessPercent() const
{
	return m_iSeizedForeignConnectednessPercent;
}

void CvPlayer::updateSeizedForeignConnectednessPercent()
{
	int iOldValue = m_iSeizedForeignConnectednessPercent;
	int iNewValue = 0;
	for (int iI = 0; iI < GC.getNumCivicOptionInfos(); iI++)
	{
		CivicTypes eCivic = getCivics((CivicOptionTypes)iI);
		if (eCivic != NO_CIVIC)
		{
			iNewValue = std::max(iNewValue, GC.getCivicInfo(eCivic).getSeizedForeignConnectednessPercent());
		}
	}
	if (iNewValue != iOldValue)
	{
		m_iSeizedForeignConnectednessPercent = iNewValue;

		for (int iI = 0; iI < MAX_PLAYERS; iI++)
		{
			if (GET_PLAYER((PlayerTypes)iI).isCanSeizeForeignConnectednessFromUs(getID()))
			{
				int iLoop;
				for (CvCity* pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
				{
					pLoopCity->doConnectednessCalculations();
				}
				GET_PLAYER((PlayerTypes)iI).AI_doCommerce();
			}
		}
	}
}

int CvPlayer::calculateTotalForeignConnectednessSeized() const
{
	int iGold = 0;
	int iSeizedPercent = getSeizedForeignConnectednessPercent();
	if (iSeizedPercent <= 0)
	{
		return 0;
	}

	for (int iI = 0; iI < MAX_PLAYERS; iI++)
	{
		if (GET_PLAYER((PlayerTypes)iI).isCanSeizeForeignConnectednessFromUs(getID()))
		{
			int iLoop;
			for (CvCity* pLoopCity = GET_PLAYER((PlayerTypes)iI).firstCity(&iLoop); pLoopCity != NULL; pLoopCity = GET_PLAYER((PlayerTypes)iI).nextCity(&iLoop))
			{
				iGold += pLoopCity->getSeizedForeignConnectednessTimes100(getID());
			}
		}
	}
	return iGold / 100;
}

bool CvPlayer::isCanSeizeForeignConnectednessFromUs(PlayerTypes ePlayer, bool bIgnoreCivics) const
{
	//We are different players, alive, and can seize commerce according to civics
	if (ePlayer != getID() && GET_PLAYER(ePlayer).isAlive() && (bIgnoreCivics || GET_PLAYER(ePlayer).getSeizedForeignConnectednessPercent() > 0))
	{
		//We are different teams, have met, and are not at war
		if (getTeam() != GET_PLAYER(ePlayer).getTeam() && GET_TEAM(getTeam()).isHasMet(GET_PLAYER(ePlayer).getTeam()) && !GET_TEAM(getTeam()).isAtWar(GET_PLAYER(ePlayer).getTeam()))
		{
			//We are not vassals of each other
			if (!GET_TEAM(getTeam()).isVassal(GET_PLAYER(ePlayer).getTeam()) && !GET_TEAM(GET_PLAYER(ePlayer).getTeam()).isVassal(getTeam()))
			{
				//They have a higher rank than us (ranks are 0 based ascending, so 0 is a higher rank than 1)
				if (GC.getGameINLINE().getPlayerRank(ePlayer) < GC.getGameINLINE().getPlayerRank(getID()))
				{
					return true;
				}
			}
		}
	}
	return false;
}