Subversion Repositories RAND

Rev

Rev 1056 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

// game.cpp


#include "CvGameCoreDLL.h"
#include "CvGameCoreUtils.h"
#include "CvGame.h"
#include "CvGameAI.h"
#include "CvMap.h"
#include "CvViewport.h"
#include "CvPlot.h"
#include "CvPlayerAI.h"
#include "CvRandom.h"
#include "CvTeamAI.h"
#include "CvGlobals.h"
#include "CvInitCore.h"
#include "CvMapGenerator.h"
#include "CvArtFileMgr.h"
#include "CvDiploParameters.h"
#include "CvReplayMessage.h"
#include "CyArgsList.h"
#include "CvInfos.h"
#include "CvPopupInfo.h"
#include "FProfiler.h"
#include "CvReplayInfo.h"
#include "CvGameTextMgr.h"
#include "CvBugOptions.h"
#include <set>
#include "CvEventReporter.h"
#include "CvMessageControl.h"
#include "CvTaggedSaveFormatWrapper.h"
#include "FDataStreamBuffer.h"

#define BOOST_THREAD_NO_LIB
#define BOOST_THREAD_USE_LIB
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>

// interface uses
#include "CvDLLInterfaceIFaceBase.h"
#include "CvDLLEngineIFaceBase.h"
#include "CvDLLPythonIFaceBase.h"

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                      10/02/09                                jdog5000      */
/*                                                                                              */
/* AI logging                                                                                   */
/************************************************************************************************/
#include "BetterBTSAI.h"
#include "CvMessageData.h"

/************************************************************************************************/
/* BETTER_BTS_AI_MOD                       END                                                  */
/************************************************************************************************/
// BUG - start
// RevolutionDCM - BugMod included in CvGlobals.h
//#include "BugMod.h"
// BUG - end

//      Koshling - save game compataibility between (most) builds
//      UI flag values in game serialization.  These are bitwise combinable
#define GAME_SAVE_UI_FLAG_VALUE_AND_BASE                0x00000001

// Public Functions...

#pragma warning( disable : 4355 )
CvGame::CvGame() : m_GameObject(),
m_Properties(this)
, m_iLastLookatX(-1)
, m_iLastLookatY(-1)
, m_bWasGraphicsPagingEnabled(false)
, m_eCurrentMap(INITIAL_MAP)

{
        InitializeCriticalSectionAndSpinCount(&m_reportableEventsSection, 5000);

        m_aiRankPlayer = new int[MAX_PLAYERS];        // Ordered by rank...
        m_aiPlayerRank = new int[MAX_PLAYERS];        // Ordered by player ID...
        m_aiPlayerScore = new int[MAX_PLAYERS];       // Ordered by player ID...
        m_aiRankTeam = new int[MAX_TEAMS];                                              // Ordered by rank...
        m_aiTeamRank = new int[MAX_TEAMS];                                              // Ordered by team ID...
        m_aiTeamScore = new int[MAX_TEAMS];                                             // Ordered by team ID...

        m_paiUnitCreatedCount = NULL;
        m_paiUnitClassCreatedCount = NULL;
        m_paiBuildingClassCreatedCount = NULL;
        m_paiProjectCreatedCount = NULL;
        m_paiForceCivicCount = NULL;
        m_paiVoteOutcome = NULL;
        m_paiReligionGameTurnFounded = NULL;
        m_paiCorporationGameTurnFounded = NULL;
        m_aiSecretaryGeneralTimer = NULL;
        m_aiVoteTimer = NULL;
        m_aiDiploVote = NULL;

        m_pabSpecialUnitValid = NULL;
        m_pabSpecialBuildingValid = NULL;
        m_abReligionSlotTaken = NULL;
/************************************************************************************************/
/* RevDCM                         Start          4/29/10                                                */
/*                                                                                              */
/* OC_LIMITED_RELIGIONS                                                                         */
/************************************************************************************************/
        m_abTechCanFoundReligion = NULL;
/************************************************************************************************/
/* LIMITED_RELIGIONS               END                                                          */
/************************************************************************************************/

        m_paHolyCity = NULL;
        m_paHeadquarters = NULL;
/************************************************************************************************/
/* Afforess                                     12/7/09                                         */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
        for (int iI = 0; iI < MAX_TEAMS; iI++)
        {
          starshipLaunched[iI] = false;
          diplomaticVictoryAchieved[iI] = false;               
          AscensionGateBuilt[iI] = false; // code added for Ascension Gate & Mastery Victory (by 45°)
        }
       
        m_abPreviousRequest = new bool[MAX_PLAYERS];
        m_aiModderGameOption = new int[NUM_MODDERGAMEOPTION_TYPES];
        m_aiFlexibleDifficultyTimer = new int[MAX_PLAYERS];
        m_resyncPackets.clear();
        m_resyncReceiveBuffer.clear();
        m_pDarkAgeState = NULL;
/************************************************************************************************/
/* Afforess                              END                                                        */
/************************************************************************************************/     

        m_pReplayInfo = NULL;

        m_aiShrineBuilding = NULL;
        m_aiShrineReligion = NULL;

        //m_bDeferVoteSourceProcessing = false;
        //m_paiDeferredVoteSources = NULL;

        m_bRecalculatingModifiers = false;

        reset(NO_HANDICAP, true);
}


CvGame::~CvGame()
{
        uninit();

        SAFE_DELETE_ARRAY(m_aiRankPlayer);
        SAFE_DELETE_ARRAY(m_aiPlayerRank);
        SAFE_DELETE_ARRAY(m_aiPlayerScore);
        SAFE_DELETE_ARRAY(m_aiRankTeam);
        SAFE_DELETE_ARRAY(m_aiTeamRank);
        SAFE_DELETE_ARRAY(m_aiTeamScore);
/************************************************************************************************/
/* Afforess                       Start          05/19/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
        SAFE_DELETE_ARRAY(m_abPreviousRequest);
        SAFE_DELETE_ARRAY(m_aiModderGameOption);
        SAFE_DELETE_ARRAY(m_aiFlexibleDifficultyTimer);
        SAFE_DELETE(m_pDarkAgeState);
/************************************************************************************************/
/* Afforess                          END                                                            */
/************************************************************************************************/

        DeleteCriticalSection(&m_reportableEventsSection);
}

void CvGame::init(HandicapTypes eHandicap)
{
        bool bValid;
        int iStartTurn;
        int iEstimateEndTurn;
        int iI;

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

        //--------------------------------
        // Init containers
        m_deals.init();
        m_voteSelections.init();
        m_votesTriggered.init();

        m_mapRand.init(GC.getInitCore().getMapRandSeed() % 73637381);
        //Afforess: disable map rand logging
        //m_mapRand.m_bLoggingEnabled = false;
        //GC.getASyncRand().m_bLoggingEnabled = false;
        m_sorenRand.init(GC.getInitCore().getSyncRandSeed() % 52319761);
        //m_sorenRand.m_bLoggingEnabled = true;

        //--------------------------------
        // Init non-saved data

        //--------------------------------
        // Init other game data

        // Turn off all MP options if it's a single player game
        if (GC.getInitCore().getType() == GAME_SP_NEW ||
                GC.getInitCore().getType() == GAME_SP_SCENARIO)
        {
                for (iI = 0; iI < NUM_MPOPTION_TYPES; ++iI)
                {
                        setMPOption((MultiplayerOptionTypes)iI, false);
                }
        }

        // If this is a hot seat game, simultaneous turns is always off
        if (isHotSeat() || isPbem())
        {
                setMPOption(MPOPTION_SIMULTANEOUS_TURNS, false);
        }
        // If we didn't set a time in the Pitboss, turn timer off
        if (isPitboss() && getPitbossTurnTime() == 0)
        {
                setMPOption(MPOPTION_TURN_TIMER, false);
        }

        if (isMPOption(MPOPTION_SHUFFLE_TEAMS))
        {
                int aiTeams[MAX_CIV_PLAYERS];

                int iNumPlayers = 0;
                for (int i = 0; i < MAX_CIV_PLAYERS; i++)
                {
                        if (GC.getInitCore().getSlotStatus((PlayerTypes)i) == SS_TAKEN)
                        {
                                aiTeams[iNumPlayers] = GC.getInitCore().getTeam((PlayerTypes)i);
                                ++iNumPlayers;
                        }
                }

                for (int i = 0; i < iNumPlayers; i++)
                {
                        int j = (getSorenRand().get(iNumPlayers - i, NULL) + i);

                        if (i != j)
                        {
                                int iTemp = aiTeams[i];
                                aiTeams[i] = aiTeams[j];
                                aiTeams[j] = iTemp;
                        }
                }

                iNumPlayers = 0;
                for (int i = 0; i < MAX_CIV_PLAYERS; i++)
                {
                        if (GC.getInitCore().getSlotStatus((PlayerTypes)i) == SS_TAKEN)
                        {
                                GC.getInitCore().setTeam((PlayerTypes)i, (TeamTypes)aiTeams[iNumPlayers]);
                                ++iNumPlayers;
                        }
                }
        }

        //TB GameOption compatability enforcement project
        for (iI = 0; iI < NUM_GAMEOPTION_TYPES; iI++)
        {
                GameOptionTypes eGameOption = ((GameOptionTypes)iI);
                if (isOption(eGameOption))
                {
                        if (GC.getGameOptionInfo(eGameOption).getNumEnforcesGameOptionOnTypes() > 0)
                        {
                                for (int iJ = 0; iJ < GC.getGameOptionInfo(eGameOption).getNumEnforcesGameOptionOnTypes(); iJ++)
                                {
                                        GameOptionTypes eGameOptionMustOn = ((GameOptionTypes)GC.getGameOptionInfo(eGameOption).isEnforcesGameOptionOnType(iJ).eGameOption);
                                        if (GC.getGameOptionInfo(eGameOption).isEnforcesGameOptionOnType(iJ).bBool && !isOption(eGameOptionMustOn))
                                        {
                                                setOption(eGameOptionMustOn, true);
                                        }
                                }
                        }
                        if (GC.getGameOptionInfo(eGameOption).getNumEnforcesGameOptionOffTypes() > 0)
                        {
                                for (int iJ = 0; iJ < GC.getGameOptionInfo(eGameOption).getNumEnforcesGameOptionOffTypes(); iJ++)
                                {
                                        GameOptionTypes eGameOptionMustOff = ((GameOptionTypes)GC.getGameOptionInfo(eGameOption).isEnforcesGameOptionOffType(iJ).eGameOption);
                                        if (GC.getGameOptionInfo(eGameOption).isEnforcesGameOptionOffType(iJ).bBool && isOption(eGameOptionMustOff))
                                        {
                                                setOption(eGameOptionMustOff, false);
                                        }
                                }
                        }
                }
        }

        if (isOption(GAMEOPTION_LOCK_MODS))
        {
                if (isGameMultiPlayer())
                {
                        setOption(GAMEOPTION_LOCK_MODS, false);
                }
                else
                {
                        static const int iPasswordSize = 8;
                        char szRandomPassword[iPasswordSize];
                        for (int i = 0; i < iPasswordSize-1; i++)
                        {
                                szRandomPassword[i] = getSorenRandNum(128, NULL);
                        }
                        szRandomPassword[iPasswordSize-1] = 0;

                        GC.getInitCore().setAdminPassword(szRandomPassword);
                }
        }

        if (getGameTurn() == 0)
        {
                iStartTurn = 0;

                for (iI = 0; iI < GC.getGameSpeedInfo(getGameSpeedType()).getNumTurnIncrements(); iI++)
                {
                        iStartTurn += GC.getGameSpeedInfo(getGameSpeedType()).getGameTurnInfo(iI).iNumGameTurnsPerIncrement;
                }

                iStartTurn *= GC.getEraInfo(getStartEra()).getStartPercent();
                iStartTurn /= 100;

                setGameTurn(iStartTurn);
        }

        setStartTurn(getGameTurn());

        if (getMaxTurns() == 0)
        {
                iEstimateEndTurn = 0;

                for (iI = 0; iI < GC.getGameSpeedInfo(getGameSpeedType()).getNumTurnIncrements(); iI++)
                {
                        iEstimateEndTurn += GC.getGameSpeedInfo(getGameSpeedType()).getGameTurnInfo(iI).iNumGameTurnsPerIncrement;
                }

                setEstimateEndTurn(iEstimateEndTurn);
/************************************************************************************************/
/* Afforess                                     12/7/09                                         */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
#if defined QC_MASTERY_VICTORY
//Sevo Begin--VCM
        // This looks like a reasonable place for me to place my own interrupts for the victory conditions
        // I need to ensure that the AI understands it has to go after everything, so ALL the victory options
        // need to be "enabled" so starships can be built, etc. etc.
        //Only exception is diplo victory, but whatever.

       
                if (getEstimateEndTurn() > getGameTurn())
                {
                        bValid = false;

                        for (iI = 0; iI < GC.getNumVictoryInfos(); iI++)
                        {
                                if (isVictoryValid((VictoryTypes)iI))
                                {
                                        if ((GC.getVictoryInfo((VictoryTypes)iI).isEndScore()) || (GC.getVictoryInfo((VictoryTypes)iI).isTotalVictory()))
                                        {
                                                bValid = true;
                                                break;
                                        }
                                }
                        }

                        if (bValid)
                        {
                                setMaxTurns(getEstimateEndTurn() - getGameTurn());
                        }
                }
        }
        else
        {
                setEstimateEndTurn(getGameTurn() + getMaxTurns());
        }

        // Okay, now we'll actually set up the other VC's to agree with the total victory
        // If Total Victory is enabled, TURN ON ALL OTHERS AS WELL
        // This allows starship construction, gets the AI thinking correctly, etc.
        // The TV condition overrides the others but requries they be "on"
        bValid = false;
        for (iI = 0; iI < GC.getNumVictoryInfos(); iI++)
        {
                if ((GC.getVictoryInfo((VictoryTypes)iI).isTotalVictory()) && (isVictoryValid((VictoryTypes)iI)))
                {
                        bValid = true;
                        break;
                }
        }

        if (bValid)
        {
                for (iI = 0; iI < GC.getNumVictoryInfos(); iI++)
                {
                        setVictoryValid((VictoryTypes)iI, true);
                }
        }

//Sevo End VCM
#else
  }
#endif

        m_plotGroupHashesInitialized = false;
       
        //resetOptionEdits();
        //setOptionEdits();

        //Ruthless AI means Aggressive AI is on too.
        if (isOption(GAMEOPTION_RUTHLESS_AI) && !isOption(GAMEOPTION_AGGRESSIVE_AI))
        {
                setOption(GAMEOPTION_AGGRESSIVE_AI, true);
        }
               
        if (!isOption(GAMEOPTION_GREAT_COMMANDERS))
        {
                for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
                {
                        if (GC.getUnitInfo((UnitTypes)iI).isGreatGeneral())
                        {
                                GC.getUnitInfo((UnitTypes)iI).setPowerValue(GC.getUnitInfo((UnitTypes)iI).getPowerValue() / 10);
                        }
                }
        }

        logMsg("Handicap Era Tech Research Cost Modifier: %d", GC.getHandicapInfo(eHandicap).getResearchPercent());
        logMsg("World Size Tech Research Cost Modifier: %d", GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getResearchPercent());
        logMsg("Game Speed Tech Research Cost Modifier: %d", GC.getGameSpeedInfo(getGameSpeedType()).getResearchPercent());
        logMsg("Starting Era Tech Research Cost Modifier: %d", GC.getEraInfo(GC.getGameINLINE().getStartEra()).getResearchPercent());
        logMsg("Global Defines Tech Research Cost Modifier: %d", GC.getTECH_COST_MODIFIER());
        for (iI = 0; iI < GC.getNumEraInfos(); iI++)
        {
                logMsg("Era [%S] Tech Research Cost Modifier: %d", GC.getEraInfo((EraTypes)iI).getDescription(), GC.getEraInfo((EraTypes)iI).getTechCostModifier());
        }
        logMsg(" -------------------------- ");
        for (int iEra = 0; iEra < GC.getNumEraInfos(); iEra++)
        {
                int iTotalBaseCost = 0;
                int iTotalFinalCost = 0;
                int iTechs = 0;
                for (iI = 0; iI < GC.getNumTechInfos(); iI++)
                {
                        if (GC.getTechInfo((TechTypes)iI).getEra() == iEra)
                        {
                                int iBaseCost = GC.getTechInfo((TechTypes)iI).getBaseResearchCost();
                                int iFinalCost = GC.getTechInfo((TechTypes)iI).getResearchCost();

                                iFinalCost *= GC.getHandicapInfo(eHandicap).getResearchPercent();
                                iFinalCost /= 100;

                                iFinalCost *= GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getResearchPercent();
                                iFinalCost /= 100;

                                iFinalCost *= GC.getGameSpeedInfo(getGameSpeedType()).getResearchPercent();
                                iFinalCost /= 100;

                                iFinalCost *= GC.getEraInfo(getStartEra()).getResearchPercent();
                                iFinalCost /= 100;

                                logMsg("\tTech [%S] Base Cost: %d, \t\t\t\tFinal Cost: %d", GC.getTechInfo((TechTypes)iI).getDescription(), iBaseCost, iFinalCost);

                                iTotalBaseCost += iBaseCost;
                                iTotalFinalCost += iFinalCost;
                                iTechs++;
                        }
                }
                logMsg("Era [%S] Total Base Research Cost: %d, Total Research Cost: %d, Era Techs: %d, Average Tech Cost: %d", GC.getEraInfo((EraTypes)iEra).getDescription(), iTotalBaseCost, iTotalFinalCost, iTechs, iTotalFinalCost / iTechs);
        }
       
        setFutureEras();
       
        if (isOption(GAMEOPTION_UNITED_NATIONS))
        {
                //Find the diplomatic victory
                BuildingTypes eUnitedNations = NO_BUILDING;
                for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
                {
                        if (GC.getBuildingInfo((BuildingTypes)iI).getVictoryPrereq() != NO_VICTORY)
                        {
                                if (GC.getBuildingInfo((BuildingTypes)iI).getVoteSourceType() != NO_VOTESOURCE)
                                {
                                        eUnitedNations = (BuildingTypes)iI;
                                        break;
                                }
                        }
                }
                if (eUnitedNations != NO_BUILDING)
                {
                        m_bDiploVictoryEnabled = isVictoryValid((VictoryTypes)GC.getBuildingInfo(eUnitedNations).getVictoryPrereq());
                        setVictoryValid((VictoryTypes)GC.getBuildingInfo(eUnitedNations).getVictoryPrereq(), true);
                }
        }

        m_resyncPackets.clear();
        m_resyncReceiveBuffer.clear();
        m_bOutOfSync = false;
/************************************************************************************************/
/* Afforess                              END                                                        */
/************************************************************************************************/     
        setStartYear(GC.getDefineINT("START_YEAR"));
        m_iDateTurn = -500;

        for (iI = 0; iI < GC.getNumSpecialUnitInfos(); iI++)
        {
                if (GC.getSpecialUnitInfo((SpecialUnitTypes)iI).isValid())
                {
                        makeSpecialUnitValid((SpecialUnitTypes)iI);
                }
        }

        for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); iI++)
        {
                if (GC.getSpecialBuildingInfo((SpecialBuildingTypes)iI).isValid())
                {
                        makeSpecialBuildingValid((SpecialBuildingTypes)iI);
                }
        }

        AI_init();

        doUpdateCacheOnTurn();
}

//
// Set initial items (units, techs, etc...)
//
void CvGame::setInitialItems()
{
        PROFILE_FUNC();

        initFreeState();
        assignStartingPlots();
/************************************************************************************************/
/* Afforess                       Start          03/30/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
#define PYCultureLinkModule             "CvCultureLinkInterface"
        if (isOption(GAMEOPTION_CULTURALLY_LINKED_STARTS))
        {
                PYTHON_CALL_FUNCTION2(__FUNCTION__, PYCultureLinkModule, "assignCulturallyLinkedStarts");
        }
/************************************************************************************************/
/* Afforess                          END                                                            */
/************************************************************************************************/     
        normalizeStartingPlots();
       
// RevolutionDCM - BarbarianWorld - thanks Kael
        // RevDCM TODO: What's right here?
    if (isOption(GAMEOPTION_BARBARIAN_WORLD))
    {
        for (int iI = 0; iI < MAX_PLAYERS; iI++)
        {
            if (GET_PLAYER((PlayerTypes)iI).isAlive() && iI != BARBARIAN_PLAYER)
            {
                foundBarbarianCity();
            }
        }
    }
// RevolutionDCM End

        initFreeUnits();

        for (int i = 0; i < MAX_PLAYERS; ++i)
        {
                CvPlayer& kPlayer = GET_PLAYER((PlayerTypes)i);
                if (kPlayer.isAlive())
                {
                        kPlayer.AI_updateFoundValues(true);
                }
        }
/************************************************************************************************/
/* Afforess                       Start          03/18/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
        if (isOption(GAMEOPTION_PERSONALIZED_MAP))
        {
                clearLandmarks();
                findMountainRanges();
                findLonePeaks();
                findBays();
                findForests();
                findJungles();
                findDeserts();
                findLakes();
                pruneLandmarks();
                addLandmarkSigns();
                updateInitialSigns();
        }

        logMsg("Handicap Era Tech Research Cost Modifier: %d", GC.getHandicapInfo(m_eHandicap).getResearchPercent());
        logMsg("World Size Tech Research Cost Modifier: %d", GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getResearchPercent());
        logMsg("Game Speed Tech Research Cost Modifier: %d", GC.getGameSpeedInfo(getGameSpeedType()).getResearchPercent());
        logMsg("Starting Era Tech Research Cost Modifier: %d", GC.getEraInfo(GC.getGameINLINE().getStartEra()).getResearchPercent());
        logMsg("Global Defines Tech Research Cost Modifier: %d", GC.getTECH_COST_MODIFIER());
        for (int iI = 0; iI < GC.getNumEraInfos(); iI++)
        {
                logMsg("Era [%S] Tech Research Cost Modifier: %d", GC.getEraInfo((EraTypes)iI).getDescription(), GC.getEraInfo((EraTypes)iI).getTechCostModifier());
        }

        checkInitialResourceAllocations();

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


// BUG - MapFinder - start
// from HOF Mod - Dianthus
bool CvGame::canRegenerateMap() const
{
        if (GC.getGameINLINE().getElapsedGameTurns() != 0) return false;
        if (GC.getGameINLINE().isGameMultiPlayer()) return false;
        if (GC.getInitCore().getWBMapScript()) return false;

        // EF: TODO clear contact at start of regenerateMap()?
        for (int iI = 1; iI < MAX_CIV_TEAMS; iI++)
        {
                CvTeam& team=GET_TEAM((TeamTypes)iI);
                for (int iJ = 0; iJ < iI; iJ++)
                {
                        if (team.isHasMet((TeamTypes)iJ)) return false;
                }
        }
        return true;
}
// BUG - MapFinder - end

void CvGame::regenerateMap()
{
        int iI;

        if (GC.getInitCore().getWBMapScript())
        {
                return;
        }

        setFinalInitialized(false);

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                GET_PLAYER((PlayerTypes)iI).killUnits();
        }

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                GET_PLAYER((PlayerTypes)iI).killCities();
        }

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                GET_PLAYER((PlayerTypes)iI).killAllDeals();
        }

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                GET_PLAYER((PlayerTypes)iI).setFoundedFirstCity(false);
                GET_PLAYER((PlayerTypes)iI).setStartingPlot(NULL, false);
        }

        for (iI = 0; iI < MAX_TEAMS; iI++)
        {
                GC.getMapINLINE().setRevealedPlots(((TeamTypes)iI), false);
        }

        gDLL->getEngineIFace()->clearSigns();

        GC.getMapINLINE().erasePlots();

        CvMapGenerator::GetInstance().generateRandomMap();
        CvMapGenerator::GetInstance().addGameElements();

        gDLL->getEngineIFace()->RebuildAllPlots();

        CvEventReporter::getInstance().resetStatistics();

        setInitialItems();

        initScoreCalculation();
        setFinalInitialized(true);

        GC.getMapINLINE().setupGraphical();
        gDLL->getEngineIFace()->SetDirty(GlobeTexture_DIRTY_BIT, true);
        gDLL->getEngineIFace()->SetDirty(MinimapTexture_DIRTY_BIT, true);
        gDLL->getInterfaceIFace()->setDirty(ColoredPlots_DIRTY_BIT, true);

        gDLL->getInterfaceIFace()->setCycleSelectionCounter(1);
/*************************************************************************************************/
/**     ADDON (regenerate Map) Sephi                                                                                    **/
/*************************************************************************************************/
    CvEventReporter::getInstance().gameStart();
/*************************************************************************************************/
/**     END                                                                                                                                             **/
/*************************************************************************************************/
        gDLL->getEngineIFace()->AutoSave(true);

// BUG - AutoSave - start
        PYTHON_CALL_FUNCTION2(__FUNCTION__, PYBugModule, "gameStartSave");
// BUG - AutoSave - end

        // EF - This doesn't work until after the game has had time to update.
        //      Centering on the starting location is now done by MapFinder using BugUtil.delayCall().
        //      Must leave this here for non-BUG
        if (NO_PLAYER != getActivePlayer())
        {
                CvPlot* pPlot = GET_PLAYER(getActivePlayer()).getStartingPlot();

                if (NULL != pPlot)
                {
                        gDLL->getInterfaceIFace()->lookAt(pPlot->getPoint(), CAMERALOOKAT_NORMAL);
                }
        }
}

void CvGame::uninit()
{
        SAFE_DELETE_ARRAY(m_aiShrineBuilding);
        SAFE_DELETE_ARRAY(m_aiShrineReligion);
        SAFE_DELETE_ARRAY(m_paiUnitCreatedCount);
        SAFE_DELETE_ARRAY(m_paiUnitClassCreatedCount);
        SAFE_DELETE_ARRAY(m_paiBuildingClassCreatedCount);
        SAFE_DELETE_ARRAY(m_paiProjectCreatedCount);
        SAFE_DELETE_ARRAY(m_paiForceCivicCount);
        SAFE_DELETE_ARRAY(m_paiVoteOutcome);
        SAFE_DELETE_ARRAY(m_paiReligionGameTurnFounded);
        SAFE_DELETE_ARRAY(m_paiCorporationGameTurnFounded);
        SAFE_DELETE_ARRAY(m_aiSecretaryGeneralTimer);
        SAFE_DELETE_ARRAY(m_aiVoteTimer);
        SAFE_DELETE_ARRAY(m_aiDiploVote);

        SAFE_DELETE_ARRAY(m_pabSpecialUnitValid);
        SAFE_DELETE_ARRAY(m_pabSpecialBuildingValid);
        SAFE_DELETE_ARRAY(m_abReligionSlotTaken);
/************************************************************************************************/
/* RevDCM                         Start          4/29/10                                                */
/*                                                                                              */
/* OC_LIMITED_RELIGIONS                                                                         */
/************************************************************************************************/
        SAFE_DELETE_ARRAY(m_abTechCanFoundReligion);
/************************************************************************************************/
/* LIMITED_RELIGIONS               END                                                          */
/************************************************************************************************/

        SAFE_DELETE_ARRAY(m_paHolyCity);
        SAFE_DELETE_ARRAY(m_paHeadquarters);

        m_aszDestroyedCities.clear();
        m_aszGreatPeopleBorn.clear();
        m_resyncPackets.clear();

        m_deals.uninit();
        m_voteSelections.uninit();
        m_votesTriggered.uninit();

        m_mapRand.uninit();
        m_sorenRand.uninit();

        clearReplayMessageMap();
        SAFE_DELETE(m_pReplayInfo);

        m_aPlotExtraYields.clear();
        m_aPlotExtraCosts.clear();
        m_mapVoteSourceReligions.clear();
        m_aeInactiveTriggers.clear();

#ifdef CAN_BUILD_VALUE_CACHING
        CvPlot::ClearCanBuildCache();
#endif
        resetOptionEdits();
        if (CvPlayerAI::areStaticsInitialized())
        {
                for (int i = 0; i < GC.getNumMapInfos(); i++)
                {
                        if ( GC.mapInitialized((MapTypes)i) )
                        {
                                // Cast to the internal class
                                CvMap&  map = GC.getMapByIndex((MapTypes)i);

                                CvMapInitData defaultMapData;

                                map.reset(&defaultMapData);
                        }
                }

                for(int i = 0; i < MAX_PLAYERS; i++)
                {
                        GET_PLAYER((PlayerTypes)i).uninit();
                }
        }
        m_allocator.clearAll();
}


// FUNCTION: reset()
// Initializes data members that are serialized.
void CvGame::reset(HandicapTypes eHandicap, bool bConstructorCall)
{
        int iI;

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

        m_iElapsedGameTurns = 0;
        m_iStartTurn = 0;
        m_iStartYear = GC.getDefineINT("START_YEAR");
        m_iEstimateEndTurn = 0;
        m_iDateTurn = -500;
        m_iTurnSlice = 0;
        m_iCutoffSlice = 0;
        m_iNumGameTurnActive = 0;
        m_iNumCities = 0;
        m_iTotalPopulation = 0;
        m_iTradeRoutes = 0;
        m_iFreeTradeCount = 0;
        m_iNoNukesCount = 0;
        m_iNukesExploded = 0;
        m_iMaxPopulation = 0;
        m_iMaxLand = 0;
        m_iMaxTech = 0;
        m_iMaxWonders = 0;
        m_iInitPopulation = 0;
        m_iInitLand = 0;
        m_iInitTech = 0;
        m_iInitWonders = 0;
/************************************************************************************************/
/* Afforess                                     12/7/09                                         */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
        m_iCurrentVoteID = 0;
        m_iWaterAnimalSpawnChance = 0;
        m_iXResolution = 1024;
        m_iYResolution = 720;
        m_iMercyRuleCounter = 0;
        m_iCutLosersCounter = 0;
        m_iHighToLowCounter = 0;
        m_iIncreasingDifficultyCounter = 0;
        m_iRiverBuildings = 0;
        m_iNumWonders = 0;
        m_bDiploVictoryEnabled = false;
        m_bAnyoneHasUnitZoneOfControl = false;
        m_iLastResyncTurnSlice = 0; //field is intentionally not saved
        m_iActiveTurnSlice = 0; //field is intentionally not saved
        m_iDarkAgeCount = 0;
        calculateRiverBuildings();
        calculateCoastalBuildings();
        calculateNumWonders();
        m_iLastNukeStrikeX = INVALID_PLOT_COORD;
        m_iLastNukeStrikeY = INVALID_PLOT_COORD;
#if defined QC_MASTERY_VICTORY
        for (int loopI = 0; loopI < MAX_TEAMS; loopI++)
        {
          starshipLaunched[loopI] = false;
          diplomaticVictoryAchieved[loopI] = false;            
          AscensionGateBuilt[loopI] = false; // code added for Ascension Gate & Mastery Victory (by 45°)
        }      
#endif
/************************************************************************************************/
/* Afforess                              END                                                        */
/************************************************************************************************/     

        m_uiInitialTime = 0;

        m_bScoreDirty = false;
        m_circumnavigatingTeam = NO_TEAM;
        m_bDebugMode = false;
        m_bDebugModeCache = false;
        m_bFinalInitialized = false;
        m_bPbemTurnSent = false;
        m_bHotPbemBetweenTurns = false;
        m_bPlayerOptionsSent = false;
        //TB Nukefix
        //m_bNukesValid = false;

        m_eHandicap = eHandicap;
        m_ePausePlayer = NO_PLAYER;
        m_eBestLandUnit = NO_UNIT;
        m_eWinner = NO_TEAM;
        m_eVictory = NO_VICTORY;
        m_eGameState = GAMESTATE_ON;

        m_szScriptData = "";

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                m_aiRankPlayer[iI] = 0;
                m_aiPlayerRank[iI] = 0;
                m_aiPlayerScore[iI] = 0;
/************************************************************************************************/
/* REVOLUTION_MOD                                                                lemmy101       */
/*                                                                               jdog5000       */
/*                                                                                              */
/************************************************************************************************/
                m_iAIAutoPlay[iI] = 0;
                m_iForcedAIAutoPlay[iI] = 0;
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
        }

        for (iI = 0; iI < MAX_TEAMS; iI++)
        {
                m_aiRankTeam[iI] = 0;
                m_aiTeamRank[iI] = 0;
                m_aiTeamScore[iI] = 0;
        }
/************************************************************************************************/
/* Afforess                       Start          06/07/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
        for (iI = 0; iI < NUM_MODDERGAMEOPTION_TYPES; iI++)
        {
                m_aiModderGameOption[iI] = 0;
        }
        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                m_abPreviousRequest[iI] = false;
                m_aiFlexibleDifficultyTimer[iI] = 0;
        }
/************************************************************************************************/
/* Afforess                          END                                                            */
/************************************************************************************************/
        if (!bConstructorCall)
        {
                FAssertMsg(m_paiUnitCreatedCount==NULL, "about to leak memory, CvGame::m_paiUnitCreatedCount");
                m_paiUnitCreatedCount = new int[GC.getNumUnitInfos()];
                for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
                {
                        m_paiUnitCreatedCount[iI] = 0;
                }
                FAssertMsg(m_paiUnitClassCreatedCount==NULL, "about to leak memory, CvGame::m_paiUnitClassCreatedCount");
                m_paiUnitClassCreatedCount = new int[GC.getNumUnitClassInfos()];
                for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
                {
                        m_paiUnitClassCreatedCount[iI] = 0;
                }
                FAssertMsg(m_paiBuildingClassCreatedCount==NULL, "about to leak memory, CvGame::m_paiBuildingClassCreatedCount");
                m_paiBuildingClassCreatedCount = new int[GC.getNumBuildingClassInfos()];
                for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
                {
                        m_paiBuildingClassCreatedCount[iI] = 0;
                }

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

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

                FAssertMsg(0 < GC.getNumVoteInfos(), "GC.getNumVoteInfos() is not greater than zero in CvGame::reset");
                FAssertMsg(m_paiVoteOutcome==NULL, "about to leak memory, CvGame::m_paiVoteOutcome");
                m_paiVoteOutcome = new PlayerVoteTypes[GC.getNumVoteInfos()];
                for (iI = 0; iI < GC.getNumVoteInfos(); iI++)
                {
                        m_paiVoteOutcome[iI] = NO_PLAYER_VOTE;
                }

                FAssertMsg(0 < GC.getNumVoteSourceInfos(), "GC.getNumVoteSourceInfos() is not greater than zero in CvGame::reset");
                FAssertMsg(m_aiDiploVote==NULL, "about to leak memory, CvGame::m_aiDiploVote");
                m_aiDiploVote = new int[GC.getNumVoteSourceInfos()];
                for (iI = 0; iI < GC.getNumVoteSourceInfos(); iI++)
                {
                        m_aiDiploVote[iI] = 0;
                }

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

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

                FAssertMsg(m_paiReligionGameTurnFounded==NULL, "about to leak memory, CvGame::m_paiReligionGameTurnFounded");
                m_paiReligionGameTurnFounded = new int[GC.getNumReligionInfos()];
                FAssertMsg(m_abReligionSlotTaken==NULL, "about to leak memory, CvGame::m_abReligionSlotTaken");
                m_abReligionSlotTaken = new bool[GC.getNumReligionInfos()];
                FAssertMsg(m_paHolyCity==NULL, "about to leak memory, CvGame::m_paHolyCity");
                m_paHolyCity = new IDInfo[GC.getNumReligionInfos()];
                for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
                {
                        m_paiReligionGameTurnFounded[iI] = -1;
                        m_paHolyCity[iI].reset();
                        m_abReligionSlotTaken[iI] = false;
                }
/************************************************************************************************/
/* RevDCM                         Start          4/29/10                                                */
/*                                                                                              */
/* OC_LIMITED_RELIGIONS                                                                         */
/************************************************************************************************/
                FAssertMsg(m_abTechCanFoundReligion==NULL, "about to leak memory, CvGame::m_abTechCanFoundReligion");
                m_abTechCanFoundReligion = new bool[GC.getNumTechInfos()];
                for (iI = 0; iI < GC.getNumTechInfos(); iI++)
                {
                        m_abTechCanFoundReligion[TechTypes(iI)] = false;
                }
                for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
                {
                        TechTypes eIndex = TechTypes(GC.getReligionInfo((ReligionTypes)iI).getTechPrereq());
                        m_abTechCanFoundReligion[eIndex] = true;
                }
/************************************************************************************************/
/* LIMITED_RELIGIONS               END                                                          */
/************************************************************************************************/

                FAssertMsg(m_paiCorporationGameTurnFounded==NULL, "about to leak memory, CvGame::m_paiCorporationGameTurnFounded");
                m_paiCorporationGameTurnFounded = new int[GC.getNumCorporationInfos()];
                m_paHeadquarters = new IDInfo[GC.getNumCorporationInfos()];
                for (iI = 0; iI < GC.getNumCorporationInfos(); iI++)
                {
                        m_paiCorporationGameTurnFounded[iI] = -1;
                        m_paHeadquarters[iI].reset();
                }

                FAssertMsg(m_aiShrineBuilding==NULL, "about to leak memory, CvGame::m_aiShrineBuilding");
                FAssertMsg(m_aiShrineReligion==NULL, "about to leak memory, CvGame::m_aiShrineReligion");
                m_aiShrineBuilding = new int[GC.getNumBuildingInfos()];
                m_aiShrineReligion = new int[GC.getNumBuildingInfos()];
                for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
                {
                        m_aiShrineBuilding[iI] = (int) NO_BUILDING;
                        m_aiShrineReligion[iI] = (int) NO_RELIGION;
                }

                FAssertMsg(m_aiSecretaryGeneralTimer==NULL, "about to leak memory, CvGame::m_aiSecretaryGeneralTimer");
                FAssertMsg(m_aiVoteTimer==NULL, "about to leak memory, CvGame::m_aiVoteTimer");
                m_aiSecretaryGeneralTimer = new int[GC.getNumVoteSourceInfos()];
                m_aiVoteTimer = new int[GC.getNumVoteSourceInfos()];
                for (iI = 0; iI < GC.getNumVoteSourceInfos(); iI++)
                {
                        m_aiSecretaryGeneralTimer[iI] = 0;
                        m_aiVoteTimer[iI] = 0;
                }
        }

        m_deals.removeAll();
        m_voteSelections.removeAll();
        m_votesTriggered.removeAll();

        m_mapRand.reset();
        m_sorenRand.reset();

        m_iNumSessions = 1;

        m_iShrineBuildingCount = 0;
        m_iNumCultureVictoryCities = 0;
        m_eCultureVictoryCultureLevel = NO_CULTURELEVEL;

        if (!bConstructorCall)
        {
                AI_reset();
        }
/************************************************************************************************/
/* Afforess/RevDCM                                     12/7/09                                  */
/*                                                                                              */
/* Advanced Automations                                                                         */
/************************************************************************************************/
                // Sanguo Mod Performance start, added by poyuzhe 07.27.09
        UnitTypes eUnit;
        std::vector<UnitTypes> aUpgradeUnits;

        for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
        {
                eUnit = (UnitTypes)iI;
                aUpgradeUnits.clear();
                do
                {
                        for (int iJ = 0; iJ < GC.getNumUnitClassInfos(); iJ++)
                        {
                                if (eUnit != NO_UNIT)
                                {
                                        if (GC.getUnitInfo(eUnit).getUpgradeUnitClass(iJ))
                                        {
                                                GC.getUnitInfo((UnitTypes)iI).addUpgradeUnitClassTypes(iJ);
                                                aUpgradeUnits.push_back((UnitTypes)GC.getUnitClassInfo((UnitClassTypes)iJ).getDefaultUnitIndex());
                                        }
                                }
                        }
                        if (!aUpgradeUnits.empty())
                        {
                                if (eUnit != NO_UNIT)
                                {
                                        eUnit = aUpgradeUnits.front();
                                        aUpgradeUnits.erase(aUpgradeUnits.begin());
                                }
                        }
                        else
                        {
                                break;
                        }
                }while(true);
        }
        // Sanguo Mod Performance, end
/************************************************************************************************/
/* Afforess                              END                                                        */
/************************************************************************************************/     
        m_Properties.clear();

        m_lastGraphicUpdateRequestTickCount = -1;

        m_plotGroupHashesInitialized = false;
        m_bWasGraphicsPagingEnabled = false;
        m_iLastLookatX = -1;
        m_iLastLookatY = -1;
}


void CvGame::initDiplomacy()
{
        PROFILE_FUNC();

        int iI, iJ;

        for (iI = 0; iI < MAX_TEAMS; iI++)
        {
                GET_TEAM((TeamTypes)iI).meet(((TeamTypes)iI), false);

                if (GET_TEAM((TeamTypes)iI).isBarbarian() || GET_TEAM((TeamTypes)iI).isMinorCiv())
                {
                        for (iJ = 0; iJ < MAX_CIV_TEAMS; iJ++)
                        {
                                if (iI != iJ)
                                {
                                        GET_TEAM((TeamTypes)iI).declareWar(((TeamTypes)iJ), false, NO_WARPLAN);
                                }
                        }
                }
        }

        // Forced peace at the beginning of Advanced starts
        if (isOption(GAMEOPTION_ADVANCED_START))
        {
                CLinkList<TradeData> player1List;
                CLinkList<TradeData> player2List;
                TradeData kTradeData;
                setTradeItem(&kTradeData, TRADE_PEACE_TREATY);
                player1List.insertAtEnd(kTradeData);
                player2List.insertAtEnd(kTradeData);

                for (int iPlayer1 = 0; iPlayer1 < MAX_CIV_PLAYERS; ++iPlayer1)
                {
                        CvPlayer& kLoopPlayer1 = GET_PLAYER((PlayerTypes)iPlayer1);

                        if (kLoopPlayer1.isAlive())
                        {
                                for (int iPlayer2 = iPlayer1 + 1; iPlayer2 < MAX_CIV_PLAYERS; ++iPlayer2)
                                {
                                        CvPlayer& kLoopPlayer2 = GET_PLAYER((PlayerTypes)iPlayer2);

                                        if (kLoopPlayer2.isAlive())
                                        {
                                                if (GET_TEAM(kLoopPlayer1.getTeam()).canChangeWarPeace(kLoopPlayer2.getTeam()))
                                                {
                                                        implementDeal((PlayerTypes)iPlayer1, (PlayerTypes)iPlayer2, &player1List, &player2List);
                                                }
                                        }
                                }
                        }
                }
        }
}


void CvGame::initFreeState()
{
        bool bValid;
        int iI, iJ, iK;

        for (iI = 0; iI < GC.getNumTechInfos(); iI++)
        {
                for (iJ = 0; iJ < MAX_TEAMS; iJ++)
                {
                        if (GET_TEAM((TeamTypes)iJ).isAlive())
                        {
                                bValid = false;

                                if (!bValid)
                                {
                                        if ((GC.getHandicapInfo(getHandicapType()).isFreeTechs(iI)) ||
                                                  (!(GET_TEAM((TeamTypes)iJ).isHuman())&& GC.getHandicapInfo(getHandicapType()).isAIFreeTechs(iI)) ||
                                                  (GC.getTechInfo((TechTypes)iI).getEra() < getStartEra()))
                                        {
                                                bValid = true;
                                        }
                                }

                                if (!bValid)
                                {
                                        for (iK = 0; iK < MAX_PLAYERS; iK++)
                                        {
                                                if (GET_PLAYER((PlayerTypes)iK).isAlive())
                                                {
                                                        if (GET_PLAYER((PlayerTypes)iK).getTeam() == iJ)
                                                        {
                                                                if (GC.getCivilizationInfo(GET_PLAYER((PlayerTypes)iK).getCivilizationType()).isCivilizationFreeTechs(iI))
                                                                {
                                                                        bValid = true;
                                                                        break;
                                                                }
                                                        }
                                                }
                                        }
                                }

                                GET_TEAM((TeamTypes)iJ).setHasTech(((TechTypes)iI), bValid, NO_PLAYER, false, false);
                                if (bValid && GC.getTechInfo((TechTypes)iI).isMapVisible())
                                {
                                        GC.getMapINLINE().setRevealedPlots((TeamTypes)iJ, true, true);
                                }
                        }
                }
        }

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        GET_PLAYER((PlayerTypes)iI).initFreeState();
                }
        }
}


void CvGame::initFreeUnits()
{
        int iI;

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        if ((GET_PLAYER((PlayerTypes)iI).getNumUnits() == 0) && (GET_PLAYER((PlayerTypes)iI).getNumCities() == 0))
                        {
                                GET_PLAYER((PlayerTypes)iI).initFreeUnits();
                        }
                }
        }
}


void CvGame::assignStartingPlots()
{
        PROFILE_FUNC();

        CvPlot* pPlot;
        CvPlot* pBestPlot;
        bool bStartFound;
        bool bValid;
        int iRandOffset;
        int iLoopTeam;
        int iLoopPlayer;
        int iHumanSlot;
        int iValue;
        int iBestValue;
        int iI, iJ, iK;
       
        std::vector<int> playerOrder;
        std::vector<int>::iterator playerOrderIter;

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
                        {
                                iBestValue = 0;
                                pBestPlot = NULL;

                                for (iJ = 0; iJ < GC.getMapINLINE().numPlotsINLINE(); iJ++)
                                {
                                        gDLL->callUpdater();    // allow window updates during launch

                                        pPlot = GC.getMapINLINE().plotByIndexINLINE(iJ);

                                        if (pPlot->isStartingPlot())
                                        {
                                                bValid = true;

                                                for (iK = 0; iK < MAX_CIV_PLAYERS; iK++)
                                                {
                                                        if (GET_PLAYER((PlayerTypes)iK).isAlive())
                                                        {
                                                                if (GET_PLAYER((PlayerTypes)iK).getStartingPlot() == pPlot)
                                                                {
                                                                        bValid = false;
                                                                        break;
                                                                }
                                                        }
                                                }

                                                if (bValid)
                                                {
                                                        iValue = (1 + getSorenRandNum(1000, "Starting Plot"));

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

                                if (pBestPlot != NULL)
                                {
                                        GET_PLAYER((PlayerTypes)iI).setStartingPlot(pBestPlot, true);
                                }
                        }
                }
        }

        if (PYTHON_CALL_FUNCTION2(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "assignStartingPlots"))
        {
                if (!gDLL->getPythonIFace()->pythonUsingDefaultImpl())
                {
                        // Python override
                        return;
                }
        }

        if (isTeamGame())
        {
                for (int iPass = 0; iPass < 2 * MAX_PLAYERS; ++iPass)
                {
                        bStartFound = false;

                        iRandOffset = getSorenRandNum(countCivTeamsAlive(), "Team Starting Plot");

                        for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
                        {
                                iLoopTeam = ((iI + iRandOffset) % MAX_CIV_TEAMS);

                                if (GET_TEAM((TeamTypes)iLoopTeam).isAlive())
                                {
                                        for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
                                        {
                                                if (GET_PLAYER((PlayerTypes)iJ).isAlive())
                                                {
                                                        if (GET_PLAYER((PlayerTypes)iJ).getTeam() == iLoopTeam)
                                                        {
                                                                if (GET_PLAYER((PlayerTypes)iJ).getStartingPlot() == NULL)
                                                                {
                                                                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iJ).findStartingPlot();

                                                                        if (NULL != pStartingPlot)
                                                                        {
                                                                                GET_PLAYER((PlayerTypes)iJ).setStartingPlot(pStartingPlot, true);
                                                                                playerOrder.push_back(iJ);
                                                                        }
                                                                        bStartFound = true;
                                                                        break;
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }

                        if (!bStartFound)
                        {
                                break;
                        }
                }

                //check all players have starting plots
                for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
                {
                        FAssertMsg(!GET_PLAYER((PlayerTypes)iJ).isAlive() || GET_PLAYER((PlayerTypes)iJ).getStartingPlot() != NULL, "Player has no starting plot");
                }
        }
        else if (isGameMultiPlayer())
        {
                iRandOffset = getSorenRandNum(countCivPlayersAlive(), "Player Starting Plot");

                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
                {
                        iLoopPlayer = ((iI + iRandOffset) % MAX_CIV_PLAYERS);

                        if (GET_PLAYER((PlayerTypes)iLoopPlayer).isAlive())
                        {
                                if (GET_PLAYER((PlayerTypes)iLoopPlayer).isHuman())
                                {
                                        if (GET_PLAYER((PlayerTypes)iLoopPlayer).getStartingPlot() == NULL)
                                        {
                                                GET_PLAYER((PlayerTypes)iLoopPlayer).setStartingPlot(GET_PLAYER((PlayerTypes)iLoopPlayer).findStartingPlot(), true);
                                                playerOrder.push_back(iLoopPlayer);
                                        }
                                }
                        }
                }

                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
                {
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
                        {
                                if (!(GET_PLAYER((PlayerTypes)iI).isHuman()))
                                {
                                        if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
                                        {
                                                GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
                                                playerOrder.push_back(iI);
                                        }
                                }
                        }
                }
        }
        else
        {
                iHumanSlot = range((((countCivPlayersAlive() - 1) * GC.getHandicapInfo(getHandicapType()).getStartingLocationPercent()) / 100), 0, (countCivPlayersAlive() - 1));

                for (iI = 0; iI < iHumanSlot; iI++)
                {
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
                        {
                                if (!(GET_PLAYER((PlayerTypes)iI).isHuman()))
                                {
                                        if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
                                        {
                                                GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
                                                playerOrder.push_back(iI);
                                        }
                                }
                        }
                }

                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
                {
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
                        {
                                if (GET_PLAYER((PlayerTypes)iI).isHuman())
                                {
                                        if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
                                        {
                                                GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
                                                playerOrder.push_back(iI);
                                        }
                                }
                        }
                }

                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
                {
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
                        {
                                if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
                                {
                                        GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
                                        playerOrder.push_back(iI);
                                }
                        }
                }
        }
       
        //Now iterate over the player starts in the original order and re-place them.
        for (playerOrderIter = playerOrder.begin(); playerOrderIter != playerOrder.end(); ++playerOrderIter)
        {
                GET_PLAYER((PlayerTypes)(*playerOrderIter)).setStartingPlot(GET_PLAYER((PlayerTypes)(*playerOrderIter)).findStartingPlot(), true);
        }
}

// Swaps starting locations until we have reached the optimal closeness between teams
// (caveat: this isn't quite "optimal" because we could get stuck in local minima, but it's pretty good)

void CvGame::normalizeStartingPlotLocations()
{
        CvPlot* apNewStartPlots[MAX_CIV_PLAYERS];
        int* aaiDistances[MAX_CIV_PLAYERS];
        int aiStartingLocs[MAX_CIV_PLAYERS];
        int iI, iJ;

        // Precalculate distances between all starting positions:
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        gDLL->callUpdater();    // allow window to update during launch
                        aaiDistances[iI] = new int[iI];
                        for (iJ = 0; iJ < iI; iJ++)
                        {
                                aaiDistances[iI][iJ] = 0;
                        }
                        CvPlot *pPlotI = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
                        if (pPlotI != NULL)
                        {
                                for (iJ = 0; iJ < iI; iJ++)
                                {
                                        if (GET_PLAYER((PlayerTypes)iJ).isAlive())
                                        {
                                                CvPlot *pPlotJ = GET_PLAYER((PlayerTypes)iJ).getStartingPlot();
                                                if (pPlotJ != NULL)
                                                {
                                                        int iDist = GC.getMapINLINE().calculatePathDistance(pPlotI, pPlotJ);
                                                        if (iDist == -1)
                                                        {
                                                                // 5x penalty for not being on the same area, or having no passable route
                                                                iDist = 5*plotDistance(pPlotI->getX_INLINE(), pPlotI->getY_INLINE(), pPlotJ->getX_INLINE(), pPlotJ->getY_INLINE());
                                                        }
                                                        aaiDistances[iI][iJ] = iDist;
                                                }
                                        }
                                }
                        }
                }
                else
                {
                        aaiDistances[iI] = NULL;
                }
        }

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                aiStartingLocs[iI] = iI; // each player starting in own location
        }

        int iBestScore = getTeamClosenessScore(aaiDistances, aiStartingLocs);
        bool bFoundSwap = true;
        while (bFoundSwap)
        {
                bFoundSwap = false;
                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
                {
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
                        {
                                for (iJ = 0; iJ < iI; iJ++)
                                {
                                        if (GET_PLAYER((PlayerTypes)iJ).isAlive())
                                        {
                                                int iTemp = aiStartingLocs[iI];
                                                aiStartingLocs[iI] = aiStartingLocs[iJ];
                                                aiStartingLocs[iJ] = iTemp;
                                                int iScore = getTeamClosenessScore(aaiDistances, aiStartingLocs);
                                                if (iScore < iBestScore)
                                                {
                                                        iBestScore = iScore;
                                                        bFoundSwap = true;
                                                }
                                                else
                                                {
                                                        // Swap them back:
                                                        iTemp = aiStartingLocs[iI];
                                                        aiStartingLocs[iI] = aiStartingLocs[iJ];
                                                        aiStartingLocs[iJ] = iTemp;
                                                }
                                        }
                                }
                        }
                }
        }

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                apNewStartPlots[iI] = NULL;
        }

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        if (aiStartingLocs[iI] != iI)
                        {
                                apNewStartPlots[iI] = GET_PLAYER((PlayerTypes)aiStartingLocs[iI]).getStartingPlot();
                        }
                }
        }

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        if (apNewStartPlots[iI] != NULL)
                        {
                                GET_PLAYER((PlayerTypes)iI).setStartingPlot(apNewStartPlots[iI], false);
                        }
                }
        }

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                SAFE_DELETE_ARRAY(aaiDistances[iI]);
        }
}


void CvGame::normalizeAddRiver()
{
        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();

                        if (pStartingPlot != NULL)
                        {
                                if (!pStartingPlot->isFreshWater())
                                {
                                        // if we will be able to add a lake, then use old river code
                                        if (normalizeFindLakePlot((PlayerTypes)iI) != NULL)
                                        {
                                                CvMapGenerator::GetInstance().doRiver(pStartingPlot);
                                        }
                                        // otherwise, use new river code which is much more likely to succeed
                                        else
                                        {
                                                CvMapGenerator::GetInstance().addRiver(pStartingPlot);
                                        }

                                        // add floodplains to any desert tiles the new river passes through
                                        for (int iK = 0; iK < GC.getMapINLINE().numPlotsINLINE(); iK++)
                                        {
                                                CvPlot* pPlot = GC.getMapINLINE().plotByIndexINLINE(iK);
                                                FAssert(pPlot != NULL);

                                                for (int iJ = 0; iJ < GC.getNumFeatureInfos(); iJ++)
                                                {
                                                        if (GC.getFeatureInfo((FeatureTypes)iJ).isRequiresRiver())
                                                        {
                                                                if (pPlot->canHaveFeature((FeatureTypes)iJ))
                                                                {
                                                                        if (GC.getFeatureInfo((FeatureTypes)iJ).getAppearanceProbability() == 10000)
                                                                        {
                                                                                if (pPlot->getBonusType() != NO_BONUS)
                                                                                {
                                                                                        pPlot->setBonusType(NO_BONUS);
                                                                                }
                                                                                pPlot->setFeatureType((FeatureTypes)iJ);
                                                                                break;
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}


void CvGame::normalizeRemovePeaks()
{
        CvPlot* pStartingPlot;
        CvPlot* pLoopPlot;
        int iRange;
        int iDX, iDY;
        int iI;

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();

                        if (pStartingPlot != NULL)
                        {
                                iRange = 3;

                                for (iDX = -(iRange); iDX <= iRange; iDX++)
                                {
                                        for (iDY = -(iRange); iDY <= iRange; iDY++)
                                        {
                                                pLoopPlot = plotXY(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iDX, iDY);

                                                if (pLoopPlot != NULL)
                                                {
                                                        if (pLoopPlot->isPeak())
                                                        {
                                                                pLoopPlot->setPlotType(PLOT_HILLS);
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}

void CvGame::normalizeAddLakes()
{
        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        CvPlot* pLakePlot = normalizeFindLakePlot((PlayerTypes)iI);
                        if (pLakePlot != NULL)
                        {
                                pLakePlot->setPlotType(PLOT_OCEAN);
                        }
                }
        }
}

CvPlot* CvGame::normalizeFindLakePlot(PlayerTypes ePlayer)
{
        if (!GET_PLAYER(ePlayer).isAlive())
        {
                return NULL;
        }

        CvPlot* pStartingPlot = GET_PLAYER(ePlayer).getStartingPlot();
        if (pStartingPlot != NULL)
        {
                if (!(pStartingPlot->isFreshWater()))
                {
                        for (int iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                        {
                                CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);

                                if (pLoopPlot != NULL)
                                {
                                        if (!(pLoopPlot->isWater()))
                                        {
                                                if (!(pLoopPlot->isCoastalLand()))
                                                {
                                                        if (!(pLoopPlot->isRiver()))
                                                        {
                                                                if (pLoopPlot->getBonusType() == NO_BONUS)
                                                                {
                                                                        bool bStartingPlot = false;

                                                                        for (int iK = 0; iK < MAX_CIV_PLAYERS; iK++)
                                                                        {
                                                                                if (GET_PLAYER((PlayerTypes)iK).isAlive())
                                                                                {
                                                                                        if (GET_PLAYER((PlayerTypes)iK).getStartingPlot() == pLoopPlot)
                                                                                        {
                                                                                                bStartingPlot = true;
                                                                                                break;
                                                                                        }
                                                                                }
                                                                        }

                                                                        if (!bStartingPlot)
                                                                        {
                                                                                return pLoopPlot;
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }

        return NULL;
}


void CvGame::normalizeRemoveBadFeatures()
{
        CvPlot* pStartingPlot;
        CvPlot* pLoopPlot;
        int iI, iJ;

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();

                        if (pStartingPlot != NULL)
                        {
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);

                                        if (pLoopPlot != NULL)
                                        {
                                                if (pLoopPlot->getFeatureType() != NO_FEATURE)
                                                {
                                                        if ((GC.getFeatureInfo(pLoopPlot->getFeatureType()).getYieldChange(YIELD_FOOD) <= 0) &&
                                                                (GC.getFeatureInfo(pLoopPlot->getFeatureType()).getYieldChange(YIELD_PRODUCTION) <= 0))
                                                        {
                                                                pLoopPlot->setFeatureType(NO_FEATURE);
                                                        }
                                                }
                                        }
                                }
                       
                                int iX, iY;
                                int iCityRange = CITY_PLOTS_RADIUS;
                                int iExtraRange = 2;
                                int iMaxRange = iCityRange + iExtraRange;
                               
                                for (iX = -iMaxRange; iX <= iMaxRange; iX++)
                                {
                                        for (iY = -iMaxRange; iY <= iMaxRange; iY++)
                                        {
                                                pLoopPlot = plotXY(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iX, iY);
                                                if (pLoopPlot != NULL)
                                                {
                                                        int iDistance = plotDistance(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());                  
                                                        if (iDistance <= iMaxRange)
                                                        {
                                                                if (pLoopPlot->getFeatureType() != NO_FEATURE)
                                                                {
                                                                        if ((GC.getFeatureInfo(pLoopPlot->getFeatureType()).getYieldChange(YIELD_FOOD) <= 0) &&
                                                                                (GC.getFeatureInfo(pLoopPlot->getFeatureType()).getYieldChange(YIELD_PRODUCTION) <= 0))
                                                                        {
                                                                                if (pLoopPlot->isWater())
                                                                                {
                                                                                        if (pLoopPlot->isAdjacentToLand() || (!(iDistance == iMaxRange) && (getSorenRandNum(2, "Remove Bad Feature") == 0)))
                                                                                        {
                                                                                                pLoopPlot->setFeatureType(NO_FEATURE);
                                                                                        }
                                                                                }
                                                                                else
                                                                                {
                                                                                        if (!(iDistance == iMaxRange) && (getSorenRandNum((2 + ((pLoopPlot->getBonusType() == NO_BONUS) ? 0 : 2)), "Remove Bad Feature") == 0))
                                                                                        {
                                                                                                pLoopPlot->setFeatureType(NO_FEATURE);                                            
                                                                                        }
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
        }
        }
}


void CvGame::normalizeRemoveBadTerrain()
{
        CvPlot* pStartingPlot;
        CvPlot* pLoopPlot;
        int iI, iK;
        int iX, iY;
       
        int iTargetFood;
        int iTargetTotal;
        int iPlotFood;
        int iPlotProduction;
       
       
        int iCityRange = CITY_PLOTS_RADIUS;
        int iExtraRange = 1;
        int iMaxRange = iCityRange + iExtraRange;

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();

                        if (pStartingPlot != NULL)
                        {
                            for (iX = -iMaxRange; iX <= iMaxRange; iX++)
                            {
                                for (iY = -iMaxRange; iY <= iMaxRange; iY++)
                                {
                                    pLoopPlot = plotXY(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iX, iY);
                        if (pLoopPlot != NULL)
                        {
                            int iDistance = plotDistance(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
                            if (iDistance <= iMaxRange)
                            {
                                if (!(pLoopPlot->isWater()) && ((iDistance <= iCityRange) || (pLoopPlot->isCoastalLand()) || (0 == getSorenRandNum(1 + iDistance - iCityRange, "Map Upgrade Terrain Food"))))
                                {
                                    iPlotFood = GC.getTerrainInfo(pLoopPlot->getTerrainType()).getYield(YIELD_FOOD);
                                    iPlotProduction = GC.getTerrainInfo(pLoopPlot->getTerrainType()).getYield(YIELD_PRODUCTION);
                                    if ((iPlotFood + iPlotProduction) <= 1)
                                    {
                                        iTargetFood = 1;
                                        iTargetTotal = 1;
                                        if (pLoopPlot->getBonusType(GET_PLAYER((PlayerTypes)iI).getTeam()) != NO_BONUS)
                                        {
                                            iTargetFood = 1;
                                            iTargetTotal = 2;
                                        }
                                        else if ((iPlotFood == 1) || (iDistance <= iCityRange))
                                        {
                                            iTargetFood = 1 + getSorenRandNum(2, "Map Upgrade Terrain Food");
                                            iTargetTotal = 2;
                                        }
                                        else
                                        {
                                            iTargetFood = pLoopPlot->isCoastalLand() ? 2 : 1;
                                            iTargetTotal = 2;
                                        }
                                       
                                        for (iK = 0; iK < GC.getNumTerrainInfos(); iK++)
                                        {
                                            if (!(GC.getTerrainInfo((TerrainTypes)iK).isWater()))
                                            {
                                                if ((GC.getTerrainInfo((TerrainTypes)iK).getYield(YIELD_FOOD) >= iTargetFood) &&
                                                    (GC.getTerrainInfo((TerrainTypes)iK).getYield(YIELD_FOOD) + GC.getTerrainInfo((TerrainTypes)iK).getYield(YIELD_PRODUCTION)) == iTargetTotal)
                                                {
                                                    if ((pLoopPlot->getFeatureType() == NO_FEATURE) || GC.getFeatureInfo(pLoopPlot->getFeatureType()).isTerrain(iK))
                                                    {
                                                        pLoopPlot->setTerrainType((TerrainTypes)iK);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
 
                                    }
                                }
                                }
                        }
                }
        }
}

void CvGame::normalizeAddFoodBonuses()
{
        bool bIgnoreLatitude = pythonIsBonusIgnoreLatitudes();

        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();

                        if (pStartingPlot != NULL)
                        {
                                int iFoodBonus = 0;
                                int iGoodNatureTileCount = 0;

                                for (int iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);

                                        if (pLoopPlot != NULL)
                                        {
                                                BonusTypes eBonus = pLoopPlot->getBonusType(GET_PLAYER((PlayerTypes)iI).getTeam());

                                                if (eBonus != NO_BONUS)
                                                {
                                                        if (GC.getBonusInfo(eBonus).getYieldChange(YIELD_FOOD) > 0)
                                                        {
                                                                if ((GC.getBonusInfo(eBonus).getTechCityTrade() == NO_TECH) || (GC.getTechInfo((TechTypes)(GC.getBonusInfo(eBonus).getTechCityTrade())).getEra() <= getStartEra()))
                                                                {
                                                                        if (pLoopPlot->isWater())
                                                                        {
                                                                                iFoodBonus += 2;
                                                                        }
                                                                        else
                                                                        {
                                                                                iFoodBonus += 3;
                                                                        }
                                                                }
                                                        }
                                                        else if (pLoopPlot->calculateBestNatureYield(YIELD_FOOD, GET_PLAYER((PlayerTypes)iI).getTeam()) >= 2)
                                                    {
                                                        iGoodNatureTileCount++;
                                                    }
                                                }
                                                else
                                                {
                            if (pLoopPlot->calculateBestNatureYield(YIELD_FOOD, GET_PLAYER((PlayerTypes)iI).getTeam()) >= 3)
                                                    {
                                                        iGoodNatureTileCount++;
                                                    }
                                                }
                                        }
                                }
                               
                                int iTargetFoodBonusCount = 3;
                                iTargetFoodBonusCount += (iGoodNatureTileCount == 0) ? 2 : 0;

                                for (int iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        if (iFoodBonus >= iTargetFoodBonusCount)
                                        {
                                                break;
                                        }

                                        CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);

                                        if (pLoopPlot != NULL)
                                        {
                                                if (pLoopPlot != pStartingPlot)
                                                {
                                                        if (pLoopPlot->getBonusType() == NO_BONUS)
                                                        {
                                                                for (int iK = 0; iK < GC.getNumBonusInfos(); iK++)
                                                                {
                                                                        if (GC.getBonusInfo((BonusTypes)iK).isNormalize())
                                                                        {
                                                                                if (GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_FOOD) > 0)
                                                                                {
                                                                                        if ((GC.getBonusInfo((BonusTypes)iK).getTechCityTrade() == NO_TECH) || (GC.getTechInfo((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechCityTrade())).getEra() <= getStartEra()))
                                                                                        {
                                                                                                if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHasTech((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechReveal())))
                                                                                                {
                                                                                                        if (pLoopPlot->canHaveBonus(((BonusTypes)iK), bIgnoreLatitude))
                                                                                                        {
                                                                                                                pLoopPlot->setBonusType((BonusTypes)iK);
                                                                                                                if (pLoopPlot->isWater())
                                                                                                                {
                                                                                                                        iFoodBonus += 2;
                                                                                                                }
                                                                                                                else
                                                                                                                {
                                                                                                                        iFoodBonus += 3;
                                                                                                                }
                                                                                                                break;
                                                                                                        }
                                                                                                }
                                                                                        }
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}


void CvGame::normalizeAddGoodTerrain()
{
        CvPlot* pStartingPlot;
        CvPlot* pLoopPlot;
        bool bChanged;
        int iGoodPlot;
        int iI, iJ, iK;

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();

                        if (pStartingPlot != NULL)
                        {
                                iGoodPlot = 0;

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

                                        if (pLoopPlot != NULL)
                                        {
                                                if (pLoopPlot != pStartingPlot)
                                                {
                                                        if ((pLoopPlot->calculateNatureYield(YIELD_FOOD, GET_PLAYER((PlayerTypes)iI).getTeam()) >= GC.getFOOD_CONSUMPTION_PER_POPULATION()) &&
                                                                  (pLoopPlot->calculateNatureYield(YIELD_PRODUCTION, GET_PLAYER((PlayerTypes)iI).getTeam()) > 0))
                                                        {
                                                                iGoodPlot++;
                                                        }
                                                }
                                        }
                                }

                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        if (iGoodPlot >= 4)
                                        {
                                                break;
                                        }

                                        pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);

                                        if (pLoopPlot != NULL)
                                        {
                                                if (pLoopPlot != pStartingPlot)
                                                {
                                                        if (!(pLoopPlot->isWater()))
                                                        {
                                                                if (!(pLoopPlot->isHills()))
                                                                {
                                                                        if (pLoopPlot->getBonusType() == NO_BONUS)
                                                                        {
                                                                                bChanged = false;

                                                                                if (pLoopPlot->calculateNatureYield(YIELD_FOOD, GET_PLAYER((PlayerTypes)iI).getTeam()) < GC.getFOOD_CONSUMPTION_PER_POPULATION())
                                                                                {
                                                                                        for (iK = 0; iK < GC.getNumTerrainInfos(); iK++)
                                                                                        {
                                                                                                if (!(GC.getTerrainInfo((TerrainTypes)iK).isWater()))
                                                                                                {
                                                                                                        if (GC.getTerrainInfo((TerrainTypes)iK).getYield(YIELD_FOOD) >= GC.getFOOD_CONSUMPTION_PER_POPULATION())
                                                                                                        {
                                                                                                                pLoopPlot->setTerrainType((TerrainTypes)iK);
                                                                                                                bChanged = true;
                                                                                                                break;
                                                                                                        }
                                                                                                }
                                                                                        }
                                                                                }

                                                                                if (pLoopPlot->calculateNatureYield(YIELD_PRODUCTION, GET_PLAYER((PlayerTypes)iI).getTeam()) == 0)
                                                                                {
                                                                                        for (iK = 0; iK < GC.getNumFeatureInfos(); iK++)
                                                                                        {
                                                                                                if ((GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_FOOD) >= 0) &&
                                                                                                          (GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_PRODUCTION) > 0))
                                                                                                {
                                                                                                        if (GC.getFeatureInfo((FeatureTypes)iK).isTerrain(pLoopPlot->getTerrainType()))
                                                                                                        {
                                                                                                                pLoopPlot->setFeatureType((FeatureTypes)iK);
                                                                                                                bChanged = true;
                                                                                                                break;
                                                                                                        }
                                                                                                }
                                                                                        }
                                                                                }

                                                                                if (bChanged)
                                                                                {
                                                                                        iGoodPlot++;
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}


void CvGame::normalizeAddExtras()
{
        bool bIgnoreLatitude = pythonIsBonusIgnoreLatitudes();

        int iTotalValue = 0;
        int iPlayerCount = 0;
        int iBestValue = 0;
        int iWorstValue = MAX_INT;
        int     iI, iJ, iK;

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();

                        if (pStartingPlot != NULL)
                        {
                                int iValue = GET_PLAYER((PlayerTypes)iI).AI_foundValue(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), -1, true);
                                iTotalValue += iValue;
                iPlayerCount++;
               
                iBestValue = std::max(iValue, iBestValue);
                iWorstValue = std::min(iValue, iWorstValue);
                        }
                }
        }

        //iTargetValue = (iTotalValue + iBestValue) / (iPlayerCount + 1);
        int iTargetValue = (iBestValue * 4) / 5;
       
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        gDLL->callUpdater();    // allow window to update during launch
                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();

                        if (pStartingPlot != NULL)
                        {
                int iCount = 0;
                                int iFeatureCount = 0;
                                int aiShuffle[NUM_CITY_PLOTS];
                                shuffleArray(aiShuffle, NUM_CITY_PLOTS, getMapRand());

                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        if (GET_PLAYER((PlayerTypes)iI).AI_foundValue(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), -1, true) >= iTargetValue)
                                        {
                                                break;
                                        }
                                        if (getSorenRandNum((iCount + 2), "Setting Feature Type") <= 1)
                                        {
                                                CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), aiShuffle[iJ]);

                                                if (pLoopPlot != NULL)
                                                {
                                                        if (pLoopPlot != pStartingPlot)
                                                        {
                                                                if (pLoopPlot->getBonusType() == NO_BONUS)
                                                                {
                                                                        if (pLoopPlot->getFeatureType() == NO_FEATURE)
                                                                        {
                                                                                for (int iK = 0; iK < GC.getNumFeatureInfos(); iK++)
                                                                                {
                                                                                        if ((GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_FOOD) + GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_PRODUCTION)) > 0)
                                                                                        {
                                                                                                if (pLoopPlot->canHaveFeature((FeatureTypes)iK))
                                                                                                {
                                                                                                        pLoopPlot->setFeatureType((FeatureTypes)iK);
                                                                                                        iCount++;
                                                                                                        break;
                                                                                                }
                                                                                        }
                                                                                }
                                                                        }
                                                                       
                                                                        iFeatureCount += (pLoopPlot->getFeatureType() != NO_FEATURE) ? 1 : 0;
                                                                }
                                                        }
                                                }
                                        }
                                }
                               
                                int iCoastFoodCount = 0;
                                int iOceanFoodCount = 0;
                                int iOtherCount = 0;
                                int iWaterCount = 0;
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
                                        if (pLoopPlot != NULL)
                                        {
                                                if (pLoopPlot != pStartingPlot)
                                                {
                                                        if (pLoopPlot->isWater())
                                                        {
                                                                iWaterCount++;
                                                                if (pLoopPlot->getBonusType() != NO_BONUS)
                                                                {
                                                                        if (pLoopPlot->isAdjacentToLand())
                                                                        {
                                                                                iCoastFoodCount++;
                                                                        }
                                                                        else
                                                                        {
                                                                                iOceanFoodCount++;                                        
                                                                        }
                                                                }
                                                        }
                                                        else
                                                        {
                                                                if (pLoopPlot->getBonusType() != NO_BONUS)
                                                                {
                                                                        iOtherCount++;
                                                                }
                                                        }
                                                }
                                        }
                                }
                               
                            bool bLandBias = (iWaterCount > NUM_CITY_PLOTS / 2);
               
                shuffleArray(aiShuffle, NUM_CITY_PLOTS, getMapRand());                

                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                    CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), aiShuffle[iJ]);

                    if ((pLoopPlot != NULL) && (pLoopPlot != pStartingPlot))
                    {
                        if (getSorenRandNum(((bLandBias && pLoopPlot->isWater()) ? 2 : 1), "Placing Bonuses") == 0)
                        {
                                if ((iOtherCount * 3 + iOceanFoodCount * 2 + iCoastFoodCount * 2) >= 12)
                                {
                                        break;
                                }
                               
                            if (GET_PLAYER((PlayerTypes)iI).AI_foundValue(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), -1, true) >= iTargetValue)
                            {
                                break;
                            }

                                                    bool bCoast = (pLoopPlot->isWater() && pLoopPlot->isAdjacentToLand());
                                                    bool bOcean = (pLoopPlot->isWater() && !bCoast);
                                                        if ((pLoopPlot != pStartingPlot)
                                && !(bCoast && (iCoastFoodCount > 2))
                                && !(bOcean && (iOceanFoodCount > 2)))
                                                        {
                                                                for (int iPass = 0; iPass < 2; iPass++)
                                                                {
                                                                        if (pLoopPlot->getBonusType() == NO_BONUS)
                                                                        {
                                                                                for (iK = 0; iK < GC.getNumBonusInfos(); iK++)
                                                                                {
                                                                                        if (GC.getBonusInfo((BonusTypes)iK).isNormalize())
                                                                                        {
                                                                                            //???no bonuses with negative yields?
                                                                                                if ((GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_FOOD) >= 0) &&
                                                                                                          (GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_PRODUCTION) >= 0))
                                                                                                {
                                                                                                        if ((GC.getBonusInfo((BonusTypes)iK).getTechCityTrade() == NO_TECH) || (GC.getTechInfo((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechCityTrade())).getEra() <= getStartEra()))
                                                                                                        {
                                                                                                                if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHasTech((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechReveal())))
                                                                                                                {
                                                                                                                        if ((iPass == 0) ? CvMapGenerator::GetInstance().canPlaceBonusAt(((BonusTypes)iK), pLoopPlot->getX(), pLoopPlot->getY(), bIgnoreLatitude) : pLoopPlot->canHaveBonus(((BonusTypes)iK), bIgnoreLatitude))
                                                                                                                        {
                                                                                                                                pLoopPlot->setBonusType((BonusTypes)iK);
                                                                                                                                iCoastFoodCount += bCoast ? 1 : 0;
                                                                                                                                iOceanFoodCount += bOcean ? 1 : 0;
                                                                                                                                iOtherCount += !(bCoast || bOcean) ? 1 : 0;
                                                                                                                                break;
                                                                                                                        }
                                                                                                                }
                                                                                                        }
                                                                                                }
                                                                                        }
                                                                                }
                                                                               
                                                                                if (bLandBias && !pLoopPlot->isWater() && pLoopPlot->getBonusType() == NO_BONUS)
                                                                                {
                                                                                        if (((iFeatureCount > 4) && (pLoopPlot->getFeatureType() != NO_FEATURE))
                                                                                                && ((iCoastFoodCount + iOceanFoodCount) > 2))
                                                                                        {
                                                                                                if (getSorenRandNum(2, "Clear feature to add bonus") == 0)
                                                                                                {
                                                                                                        pLoopPlot->setFeatureType(NO_FEATURE);

                                                                                                        for (iK = 0; iK < GC.getNumBonusInfos(); iK++)
                                                                                                        {
                                                                                                                if (GC.getBonusInfo((BonusTypes)iK).isNormalize())
                                                                                                                {
                                                                                                                        //???no bonuses with negative yields?
                                                                                                                        if ((GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_FOOD) >= 0) &&
                                                                                                                                  (GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_PRODUCTION) >= 0))
                                                                                                                        {
                                                                                                                                if ((GC.getBonusInfo((BonusTypes)iK).getTechCityTrade() == NO_TECH) || (GC.getTechInfo((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechCityTrade())).getEra() <= getStartEra()))
                                                                                                                                {
                                                                                                                                        if ((iPass == 0) ? CvMapGenerator::GetInstance().canPlaceBonusAt(((BonusTypes)iK), pLoopPlot->getX(), pLoopPlot->getY(), bIgnoreLatitude) : pLoopPlot->canHaveBonus(((BonusTypes)iK), bIgnoreLatitude))
                                                                                                                                        {
                                                                                                                                                pLoopPlot->setBonusType((BonusTypes)iK);
                                                                                                                                                iOtherCount++;
                                                                                                                                                break;
                                                                                                                                        }
                                                                                                                                }
                                                                                                                        }
                                                                                                                }
                                                                                                        }
                                                                                                }
                                                                                        }                                                                              
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                               
                                shuffleArray(aiShuffle, NUM_CITY_PLOTS, getMapRand());

                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        if (GET_PLAYER((PlayerTypes)iI).AI_foundValue(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), -1, true) >= iTargetValue)
                                        {
                                                break;
                                        }
                               
                                        CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), aiShuffle[iJ]);

                                        if (pLoopPlot != NULL)
                                        {
                                                if (pLoopPlot != pStartingPlot)
                                                {
                                                        if (pLoopPlot->getBonusType() == NO_BONUS)
                                                        {
                                                                if (pLoopPlot->getFeatureType() == NO_FEATURE)
                                                                {
                                                                        for (iK = 0; iK < GC.getNumFeatureInfos(); iK++)
                                                                        {
                                                                                if ((GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_FOOD) + GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_PRODUCTION)) > 0)
                                                                                {
                                                                                        if (pLoopPlot->canHaveFeature((FeatureTypes)iK))
                                                                                        {
                                                                                                pLoopPlot->setFeatureType((FeatureTypes)iK);
                                                                                                break;
                                                                                        }
                                                                                }
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                               
                                int iHillsCount = 0;
                               
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        CvPlot* pLoopPlot =plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
                                        if (pLoopPlot != NULL)
                                        {
                                                if (pLoopPlot->isHills())
                                                {
                                                        iHillsCount++;
                                                }
                                        }
                                }
                                shuffleArray(aiShuffle, NUM_CITY_PLOTS, getMapRand());
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
                                {
                                        if (iHillsCount >= 3)
                                        {
                                                break;
                                        }
                                        CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), aiShuffle[iJ]);
                                        if (pLoopPlot != NULL)
                                        {
                                                if (!pLoopPlot->isWater())
                                                {
                                                        if (!pLoopPlot->isHills())
                                                        {
                                                                if ((pLoopPlot->getFeatureType() == NO_FEATURE) ||
                                                                        !GC.getFeatureInfo(pLoopPlot->getFeatureType()).isRequiresFlatlands())
                                                                {
                                                                        if ((pLoopPlot->getBonusType() == NO_BONUS) ||
                                                                                GC.getBonusInfo(pLoopPlot->getBonusType()).isHills())
                                                                        {
                                                                                pLoopPlot->setPlotType(PLOT_HILLS, false, true);                                                                       
                                                                                iHillsCount++;
                                                                        }
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
}


void CvGame::normalizeStartingPlots()
{
        PROFILE_FUNC();

        if (!(GC.getInitCore().getWBMapScript()) || GC.getInitCore().getWBMapNoPlayers())
        {
                if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeStartingPlotLocations", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
                {
/************************************************************************************************/
/* Afforess                       Start          03/10/10                                               */
/*                                                                                              */
/*                                                                                              */
/************************************************************************************************/
                        if (!isOption(GAMEOPTION_CULTURALLY_LINKED_STARTS))
                        {
                                normalizeStartingPlotLocations();
                        }
/************************************************************************************************/
/* Afforess                          END                                                            */
/************************************************************************************************/
                }
        }

        if (GC.getInitCore().getWBMapScript())
        {
                return;
        }

        if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeAddRiver", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
        {
                normalizeAddRiver();
        }

        if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeRemovePeaks", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
        {
                normalizeRemovePeaks();
        }

        if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeAddLakes", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
        {
                normalizeAddLakes();
        }

        if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeRemoveBadFeatures", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
        {
                normalizeRemoveBadFeatures();
        }

        if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeRemoveBadTerrain", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
        {
                normalizeRemoveBadTerrain();
        }

        if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeAddFoodBonuses", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
        {
                normalizeAddFoodBonuses();
        }

        if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeAddGoodTerrain", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
        {
                normalizeAddGoodTerrain();
        }

        if (!PYTHON_CALL_FUNCTION(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "normalizeAddExtras", NULL)  || gDLL->getPythonIFace()->pythonUsingDefaultImpl())
        {
                normalizeAddExtras();
        }
}

// For each of n teams, let the closeness score for that team be the average distance of an edge between two players on that team.
// This function calculates the closeness score for each team and returns the sum of those n scores.
// The lower the result, the better "clumped" the players' starting locations are.
//
// Note: for the purposes of this function, player i will be assumed to start in the location of player aiStartingLocs[i]

int CvGame::getTeamClosenessScore(int** aaiDistances, int* aiStartingLocs)
{
        int iScore = 0;

        for (int iTeam = 0; iTeam < MAX_CIV_TEAMS; iTeam++)
        {
                if (GET_TEAM((TeamTypes)iTeam).isAlive())
                {
                        int iTeamTotalDist = 0;
                        int iNumEdges = 0;
                        for (int iPlayer = 0; iPlayer < MAX_CIV_PLAYERS; iPlayer++)
                        {
                                if (GET_PLAYER((PlayerTypes)iPlayer).isAlive())
                                {
                                        if (GET_PLAYER((PlayerTypes)iPlayer).getTeam() == (TeamTypes)iTeam)
                                        {
                                                for (int iOtherPlayer = 0; iOtherPlayer < iPlayer; iOtherPlayer++)
                                                {
                                                        if (GET_PLAYER((PlayerTypes)iOtherPlayer).getTeam() == (TeamTypes)iTeam)
                                                        {
                                                                // Add the edge between these two players that are on the same team
                                                                iNumEdges++;
                                                                int iPlayerStart = aiStartingLocs[iPlayer];
                                                                int iOtherPlayerStart = aiStartingLocs[iOtherPlayer];

                                                                if (iPlayerStart < iOtherPlayerStart) // Make sure that iPlayerStart > iOtherPlayerStart
                                                                {
                                                                        int iTemp = iPlayerStart;
                                                                        iPlayerStart = iOtherPlayerStart;
                                                                        iOtherPlayerStart = iTemp;
                                                                }
                                                                else if (iPlayerStart == iOtherPlayerStart)
                                                                {
                                                                        FAssertMsg(false, "Two players are (hypothetically) assigned to the same starting location!");
                                                                }
                                                                iTeamTotalDist += aaiDistances[iPlayerStart][iOtherPlayerStart];
                                                        }
                                                }
                                        }
                                }
                        }

                        int iTeamScore;
                        if (iNumEdges == 0)
                        {
                                iTeamScore = 0;
                        }
                        else
                        {
                                iTeamScore = iTeamTotalDist/iNumEdges; // the avg distance between team edges is the team score
                        }

                        iScore += iTeamScore;
                }
        }
        return iScore;
}


void CvGame::update()
{

        MEMORY_TRACE_FUNCTION();

#ifdef LOG_AI
        gPlayerLogLevel = getBugOptionINT("Autolog__BBAILevel", 0);
        gTeamLogLevel = gPlayerLogLevel;
        gCityLogLevel = gPlayerLogLevel;
        gUnitLogLevel = gPlayerLogLevel;

        if ( gPlayerLogLevel > 0 )
        {
                GC.setXMLLogging(true);
        }
#endif

        startProfilingDLL(false);
        if ( !gDLL->IsPitbossHost() )
        {
                CvPlot* lookatPlot = gDLL->getInterfaceIFace()->getLookAtPlot();
       
                if ( lookatPlot != NULL )
                {
                        //      Sample th BUG setting in the main thread on entry to game update here (it requires a Python call
                        //      so we don't want it happening in background, or more frequently than once per turn slice)
                        bool bPagingEnabled = getBugOptionBOOL("MainInterface__EnableGraphicalPaging", true);
                        GC.setGraphicalDetailPagingEnabled(bPagingEnabled);

                        if ( m_bWasGraphicsPagingEnabled != bPagingEnabled)
                        {
                                for(int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++)
                                {
                                        CvPlot* pPlot = GC.getMapINLINE().plotByIndexINLINE(iI);
                                        if ( pPlot != NULL )
                                        {
                                                if ( m_bWasGraphicsPagingEnabled )
                                                {
                                                        pPlot->setShouldHaveFullGraphics(true);
                                                }
                                                else
                                                {
                                                        pPlot->setShouldHaveFullGraphics(false);
                                                }
                                        }
                                }
                        }

                        m_bWasGraphicsPagingEnabled = bPagingEnabled;

                        if ( GC.getGraphicalDetailPagingEnabled() )
                        {
                                if ( (m_iLastLookatX != lookatPlot->getX_INLINE() || m_iLastLookatY != lookatPlot->getY_INLINE()) )
                                {
                                        int pageInRange = GC.getGraphicalDetailPageInRange();
                                        CvPlot::notePageRenderStart((pageInRange*2+1)*(pageInRange*2+1));

                                        for(int iX = -pageInRange; iX <= pageInRange; iX++)
                                        {
                                                for(int iY = -pageInRange; iY <= pageInRange; iY++)
                                                {
                                                        CvPlot* pPlot = plotXY(lookatPlot->getX_INLINE(),lookatPlot->getY_INLINE(),iX,iY);

                                                        if ( pPlot != NULL )
                                                        {
                                                                pPlot->setShouldHaveFullGraphics(true);
                                                        }
                                                }
                                        }

                                        m_iLastLookatX = lookatPlot->getX_INLINE();
                                        m_iLastLookatY = lookatPlot->getY_INLINE();
                                }

                                CvPlot::EvictGraphicsIfNecessary();
                        }
                }
        }
        //OutputDebugString(CvString::format("Start profiling(false) for CvGame::update()\n").c_str());
        PROFILE_BEGIN("CvGame::update");

        if ( !m_plotGroupHashesInitialized )
        {
                PROFILE("CvGame::update.OneTimeInit");

                //      First opportunity after a load or save is here since sadly the DLL structure
                //      gives us no load/save-completed event
                CvTaggedSaveFormatWrapper&      wrapper = CvTaggedSaveFormatWrapper::getSaveFormatWrapper();

                //      Close will free any resources and display any warnings if we've just finished loading/saving
                wrapper.close();

                GC.getLoadedInitCore().checkVersions();

                for(int iI = 0; iI < MAX_PLAYERS; iI++)
                {
                        if ( GET_PLAYER((PlayerTypes)iI).isAlive() )
                        {
                                GET_PLAYER((PlayerTypes)iI).RecalculatePlotGroupHashes();
                        }
                }

                m_plotGroupHashesInitialized = true;

                gDLL->getEngineIFace()->clearSigns();
                gDLL->getEngineIFace()->setResourceLayer(GC.getResourceLayer());

                //      Remove and re-add the GW on load
                processGreatWall(false, true, false);
                processGreatWall(true, true);
        }

        {
                PROFILE("CvGame::update.ViewportInit");

                //      Some processing that is done in viewport tranisitions has to occur
                //      over several messaging timeslices (empirically - the game engine
                //      gets things wrong if you don't give it a chnace to process messages
                //      in between).  To enact that we use a state machine which performs state
                //      transitions on each call to CvGame::update().
                if ( !gDLL->IsPitbossHost() )
                {              
                        GC.getCurrentViewport()->processActionState();
                }              
                //      On each time slice put back the signs if they have been temporarily removed
                //      (as happens across a save or a map/viewport switch)
                GC.reprocessSigns();
                //      If a rebuild of the graphics is needed and about a second has gone by since a new refresh was last
                //      requested perform the rebuild (this amalgamates all the rebuild requests pertaining to a move or
                //      a sequence of moves)
                if ( m_lastGraphicUpdateRequestTickCount != -1 && (GetTickCount() - m_lastGraphicUpdateRequestTickCount) > 500 )
                {
                        m_lastGraphicUpdateRequestTickCount = -1;

                        gDLL->getEngineIFace()->RebuildAllPlots();
                        gDLL->getInterfaceIFace()->setDirty(GlobeLayer_DIRTY_BIT, true);
                }
        }
       
        int iActiveTurn = 0;
        if (!isPbem())
        {      
                iActiveTurn = getGameTurn();
        }
again:
        if (!gDLL->GetWorldBuilderMode() || isInAdvancedStart())
        {
                PROFILE("CvGame::update.Turn");

                sendPlayerOptions();
                // sample generic event
                CyArgsList pyArgs;
                pyArgs.add(getTurnSlice());
                CvEventReporter::getInstance().genericEvent("gameUpdate", pyArgs.makeFunctionArgs());

                if (getTurnSlice() == 0)
                {
                        PROFILE("CvGame::update.AutoSave");

                        gDLL->getEngineIFace()->AutoSave(true);
                }

                if (getNumGameTurnActive() == 0)
                {
                        if (!isPbem() || !getPbemTurnSent())
                        {
                                doTurn();
                        }
                }

                updateScore();

                updateWar();

                updateMoves();

                updateTimers();

                updateTurnTimer();

                AI_updateAssignWork();

                testAlive();

                if (GC.isENABLE_RESYNC_CODE())
                {
                        if (isNetworkMultiPlayer())
                        {
                                if (getTurnSlice() == 0)
                                {
                                        m_resyncPackets.clear();
                                        m_bOutOfSync = false;
                                }
                                else if (m_resyncPackets.size() > 0)
                                {
                                        std::vector<CvGameResyncPacket*>::iterator it;
                                        int iCount = 20;
                                        for (it = m_resyncPackets.begin(); it != m_resyncPackets.end();)
                                        {
                                                CvGameResyncPacket* packet = (*it);
                                                it = m_resyncPackets.erase(it);
                                                gDLL->sendMessageData(packet);
                                                iCount--;
                                                if (iCount <= 0)
                                                {
                                                        break;
                                                }
                                        }
                                }
                                else if (isMultiplayerHost())
                                {
                                        checkOutOfSyncPlayers();
                                }
                        }
                }
/************************************************************************************************/
/* REVOLUTION_MOD                                                                 lemmy101      */
/*                                                                                jdog5000      */
/*                                                                                              */
/************************************************************************************************/
                if ((isNetworkMultiPlayer() || (getAIAutoPlay(getActivePlayer()) <= 0) && !(gDLL->GetAutorun()) && GAMESTATE_EXTENDED != getGameState()))
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
                {
                        if (countHumanPlayersAlive() == 0)
                        {
                                setGameState(GAMESTATE_OVER);
                        }
                }

                changeTurnSlice(1);
                m_iActiveTurnSlice += 1;

                if (NO_PLAYER != getActivePlayer() && GET_PLAYER(getActivePlayer()).getAdvancedStartPoints() >= 0 && !gDLL->getInterfaceIFace()->isInAdvancedStart())
                {
                        gDLL->getInterfaceIFace()->setInAdvancedStart(true);
                        gDLL->getInterfaceIFace()->setWorldBuilder(true);
                }
        }

        reportQueuedEvents();
        doQueuedUIActivity();

        //OutputDebugString(CvString::format("Stop profiling(false) after CvGame::update()\n").c_str());
        if(!isPitboss())
        {
                CvPlayerAI& kActivePlayer = GET_PLAYER(getActivePlayer());
                if (!isPbem())
                {
                        if ( (!kActivePlayer.isTurnActive() || kActivePlayer.isAutoMoves()) && !kActivePlayer.hasBusyUnit() && !isNetworkMultiPlayer())
                        {
                                updateTimers();

                                if (iActiveTurn == getGameTurn())
                                {
                                        goto again;
                                }
                        }
                }
                else
                {      
                        if ( (!kActivePlayer.isTurnActive() || kActivePlayer.isAutoMoves()) && !kActivePlayer.hasBusyUnit() && !isNetworkMultiPlayer()  &&
                                !isPbem() )
                        {
                                updateTimers();

                                goto again;
                        }      
                }      
        }
        PROFILE_END();
        stopProfilingDLL(false);

}


void CvGame::updateScore(bool bForce)
{
        PROFILE_FUNC();

        MEMORY_TRACE_FUNCTION();

        bool abPlayerScored[MAX_CIV_PLAYERS];
        bool abTeamScored[MAX_CIV_TEAMS];
        int iScore;
        int iBestScore;
        PlayerTypes eBestPlayer;
        TeamTypes eBestTeam;
        int iI, iJ, iK;

        if (!isScoreDirty() && !bForce)
        {
                return;
        }

        setScoreDirty(false);

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                abPlayerScored[iI] = false;
        }

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                iBestScore = MIN_INT;
                eBestPlayer = NO_PLAYER;

                for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
                {
                        if (!abPlayerScored[iJ])
                        {
                                iScore = GET_PLAYER((PlayerTypes)iJ).calculateScore(false);

                                if (iScore >= iBestScore)
                                {
                                        iBestScore = iScore;
                                        eBestPlayer = (PlayerTypes)iJ;
                                }
                        }
                }

                abPlayerScored[eBestPlayer] = true;

                setRankPlayer(iI, eBestPlayer);
                setPlayerRank(eBestPlayer, iI);
                setPlayerScore(eBestPlayer, iBestScore);
                GET_PLAYER(eBestPlayer).updateScoreHistory(getGameTurn(), iBestScore);
        }

        for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
        {
                abTeamScored[iI] = false;
        }

        for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
        {
                iBestScore = MIN_INT;
                eBestTeam = NO_TEAM;

                for (iJ = 0; iJ < MAX_CIV_TEAMS; iJ++)
                {
                        if (!abTeamScored[iJ])
                        {
                                iScore = 0;

                                for (iK = 0; iK < MAX_CIV_PLAYERS; iK++)
                                {
                                        if (GET_PLAYER((PlayerTypes)iK).getTeam() == iJ)
                                        {
                                                iScore += getPlayerScore((PlayerTypes)iK);
                                        }
                                }

                                if (iScore >= iBestScore)
                                {
                                        iBestScore = iScore;
                                        eBestTeam = (TeamTypes)iJ;
                                }
                        }
                }

                abTeamScored[eBestTeam] = true;

                setRankTeam(iI, eBestTeam);
                setTeamRank(eBestTeam, iI);
                setTeamScore(eBestTeam, iBestScore);
        }
}

void CvGame::updatePlotGroups(bool reInitialize)
{
        PROFILE_FUNC();

        int iI;

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        GET_PLAYER((PlayerTypes)iI).updatePlotGroups(NULL, reInitialize);
                }
        }
}


void CvGame::updateBuildingCommerce()
{
        PROFILE_FUNC();

        int iI;

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        GET_PLAYER((PlayerTypes)iI).updateBuildingCommerce();
                }
        }
}


void CvGame::updateCitySight(bool bIncrement)
{
        PROFILE_FUNC();

        int iI;

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        GET_PLAYER((PlayerTypes)iI).updateCitySight(bIncrement, false);
                }
        }

        updatePlotGroups();
}


void CvGame::updateTradeRoutes()
{
        PROFILE_FUNC();

        int iI;

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        GET_PLAYER((PlayerTypes)iI).updateTradeRoutes();
                }
        }
}


void CvGame::testExtendedGame()
{
        PROFILE_FUNC();

        int iI;

        if (getGameState() != GAMESTATE_OVER)
        {
                return;
        }

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        if (GET_PLAYER((PlayerTypes)iI).isHuman())
                        {
                                if (GET_PLAYER((PlayerTypes)iI).isExtendedGame())
                                {
                                        setGameState(GAMESTATE_EXTENDED);
                                        break;
                                }
                        }
                }
        }
}


void CvGame::cityPushOrder(CvCity* pCity, OrderTypes eOrder, int iData, bool bAlt, bool bShift, bool bCtrl) const
{
        if (pCity->getProduction() > 0)
        {
                CvMessageControl::getInstance().sendPushOrder(pCity->getID(), eOrder, iData, bAlt, bShift, !bShift);
        }
        else if ((eOrder == ORDER_TRAIN) && (pCity->getProductionUnit() == iData))
        {
                CvMessageControl::getInstance().sendPushOrder(pCity->getID(), eOrder, iData, bAlt, !bCtrl, bCtrl);
        }
        else
        {
                CvMessageControl::getInstance().sendPushOrder(pCity->getID(), eOrder, iData, bAlt, bShift, bCtrl);
        }
}


void CvGame::selectUnit(CvUnit* pUnit, bool bClear, bool bToggle, bool bSound) const
{
        PROFILE_FUNC();

        CLLNode<IDInfo>* pEntityNode;
        CvSelectionGroup* pSelectionGroup;
        bool bSelectGroup;
        bool bGroup;

        if (gDLL->getInterfaceIFace()->getHeadSelectedUnit() == NULL)
        {
                bSelectGroup = true;
        }
        else if (gDLL->getInterfaceIFace()->getHeadSelectedUnit()->getGroup() != pUnit->getGroup())
        {
                bSelectGroup = true;
        }
        else if (pUnit->IsSelected() && !(gDLL->getInterfaceIFace()->mirrorsSelectionGroup()))
        {
                bSelectGroup = !bToggle;
        }
        else
        {
                bSelectGroup = false;
        }

        gDLL->getInterfaceIFace()->clearSelectedCities();

        if (bClear)
        {
                gDLL->getInterfaceIFace()->clearSelectionList();
                bGroup = false;
        }
        else
        {
                bGroup = gDLL->getInterfaceIFace()->mirrorsSelectionGroup();
        }

        if (bSelectGroup)
        {
                pSelectionGroup = pUnit->getGroup();

                gDLL->getInterfaceIFace()->selectionListPreChange();

                pEntityNode = pSelectionGroup->headUnitNode();

                while (pEntityNode != NULL)
                {
                        FAssertMsg(::getUnit(pEntityNode->m_data), "null entity in selection group");
                        gDLL->getInterfaceIFace()->insertIntoSelectionList(::getUnit(pEntityNode->m_data), false, bToggle, bGroup, bSound, true);

                        pEntityNode = pSelectionGroup->nextUnitNode(pEntityNode);
                }

                gDLL->getInterfaceIFace()->selectionListPostChange();
        }
        else
        {
                gDLL->getInterfaceIFace()->insertIntoSelectionList(pUnit, false, bToggle, bGroup, bSound);
        }

        gDLL->getInterfaceIFace()->makeSelectionListDirty();
}


void CvGame::selectGroup(CvUnit* pUnit, bool bShift, bool bCtrl, bool bAlt) const
{
        PROFILE_FUNC();

        CLLNode<IDInfo>* pUnitNode;
        CvUnit* pLoopUnit;
        CvPlot* pUnitPlot;
        bool bGroup;

        FAssertMsg(pUnit != NULL, "pUnit == NULL unexpectedly");

        if (bAlt || bCtrl)
        {
                gDLL->getInterfaceIFace()->clearSelectedCities();

                if (!bShift)
                {
                        gDLL->getInterfaceIFace()->clearSelectionList();
                        bGroup = true;
                }
                else
                {
                        bGroup = gDLL->getInterfaceIFace()->mirrorsSelectionGroup();
                }

                pUnitPlot = pUnit->plot();

                pUnitNode = pUnitPlot->headUnitNode();

                gDLL->getInterfaceIFace()->selectionListPreChange();

                while (pUnitNode != NULL)
                {
                        pLoopUnit = ::getUnit(pUnitNode->m_data);
                        pUnitNode = pUnitPlot->nextUnitNode(pUnitNode);

                        if (pLoopUnit->getOwnerINLINE() == getActivePlayer())
                        {
                                if (pLoopUnit->canMove())
                                {
                                        if (!isMPOption(MPOPTION_SIMULTANEOUS_TURNS) || getTurnSlice() - pLoopUnit->getLastMoveTurn() > GC.getDefineINT("MIN_TIMER_UNIT_DOUBLE_MOVES"))
                                        {
                                                if (bAlt || (pLoopUnit->getUnitType() == pUnit->getUnitType()))
                                                {
                                                        gDLL->getInterfaceIFace()->insertIntoSelectionList(pLoopUnit, false, false, bGroup, false, true);
                                                }
                                        }
                                }
                        }
                }

                gDLL->getInterfaceIFace()->selectionListPostChange();
        }
        else
        {
                gDLL->getInterfaceIFace()->selectUnit(pUnit, !bShift, bShift, true);
        }
}


void CvGame::selectAll(CvPlot* pPlot) const
{
        CvUnit* pSelectUnit;
        CvUnit* pCenterUnit;

        pSelectUnit = NULL;

        if (pPlot != NULL)
        {
                pCenterUnit = pPlot->getDebugCenterUnit();

                if ((pCenterUnit != NULL) && (pCenterUnit->getOwnerINLINE() == getActivePlayer()))
                {
                        pSelectUnit = pCenterUnit;
                }
        }

        if (pSelectUnit != NULL)
        {
                gDLL->getInterfaceIFace()->selectGroup(pSelectUnit, false, false, true);
        }
}


bool CvGame::selectionListIgnoreBuildingDefense() const
{
        PROFILE_FUNC();

        CLLNode<IDInfo>* pSelectedUnitNode;
        CvUnit* pSelectedUnit;
        bool bIgnoreBuilding;
        bool bAttackLandUnit;

        bIgnoreBuilding = false;
        bAttackLandUnit = false;

        pSelectedUnitNode = gDLL->getInterfaceIFace()->headSelectionListNode();

        while (pSelectedUnitNode != NULL)
        {
                pSelectedUnit = ::getUnit(pSelectedUnitNode->m_data);
                pSelectedUnitNode = gDLL->getInterfaceIFace()->nextSelectionListNode(pSelectedUnitNode);

                if (pSelectedUnit != NULL)
                {
                        if (pSelectedUnit->ignoreBuildingDefense())
                        {
                                bIgnoreBuilding = true;
                        }

                        if ((pSelectedUnit->getDomainType() == DOMAIN_LAND) && pSelectedUnit->canAttack())
                        {
                                bAttackLandUnit = true;
                        }
                }
        }

        if (!bIgnoreBuilding && !bAttackLandUnit)
        {
                if (getBestLandUnit() != NO_UNIT)
                {
                        bIgnoreBuilding = GC.getUnitInfo(getBestLandUnit()).isIgnoreBuildingDefense();
                }
        }

        return bIgnoreBuilding;
}


void CvGame::implementDeal(PlayerTypes eWho, PlayerTypes eOtherWho, CLinkList<TradeData>* pOurList, CLinkList<TradeData>* pTheirList, bool bForce)
{
        CvDeal* pDeal;

        FAssertMsg(eWho != NO_PLAYER, "Who is not assigned a valid value");
        FAssertMsg(eOtherWho != NO_PLAYER, "OtherWho is not assigned a valid value");
        FAssertMsg(eWho != eOtherWho, "eWho is not expected to be equal with eOtherWho");

        pDeal = addDeal();
        pDeal->init(pDeal->getID(), eWho, eOtherWho);
        pDeal->addTrades(pOurList, pTheirList, !bForce);
        if ((pDeal->getLengthFirstTrades() == 0) && (pDeal->getLengthSecondTrades() == 0))
        {
                pDeal->kill();
        }
}


void CvGame::verifyDeals()
{
        CvDeal* pLoopDeal;
        int iLoop = 0;

        for(pLoopDeal = firstDeal(&iLoop); pLoopDeal != NULL; pLoopDeal = nextDeal(&iLoop))
        {
                pLoopDeal->verify();
        }
}


/* Globeview configuration control:
If bStarsVisible, then there will be stars visible behind the globe when it is on
If bWorldIsRound, then the world will bend into a globe; otherwise, it will show up as a plane  */

void CvGame::getGlobeviewConfigurationParameters(TeamTypes eTeam, bool& bStarsVisible, bool& bWorldIsRound)
{
        if(GET_TEAM(eTeam).isMapCentering() || isCircumnavigated())
        {
                bStarsVisible = true;
                bWorldIsRound = true;
        }
        else
        {
                bStarsVisible = false;
                bWorldIsRound = false;
        }
}


int CvGame::getSymbolID(int iSymbol)
{
        return gDLL->getInterfaceIFace()->getSymbolID(iSymbol);
}


int CvGame::getAdjustedPopulationPercent(VictoryTypes eVictory) const
{
        int iPopulation;
        int iBestPopulation;
        int iNextBestPopulation;
        int iI;

        if (GC.getVictoryInfo(eVictory).getPopulationPercentLead() == 0)
        {
                return 0;
        }

        if (getTotalPopulation() == 0)
        {
                return 100;
        }

        iBestPopulation = 0;
        iNextBestPopulation = 0;

        for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
        {
                if (GET_TEAM((TeamTypes)iI).isAlive())
                {
                        iPopulation = GET_TEAM((TeamTypes)iI).getTotalPopulation();

                        if (iPopulation > iBestPopulation)
                        {
                                iNextBestPopulation = iBestPopulation;
                                iBestPopulation = iPopulation;
                        }
                        else if (iPopulation > iNextBestPopulation)
                        {
                                iNextBestPopulation = iPopulation;
                        }
                }
        }

        return std::min(100, (((iNextBestPopulation * 100) / getTotalPopulation()) + GC.getVictoryInfo(eVictory).getPopulationPercentLead()));
}


int CvGame::getProductionPerPopulation(HurryTypes eHurry)
{
        if (NO_HURRY == eHurry)
        {
                return 0;
        }
        return (GC.getHurryInfo(eHurry).getProductionPerPopulation() * 100) / std::max(1, GC.getGameSpeedInfo(getGameSpeedType()).getHurryPercent());
}


int CvGame::getAdjustedLandPercent(VictoryTypes eVictory) const
{
        int iPercent;

        if (GC.getVictoryInfo(eVictory).getLandPercent() == 0)
        {
                return 0;
        }

        iPercent = GC.getVictoryInfo(eVictory).getLandPercent();

        iPercent -= (countCivTeamsEverAlive() * 2);

        return std::max(iPercent, GC.getVictoryInfo(eVictory).getMinLandPercent());
}


bool CvGame::isTeamVote(VoteTypes eVote) const
{
        return (GC.getVoteInfo(eVote).isSecretaryGeneral() || GC.getVoteInfo(eVote).isVictory());
}


bool CvGame::isChooseElection(VoteTypes eVote) const
{
        return !(GC.getVoteInfo(eVote).isSecretaryGeneral());
}


bool CvGame::isTeamVoteEligible(TeamTypes eTeam, VoteSourceTypes eVoteSource) const
{
        CvTeam& kTeam = GET_TEAM(eTeam);
/* Munch edit 06/10/09, added by 45° on 02/17/13 */
/* so that the incumbent resident is forbidden from being reelected, but not forbidden from being elected to total victory */
/* to revert, delete all; should work with "normal" Diplomatic Victory; when Mastery Victory is enabled, Secretary General cannot be a candidate for */
/* Diplomatic Victory, which isn't a problem anyway, since Mastery Victory overrules Diplomatic Victory (added by 45°)*/
        int bSecretaryElection = 0;
        for (int iI = 0; iI < GC.getNumVoteInfos(); iI++)
        {
                if ((GC.getVoteInfo((VoteTypes)iI).isVoteSourceType(eVoteSource)) && (VoteSourceTypes(eVoteSource) != 1))  /* here's a check so that inelegibility applies to UN Secretary only and not to AP Resident) by 45° */
                {
                        if (!GC.getVoteInfo((VoteTypes)iI).isVictory())
                        {
                                bSecretaryElection = 1;
                        }
                }
        }

        int incumbentTeam = getSecretaryGeneral(eVoteSource);
        if (eTeam == incumbentTeam)
        {
                if (bSecretaryElection == 1) return false;
        }
/* end Munch edit */
        if (kTeam.isForceTeamVoteEligible(eVoteSource))
        {
                return true;
        }

        if (!kTeam.isFullMember(eVoteSource))
        {
                return false;
        }

        int iCount = 0;
        for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
        {
                CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iI);
                if (kLoopTeam.isAlive())
                {
                        if (kLoopTeam.isForceTeamVoteEligible(eVoteSource))
                        {
                                ++iCount;
                        }
                }
        }

        int iExtraEligible = GC.getDefineINT("TEAM_VOTE_MIN_CANDIDATES") - iCount;
        if (iExtraEligible <= 0)
        {
                return false;
        }

        for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
        {
                if (iI != eTeam)
                {
                        CvTeam& kLoopTeam = GET_TEAM((TeamTypes)iI);
                        if (kLoopTeam.isAlive())
                        {
                                if (!kLoopTeam.isForceTeamVoteEligible(eVoteSource))
                                {
                                        if (kLoopTeam.isFullMember(eVoteSource))
                                        {
                                                int iLoopVotes = kLoopTeam.getVotes(NO_VOTE, eVoteSource);
                                                int iVotes = kTeam.getVotes(NO_VOTE, eVoteSource);
                                                if (iLoopVotes > iVotes || (iLoopVotes == iVotes && iI < eTeam))
                                                {
/* Munch edit 22/10/09, added by 45° on 02/17/13 */
                                                        iExtraEligible--;
                                                        if (bSecretaryElection == 1 && iI == incumbentTeam) iExtraEligible++;
/* the purpose of this is to not 'reserve' an election space due to higher vote count for the incumbent, who is supposed to be now ineligible */
/* exception being if the teamvote is actually a victory vote rather than a secretary general vote */
/* to revert, delete all except iExtraEligible--; */
                                                }
                                        }
                                }
                        }
                }
        }

        return (iExtraEligible > 0);
}


int CvGame::countVote(const VoteTriggeredData& kData, PlayerVoteTypes eChoice) const
{
        int iCount = 0;

        for (int iI = 0; iI < MAX_CIV_PLAYERS; ++iI)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        if (getPlayerVote(((PlayerTypes)iI), kData.getID()) == eChoice)
                        {
                                iCount += GET_PLAYER((PlayerTypes)iI).getVotes(kData.kVoteOption.eVote, kData.eVoteSource);
                        }
                }
        }

        return iCount;
}


int CvGame::countPossibleVote(VoteTypes eVote, VoteSourceTypes eVoteSource) const
{
        int iCount;
        int iI;

        iCount = 0;

        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if ( GET_PLAYER((PlayerTypes)iI).isAlive() )
                {
                        iCount += GET_PLAYER((PlayerTypes)iI).getVotes(eVote, eVoteSource);
                }
        }

        return iCount;
}



TeamTypes CvGame::findHighestVoteTeam(const VoteTriggeredData& kData) const
{
        TeamTypes eBestTeam = NO_TEAM;
        int iBestCount = 0;

        if (isTeamVote(kData.kVoteOption.eVote))
        {
                for (int iI = 0; iI < MAX_CIV_TEAMS; ++iI)
                {
                        if (GET_TEAM((TeamTypes)iI).isAlive())
                        {
                                int iCount = countVote(kData, (PlayerVoteTypes)iI);

                                if (iCount > iBestCount)
                                {
                                        iBestCount = iCount;
                                        eBestTeam = (TeamTypes)iI;
                                }
                        }
                }
        }

        return eBestTeam;
}


int CvGame::getVoteRequired(VoteTypes eVote, VoteSourceTypes eVoteSource) const
{
        return ((countPossibleVote(eVote, eVoteSource) * GC.getVoteInfo(eVote).getPopulationThreshold()) / 100);
}


TeamTypes CvGame::getSecretaryGeneral(VoteSourceTypes eVoteSource) const
{
        int iI;

        if (!canHaveSecretaryGeneral(eVoteSource))
        {
                for (int iBuilding = 0; iBuilding < GC.getNumBuildingInfos(); ++iBuilding)
                {
                        if (GC.getBuildingInfo((BuildingTypes)iBuilding).getVoteSourceType() == eVoteSource)
                        {
                                for (iI = 0; iI < MAX_CIV_PLAYERS; ++iI)
                                {
                                        CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iI);
                                        if (kLoopPlayer.isAlive())
                                        {
                                                if (kLoopPlayer.getBuildingClassCount((BuildingClassTypes)GC.getBuildingInfo((BuildingTypes)iBuilding).getBuildingClassType()) > 0)
                                                {
                                                        ReligionTypes eReligion = getVoteSourceReligion(eVoteSource);
                                                        if (NO_RELIGION == eReligion || kLoopPlayer.getStateReligion() == eReligion)
                                                        {
                                                                return kLoopPlayer.getTeam();
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }
        else
        {
                for (iI = 0; iI < GC.getNumVoteInfos(); iI++)
                {
                        if (GC.getVoteInfo((VoteTypes)iI).isVoteSourceType(eVoteSource))
                        {
                                if (GC.getVoteInfo((VoteTypes)iI).isSecretaryGeneral())
                                {
                                        if (isVotePassed((VoteTypes)iI))
                                        {
                                                return ((TeamTypes)(getVoteOutcome((VoteTypes)iI)));
                                        }
                                }
                        }
                }
        }


        return NO_TEAM;
}

bool CvGame::canHaveSecretaryGeneral(VoteSourceTypes eVoteSource) const
{
        for (int iI = 0; iI < GC.getNumVoteInfos(); iI++)
        {
                if (GC.getVoteInfo((VoteTypes)iI).isVoteSourceType(eVoteSource))
                {
                        if (GC.getVoteInfo((VoteTypes)iI).isSecretaryGeneral())
                        {
                                return true;
                        }
                }
        }

        return false;
}

void CvGame::clearSecretaryGeneral(VoteSourceTypes eVoteSource)
{
        for (int j = 0; j < GC.getNumVoteInfos(); ++j)
        {
                CvVoteInfo& kVote = GC.getVoteInfo((VoteTypes)j);

                if (kVote.isVoteSourceType(eVoteSource))
                {
                        if (kVote.isSecretaryGeneral())
                        {
                                VoteTriggeredData kData;
                                kData.eVoteSource = eVoteSource;
                                kData.kVoteOption.eVote = (VoteTypes)j;
                                kData.kVoteOption.iCityId = -1;
                                kData.kVoteOption.szText.clear();
                                kData.kVoteOption.ePlayer = NO_PLAYER;
                                setVoteOutcome(kData, NO_PLAYER_VOTE);
                                setSecretaryGeneralTimer(eVoteSource, 0);
                        }
                }
        }
}

void CvGame::updateSecretaryGeneral()
{
        PROFILE_FUNC();

        for (int i = 0; i < GC.getNumVoteSourceInfos(); ++i)
        {
                TeamTypes eSecretaryGeneral = getSecretaryGeneral((VoteSourceTypes)i);
                if (NO_TEAM != eSecretaryGeneral && !GET_TEAM(eSecretaryGeneral).isFullMember((VoteSourceTypes)i))
                {
                        clearSecretaryGeneral((VoteSourceTypes)i);
                }
        }
}

int CvGame::countCivPlayersAlive() const
{
        int iCount = 0;

        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        iCount++;
                }
        }

        return iCount;
}


int CvGame::countCivPlayersEverAlive() const
{
        int iCount = 0;

        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                CvPlayer& kPlayer = GET_PLAYER((PlayerTypes) iI);
                if (kPlayer.isEverAlive())
                {
                        if (kPlayer.getParent() == NO_PLAYER)
                        {
                                iCount++;
                        }
                }
        }

        return iCount;
}


int CvGame::countCivTeamsAlive() const
{
        int iCount = 0;

        for (int iI = 0; iI < MAX_CIV_TEAMS; iI++)
        {
                if (GET_TEAM((TeamTypes)iI).isAlive())
                {
                        iCount++;
                }
        }

        return iCount;
}


int CvGame::countCivTeamsEverAlive() const
{
        bool    teamsAlive[MAX_CIV_TEAMS];
        int             iCount = 0;

        memset(teamsAlive,0,sizeof(bool)*MAX_CIV_TEAMS);

        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                CvPlayer& kPlayer = GET_PLAYER((PlayerTypes) iI);
                if (kPlayer.isEverAlive())
                {
                        if (kPlayer.getParent() == NO_PLAYER)
                        {
                                FAssert(0 <= kPlayer.getTeam());
                                FAssert(MAX_CIV_TEAMS > kPlayer.getTeam());

                                if ( !teamsAlive[kPlayer.getTeam()] )
                                {
                                        teamsAlive[kPlayer.getTeam()] = true;
                                        iCount++;
                                }
                        }
                }
        }

        return iCount;
}


int CvGame::countHumanPlayersAlive() const
{
        int iCount = 0;

/************************************************************************************************/
/* REVOLUTION_MOD                         02/01/08                                jdog5000      */
/*                                                                                              */
/* Allow humans to control barbs                                                                */
/************************************************************************************************/
/* original code
        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
*/

        for (int iI = 0; iI < MAX_PLAYERS; iI++)
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/
        {
                CvPlayer& kPlayer = GET_PLAYER((PlayerTypes) iI);
                if (kPlayer.isAlive() && kPlayer.isHuman())
                {
                        iCount++;
                }
        }

        return iCount;
}


int CvGame::countTotalCivPower()
{
        int iCount = 0;

        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                CvPlayer& kPlayer = GET_PLAYER((PlayerTypes) iI);
                if (kPlayer.isAlive())
                {
                        iCount += kPlayer.getPower();
                }
        }

        return iCount;
}


int CvGame::countTotalNukeUnits()
{
        int iCount = 0;
        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
        {
                CvPlayer& kPlayer = GET_PLAYER((PlayerTypes) iI);
                if (kPlayer.isAlive())
                {
                        iCount += kPlayer.getNumNukeUnits();
                }
        }

        return iCount;
}


int CvGame::countKnownTechNumTeams(TechTypes eTech)
{
        int iCount = 0;

        for (int iI = 0; iI < MAX_TEAMS; iI++)
        {
                if (GET_TEAM((TeamTypes)iI).isEverAlive())
                {
                        if (GET_TEAM((TeamTypes)iI).isHasTech(eTech))
                        {
                                if (!GET_TEAM((TeamTypes)iI).isBarbarian())
                                {
                                        iCount++;
                                }
                        }
                }
        }

        return iCount;
}


int CvGame::getNumFreeBonuses(BuildingTypes eBuilding)
{
        if (GC.getBuildingInfo(eBuilding).getNumFreeBonuses() == -1)
        {
                return GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getNumFreeBuildingBonuses();
        }
        else
        {
                return GC.getBuildingInfo(eBuilding).getNumFreeBonuses();
        }
}


int CvGame::countReligionLevels(ReligionTypes eReligion)
{
        int iCount;
        int iI;

        iCount = 0;

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        iCount += GET_PLAYER((PlayerTypes)iI).getHasReligionCount(eReligion);
                }
        }

        return iCount;
}

int CvGame::countCorporationLevels(CorporationTypes eCorporation)
{
        int iCount = 0;

        for (int iI = 0; iI < MAX_PLAYERS; iI++)
        {
                CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iI);
                if (kLoopPlayer.isAlive())
                {
                        iCount += GET_PLAYER((PlayerTypes)iI).getHasCorporationCount(eCorporation);
                }
        }

        return iCount;
}

void CvGame::replaceCorporation(CorporationTypes eCorporation1, CorporationTypes eCorporation2)
{
        for (int iI = 0; iI < MAX_PLAYERS; iI++)
        {
                CvPlayer& kLoopPlayer = GET_PLAYER((PlayerTypes)iI);
                if (kLoopPlayer.isAlive())
                {
                        int iIter = 0;
                        for (CvCity* pCity = kLoopPlayer.firstCity(&iIter); NULL != pCity; pCity = kLoopPlayer.nextCity(&iIter))
                        {
                                if (pCity->isHasCorporation(eCorporation1))
                                {
                                        pCity->setHasCorporation(eCorporation1, false, false, false);
                                        pCity->setHasCorporation(eCorporation2, true, true);
                                }
                        }

                        for (CvUnit* pUnit = kLoopPlayer.firstUnit(&iIter); NULL != pUnit; pUnit = kLoopPlayer.nextUnit(&iIter))
                        {
                                if (pUnit->getUnitInfo().getCorporationSpreads(eCorporation1) > 0)
                                {
                                        pUnit->kill(false);
                                }
                        }
                }
        }
}


int CvGame::calculateReligionPercent(ReligionTypes eReligion) const
{
        CvCity* pLoopCity;
        int iCount;
        int iLoop = 0;
        int iI;

        if (getTotalPopulation() == 0)
        {
                return 0;
        }

        iCount = 0;

        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))
                        {
                                if (pLoopCity->isHasReligion(eReligion))
                                {
                                        iCount += ((pLoopCity->getPopulation() + (pLoopCity->getReligionCount() / 2)) / pLoopCity->getReligionCount());
                                }
                        }
                }
        }

        return ((iCount * 100) / getTotalPopulation());
}


int CvGame::goldenAgeLength() const
{
        int iLength;

        iLength = GC.getDefineINT("GOLDEN_AGE_LENGTH");

        iLength *= GC.getGameSpeedInfo(getGameSpeedType()).getGoldenAgePercent();
        iLength /= 100;

        return iLength;
}

int CvGame::victoryDelay(VictoryTypes eVictory) const
{
        FAssert(eVictory >= 0 && eVictory < GC.getNumVictoryInfos());

        int iLength = GC.getVictoryInfo(eVictory).getVictoryDelayTurns();

        iLength *= GC.getGameSpeedInfo(getGameSpeedType()).getVictoryDelayPercent();
        iLength /= 100;

        return iLength;
}



int CvGame::getImprovementUpgradeTime(ImprovementTypes eImprovement) const
{
        int iTime;

        iTime = GC.getImprovementInfo(eImprovement).getUpgradeTime();

        iTime *= GC.getGameSpeedInfo(getGameSpeedType()).getImprovementPercent();
        iTime /= 100;

        iTime *= GC.getEraInfo(getStartEra()).getImprovementPercent();
        iTime /= 100;

        return iTime;
}


bool CvGame::canTrainNukes() const
{
        for (int iI = 0; iI < MAX_PLAYERS; iI++)
        {
                CvPlayer& kPlayer = GET_PLAYER((PlayerTypes)iI);
                if (kPlayer.isAlive())
                {
                        for (int iJ = 0; iJ < GC.getNumUnitClassInfos(); iJ++)
                        {
                                UnitTypes eUnit = (UnitTypes)GC.getCivilizationInfo(kPlayer.getCivilizationType()).getCivilizationUnits((UnitClassTypes)iJ);

                                if (NO_UNIT != eUnit)
                                {
                                        if (-1 != GC.getUnitInfo(eUnit).getNukeRange())
                                        {
                                                if (kPlayer.canTrain(eUnit))
                                                {
                                                        return true;
                                                }
                                        }
                                }
                        }
                }
        }

        return false;
}



/************************************************************************************************/
/* RevDCM                         Start          11/04/10                                phungus420     */
/*                                                                                              */
/* New World Logic                                                                              */
/************************************************************************************************/
EraTypes CvGame::getHighestEra() const
{
        int iI;
        int iHighestEra = 0;
        int iLoopEra;
       
        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        iLoopEra = GET_PLAYER((PlayerTypes)iI).getCurrentEra();

                        if(iLoopEra > iHighestEra)
                        {
                                iHighestEra = iLoopEra;
                        }
                }
        }

        return EraTypes(iHighestEra);
}
/************************************************************************************************/
/* LIMITED_RELIGIONS               END                                                          */
/************************************************************************************************/
EraTypes CvGame::getCurrentEra() const
{
        int iEra;
        int iCount;
        int iI;

        iEra = 0;
        iCount = 0;

        for (iI = 0; iI < MAX_PLAYERS; iI++)
        {
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
                {
                        iEra += GET_PLAYER((PlayerTypes)iI).getCurrentEra();
                        iCount++;
                }
        }

        if (iCount > 0)
        {
                return ((EraTypes)(iEra / iCount));
        }

        return NO_ERA;
}


TeamTypes CvGame::getActiveTeam() const
{
        if (getActivePlayer() == NO_PLAYER)
        {
                return NO_TEAM;
        }
        else
        {
                return (TeamTypes)GET_PLAYER(getActivePlayer()).getTeam();
        }
}


CivilizationTypes CvGame::getActiveCivilizationType() const
{
        if (getActivePlayer() == NO_PLAYER)
        {
                return NO_CIVILIZATION;
        }
        else
        {
                return (CivilizationTypes)GET_PLAYER(getActivePlayer()).getCivilizationType();
        }
}


bool CvGame::isNetworkMultiPlayer() const                                                                                                                                        
{
        return GC.getInitCore().getMultiplayer();
}


bool CvGame::isGameMultiPlayer() const                                                                                                                           
{
        return (isNetworkMultiPlayer() || isPbem() || isHotSeat());
}


bool CvGame::isTeamGame() const                                                                                                                                          
{
        FAssert(countCivPlayersAlive() >= countCivTeamsAlive());
        return (countCivPlayersAlive() > countCivTeamsAlive());
}


bool CvGame::isModem()
{
        return gDLL->IsModem();
}
void CvGame::setModem(bool bModem)
{
        if (bModem)
        {
                gDLL->ChangeINIKeyValue("CONFIG", "Bandwidth", "modem");
        }
        else
        {
                gDLL->ChangeINIKeyValue("CONFIG", "Bandwidth", "broadband");
        }

        gDLL->SetModem(bModem);
}
/************************************************************************************************/
/* REVOLUTION_MOD                                                                 lemmy101      */
/*                                                                                jdog5000      */
/*                                                                                              */
/************************************************************************************************/
void CvGame::reviveActivePlayer()
{
        if (!(GET_PLAYER(getActivePlayer()).isAlive()))
        {
                if(isForcedAIAutoPlay(getActivePlayer()))
                {
                        setForcedAIAutoPlay(getActivePlayer(), 0);
                } else
                {
                        setAIAutoPlay(getActivePlayer(), 0);
                }

                GC.getInitCore().setSlotStatus(getActivePlayer(), SS_TAKEN);
               
                // Let Python handle it
                {
                        PYTHON_ACCESS_LOCK_SCOPE

                        long lResult=0;
                        CyArgsList argsList;
                        argsList.add(getActivePlayer());

                        PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "doReviveActivePlayer", argsList.makeFunctionArgs(), &lResult);
                        if (lResult == 1)
                        {
                                return;
                        }
                }

                GET_PLAYER(getActivePlayer()).initUnit(((UnitTypes)0), 0, 0, NO_UNITAI, NO_DIRECTION, 0);
        }
}

void CvGame::reviveActivePlayer(PlayerTypes iPlayer)
{
        if (!(GET_PLAYER(iPlayer).isAlive()))
        {
                if(isForcedAIAutoPlay(iPlayer))
                {
                        setForcedAIAutoPlay(iPlayer, 0);
                } else
                {
                        setAIAutoPlay(iPlayer, 0);
                }

                GC.getInitCore().setSlotStatus(iPlayer, SS_TAKEN);
               
                // Let Python handle it
                {
                        PYTHON_ACCESS_LOCK_SCOPE

                        long lResult=0;
                        CyArgsList argsList;
                        argsList.add(iPlayer);

                        PYTHON_CALL_FUNCTION4(__FUNCTION__, PYGameModule, "doReviveActivePlayer", argsList.makeFunctionArgs(), &lResult);
                        if (lResult == 1)
                        {
                                return;
                        }
                }

                GET_PLAYER(iPlayer).initUnit(((UnitTypes)0), 0, 0, NO_UNITAI, NO_DIRECTION, 0);
        }
}
/************************************************************************************************/
/* REVOLUTION_MOD                          END                                                  */
/************************************************************************************************/


int CvGame::getNumHumanPlayers()
{
        return GC.getInitCore().getNumHumans();
}

int CvGame::getGameTurn()
{
        return GC.getInitCore().getGameTurn();
}


void CvGame::setGameTurn(int iNewValue)
{
        if (getGameTurn() != iNewValue)
        {
                GC.getInitCore().setGameTurn(iNewValue);
                FAssert(getGameTurn() >= 0);

                if (m_iDateTurn == iNewValue - 1)
                {
                        m_currentDate.increment();
                }
                else
                {
                        m_currentDate = CvDate::getDate(iNewValue);
                }
                m_iDateTurn = iNewValue;

                updateBuildingCommerce();

                setScoreDirty(true);

                gDLL->getInterfaceIFace()->setDirty(TurnTimer_DIRTY_BIT, true);
                gDLL->getInterfaceIFace()->setDirty(GameData_DIRTY_BIT, true);
        }
}


void CvGame::incrementGameTurn()
{
        setGameTurn(getGameTurn() + 1);
}


int CvGame::getTurnYear(int iGameTurn)
{
        // moved the body of this method to Game Core Utils so we have access for other games than the current one (replay screen in HOF)
        return getTurnYearForGame(iGameTurn, getStartYear(), getCalendar(), getGameSpeedType());
}


int CvGame::getGameTurnYear()
{
        return getTurnYear(getGameTurn());
}

CvDate CvGame::getCurrentDate()
{
        if (m_iDateTurn != getGameTurn())
        {
                m_currentDate = CvDate::getDate(getGameTurn());
                m_iDateTurn = getGameTurn();
        }
        return m_currentDate;
}


int CvGame::getElapsedGameTurns() const
{
        return m_iElapsedGameTurns;
}


void CvGame::incrementElapsedGameTurns()
{
        m_iElapsedGameTurns++;
}


int CvGame::getMaxTurns() const
{
        return GC.getInitCore().getMaxTurns();
}


void CvGame::setMaxTurns(int iNewValue)
{
        GC.getInitCore().setMaxTurns(iNewValue);
        FAssert(getMaxTurns() >= 0);
}


void CvGame::changeMaxTurns(int iChange)
{
        setMaxTurns(getMaxTurns() + iChange);
}


int CvGame::getMaxCityElimination() const
{
        return GC.getInitCore().getMaxCityElimination();
}


void CvGame::setMaxCityElimination(int iNewValue)
{
        GC.getInitCore().setMaxCityElimination(iNewValue);
        FAssert(getMaxCityElimination() >= 0);
}

int CvGame::getNumAdvancedStartPoints() const
{
        return GC.getInitCore().getNumAdvancedStartPoints();
}


void CvGame::setNumAdvancedStartPoints(int iNewValue)
{
        GC.getInitCore().setNumAdvancedStartPoints(iNewValue);
        FAssert(getNumAdvancedStartPoints(