Subversion Repositories RAND

Rev

Rev 1036 | Rev 1045 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
780 afforess 1
// game.cpp
2
 
3
 
4
#include "CvGameCoreDLL.h"
5
#include "CvGameCoreUtils.h"
6
#include "CvGame.h"
7
#include "CvGameAI.h"
8
#include "CvMap.h"
9
#include "CvViewport.h"
10
#include "CvPlot.h"
11
#include "CvPlayerAI.h"
12
#include "CvRandom.h"
13
#include "CvTeamAI.h"
14
#include "CvGlobals.h"
15
#include "CvInitCore.h"
16
#include "CvMapGenerator.h"
17
#include "CvArtFileMgr.h"
18
#include "CvDiploParameters.h"
19
#include "CvReplayMessage.h"
20
#include "CyArgsList.h"
21
#include "CvInfos.h"
22
#include "CvPopupInfo.h"
23
#include "FProfiler.h"
24
#include "CvReplayInfo.h"
25
#include "CvGameTextMgr.h"
26
#include "CvBugOptions.h"
27
#include <set>
28
#include "CvEventReporter.h"
29
#include "CvMessageControl.h"
30
#include "CvTaggedSaveFormatWrapper.h"
799 afforess 31
#include "FDataStreamBuffer.h"
780 afforess 32
 
33
#define BOOST_THREAD_NO_LIB
34
#define BOOST_THREAD_USE_LIB
35
#include <boost/thread/thread.hpp>
36
#include <boost/bind.hpp>
37
 
38
// interface uses
39
#include "CvDLLInterfaceIFaceBase.h"
40
#include "CvDLLEngineIFaceBase.h"
41
#include "CvDLLPythonIFaceBase.h"
42
 
43
/************************************************************************************************/
44
/* BETTER_BTS_AI_MOD                      10/02/09                                jdog5000      */
45
/*                                                                                              */
46
/* AI logging                                                                                   */
47
/************************************************************************************************/
48
#include "BetterBTSAI.h"
816 afforess 49
#include "CvMessageData.h"
50
 
780 afforess 51
/************************************************************************************************/
52
/* BETTER_BTS_AI_MOD                       END                                                  */
53
/************************************************************************************************/
54
// BUG - start
55
// RevolutionDCM - BugMod included in CvGlobals.h
56
//#include "BugMod.h"
57
// BUG - end
58
 
59
//      Koshling - save game compataibility between (most) builds
60
//      UI flag values in game serialization.  These are bitwise combinable
61
#define GAME_SAVE_UI_FLAG_VALUE_AND_BASE                0x00000001
62
 
63
// Public Functions...
64
 
65
#pragma warning( disable : 4355 )
66
CvGame::CvGame() : m_GameObject(),
67
m_Properties(this)
68
, m_iLastLookatX(-1)
69
, m_iLastLookatY(-1)
70
, m_bWasGraphicsPagingEnabled(false)
71
, m_eCurrentMap(INITIAL_MAP)
72
 
73
{
74
        InitializeCriticalSectionAndSpinCount(&m_reportableEventsSection, 5000);
75
 
76
        m_aiRankPlayer = new int[MAX_PLAYERS];        // Ordered by rank...
77
        m_aiPlayerRank = new int[MAX_PLAYERS];        // Ordered by player ID...
78
        m_aiPlayerScore = new int[MAX_PLAYERS];       // Ordered by player ID...
79
        m_aiRankTeam = new int[MAX_TEAMS];                                              // Ordered by rank...
80
        m_aiTeamRank = new int[MAX_TEAMS];                                              // Ordered by team ID...
81
        m_aiTeamScore = new int[MAX_TEAMS];                                             // Ordered by team ID...
82
 
83
        m_paiUnitCreatedCount = NULL;
84
        m_paiUnitClassCreatedCount = NULL;
85
        m_paiBuildingClassCreatedCount = NULL;
86
        m_paiProjectCreatedCount = NULL;
87
        m_paiForceCivicCount = NULL;
88
        m_paiVoteOutcome = NULL;
89
        m_paiReligionGameTurnFounded = NULL;
90
        m_paiCorporationGameTurnFounded = NULL;
91
        m_aiSecretaryGeneralTimer = NULL;
92
        m_aiVoteTimer = NULL;
93
        m_aiDiploVote = NULL;
94
 
95
        m_pabSpecialUnitValid = NULL;
96
        m_pabSpecialBuildingValid = NULL;
97
        m_abReligionSlotTaken = NULL;
98
/************************************************************************************************/
99
/* RevDCM                         Start          4/29/10                                                */
100
/*                                                                                              */
101
/* OC_LIMITED_RELIGIONS                                                                         */
102
/************************************************************************************************/
103
        m_abTechCanFoundReligion = NULL;
104
/************************************************************************************************/
105
/* LIMITED_RELIGIONS               END                                                          */
106
/************************************************************************************************/
107
 
108
        m_paHolyCity = NULL;
109
        m_paHeadquarters = NULL;
110
/************************************************************************************************/
111
/* Afforess                                     12/7/09                                         */
112
/*                                                                                              */
113
/*                                                                                              */
114
/************************************************************************************************/
115
        for (int iI = 0; iI < MAX_TEAMS; iI++)
116
        {
117
          starshipLaunched[iI] = false;
118
          diplomaticVictoryAchieved[iI] = false;               
119
          AscensionGateBuilt[iI] = false; // code added for Ascension Gate & Mastery Victory (by 45°)
120
        }
121
 
122
        m_abPreviousRequest = new bool[MAX_PLAYERS];
123
        m_aiModderGameOption = new int[NUM_MODDERGAMEOPTION_TYPES];
124
        m_aiFlexibleDifficultyTimer = new int[MAX_PLAYERS];
816 afforess 125
        m_resyncPackets.clear();
126
        m_resyncReceiveBuffer.clear();
889 afforess 127
        m_pDarkAgeState = NULL;
780 afforess 128
/************************************************************************************************/
129
/* Afforess                              END                                                        */
130
/************************************************************************************************/     
131
 
132
        m_pReplayInfo = NULL;
133
 
134
        m_aiShrineBuilding = NULL;
135
        m_aiShrineReligion = NULL;
136
 
137
        //m_bDeferVoteSourceProcessing = false;
138
        //m_paiDeferredVoteSources = NULL;
139
 
140
        m_bRecalculatingModifiers = false;
141
 
142
        reset(NO_HANDICAP, true);
143
}
144
 
145
 
146
CvGame::~CvGame()
147
{
148
        uninit();
149
 
150
        SAFE_DELETE_ARRAY(m_aiRankPlayer);
151
        SAFE_DELETE_ARRAY(m_aiPlayerRank);
152
        SAFE_DELETE_ARRAY(m_aiPlayerScore);
153
        SAFE_DELETE_ARRAY(m_aiRankTeam);
154
        SAFE_DELETE_ARRAY(m_aiTeamRank);
155
        SAFE_DELETE_ARRAY(m_aiTeamScore);
156
/************************************************************************************************/
157
/* Afforess                       Start          05/19/10                                               */
158
/*                                                                                              */
159
/*                                                                                              */
160
/************************************************************************************************/
161
        SAFE_DELETE_ARRAY(m_abPreviousRequest);
162
        SAFE_DELETE_ARRAY(m_aiModderGameOption);
163
        SAFE_DELETE_ARRAY(m_aiFlexibleDifficultyTimer);
889 afforess 164
        SAFE_DELETE(m_pDarkAgeState);
780 afforess 165
/************************************************************************************************/
166
/* Afforess                          END                                                            */
167
/************************************************************************************************/
168
 
169
        DeleteCriticalSection(&m_reportableEventsSection);
170
}
171
 
172
void CvGame::init(HandicapTypes eHandicap)
173
{
174
        bool bValid;
175
        int iStartTurn;
176
        int iEstimateEndTurn;
177
        int iI;
178
 
179
        //--------------------------------
180
        // Init saved data
181
        reset(eHandicap);
182
 
183
        //--------------------------------
184
        // Init containers
185
        m_deals.init();
186
        m_voteSelections.init();
187
        m_votesTriggered.init();
188
 
189
        m_mapRand.init(GC.getInitCore().getMapRandSeed() % 73637381);
794 afforess 190
        //Afforess: disable map rand logging
796 afforess 191
        //m_mapRand.m_bLoggingEnabled = false;
192
        //GC.getASyncRand().m_bLoggingEnabled = false;
780 afforess 193
        m_sorenRand.init(GC.getInitCore().getSyncRandSeed() % 52319761);
796 afforess 194
        //m_sorenRand.m_bLoggingEnabled = true;
780 afforess 195
 
196
        //--------------------------------
197
        // Init non-saved data
198
 
199
        //--------------------------------
200
        // Init other game data
201
 
202
        // Turn off all MP options if it's a single player game
203
        if (GC.getInitCore().getType() == GAME_SP_NEW ||
204
                GC.getInitCore().getType() == GAME_SP_SCENARIO)
205
        {
206
                for (iI = 0; iI < NUM_MPOPTION_TYPES; ++iI)
207
                {
208
                        setMPOption((MultiplayerOptionTypes)iI, false);
209
                }
210
        }
211
 
212
        // If this is a hot seat game, simultaneous turns is always off
213
        if (isHotSeat() || isPbem())
214
        {
215
                setMPOption(MPOPTION_SIMULTANEOUS_TURNS, false);
216
        }
217
        // If we didn't set a time in the Pitboss, turn timer off
218
        if (isPitboss() && getPitbossTurnTime() == 0)
219
        {
220
                setMPOption(MPOPTION_TURN_TIMER, false);
221
        }
222
 
223
        if (isMPOption(MPOPTION_SHUFFLE_TEAMS))
224
        {
225
                int aiTeams[MAX_CIV_PLAYERS];
226
 
227
                int iNumPlayers = 0;
228
                for (int i = 0; i < MAX_CIV_PLAYERS; i++)
229
                {
230
                        if (GC.getInitCore().getSlotStatus((PlayerTypes)i) == SS_TAKEN)
231
                        {
232
                                aiTeams[iNumPlayers] = GC.getInitCore().getTeam((PlayerTypes)i);
233
                                ++iNumPlayers;
234
                        }
235
                }
236
 
237
                for (int i = 0; i < iNumPlayers; i++)
238
                {
239
                        int j = (getSorenRand().get(iNumPlayers - i, NULL) + i);
240
 
241
                        if (i != j)
242
                        {
243
                                int iTemp = aiTeams[i];
244
                                aiTeams[i] = aiTeams[j];
245
                                aiTeams[j] = iTemp;
246
                        }
247
                }
248
 
249
                iNumPlayers = 0;
250
                for (int i = 0; i < MAX_CIV_PLAYERS; i++)
251
                {
252
                        if (GC.getInitCore().getSlotStatus((PlayerTypes)i) == SS_TAKEN)
253
                        {
254
                                GC.getInitCore().setTeam((PlayerTypes)i, (TeamTypes)aiTeams[iNumPlayers]);
255
                                ++iNumPlayers;
256
                        }
257
                }
258
        }
259
 
260
        //TB GameOption compatability enforcement project
261
        for (iI = 0; iI < NUM_GAMEOPTION_TYPES; iI++)
262
        {
263
                GameOptionTypes eGameOption = ((GameOptionTypes)iI);
264
                if (isOption(eGameOption))
265
                {
266
                        if (GC.getGameOptionInfo(eGameOption).getNumEnforcesGameOptionOnTypes() > 0)
267
                        {
268
                                for (int iJ = 0; iJ < GC.getGameOptionInfo(eGameOption).getNumEnforcesGameOptionOnTypes(); iJ++)
269
                                {
270
                                        GameOptionTypes eGameOptionMustOn = ((GameOptionTypes)GC.getGameOptionInfo(eGameOption).isEnforcesGameOptionOnType(iJ).eGameOption);
271
                                        if (GC.getGameOptionInfo(eGameOption).isEnforcesGameOptionOnType(iJ).bBool && !isOption(eGameOptionMustOn))
272
                                        {
273
                                                setOption(eGameOptionMustOn, true);
274
                                        }
275
                                }
276
                        }
277
                        if (GC.getGameOptionInfo(eGameOption).getNumEnforcesGameOptionOffTypes() > 0)
278
                        {
279
                                for (int iJ = 0; iJ < GC.getGameOptionInfo(eGameOption).getNumEnforcesGameOptionOffTypes(); iJ++)
280
                                {
281
                                        GameOptionTypes eGameOptionMustOff = ((GameOptionTypes)GC.getGameOptionInfo(eGameOption).isEnforcesGameOptionOffType(iJ).eGameOption);
282
                                        if (GC.getGameOptionInfo(eGameOption).isEnforcesGameOptionOffType(iJ).bBool && isOption(eGameOptionMustOff))
283
                                        {
284
                                                setOption(eGameOptionMustOff, false);
285
                                        }
286
                                }
287
                        }
288
                }
289
        }
290
 
291
        if (isOption(GAMEOPTION_LOCK_MODS))
292
        {
293
                if (isGameMultiPlayer())
294
                {
295
                        setOption(GAMEOPTION_LOCK_MODS, false);
296
                }
297
                else
298
                {
299
                        static const int iPasswordSize = 8;
300
                        char szRandomPassword[iPasswordSize];
301
                        for (int i = 0; i < iPasswordSize-1; i++)
302
                        {
303
                                szRandomPassword[i] = getSorenRandNum(128, NULL);
304
                        }
305
                        szRandomPassword[iPasswordSize-1] = 0;
306
 
307
                        GC.getInitCore().setAdminPassword(szRandomPassword);
308
                }
309
        }
310
 
311
        if (getGameTurn() == 0)
312
        {
313
                iStartTurn = 0;
314
 
315
                for (iI = 0; iI < GC.getGameSpeedInfo(getGameSpeedType()).getNumTurnIncrements(); iI++)
316
                {
317
                        iStartTurn += GC.getGameSpeedInfo(getGameSpeedType()).getGameTurnInfo(iI).iNumGameTurnsPerIncrement;
318
                }
319
 
320
                iStartTurn *= GC.getEraInfo(getStartEra()).getStartPercent();
321
                iStartTurn /= 100;
322
 
323
                setGameTurn(iStartTurn);
324
        }
325
 
326
        setStartTurn(getGameTurn());
327
 
328
        if (getMaxTurns() == 0)
329
        {
330
                iEstimateEndTurn = 0;
331
 
332
                for (iI = 0; iI < GC.getGameSpeedInfo(getGameSpeedType()).getNumTurnIncrements(); iI++)
333
                {
334
                        iEstimateEndTurn += GC.getGameSpeedInfo(getGameSpeedType()).getGameTurnInfo(iI).iNumGameTurnsPerIncrement;
335
                }
336
 
337
                setEstimateEndTurn(iEstimateEndTurn);
338
/************************************************************************************************/
339
/* Afforess                                     12/7/09                                         */
340
/*                                                                                              */
341
/*                                                                                              */
342
/************************************************************************************************/
343
#if defined QC_MASTERY_VICTORY
344
//Sevo Begin--VCM
345
        // This looks like a reasonable place for me to place my own interrupts for the victory conditions
346
        // I need to ensure that the AI understands it has to go after everything, so ALL the victory options
347
        // need to be "enabled" so starships can be built, etc. etc.
348
        //Only exception is diplo victory, but whatever.
349
 
350
 
351
                if (getEstimateEndTurn() > getGameTurn())
352
                {
353
                        bValid = false;
354
 
355
                        for (iI = 0; iI < GC.getNumVictoryInfos(); iI++)
356
                        {
357
                                if (isVictoryValid((VictoryTypes)iI))
358
                                {
359
                                        if ((GC.getVictoryInfo((VictoryTypes)iI).isEndScore()) || (GC.getVictoryInfo((VictoryTypes)iI).isTotalVictory()))
360
                                        {
361
                                                bValid = true;
362
                                                break;
363
                                        }
364
                                }
365
                        }
366
 
367
                        if (bValid)
368
                        {
369
                                setMaxTurns(getEstimateEndTurn() - getGameTurn());
370
                        }
371
                }
372
        }
373
        else
374
        {
375
                setEstimateEndTurn(getGameTurn() + getMaxTurns());
376
        }
377
 
378
        // Okay, now we'll actually set up the other VC's to agree with the total victory
379
        // If Total Victory is enabled, TURN ON ALL OTHERS AS WELL
380
        // This allows starship construction, gets the AI thinking correctly, etc.
381
        // The TV condition overrides the others but requries they be "on"
382
        bValid = false;
383
        for (iI = 0; iI < GC.getNumVictoryInfos(); iI++)
384
        {
385
                if ((GC.getVictoryInfo((VictoryTypes)iI).isTotalVictory()) && (isVictoryValid((VictoryTypes)iI)))
386
                {
387
                        bValid = true;
388
                        break;
389
                }
390
        }
391
 
392
        if (bValid)
393
        {
394
                for (iI = 0; iI < GC.getNumVictoryInfos(); iI++)
395
                {
396
                        setVictoryValid((VictoryTypes)iI, true);
397
                }
398
        }
399
 
400
//Sevo End VCM
401
#else
402
  }
403
#endif
404
 
405
        m_plotGroupHashesInitialized = false;
406
 
407
        //resetOptionEdits();
408
        //setOptionEdits();
409
 
410
        //Ruthless AI means Aggressive AI is on too.
411
        if (isOption(GAMEOPTION_RUTHLESS_AI) && !isOption(GAMEOPTION_AGGRESSIVE_AI))
412
        {
413
                setOption(GAMEOPTION_AGGRESSIVE_AI, true);
414
        }
415
 
416
        if (!isOption(GAMEOPTION_GREAT_COMMANDERS))
417
        {
418
                for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
419
                {
420
                        if (GC.getUnitInfo((UnitTypes)iI).isGreatGeneral())
421
                        {
422
                                GC.getUnitInfo((UnitTypes)iI).setPowerValue(GC.getUnitInfo((UnitTypes)iI).getPowerValue() / 10);
423
                        }
424
                }
425
        }
426
 
427
        logMsg("Handicap Era Tech Research Cost Modifier: %d", GC.getHandicapInfo(eHandicap).getResearchPercent());
428
        logMsg("World Size Tech Research Cost Modifier: %d", GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getResearchPercent());
429
        logMsg("Game Speed Tech Research Cost Modifier: %d", GC.getGameSpeedInfo(getGameSpeedType()).getResearchPercent());
430
        logMsg("Starting Era Tech Research Cost Modifier: %d", GC.getEraInfo(GC.getGameINLINE().getStartEra()).getResearchPercent());
431
        logMsg("Global Defines Tech Research Cost Modifier: %d", GC.getTECH_COST_MODIFIER());
432
        for (iI = 0; iI < GC.getNumEraInfos(); iI++)
433
        {
434
                logMsg("Era [%S] Tech Research Cost Modifier: %d", GC.getEraInfo((EraTypes)iI).getDescription(), GC.getEraInfo((EraTypes)iI).getTechCostModifier());
435
        }
436
        logMsg(" -------------------------- ");
437
        for (int iEra = 0; iEra < GC.getNumEraInfos(); iEra++)
438
        {
439
                int iTotalBaseCost = 0;
440
                int iTotalFinalCost = 0;
441
                int iTechs = 0;
442
                for (iI = 0; iI < GC.getNumTechInfos(); iI++)
443
                {
444
                        if (GC.getTechInfo((TechTypes)iI).getEra() == iEra)
445
                        {
446
                                int iBaseCost = GC.getTechInfo((TechTypes)iI).getBaseResearchCost();
447
                                int iFinalCost = GC.getTechInfo((TechTypes)iI).getResearchCost();
448
 
449
                                iFinalCost *= GC.getHandicapInfo(eHandicap).getResearchPercent();
450
                                iFinalCost /= 100;
451
 
452
                                iFinalCost *= GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getResearchPercent();
453
                                iFinalCost /= 100;
454
 
455
                                iFinalCost *= GC.getGameSpeedInfo(getGameSpeedType()).getResearchPercent();
456
                                iFinalCost /= 100;
457
 
458
                                iFinalCost *= GC.getEraInfo(getStartEra()).getResearchPercent();
459
                                iFinalCost /= 100;
460
 
461
                                logMsg("\tTech [%S] Base Cost: %d, \t\t\t\tFinal Cost: %d", GC.getTechInfo((TechTypes)iI).getDescription(), iBaseCost, iFinalCost);
462
 
463
                                iTotalBaseCost += iBaseCost;
464
                                iTotalFinalCost += iFinalCost;
465
                                iTechs++;
466
                        }
467
                }
468
                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);
469
        }
470
 
471
        setFutureEras();
472
 
473
        if (isOption(GAMEOPTION_UNITED_NATIONS))
474
        {
475
                //Find the diplomatic victory
476
                BuildingTypes eUnitedNations = NO_BUILDING;
477
                for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
478
                {
479
                        if (GC.getBuildingInfo((BuildingTypes)iI).getVictoryPrereq() != NO_VICTORY)
480
                        {
481
                                if (GC.getBuildingInfo((BuildingTypes)iI).getVoteSourceType() != NO_VOTESOURCE)
482
                                {
483
                                        eUnitedNations = (BuildingTypes)iI;
484
                                        break;
485
                                }
486
                        }
487
                }
488
                if (eUnitedNations != NO_BUILDING)
489
                {
490
                        m_bDiploVictoryEnabled = isVictoryValid((VictoryTypes)GC.getBuildingInfo(eUnitedNations).getVictoryPrereq());
491
                        setVictoryValid((VictoryTypes)GC.getBuildingInfo(eUnitedNations).getVictoryPrereq(), true);
492
                }
493
        }
494
 
816 afforess 495
        m_resyncPackets.clear();
496
        m_resyncReceiveBuffer.clear();
497
        m_bOutOfSync = false;
780 afforess 498
/************************************************************************************************/
499
/* Afforess                              END                                                        */
500
/************************************************************************************************/     
501
        setStartYear(GC.getDefineINT("START_YEAR"));
502
        m_iDateTurn = -500;
503
 
504
        for (iI = 0; iI < GC.getNumSpecialUnitInfos(); iI++)
505
        {
506
                if (GC.getSpecialUnitInfo((SpecialUnitTypes)iI).isValid())
507
                {
508
                        makeSpecialUnitValid((SpecialUnitTypes)iI);
509
                }
510
        }
511
 
512
        for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); iI++)
513
        {
514
                if (GC.getSpecialBuildingInfo((SpecialBuildingTypes)iI).isValid())
515
                {
516
                        makeSpecialBuildingValid((SpecialBuildingTypes)iI);
517
                }
518
        }
519
 
520
        AI_init();
521
 
522
        doUpdateCacheOnTurn();
523
}
524
 
525
//
526
// Set initial items (units, techs, etc...)
527
//
528
void CvGame::setInitialItems()
529
{
530
        PROFILE_FUNC();
531
 
532
        initFreeState();
533
        assignStartingPlots();
534
/************************************************************************************************/
535
/* Afforess                       Start          03/30/10                                               */
536
/*                                                                                              */
537
/*                                                                                              */
538
/************************************************************************************************/
539
#define PYCultureLinkModule             "CvCultureLinkInterface"
540
        if (isOption(GAMEOPTION_CULTURALLY_LINKED_STARTS))
541
        {
542
                PYTHON_CALL_FUNCTION2(__FUNCTION__, PYCultureLinkModule, "assignCulturallyLinkedStarts");
543
        }
544
/************************************************************************************************/
545
/* Afforess                          END                                                            */
546
/************************************************************************************************/     
547
        normalizeStartingPlots();
548
 
549
// RevolutionDCM - BarbarianWorld - thanks Kael
550
        // RevDCM TODO: What's right here?
551
    if (isOption(GAMEOPTION_BARBARIAN_WORLD))
552
    {
553
        for (int iI = 0; iI < MAX_PLAYERS; iI++)
554
        {
555
            if (GET_PLAYER((PlayerTypes)iI).isAlive() && iI != BARBARIAN_PLAYER)
556
            {
557
                foundBarbarianCity();
558
            }
559
        }
560
    }
561
// RevolutionDCM End
562
 
563
        initFreeUnits();
564
 
565
        for (int i = 0; i < MAX_PLAYERS; ++i)
566
        {
567
                CvPlayer& kPlayer = GET_PLAYER((PlayerTypes)i);
568
                if (kPlayer.isAlive())
569
                {
570
                        kPlayer.AI_updateFoundValues(true);
571
                }
572
        }
573
/************************************************************************************************/
574
/* Afforess                       Start          03/18/10                                               */
575
/*                                                                                              */
576
/*                                                                                              */
577
/************************************************************************************************/
578
        if (isOption(GAMEOPTION_PERSONALIZED_MAP))
579
        {
580
                clearLandmarks();
581
                findMountainRanges();
582
                findLonePeaks();
583
                findBays();
584
                findForests();
585
                findJungles();
586
                findDeserts();
587
                findLakes();
588
                pruneLandmarks();
589
                addLandmarkSigns();
590
                updateInitialSigns();
591
        }
787 afforess 592
 
593
        logMsg("Handicap Era Tech Research Cost Modifier: %d", GC.getHandicapInfo(m_eHandicap).getResearchPercent());
594
        logMsg("World Size Tech Research Cost Modifier: %d", GC.getWorldInfo(GC.getMapINLINE().getWorldSize()).getResearchPercent());
595
        logMsg("Game Speed Tech Research Cost Modifier: %d", GC.getGameSpeedInfo(getGameSpeedType()).getResearchPercent());
596
        logMsg("Starting Era Tech Research Cost Modifier: %d", GC.getEraInfo(GC.getGameINLINE().getStartEra()).getResearchPercent());
597
        logMsg("Global Defines Tech Research Cost Modifier: %d", GC.getTECH_COST_MODIFIER());
598
        for (int iI = 0; iI < GC.getNumEraInfos(); iI++)
780 afforess 599
        {
787 afforess 600
                logMsg("Era [%S] Tech Research Cost Modifier: %d", GC.getEraInfo((EraTypes)iI).getDescription(), GC.getEraInfo((EraTypes)iI).getTechCostModifier());
601
        }
602
 
818 afforess 603
        checkInitialResourceAllocations();
604
 
780 afforess 605
/************************************************************************************************/
606
/* Afforess                          END                                                            */
607
/************************************************************************************************/
608
}
609
 
610
 
611
// BUG - MapFinder - start
612
// from HOF Mod - Dianthus
613
bool CvGame::canRegenerateMap() const
614
{
615
        if (GC.getGameINLINE().getElapsedGameTurns() != 0) return false;
616
        if (GC.getGameINLINE().isGameMultiPlayer()) return false;
617
        if (GC.getInitCore().getWBMapScript()) return false;
618
 
619
        // EF: TODO clear contact at start of regenerateMap()?
620
        for (int iI = 1; iI < MAX_CIV_TEAMS; iI++)
621
        {
622
                CvTeam& team=GET_TEAM((TeamTypes)iI);
623
                for (int iJ = 0; iJ < iI; iJ++)
624
                {
625
                        if (team.isHasMet((TeamTypes)iJ)) return false;
626
                }
627
        }
628
        return true;
629
}
630
// BUG - MapFinder - end
631
 
632
void CvGame::regenerateMap()
633
{
634
        int iI;
635
 
636
        if (GC.getInitCore().getWBMapScript())
637
        {
638
                return;
639
        }
640
 
641
        setFinalInitialized(false);
642
 
643
        for (iI = 0; iI < MAX_PLAYERS; iI++)
644
        {
645
                GET_PLAYER((PlayerTypes)iI).killUnits();
646
        }
647
 
648
        for (iI = 0; iI < MAX_PLAYERS; iI++)
649
        {
650
                GET_PLAYER((PlayerTypes)iI).killCities();
651
        }
652
 
653
        for (iI = 0; iI < MAX_PLAYERS; iI++)
654
        {
655
                GET_PLAYER((PlayerTypes)iI).killAllDeals();
656
        }
657
 
658
        for (iI = 0; iI < MAX_PLAYERS; iI++)
659
        {
660
                GET_PLAYER((PlayerTypes)iI).setFoundedFirstCity(false);
661
                GET_PLAYER((PlayerTypes)iI).setStartingPlot(NULL, false);
662
        }
663
 
664
        for (iI = 0; iI < MAX_TEAMS; iI++)
665
        {
666
                GC.getMapINLINE().setRevealedPlots(((TeamTypes)iI), false);
667
        }
668
 
669
        gDLL->getEngineIFace()->clearSigns();
670
 
671
        GC.getMapINLINE().erasePlots();
672
 
673
        CvMapGenerator::GetInstance().generateRandomMap();
674
        CvMapGenerator::GetInstance().addGameElements();
675
 
676
        gDLL->getEngineIFace()->RebuildAllPlots();
677
 
678
        CvEventReporter::getInstance().resetStatistics();
679
 
680
        setInitialItems();
681
 
682
        initScoreCalculation();
683
        setFinalInitialized(true);
684
 
685
        GC.getMapINLINE().setupGraphical();
686
        gDLL->getEngineIFace()->SetDirty(GlobeTexture_DIRTY_BIT, true);
687
        gDLL->getEngineIFace()->SetDirty(MinimapTexture_DIRTY_BIT, true);
688
        gDLL->getInterfaceIFace()->setDirty(ColoredPlots_DIRTY_BIT, true);
689
 
690
        gDLL->getInterfaceIFace()->setCycleSelectionCounter(1);
691
/*************************************************************************************************/
692
/**     ADDON (regenerate Map) Sephi                                                                                    **/
693
/*************************************************************************************************/
694
    CvEventReporter::getInstance().gameStart();
695
/*************************************************************************************************/
696
/**     END                                                                                                                                             **/
697
/*************************************************************************************************/
698
        gDLL->getEngineIFace()->AutoSave(true);
699
 
700
// BUG - AutoSave - start
701
        PYTHON_CALL_FUNCTION2(__FUNCTION__, PYBugModule, "gameStartSave");
702
// BUG - AutoSave - end
703
 
704
        // EF - This doesn't work until after the game has had time to update.
705
        //      Centering on the starting location is now done by MapFinder using BugUtil.delayCall().
706
        //      Must leave this here for non-BUG
707
        if (NO_PLAYER != getActivePlayer())
708
        {
709
                CvPlot* pPlot = GET_PLAYER(getActivePlayer()).getStartingPlot();
710
 
711
                if (NULL != pPlot)
712
                {
713
                        gDLL->getInterfaceIFace()->lookAt(pPlot->getPoint(), CAMERALOOKAT_NORMAL);
714
                }
715
        }
716
}
717
 
718
void CvGame::uninit()
719
{
720
        SAFE_DELETE_ARRAY(m_aiShrineBuilding);
721
        SAFE_DELETE_ARRAY(m_aiShrineReligion);
722
        SAFE_DELETE_ARRAY(m_paiUnitCreatedCount);
723
        SAFE_DELETE_ARRAY(m_paiUnitClassCreatedCount);
724
        SAFE_DELETE_ARRAY(m_paiBuildingClassCreatedCount);
725
        SAFE_DELETE_ARRAY(m_paiProjectCreatedCount);
726
        SAFE_DELETE_ARRAY(m_paiForceCivicCount);
727
        SAFE_DELETE_ARRAY(m_paiVoteOutcome);
728
        SAFE_DELETE_ARRAY(m_paiReligionGameTurnFounded);
729
        SAFE_DELETE_ARRAY(m_paiCorporationGameTurnFounded);
730
        SAFE_DELETE_ARRAY(m_aiSecretaryGeneralTimer);
731
        SAFE_DELETE_ARRAY(m_aiVoteTimer);
732
        SAFE_DELETE_ARRAY(m_aiDiploVote);
733
 
734
        SAFE_DELETE_ARRAY(m_pabSpecialUnitValid);
735
        SAFE_DELETE_ARRAY(m_pabSpecialBuildingValid);
736
        SAFE_DELETE_ARRAY(m_abReligionSlotTaken);
737
/************************************************************************************************/
738
/* RevDCM                         Start          4/29/10                                                */
739
/*                                                                                              */
740
/* OC_LIMITED_RELIGIONS                                                                         */
741
/************************************************************************************************/
742
        SAFE_DELETE_ARRAY(m_abTechCanFoundReligion);
743
/************************************************************************************************/
744
/* LIMITED_RELIGIONS               END                                                          */
745
/************************************************************************************************/
746
 
747
        SAFE_DELETE_ARRAY(m_paHolyCity);
748
        SAFE_DELETE_ARRAY(m_paHeadquarters);
749
 
750
        m_aszDestroyedCities.clear();
751
        m_aszGreatPeopleBorn.clear();
816 afforess 752
        m_resyncPackets.clear();
780 afforess 753
 
754
        m_deals.uninit();
755
        m_voteSelections.uninit();
756
        m_votesTriggered.uninit();
757
 
758
        m_mapRand.uninit();
759
        m_sorenRand.uninit();
760
 
761
        clearReplayMessageMap();
762
        SAFE_DELETE(m_pReplayInfo);
763
 
764
        m_aPlotExtraYields.clear();
765
        m_aPlotExtraCosts.clear();
766
        m_mapVoteSourceReligions.clear();
767
        m_aeInactiveTriggers.clear();
768
 
769
#ifdef CAN_BUILD_VALUE_CACHING
770
        CvPlot::ClearCanBuildCache();
771
#endif
772
        resetOptionEdits();
801 afforess 773
        if (CvPlayerAI::areStaticsInitialized())
780 afforess 774
        {
775
                for (int i = 0; i < GC.getNumMapInfos(); i++)
776
                {
777
                        if ( GC.mapInitialized((MapTypes)i) )
778
                        {
779
                                // Cast to the internal class
780
                                CvMap&  map = GC.getMapByIndex((MapTypes)i);
781
 
782
                                CvMapInitData defaultMapData;
783
 
784
                                map.reset(&defaultMapData);
785
                        }
786
                }
787
 
788
                for(int i = 0; i < MAX_PLAYERS; i++)
789
                {
790
                        GET_PLAYER((PlayerTypes)i).uninit();
791
                }
792
        }
793
        m_allocator.clearAll();
794
}
795
 
796
 
797
// FUNCTION: reset()
798
// Initializes data members that are serialized.
799
void CvGame::reset(HandicapTypes eHandicap, bool bConstructorCall)
800
{
801
        int iI;
802
 
803
        //--------------------------------
804
        // Uninit class
805
        uninit();
806
 
807
        m_iElapsedGameTurns = 0;
808
        m_iStartTurn = 0;
1038 n4538-e134 809
        m_iStartYear = GC.getDefineINT("START_YEAR");
780 afforess 810
        m_iEstimateEndTurn = 0;
811
        m_iDateTurn = -500;
812
        m_iTurnSlice = 0;
813
        m_iCutoffSlice = 0;
814
        m_iNumGameTurnActive = 0;
815
        m_iNumCities = 0;
816
        m_iTotalPopulation = 0;
817
        m_iTradeRoutes = 0;
818
        m_iFreeTradeCount = 0;
819
        m_iNoNukesCount = 0;
820
        m_iNukesExploded = 0;
821
        m_iMaxPopulation = 0;
822
        m_iMaxLand = 0;
823
        m_iMaxTech = 0;
824
        m_iMaxWonders = 0;
825
        m_iInitPopulation = 0;
826
        m_iInitLand = 0;
827
        m_iInitTech = 0;
828
        m_iInitWonders = 0;
829
/************************************************************************************************/
830
/* Afforess                                     12/7/09                                         */
831
/*                                                                                              */
832
/*                                                                                              */
833
/************************************************************************************************/
834
        m_iCurrentVoteID = 0;
835
        m_iWaterAnimalSpawnChance = 0;
836
        m_iXResolution = 1024;
837
        m_iYResolution = 720;
838
        m_iMercyRuleCounter = 0;
839
        m_iCutLosersCounter = 0;
840
        m_iHighToLowCounter = 0;
841
        m_iIncreasingDifficultyCounter = 0;
842
        m_iRiverBuildings = 0;
843
        m_iNumWonders = 0;
844
        m_bDiploVictoryEnabled = false;
796 afforess 845
        m_bAnyoneHasUnitZoneOfControl = false;
817 afforess 846
        m_iLastResyncTurnSlice = 0; //field is intentionally not saved
847
        m_iActiveTurnSlice = 0; //field is intentionally not saved
904 afforess 848
        m_iDarkAgeCount = 0;
780 afforess 849
        calculateRiverBuildings();
850
        calculateCoastalBuildings();
851
        calculateNumWonders();
852
        m_iLastNukeStrikeX = INVALID_PLOT_COORD;
853
        m_iLastNukeStrikeY = INVALID_PLOT_COORD;
854
#if defined QC_MASTERY_VICTORY
855
        for (int loopI = 0; loopI < MAX_TEAMS; loopI++)
856
        {
857
          starshipLaunched[loopI] = false;
858
          diplomaticVictoryAchieved[loopI] = false;            
859
          AscensionGateBuilt[loopI] = false; // code added for Ascension Gate & Mastery Victory (by 45°)
860
        }      
861
#endif
862
/************************************************************************************************/
863
/* Afforess                              END                                                        */
864
/************************************************************************************************/     
865
 
866
        m_uiInitialTime = 0;
867
 
868
        m_bScoreDirty = false;
869
        m_circumnavigatingTeam = NO_TEAM;
870
        m_bDebugMode = false;
871
        m_bDebugModeCache = false;
872
        m_bFinalInitialized = false;
873
        m_bPbemTurnSent = false;
874
        m_bHotPbemBetweenTurns = false;
875
        m_bPlayerOptionsSent = false;
876
        //TB Nukefix
877
        //m_bNukesValid = false;
878
 
879
        m_eHandicap = eHandicap;
880
        m_ePausePlayer = NO_PLAYER;
881
        m_eBestLandUnit = NO_UNIT;
882
        m_eWinner = NO_TEAM;
883
        m_eVictory = NO_VICTORY;
884
        m_eGameState = GAMESTATE_ON;
885
 
886
        m_szScriptData = "";
887
 
888
        for (iI = 0; iI < MAX_PLAYERS; iI++)
889
        {
890
                m_aiRankPlayer[iI] = 0;
891
                m_aiPlayerRank[iI] = 0;
892
                m_aiPlayerScore[iI] = 0;
893
/************************************************************************************************/
894
/* REVOLUTION_MOD                                                                lemmy101       */
895
/*                                                                               jdog5000       */
896
/*                                                                                              */
897
/************************************************************************************************/
898
                m_iAIAutoPlay[iI] = 0;
899
                m_iForcedAIAutoPlay[iI] = 0;
900
/************************************************************************************************/
901
/* REVOLUTION_MOD                          END                                                  */
902
/************************************************************************************************/
903
        }
904
 
905
        for (iI = 0; iI < MAX_TEAMS; iI++)
906
        {
907
                m_aiRankTeam[iI] = 0;
908
                m_aiTeamRank[iI] = 0;
909
                m_aiTeamScore[iI] = 0;
910
        }
911
/************************************************************************************************/
912
/* Afforess                       Start          06/07/10                                               */
913
/*                                                                                              */
914
/*                                                                                              */
915
/************************************************************************************************/
916
        for (iI = 0; iI < NUM_MODDERGAMEOPTION_TYPES; iI++)
917
        {
918
                m_aiModderGameOption[iI] = 0;
919
        }
920
        for (iI = 0; iI < MAX_PLAYERS; iI++)
921
        {
922
                m_abPreviousRequest[iI] = false;
923
                m_aiFlexibleDifficultyTimer[iI] = 0;
924
        }
925
/************************************************************************************************/
926
/* Afforess                          END                                                            */
927
/************************************************************************************************/
928
        if (!bConstructorCall)
929
        {
930
                FAssertMsg(m_paiUnitCreatedCount==NULL, "about to leak memory, CvGame::m_paiUnitCreatedCount");
931
                m_paiUnitCreatedCount = new int[GC.getNumUnitInfos()];
932
                for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
933
                {
934
                        m_paiUnitCreatedCount[iI] = 0;
935
                }
936
                FAssertMsg(m_paiUnitClassCreatedCount==NULL, "about to leak memory, CvGame::m_paiUnitClassCreatedCount");
937
                m_paiUnitClassCreatedCount = new int[GC.getNumUnitClassInfos()];
938
                for (iI = 0; iI < GC.getNumUnitClassInfos(); iI++)
939
                {
940
                        m_paiUnitClassCreatedCount[iI] = 0;
941
                }
942
                FAssertMsg(m_paiBuildingClassCreatedCount==NULL, "about to leak memory, CvGame::m_paiBuildingClassCreatedCount");
943
                m_paiBuildingClassCreatedCount = new int[GC.getNumBuildingClassInfos()];
944
                for (iI = 0; iI < GC.getNumBuildingClassInfos(); iI++)
945
                {
946
                        m_paiBuildingClassCreatedCount[iI] = 0;
947
                }
948
 
949
                FAssertMsg(m_paiProjectCreatedCount==NULL, "about to leak memory, CvGame::m_paiProjectCreatedCount");
950
                m_paiProjectCreatedCount = new int[GC.getNumProjectInfos()];
951
                for (iI = 0; iI < GC.getNumProjectInfos(); iI++)
952
                {
953
                        m_paiProjectCreatedCount[iI] = 0;
954
                }
955
 
956
                FAssertMsg(m_paiForceCivicCount==NULL, "about to leak memory, CvGame::m_paiForceCivicCount");
957
                m_paiForceCivicCount = new int[GC.getNumCivicInfos()];
958
                for (iI = 0; iI < GC.getNumCivicInfos(); iI++)
959
                {
960
                        m_paiForceCivicCount[iI] = 0;
961
                }
962
 
963
                FAssertMsg(0 < GC.getNumVoteInfos(), "GC.getNumVoteInfos() is not greater than zero in CvGame::reset");
964
                FAssertMsg(m_paiVoteOutcome==NULL, "about to leak memory, CvGame::m_paiVoteOutcome");
965
                m_paiVoteOutcome = new PlayerVoteTypes[GC.getNumVoteInfos()];
966
                for (iI = 0; iI < GC.getNumVoteInfos(); iI++)
967
                {
968
                        m_paiVoteOutcome[iI] = NO_PLAYER_VOTE;
969
                }
970
 
971
                FAssertMsg(0 < GC.getNumVoteSourceInfos(), "GC.getNumVoteSourceInfos() is not greater than zero in CvGame::reset");
972
                FAssertMsg(m_aiDiploVote==NULL, "about to leak memory, CvGame::m_aiDiploVote");
973
                m_aiDiploVote = new int[GC.getNumVoteSourceInfos()];
974
                for (iI = 0; iI < GC.getNumVoteSourceInfos(); iI++)
975
                {
976
                        m_aiDiploVote[iI] = 0;
977
                }
978
 
979
                FAssertMsg(m_pabSpecialUnitValid==NULL, "about to leak memory, CvGame::m_pabSpecialUnitValid");
980
                m_pabSpecialUnitValid = new bool[GC.getNumSpecialUnitInfos()];
981
                for (iI = 0; iI < GC.getNumSpecialUnitInfos(); iI++)
982
                {
983
                        m_pabSpecialUnitValid[iI] = false;
984
                }
985
 
986
                FAssertMsg(m_pabSpecialBuildingValid==NULL, "about to leak memory, CvGame::m_pabSpecialBuildingValid");
987
                m_pabSpecialBuildingValid = new bool[GC.getNumSpecialBuildingInfos()];
988
                for (iI = 0; iI < GC.getNumSpecialBuildingInfos(); iI++)
989
                {
990
                        m_pabSpecialBuildingValid[iI] = false;
991
                }
992
 
993
                FAssertMsg(m_paiReligionGameTurnFounded==NULL, "about to leak memory, CvGame::m_paiReligionGameTurnFounded");
994
                m_paiReligionGameTurnFounded = new int[GC.getNumReligionInfos()];
995
                FAssertMsg(m_abReligionSlotTaken==NULL, "about to leak memory, CvGame::m_abReligionSlotTaken");
996
                m_abReligionSlotTaken = new bool[GC.getNumReligionInfos()];
997
                FAssertMsg(m_paHolyCity==NULL, "about to leak memory, CvGame::m_paHolyCity");
998
                m_paHolyCity = new IDInfo[GC.getNumReligionInfos()];
999
                for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
1000
                {
1001
                        m_paiReligionGameTurnFounded[iI] = -1;
1002
                        m_paHolyCity[iI].reset();
1003
                        m_abReligionSlotTaken[iI] = false;
1004
                }
1005
/************************************************************************************************/
1006
/* RevDCM                         Start          4/29/10                                                */
1007
/*                                                                                              */
1008
/* OC_LIMITED_RELIGIONS                                                                         */
1009
/************************************************************************************************/
1010
                FAssertMsg(m_abTechCanFoundReligion==NULL, "about to leak memory, CvGame::m_abTechCanFoundReligion");
1011
                m_abTechCanFoundReligion = new bool[GC.getNumTechInfos()];
1012
                for (iI = 0; iI < GC.getNumTechInfos(); iI++)
1013
                {
1014
                        m_abTechCanFoundReligion[TechTypes(iI)] = false;
1015
                }
1016
                for (iI = 0; iI < GC.getNumReligionInfos(); iI++)
1017
                {
1018
                        TechTypes eIndex = TechTypes(GC.getReligionInfo((ReligionTypes)iI).getTechPrereq());
1019
                        m_abTechCanFoundReligion[eIndex] = true;
1020
                }
1021
/************************************************************************************************/
1022
/* LIMITED_RELIGIONS               END                                                          */
1023
/************************************************************************************************/
1024
 
1025
                FAssertMsg(m_paiCorporationGameTurnFounded==NULL, "about to leak memory, CvGame::m_paiCorporationGameTurnFounded");
1026
                m_paiCorporationGameTurnFounded = new int[GC.getNumCorporationInfos()];
1027
                m_paHeadquarters = new IDInfo[GC.getNumCorporationInfos()];
1028
                for (iI = 0; iI < GC.getNumCorporationInfos(); iI++)
1029
                {
1030
                        m_paiCorporationGameTurnFounded[iI] = -1;
1031
                        m_paHeadquarters[iI].reset();
1032
                }
1033
 
1034
                FAssertMsg(m_aiShrineBuilding==NULL, "about to leak memory, CvGame::m_aiShrineBuilding");
1035
                FAssertMsg(m_aiShrineReligion==NULL, "about to leak memory, CvGame::m_aiShrineReligion");
1036
                m_aiShrineBuilding = new int[GC.getNumBuildingInfos()];
1037
                m_aiShrineReligion = new int[GC.getNumBuildingInfos()];
1038
                for (iI = 0; iI < GC.getNumBuildingInfos(); iI++)
1039
                {
1040
                        m_aiShrineBuilding[iI] = (int) NO_BUILDING;
1041
                        m_aiShrineReligion[iI] = (int) NO_RELIGION;
1042
                }
1043
 
1044
                FAssertMsg(m_aiSecretaryGeneralTimer==NULL, "about to leak memory, CvGame::m_aiSecretaryGeneralTimer");
1045
                FAssertMsg(m_aiVoteTimer==NULL, "about to leak memory, CvGame::m_aiVoteTimer");
1046
                m_aiSecretaryGeneralTimer = new int[GC.getNumVoteSourceInfos()];
1047
                m_aiVoteTimer = new int[GC.getNumVoteSourceInfos()];
1048
                for (iI = 0; iI < GC.getNumVoteSourceInfos(); iI++)
1049
                {
1050
                        m_aiSecretaryGeneralTimer[iI] = 0;
1051
                        m_aiVoteTimer[iI] = 0;
1052
                }
1053
        }
1054
 
1055
        m_deals.removeAll();
1056
        m_voteSelections.removeAll();
1057
        m_votesTriggered.removeAll();
1058
 
1059
        m_mapRand.reset();
1060
        m_sorenRand.reset();
1061
 
1062
        m_iNumSessions = 1;
1063
 
1064
        m_iShrineBuildingCount = 0;
1065
        m_iNumCultureVictoryCities = 0;
1066
        m_eCultureVictoryCultureLevel = NO_CULTURELEVEL;
1067
 
1068
        if (!bConstructorCall)
1069
        {
1070
                AI_reset();
1071
        }
1072
/************************************************************************************************/
1073
/* Afforess/RevDCM                                     12/7/09                                  */
1074
/*                                                                                              */
1075
/* Advanced Automations                                                                         */
1076
/************************************************************************************************/
1077
                // Sanguo Mod Performance start, added by poyuzhe 07.27.09
1078
        UnitTypes eUnit;
1079
        std::vector<UnitTypes> aUpgradeUnits;
1080
 
1081
        for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
1082
        {
1083
                eUnit = (UnitTypes)iI;
1084
                aUpgradeUnits.clear();
1085
                do
1086
                {
1087
                        for (int iJ = 0; iJ < GC.getNumUnitClassInfos(); iJ++)
1088
                        {
838 n4538-e134 1089
                                if (eUnit != NO_UNIT)
780 afforess 1090
                                {
838 n4538-e134 1091
                                        if (GC.getUnitInfo(eUnit).getUpgradeUnitClass(iJ))
1092
                                        {
1093
                                                GC.getUnitInfo((UnitTypes)iI).addUpgradeUnitClassTypes(iJ);
1094
                                                aUpgradeUnits.push_back((UnitTypes)GC.getUnitClassInfo((UnitClassTypes)iJ).getDefaultUnitIndex());
1095
                                        }
780 afforess 1096
                                }
1097
                        }
1098
                        if (!aUpgradeUnits.empty())
1099
                        {
838 n4538-e134 1100
                                if (eUnit != NO_UNIT)
1101
                                {
1102
                                        eUnit = aUpgradeUnits.front();
1103
                                        aUpgradeUnits.erase(aUpgradeUnits.begin());
1104
                                }
780 afforess 1105
                        }
1106
                        else
1107
                        {
1108
                                break;
1109
                        }
1110
                }while(true);
1111
        }
1112
        // Sanguo Mod Performance, end
1113
/************************************************************************************************/
1114
/* Afforess                              END                                                        */
1115
/************************************************************************************************/     
1116
        m_Properties.clear();
1117
 
1118
        m_lastGraphicUpdateRequestTickCount = -1;
1119
 
1120
        m_plotGroupHashesInitialized = false;
1121
        m_bWasGraphicsPagingEnabled = false;
1122
        m_iLastLookatX = -1;
1123
        m_iLastLookatY = -1;
1124
}
1125
 
1126
 
1127
void CvGame::initDiplomacy()
1128
{
1129
        PROFILE_FUNC();
1130
 
1131
        int iI, iJ;
1132
 
1133
        for (iI = 0; iI < MAX_TEAMS; iI++)
1134
        {
1135
                GET_TEAM((TeamTypes)iI).meet(((TeamTypes)iI), false);
1136
 
1137
                if (GET_TEAM((TeamTypes)iI).isBarbarian() || GET_TEAM((TeamTypes)iI).isMinorCiv())
1138
                {
1139
                        for (iJ = 0; iJ < MAX_CIV_TEAMS; iJ++)
1140
                        {
1141
                                if (iI != iJ)
1142
                                {
1143
                                        GET_TEAM((TeamTypes)iI).declareWar(((TeamTypes)iJ), false, NO_WARPLAN);
1144
                                }
1145
                        }
1146
                }
1147
        }
1148
 
1149
        // Forced peace at the beginning of Advanced starts
1150
        if (isOption(GAMEOPTION_ADVANCED_START))
1151
        {
1152
                CLinkList<TradeData> player1List;
1153
                CLinkList<TradeData> player2List;
1154
                TradeData kTradeData;
1155
                setTradeItem(&kTradeData, TRADE_PEACE_TREATY);
1156
                player1List.insertAtEnd(kTradeData);
1157
                player2List.insertAtEnd(kTradeData);
1158
 
1159
                for (int iPlayer1 = 0; iPlayer1 < MAX_CIV_PLAYERS; ++iPlayer1)
1160
                {
1161
                        CvPlayer& kLoopPlayer1 = GET_PLAYER((PlayerTypes)iPlayer1);
1162
 
1163
                        if (kLoopPlayer1.isAlive())
1164
                        {
1165
                                for (int iPlayer2 = iPlayer1 + 1; iPlayer2 < MAX_CIV_PLAYERS; ++iPlayer2)
1166
                                {
1167
                                        CvPlayer& kLoopPlayer2 = GET_PLAYER((PlayerTypes)iPlayer2);
1168
 
1169
                                        if (kLoopPlayer2.isAlive())
1170
                                        {
1171
                                                if (GET_TEAM(kLoopPlayer1.getTeam()).canChangeWarPeace(kLoopPlayer2.getTeam()))
1172
                                                {
1173
                                                        implementDeal((PlayerTypes)iPlayer1, (PlayerTypes)iPlayer2, &player1List, &player2List);
1174
                                                }
1175
                                        }
1176
                                }
1177
                        }
1178
                }
1179
        }
1180
}
1181
 
1182
 
1183
void CvGame::initFreeState()
1184
{
1185
        bool bValid;
1186
        int iI, iJ, iK;
1187
 
1188
        for (iI = 0; iI < GC.getNumTechInfos(); iI++)
1189
        {
1190
                for (iJ = 0; iJ < MAX_TEAMS; iJ++)
1191
                {
1192
                        if (GET_TEAM((TeamTypes)iJ).isAlive())
1193
                        {
1194
                                bValid = false;
1195
 
1196
                                if (!bValid)
1197
                                {
1198
                                        if ((GC.getHandicapInfo(getHandicapType()).isFreeTechs(iI)) ||
1199
                                                  (!(GET_TEAM((TeamTypes)iJ).isHuman())&& GC.getHandicapInfo(getHandicapType()).isAIFreeTechs(iI)) ||
1200
                                                  (GC.getTechInfo((TechTypes)iI).getEra() < getStartEra()))
1201
                                        {
1202
                                                bValid = true;
1203
                                        }
1204
                                }
1205
 
1206
                                if (!bValid)
1207
                                {
1208
                                        for (iK = 0; iK < MAX_PLAYERS; iK++)
1209
                                        {
1210
                                                if (GET_PLAYER((PlayerTypes)iK).isAlive())
1211
                                                {
1212
                                                        if (GET_PLAYER((PlayerTypes)iK).getTeam() == iJ)
1213
                                                        {
1214
                                                                if (GC.getCivilizationInfo(GET_PLAYER((PlayerTypes)iK).getCivilizationType()).isCivilizationFreeTechs(iI))
1215
                                                                {
1216
                                                                        bValid = true;
1217
                                                                        break;
1218
                                                                }
1219
                                                        }
1220
                                                }
1221
                                        }
1222
                                }
1223
 
1224
                                GET_TEAM((TeamTypes)iJ).setHasTech(((TechTypes)iI), bValid, NO_PLAYER, false, false);
1225
                                if (bValid && GC.getTechInfo((TechTypes)iI).isMapVisible())
1226
                                {
1227
                                        GC.getMapINLINE().setRevealedPlots((TeamTypes)iJ, true, true);
1228
                                }
1229
                        }
1230
                }
1231
        }
1232
 
1233
        for (iI = 0; iI < MAX_PLAYERS; iI++)
1234
        {
1235
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1236
                {
1237
                        GET_PLAYER((PlayerTypes)iI).initFreeState();
1238
                }
1239
        }
1240
}
1241
 
1242
 
1243
void CvGame::initFreeUnits()
1244
{
1245
        int iI;
1246
 
1247
        for (iI = 0; iI < MAX_PLAYERS; iI++)
1248
        {
1249
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1250
                {
1251
                        if ((GET_PLAYER((PlayerTypes)iI).getNumUnits() == 0) && (GET_PLAYER((PlayerTypes)iI).getNumCities() == 0))
1252
                        {
1253
                                GET_PLAYER((PlayerTypes)iI).initFreeUnits();
1254
                        }
1255
                }
1256
        }
1257
}
1258
 
1259
 
1260
void CvGame::assignStartingPlots()
1261
{
1262
        PROFILE_FUNC();
1263
 
1264
        CvPlot* pPlot;
1265
        CvPlot* pBestPlot;
1266
        bool bStartFound;
1267
        bool bValid;
1268
        int iRandOffset;
1269
        int iLoopTeam;
1270
        int iLoopPlayer;
1271
        int iHumanSlot;
1272
        int iValue;
1273
        int iBestValue;
1274
        int iI, iJ, iK;
1275
 
1276
        std::vector<int> playerOrder;
1277
        std::vector<int>::iterator playerOrderIter;
1278
 
1279
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1280
        {
1281
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1282
                {
1283
                        if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
1284
                        {
1285
                                iBestValue = 0;
1286
                                pBestPlot = NULL;
1287
 
1288
                                for (iJ = 0; iJ < GC.getMapINLINE().numPlotsINLINE(); iJ++)
1289
                                {
1290
                                        gDLL->callUpdater();    // allow window updates during launch
1291
 
1292
                                        pPlot = GC.getMapINLINE().plotByIndexINLINE(iJ);
1293
 
1294
                                        if (pPlot->isStartingPlot())
1295
                                        {
1296
                                                bValid = true;
1297
 
1298
                                                for (iK = 0; iK < MAX_CIV_PLAYERS; iK++)
1299
                                                {
1300
                                                        if (GET_PLAYER((PlayerTypes)iK).isAlive())
1301
                                                        {
1302
                                                                if (GET_PLAYER((PlayerTypes)iK).getStartingPlot() == pPlot)
1303
                                                                {
1304
                                                                        bValid = false;
1305
                                                                        break;
1306
                                                                }
1307
                                                        }
1308
                                                }
1309
 
1310
                                                if (bValid)
1311
                                                {
1312
                                                        iValue = (1 + getSorenRandNum(1000, "Starting Plot"));
1313
 
1314
                                                        if (iValue > iBestValue)
1315
                                                        {
1316
                                                                iBestValue = iValue;
1317
                                                                pBestPlot = pPlot;
1318
                                                        }
1319
                                                }
1320
                                        }
1321
                                }
1322
 
1323
                                if (pBestPlot != NULL)
1324
                                {
1325
                                        GET_PLAYER((PlayerTypes)iI).setStartingPlot(pBestPlot, true);
1326
                                }
1327
                        }
1328
                }
1329
        }
1330
 
1331
        if (PYTHON_CALL_FUNCTION2(__FUNCTION__, gDLL->getPythonIFace()->getMapScriptModule(), "assignStartingPlots"))
1332
        {
1333
                if (!gDLL->getPythonIFace()->pythonUsingDefaultImpl())
1334
                {
1335
                        // Python override
1336
                        return;
1337
                }
1338
        }
1339
 
1340
        if (isTeamGame())
1341
        {
1342
                for (int iPass = 0; iPass < 2 * MAX_PLAYERS; ++iPass)
1343
                {
1344
                        bStartFound = false;
1345
 
1346
                        iRandOffset = getSorenRandNum(countCivTeamsAlive(), "Team Starting Plot");
1347
 
1348
                        for (iI = 0; iI < MAX_CIV_TEAMS; iI++)
1349
                        {
1350
                                iLoopTeam = ((iI + iRandOffset) % MAX_CIV_TEAMS);
1351
 
1352
                                if (GET_TEAM((TeamTypes)iLoopTeam).isAlive())
1353
                                {
1354
                                        for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
1355
                                        {
1356
                                                if (GET_PLAYER((PlayerTypes)iJ).isAlive())
1357
                                                {
1358
                                                        if (GET_PLAYER((PlayerTypes)iJ).getTeam() == iLoopTeam)
1359
                                                        {
1360
                                                                if (GET_PLAYER((PlayerTypes)iJ).getStartingPlot() == NULL)
1361
                                                                {
1362
                                                                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iJ).findStartingPlot();
1363
 
1364
                                                                        if (NULL != pStartingPlot)
1365
                                                                        {
1366
                                                                                GET_PLAYER((PlayerTypes)iJ).setStartingPlot(pStartingPlot, true);
1367
                                                                                playerOrder.push_back(iJ);
1368
                                                                        }
1369
                                                                        bStartFound = true;
1370
                                                                        break;
1371
                                                                }
1372
                                                        }
1373
                                                }
1374
                                        }
1375
                                }
1376
                        }
1377
 
1378
                        if (!bStartFound)
1379
                        {
1380
                                break;
1381
                        }
1382
                }
1383
 
1384
                //check all players have starting plots
1385
                for (iJ = 0; iJ < MAX_CIV_PLAYERS; iJ++)
1386
                {
1387
                        FAssertMsg(!GET_PLAYER((PlayerTypes)iJ).isAlive() || GET_PLAYER((PlayerTypes)iJ).getStartingPlot() != NULL, "Player has no starting plot");
1388
                }
1389
        }
1390
        else if (isGameMultiPlayer())
1391
        {
1392
                iRandOffset = getSorenRandNum(countCivPlayersAlive(), "Player Starting Plot");
1393
 
1394
                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1395
                {
1396
                        iLoopPlayer = ((iI + iRandOffset) % MAX_CIV_PLAYERS);
1397
 
1398
                        if (GET_PLAYER((PlayerTypes)iLoopPlayer).isAlive())
1399
                        {
1400
                                if (GET_PLAYER((PlayerTypes)iLoopPlayer).isHuman())
1401
                                {
1402
                                        if (GET_PLAYER((PlayerTypes)iLoopPlayer).getStartingPlot() == NULL)
1403
                                        {
1404
                                                GET_PLAYER((PlayerTypes)iLoopPlayer).setStartingPlot(GET_PLAYER((PlayerTypes)iLoopPlayer).findStartingPlot(), true);
1405
                                                playerOrder.push_back(iLoopPlayer);
1406
                                        }
1407
                                }
1408
                        }
1409
                }
1410
 
1411
                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1412
                {
1413
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
1414
                        {
1415
                                if (!(GET_PLAYER((PlayerTypes)iI).isHuman()))
1416
                                {
1417
                                        if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
1418
                                        {
1419
                                                GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
1420
                                                playerOrder.push_back(iI);
1421
                                        }
1422
                                }
1423
                        }
1424
                }
1425
        }
1426
        else
1427
        {
1428
                iHumanSlot = range((((countCivPlayersAlive() - 1) * GC.getHandicapInfo(getHandicapType()).getStartingLocationPercent()) / 100), 0, (countCivPlayersAlive() - 1));
1429
 
1430
                for (iI = 0; iI < iHumanSlot; iI++)
1431
                {
1432
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
1433
                        {
1434
                                if (!(GET_PLAYER((PlayerTypes)iI).isHuman()))
1435
                                {
1436
                                        if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
1437
                                        {
1438
                                                GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
1439
                                                playerOrder.push_back(iI);
1440
                                        }
1441
                                }
1442
                        }
1443
                }
1444
 
1445
                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1446
                {
1447
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
1448
                        {
1449
                                if (GET_PLAYER((PlayerTypes)iI).isHuman())
1450
                                {
1451
                                        if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
1452
                                        {
1453
                                                GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
1454
                                                playerOrder.push_back(iI);
1455
                                        }
1456
                                }
1457
                        }
1458
                }
1459
 
1460
                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1461
                {
1462
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
1463
                        {
1464
                                if (GET_PLAYER((PlayerTypes)iI).getStartingPlot() == NULL)
1465
                                {
1466
                                        GET_PLAYER((PlayerTypes)iI).setStartingPlot(GET_PLAYER((PlayerTypes)iI).findStartingPlot(), true);
1467
                                        playerOrder.push_back(iI);
1468
                                }
1469
                        }
1470
                }
1471
        }
1472
 
1473
        //Now iterate over the player starts in the original order and re-place them.
1474
        for (playerOrderIter = playerOrder.begin(); playerOrderIter != playerOrder.end(); ++playerOrderIter)
1475
        {
1476
                GET_PLAYER((PlayerTypes)(*playerOrderIter)).setStartingPlot(GET_PLAYER((PlayerTypes)(*playerOrderIter)).findStartingPlot(), true);
1477
        }
1478
}
1479
 
1480
// Swaps starting locations until we have reached the optimal closeness between teams
1481
// (caveat: this isn't quite "optimal" because we could get stuck in local minima, but it's pretty good)
1482
 
1483
void CvGame::normalizeStartingPlotLocations()
1484
{
1485
        CvPlot* apNewStartPlots[MAX_CIV_PLAYERS];
1486
        int* aaiDistances[MAX_CIV_PLAYERS];
1487
        int aiStartingLocs[MAX_CIV_PLAYERS];
1488
        int iI, iJ;
1489
 
1490
        // Precalculate distances between all starting positions:
1491
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1492
        {
1493
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1494
                {
1495
                        gDLL->callUpdater();    // allow window to update during launch
1496
                        aaiDistances[iI] = new int[iI];
1497
                        for (iJ = 0; iJ < iI; iJ++)
1498
                        {
1499
                                aaiDistances[iI][iJ] = 0;
1500
                        }
1501
                        CvPlot *pPlotI = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
1502
                        if (pPlotI != NULL)
1503
                        {
1504
                                for (iJ = 0; iJ < iI; iJ++)
1505
                                {
1506
                                        if (GET_PLAYER((PlayerTypes)iJ).isAlive())
1507
                                        {
1508
                                                CvPlot *pPlotJ = GET_PLAYER((PlayerTypes)iJ).getStartingPlot();
1509
                                                if (pPlotJ != NULL)
1510
                                                {
1511
                                                        int iDist = GC.getMapINLINE().calculatePathDistance(pPlotI, pPlotJ);
1512
                                                        if (iDist == -1)
1513
                                                        {
1514
                                                                // 5x penalty for not being on the same area, or having no passable route
1515
                                                                iDist = 5*plotDistance(pPlotI->getX_INLINE(), pPlotI->getY_INLINE(), pPlotJ->getX_INLINE(), pPlotJ->getY_INLINE());
1516
                                                        }
1517
                                                        aaiDistances[iI][iJ] = iDist;
1518
                                                }
1519
                                        }
1520
                                }
1521
                        }
1522
                }
1523
                else
1524
                {
1525
                        aaiDistances[iI] = NULL;
1526
                }
1527
        }
1528
 
1529
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1530
        {
1531
                aiStartingLocs[iI] = iI; // each player starting in own location
1532
        }
1533
 
1534
        int iBestScore = getTeamClosenessScore(aaiDistances, aiStartingLocs);
1535
        bool bFoundSwap = true;
1536
        while (bFoundSwap)
1537
        {
1538
                bFoundSwap = false;
1539
                for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1540
                {
1541
                        if (GET_PLAYER((PlayerTypes)iI).isAlive())
1542
                        {
1543
                                for (iJ = 0; iJ < iI; iJ++)
1544
                                {
1545
                                        if (GET_PLAYER((PlayerTypes)iJ).isAlive())
1546
                                        {
1547
                                                int iTemp = aiStartingLocs[iI];
1548
                                                aiStartingLocs[iI] = aiStartingLocs[iJ];
1549
                                                aiStartingLocs[iJ] = iTemp;
1550
                                                int iScore = getTeamClosenessScore(aaiDistances, aiStartingLocs);
1551
                                                if (iScore < iBestScore)
1552
                                                {
1553
                                                        iBestScore = iScore;
1554
                                                        bFoundSwap = true;
1555
                                                }
1556
                                                else
1557
                                                {
1558
                                                        // Swap them back:
1559
                                                        iTemp = aiStartingLocs[iI];
1560
                                                        aiStartingLocs[iI] = aiStartingLocs[iJ];
1561
                                                        aiStartingLocs[iJ] = iTemp;
1562
                                                }
1563
                                        }
1564
                                }
1565
                        }
1566
                }
1567
        }
1568
 
1569
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1570
        {
1571
                apNewStartPlots[iI] = NULL;
1572
        }
1573
 
1574
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1575
        {
1576
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1577
                {
1578
                        if (aiStartingLocs[iI] != iI)
1579
                        {
1580
                                apNewStartPlots[iI] = GET_PLAYER((PlayerTypes)aiStartingLocs[iI]).getStartingPlot();
1581
                        }
1582
                }
1583
        }
1584
 
1585
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1586
        {
1587
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1588
                {
1589
                        if (apNewStartPlots[iI] != NULL)
1590
                        {
1591
                                GET_PLAYER((PlayerTypes)iI).setStartingPlot(apNewStartPlots[iI], false);
1592
                        }
1593
                }
1594
        }
1595
 
1596
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1597
        {
1598
                SAFE_DELETE_ARRAY(aaiDistances[iI]);
1599
        }
1600
}
1601
 
1602
 
1603
void CvGame::normalizeAddRiver()
1604
{
1605
        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1606
        {
1607
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1608
                {
1609
                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
1610
 
1611
                        if (pStartingPlot != NULL)
1612
                        {
1613
                                if (!pStartingPlot->isFreshWater())
1614
                                {
1615
                                        // if we will be able to add a lake, then use old river code
1616
                                        if (normalizeFindLakePlot((PlayerTypes)iI) != NULL)
1617
                                        {
1618
                                                CvMapGenerator::GetInstance().doRiver(pStartingPlot);
1619
                                        }
1620
                                        // otherwise, use new river code which is much more likely to succeed
1621
                                        else
1622
                                        {
1623
                                                CvMapGenerator::GetInstance().addRiver(pStartingPlot);
1624
                                        }
1625
 
1626
                                        // add floodplains to any desert tiles the new river passes through
1627
                                        for (int iK = 0; iK < GC.getMapINLINE().numPlotsINLINE(); iK++)
1628
                                        {
1629
                                                CvPlot* pPlot = GC.getMapINLINE().plotByIndexINLINE(iK);
1630
                                                FAssert(pPlot != NULL);
1631
 
1632
                                                for (int iJ = 0; iJ < GC.getNumFeatureInfos(); iJ++)
1633
                                                {
1634
                                                        if (GC.getFeatureInfo((FeatureTypes)iJ).isRequiresRiver())
1635
                                                        {
1636
                                                                if (pPlot->canHaveFeature((FeatureTypes)iJ))
1637
                                                                {
1638
                                                                        if (GC.getFeatureInfo((FeatureTypes)iJ).getAppearanceProbability() == 10000)
1639
                                                                        {
1640
                                                                                if (pPlot->getBonusType() != NO_BONUS)
1641
                                                                                {
1642
                                                                                        pPlot->setBonusType(NO_BONUS);
1643
                                                                                }
1644
                                                                                pPlot->setFeatureType((FeatureTypes)iJ);
1645
                                                                                break;
1646
                                                                        }
1647
                                                                }
1648
                                                        }
1649
                                                }
1650
                                        }
1651
                                }
1652
                        }
1653
                }
1654
        }
1655
}
1656
 
1657
 
1658
void CvGame::normalizeRemovePeaks()
1659
{
1660
        CvPlot* pStartingPlot;
1661
        CvPlot* pLoopPlot;
1662
        int iRange;
1663
        int iDX, iDY;
1664
        int iI;
1665
 
1666
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1667
        {
1668
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1669
                {
1670
                        pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
1671
 
1672
                        if (pStartingPlot != NULL)
1673
                        {
1674
                                iRange = 3;
1675
 
1676
                                for (iDX = -(iRange); iDX <= iRange; iDX++)
1677
                                {
1678
                                        for (iDY = -(iRange); iDY <= iRange; iDY++)
1679
                                        {
1680
                                                pLoopPlot = plotXY(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iDX, iDY);
1681
 
1682
                                                if (pLoopPlot != NULL)
1683
                                                {
1684
                                                        if (pLoopPlot->isPeak())
1685
                                                        {
1686
                                                                pLoopPlot->setPlotType(PLOT_HILLS);
1687
                                                        }
1688
                                                }
1689
                                        }
1690
                                }
1691
                        }
1692
                }
1693
        }
1694
}
1695
 
1696
void CvGame::normalizeAddLakes()
1697
{
1698
        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1699
        {
1700
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1701
                {
1702
                        CvPlot* pLakePlot = normalizeFindLakePlot((PlayerTypes)iI);
1703
                        if (pLakePlot != NULL)
1704
                        {
1705
                                pLakePlot->setPlotType(PLOT_OCEAN);
1706
                        }
1707
                }
1708
        }
1709
}
1710
 
1711
CvPlot* CvGame::normalizeFindLakePlot(PlayerTypes ePlayer)
1712
{
1713
        if (!GET_PLAYER(ePlayer).isAlive())
1714
        {
1715
                return NULL;
1716
        }
1717
 
1718
        CvPlot* pStartingPlot = GET_PLAYER(ePlayer).getStartingPlot();
1719
        if (pStartingPlot != NULL)
1720
        {
1721
                if (!(pStartingPlot->isFreshWater()))
1722
                {
1723
                        for (int iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
1724
                        {
1725
                                CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
1726
 
1727
                                if (pLoopPlot != NULL)
1728
                                {
1729
                                        if (!(pLoopPlot->isWater()))
1730
                                        {
1731
                                                if (!(pLoopPlot->isCoastalLand()))
1732
                                                {
1733
                                                        if (!(pLoopPlot->isRiver()))
1734
                                                        {
1735
                                                                if (pLoopPlot->getBonusType() == NO_BONUS)
1736
                                                                {
1737
                                                                        bool bStartingPlot = false;
1738
 
1739
                                                                        for (int iK = 0; iK < MAX_CIV_PLAYERS; iK++)
1740
                                                                        {
1741
                                                                                if (GET_PLAYER((PlayerTypes)iK).isAlive())
1742
                                                                                {
1743
                                                                                        if (GET_PLAYER((PlayerTypes)iK).getStartingPlot() == pLoopPlot)
1744
                                                                                        {
1745
                                                                                                bStartingPlot = true;
1746
                                                                                                break;
1747
                                                                                        }
1748
                                                                                }
1749
                                                                        }
1750
 
1751
                                                                        if (!bStartingPlot)
1752
                                                                        {
1753
                                                                                return pLoopPlot;
1754
                                                                        }
1755
                                                                }
1756
                                                        }
1757
                                                }
1758
                                        }
1759
                                }
1760
                        }
1761
                }
1762
        }
1763
 
1764
        return NULL;
1765
}
1766
 
1767
 
1768
void CvGame::normalizeRemoveBadFeatures()
1769
{
1770
        CvPlot* pStartingPlot;
1771
        CvPlot* pLoopPlot;
1772
        int iI, iJ;
1773
 
1774
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1775
        {
1776
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1777
                {
1778
                        pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
1779
 
1780
                        if (pStartingPlot != NULL)
1781
                        {
1782
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
1783
                                {
1784
                                        pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
1785
 
1786
                                        if (pLoopPlot != NULL)
1787
                                        {
1788
                                                if (pLoopPlot->getFeatureType() != NO_FEATURE)
1789
                                                {
1790
                                                        if ((GC.getFeatureInfo(pLoopPlot->getFeatureType()).getYieldChange(YIELD_FOOD) <= 0) &&
1791
                                                                (GC.getFeatureInfo(pLoopPlot->getFeatureType()).getYieldChange(YIELD_PRODUCTION) <= 0))
1792
                                                        {
1793
                                                                pLoopPlot->setFeatureType(NO_FEATURE);
1794
                                                        }
1795
                                                }
1796
                                        }
1797
                                }
1798
 
1799
                                int iX, iY;
1800
                                int iCityRange = CITY_PLOTS_RADIUS;
1801
                                int iExtraRange = 2;
1802
                                int iMaxRange = iCityRange + iExtraRange;
1803
 
1804
                                for (iX = -iMaxRange; iX <= iMaxRange; iX++)
1805
                                {
1806
                                        for (iY = -iMaxRange; iY <= iMaxRange; iY++)
1807
                                        {
1808
                                                pLoopPlot = plotXY(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iX, iY);
1809
                                                if (pLoopPlot != NULL)
1810
                                                {
1811
                                                        int iDistance = plotDistance(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());                  
1812
                                                        if (iDistance <= iMaxRange)
1813
                                                        {
1814
                                                                if (pLoopPlot->getFeatureType() != NO_FEATURE)
1815
                                                                {
1816
                                                                        if ((GC.getFeatureInfo(pLoopPlot->getFeatureType()).getYieldChange(YIELD_FOOD) <= 0) &&
1817
                                                                                (GC.getFeatureInfo(pLoopPlot->getFeatureType()).getYieldChange(YIELD_PRODUCTION) <= 0))
1818
                                                                        {
1819
                                                                                if (pLoopPlot->isWater())
1820
                                                                                {
1821
                                                                                        if (pLoopPlot->isAdjacentToLand() || (!(iDistance == iMaxRange) && (getSorenRandNum(2, "Remove Bad Feature") == 0)))
1822
                                                                                        {
1823
                                                                                                pLoopPlot->setFeatureType(NO_FEATURE);
1824
                                                                                        }
1825
                                                                                }
1826
                                                                                else
1827
                                                                                {
1828
                                                                                        if (!(iDistance == iMaxRange) && (getSorenRandNum((2 + ((pLoopPlot->getBonusType() == NO_BONUS) ? 0 : 2)), "Remove Bad Feature") == 0))
1829
                                                                                        {
1830
                                                                                                pLoopPlot->setFeatureType(NO_FEATURE);                                            
1831
                                                                                        }
1832
                                                                                }
1833
                                                                        }
1834
                                                                }
1835
                                                        }
1836
                                                }
1837
                                        }
1838
                                }
1839
                        }
1840
        }
1841
        }
1842
}
1843
 
1844
 
1845
void CvGame::normalizeRemoveBadTerrain()
1846
{
1847
        CvPlot* pStartingPlot;
1848
        CvPlot* pLoopPlot;
1849
        int iI, iK;
1850
        int iX, iY;
1851
 
1852
        int iTargetFood;
1853
        int iTargetTotal;
1854
        int iPlotFood;
1855
        int iPlotProduction;
1856
 
1857
 
1858
        int iCityRange = CITY_PLOTS_RADIUS;
1859
        int iExtraRange = 1;
1860
        int iMaxRange = iCityRange + iExtraRange;
1861
 
1862
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1863
        {
1864
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1865
                {
1866
                        pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
1867
 
1868
                        if (pStartingPlot != NULL)
1869
                        {
1870
                            for (iX = -iMaxRange; iX <= iMaxRange; iX++)
1871
                            {
1872
                                for (iY = -iMaxRange; iY <= iMaxRange; iY++)
1873
                                {
1874
                                    pLoopPlot = plotXY(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iX, iY);
1875
                        if (pLoopPlot != NULL)
1876
                        {
1877
                            int iDistance = plotDistance(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), pLoopPlot->getX_INLINE(), pLoopPlot->getY_INLINE());
1878
                            if (iDistance <= iMaxRange)
1879
                            {
1880
                                if (!(pLoopPlot->isWater()) && ((iDistance <= iCityRange) || (pLoopPlot->isCoastalLand()) || (0 == getSorenRandNum(1 + iDistance - iCityRange, "Map Upgrade Terrain Food"))))
1881
                                {
1882
                                    iPlotFood = GC.getTerrainInfo(pLoopPlot->getTerrainType()).getYield(YIELD_FOOD);
1883
                                    iPlotProduction = GC.getTerrainInfo(pLoopPlot->getTerrainType()).getYield(YIELD_PRODUCTION);
1884
                                    if ((iPlotFood + iPlotProduction) <= 1)
1885
                                    {
1886
                                        iTargetFood = 1;
1887
                                        iTargetTotal = 1;
1888
                                        if (pLoopPlot->getBonusType(GET_PLAYER((PlayerTypes)iI).getTeam()) != NO_BONUS)
1889
                                        {
1890
                                            iTargetFood = 1;
1891
                                            iTargetTotal = 2;
1892
                                        }
1893
                                        else if ((iPlotFood == 1) || (iDistance <= iCityRange))
1894
                                        {
1895
                                            iTargetFood = 1 + getSorenRandNum(2, "Map Upgrade Terrain Food");
1896
                                            iTargetTotal = 2;
1897
                                        }
1898
                                        else
1899
                                        {
1900
                                            iTargetFood = pLoopPlot->isCoastalLand() ? 2 : 1;
1901
                                            iTargetTotal = 2;
1902
                                        }
1903
 
1904
                                        for (iK = 0; iK < GC.getNumTerrainInfos(); iK++)
1905
                                        {
1906
                                            if (!(GC.getTerrainInfo((TerrainTypes)iK).isWater()))
1907
                                            {
1908
                                                if ((GC.getTerrainInfo((TerrainTypes)iK).getYield(YIELD_FOOD) >= iTargetFood) &&
1909
                                                    (GC.getTerrainInfo((TerrainTypes)iK).getYield(YIELD_FOOD) + GC.getTerrainInfo((TerrainTypes)iK).getYield(YIELD_PRODUCTION)) == iTargetTotal)
1910
                                                {
1911
                                                    if ((pLoopPlot->getFeatureType() == NO_FEATURE) || GC.getFeatureInfo(pLoopPlot->getFeatureType()).isTerrain(iK))
1912
                                                    {
1913
                                                        pLoopPlot->setTerrainType((TerrainTypes)iK);
1914
                                                    }
1915
                                                }
1916
                                            }
1917
                                        }
1918
                                    }
1919
                                }
1920
                            }
1921
 
1922
                                    }
1923
                                }
1924
                                }
1925
                        }
1926
                }
1927
        }
1928
}
1929
 
1930
void CvGame::normalizeAddFoodBonuses()
1931
{
1932
        bool bIgnoreLatitude = pythonIsBonusIgnoreLatitudes();
1933
 
1934
        for (int iI = 0; iI < MAX_CIV_PLAYERS; iI++)
1935
        {
1936
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
1937
                {
1938
                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
1939
 
1940
                        if (pStartingPlot != NULL)
1941
                        {
1942
                                int iFoodBonus = 0;
1943
                                int iGoodNatureTileCount = 0;
1944
 
1945
                                for (int iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
1946
                                {
1947
                                        CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
1948
 
1949
                                        if (pLoopPlot != NULL)
1950
                                        {
1951
                                                BonusTypes eBonus = pLoopPlot->getBonusType(GET_PLAYER((PlayerTypes)iI).getTeam());
1952
 
1953
                                                if (eBonus != NO_BONUS)
1954
                                                {
1955
                                                        if (GC.getBonusInfo(eBonus).getYieldChange(YIELD_FOOD) > 0)
1956
                                                        {
1957
                                                                if ((GC.getBonusInfo(eBonus).getTechCityTrade() == NO_TECH) || (GC.getTechInfo((TechTypes)(GC.getBonusInfo(eBonus).getTechCityTrade())).getEra() <= getStartEra()))
1958
                                                                {
1959
                                                                        if (pLoopPlot->isWater())
1960
                                                                        {
1961
                                                                                iFoodBonus += 2;
1962
                                                                        }
1963
                                                                        else
1964
                                                                        {
1965
                                                                                iFoodBonus += 3;
1966
                                                                        }
1967
                                                                }
1968
                                                        }
1969
                                                        else if (pLoopPlot->calculateBestNatureYield(YIELD_FOOD, GET_PLAYER((PlayerTypes)iI).getTeam()) >= 2)
1970
                                                    {
1971
                                                        iGoodNatureTileCount++;
1972
                                                    }
1973
                                                }
1974
                                                else
1975
                                                {
1976
                            if (pLoopPlot->calculateBestNatureYield(YIELD_FOOD, GET_PLAYER((PlayerTypes)iI).getTeam()) >= 3)
1977
                                                    {
1978
                                                        iGoodNatureTileCount++;
1979
                                                    }
1980
                                                }
1981
                                        }
1982
                                }
1983
 
1984
                                int iTargetFoodBonusCount = 3;
1985
                                iTargetFoodBonusCount += (iGoodNatureTileCount == 0) ? 2 : 0;
1986
 
1987
                                for (int iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
1988
                                {
1989
                                        if (iFoodBonus >= iTargetFoodBonusCount)
1990
                                        {
1991
                                                break;
1992
                                        }
1993
 
1994
                                        CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
1995
 
1996
                                        if (pLoopPlot != NULL)
1997
                                        {
1998
                                                if (pLoopPlot != pStartingPlot)
1999
                                                {
2000
                                                        if (pLoopPlot->getBonusType() == NO_BONUS)
2001
                                                        {
2002
                                                                for (int iK = 0; iK < GC.getNumBonusInfos(); iK++)
2003
                                                                {
2004
                                                                        if (GC.getBonusInfo((BonusTypes)iK).isNormalize())
2005
                                                                        {
2006
                                                                                if (GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_FOOD) > 0)
2007
                                                                                {
2008
                                                                                        if ((GC.getBonusInfo((BonusTypes)iK).getTechCityTrade() == NO_TECH) || (GC.getTechInfo((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechCityTrade())).getEra() <= getStartEra()))
2009
                                                                                        {
2010
                                                                                                if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHasTech((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechReveal())))
2011
                                                                                                {
2012
                                                                                                        if (pLoopPlot->canHaveBonus(((BonusTypes)iK), bIgnoreLatitude))
2013
                                                                                                        {
2014
                                                                                                                pLoopPlot->setBonusType((BonusTypes)iK);
2015
                                                                                                                if (pLoopPlot->isWater())
2016
                                                                                                                {
2017
                                                                                                                        iFoodBonus += 2;
2018
                                                                                                                }
2019
                                                                                                                else
2020
                                                                                                                {
2021
                                                                                                                        iFoodBonus += 3;
2022
                                                                                                                }
2023
                                                                                                                break;
2024
                                                                                                        }
2025
                                                                                                }
2026
                                                                                        }
2027
                                                                                }
2028
                                                                        }
2029
                                                                }
2030
                                                        }
2031
                                                }
2032
                                        }
2033
                                }
2034
                        }
2035
                }
2036
        }
2037
}
2038
 
2039
 
2040
void CvGame::normalizeAddGoodTerrain()
2041
{
2042
        CvPlot* pStartingPlot;
2043
        CvPlot* pLoopPlot;
2044
        bool bChanged;
2045
        int iGoodPlot;
2046
        int iI, iJ, iK;
2047
 
2048
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
2049
        {
2050
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
2051
                {
2052
                        pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
2053
 
2054
                        if (pStartingPlot != NULL)
2055
                        {
2056
                                iGoodPlot = 0;
2057
 
2058
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
2059
                                {
2060
                                        pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
2061
 
2062
                                        if (pLoopPlot != NULL)
2063
                                        {
2064
                                                if (pLoopPlot != pStartingPlot)
2065
                                                {
2066
                                                        if ((pLoopPlot->calculateNatureYield(YIELD_FOOD, GET_PLAYER((PlayerTypes)iI).getTeam()) >= GC.getFOOD_CONSUMPTION_PER_POPULATION()) &&
2067
                                                                  (pLoopPlot->calculateNatureYield(YIELD_PRODUCTION, GET_PLAYER((PlayerTypes)iI).getTeam()) > 0))
2068
                                                        {
2069
                                                                iGoodPlot++;
2070
                                                        }
2071
                                                }
2072
                                        }
2073
                                }
2074
 
2075
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
2076
                                {
2077
                                        if (iGoodPlot >= 4)
2078
                                        {
2079
                                                break;
2080
                                        }
2081
 
2082
                                        pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
2083
 
2084
                                        if (pLoopPlot != NULL)
2085
                                        {
2086
                                                if (pLoopPlot != pStartingPlot)
2087
                                                {
2088
                                                        if (!(pLoopPlot->isWater()))
2089
                                                        {
2090
                                                                if (!(pLoopPlot->isHills()))
2091
                                                                {
2092
                                                                        if (pLoopPlot->getBonusType() == NO_BONUS)
2093
                                                                        {
2094
                                                                                bChanged = false;
2095
 
2096
                                                                                if (pLoopPlot->calculateNatureYield(YIELD_FOOD, GET_PLAYER((PlayerTypes)iI).getTeam()) < GC.getFOOD_CONSUMPTION_PER_POPULATION())
2097
                                                                                {
2098
                                                                                        for (iK = 0; iK < GC.getNumTerrainInfos(); iK++)
2099
                                                                                        {
2100
                                                                                                if (!(GC.getTerrainInfo((TerrainTypes)iK).isWater()))
2101
                                                                                                {
2102
                                                                                                        if (GC.getTerrainInfo((TerrainTypes)iK).getYield(YIELD_FOOD) >= GC.getFOOD_CONSUMPTION_PER_POPULATION())
2103
                                                                                                        {
2104
                                                                                                                pLoopPlot->setTerrainType((TerrainTypes)iK);
2105
                                                                                                                bChanged = true;
2106
                                                                                                                break;
2107
                                                                                                        }
2108
                                                                                                }
2109
                                                                                        }
2110
                                                                                }
2111
 
2112
                                                                                if (pLoopPlot->calculateNatureYield(YIELD_PRODUCTION, GET_PLAYER((PlayerTypes)iI).getTeam()) == 0)
2113
                                                                                {
2114
                                                                                        for (iK = 0; iK < GC.getNumFeatureInfos(); iK++)
2115
                                                                                        {
2116
                                                                                                if ((GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_FOOD) >= 0) &&
2117
                                                                                                          (GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_PRODUCTION) > 0))
2118
                                                                                                {
2119
                                                                                                        if (GC.getFeatureInfo((FeatureTypes)iK).isTerrain(pLoopPlot->getTerrainType()))
2120
                                                                                                        {
2121
                                                                                                                pLoopPlot->setFeatureType((FeatureTypes)iK);
2122
                                                                                                                bChanged = true;
2123
                                                                                                                break;
2124
                                                                                                        }
2125
                                                                                                }
2126
                                                                                        }
2127
                                                                                }
2128
 
2129
                                                                                if (bChanged)
2130
                                                                                {
2131
                                                                                        iGoodPlot++;
2132
                                                                                }
2133
                                                                        }
2134
                                                                }
2135
                                                        }
2136
                                                }
2137
                                        }
2138
                                }
2139
                        }
2140
                }
2141
        }
2142
}
2143
 
2144
 
2145
void CvGame::normalizeAddExtras()
2146
{
2147
        bool bIgnoreLatitude = pythonIsBonusIgnoreLatitudes();
2148
 
2149
        int iTotalValue = 0;
2150
        int iPlayerCount = 0;
2151
        int iBestValue = 0;
2152
        int iWorstValue = MAX_INT;
2153
        int     iI, iJ, iK;
2154
 
2155
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
2156
        {
2157
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
2158
                {
2159
                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
2160
 
2161
                        if (pStartingPlot != NULL)
2162
                        {
2163
                                int iValue = GET_PLAYER((PlayerTypes)iI).AI_foundValue(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), -1, true);
2164
                                iTotalValue += iValue;
2165
                iPlayerCount++;
2166
 
2167
                iBestValue = std::max(iValue, iBestValue);
2168
                iWorstValue = std::min(iValue, iWorstValue);
2169
                        }
2170
                }
2171
        }
2172
 
2173
        //iTargetValue = (iTotalValue + iBestValue) / (iPlayerCount + 1);
2174
        int iTargetValue = (iBestValue * 4) / 5;
2175
 
2176
        for (iI = 0; iI < MAX_CIV_PLAYERS; iI++)
2177
        {
2178
                if (GET_PLAYER((PlayerTypes)iI).isAlive())
2179
                {
2180
                        gDLL->callUpdater();    // allow window to update during launch
2181
                        CvPlot* pStartingPlot = GET_PLAYER((PlayerTypes)iI).getStartingPlot();
2182
 
2183
                        if (pStartingPlot != NULL)
2184
                        {
2185
                int iCount = 0;
2186
                                int iFeatureCount = 0;
2187
                                int aiShuffle[NUM_CITY_PLOTS];
2188
                                shuffleArray(aiShuffle, NUM_CITY_PLOTS, getMapRand());
2189
 
2190
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
2191
                                {
2192
                                        if (GET_PLAYER((PlayerTypes)iI).AI_foundValue(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), -1, true) >= iTargetValue)
2193
                                        {
2194
                                                break;
2195
                                        }
2196
                                        if (getSorenRandNum((iCount + 2), "Setting Feature Type") <= 1)
2197
                                        {
2198
                                                CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), aiShuffle[iJ]);
2199
 
2200
                                                if (pLoopPlot != NULL)
2201
                                                {
2202
                                                        if (pLoopPlot != pStartingPlot)
2203
                                                        {
2204
                                                                if (pLoopPlot->getBonusType() == NO_BONUS)
2205
                                                                {
2206
                                                                        if (pLoopPlot->getFeatureType() == NO_FEATURE)
2207
                                                                        {
2208
                                                                                for (int iK = 0; iK < GC.getNumFeatureInfos(); iK++)
2209
                                                                                {
2210
                                                                                        if ((GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_FOOD) + GC.getFeatureInfo((FeatureTypes)iK).getYieldChange(YIELD_PRODUCTION)) > 0)
2211
                                                                                        {
2212
                                                                                                if (pLoopPlot->canHaveFeature((FeatureTypes)iK))
2213
                                                                                                {
2214
                                                                                                        pLoopPlot->setFeatureType((FeatureTypes)iK);
2215
                                                                                                        iCount++;
2216
                                                                                                        break;
2217
                                                                                                }
2218
                                                                                        }
2219
                                                                                }
2220
                                                                        }
2221
 
2222
                                                                        iFeatureCount += (pLoopPlot->getFeatureType() != NO_FEATURE) ? 1 : 0;
2223
                                                                }
2224
                                                        }
2225
                                                }
2226
                                        }
2227
                                }
2228
 
2229
                                int iCoastFoodCount = 0;
2230
                                int iOceanFoodCount = 0;
2231
                                int iOtherCount = 0;
2232
                                int iWaterCount = 0;
2233
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
2234
                                {
2235
                                        CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), iJ);
2236
                                        if (pLoopPlot != NULL)
2237
                                        {
2238
                                                if (pLoopPlot != pStartingPlot)
2239
                                                {
2240
                                                        if (pLoopPlot->isWater())
2241
                                                        {
2242
                                                                iWaterCount++;
2243
                                                                if (pLoopPlot->getBonusType() != NO_BONUS)
2244
                                                                {
2245
                                                                        if (pLoopPlot->isAdjacentToLand())
2246
                                                                        {
2247
                                                                                iCoastFoodCount++;
2248
                                                                        }
2249
                                                                        else
2250
                                                                        {
2251
                                                                                iOceanFoodCount++;                                        
2252
                                                                        }
2253
                                                                }
2254
                                                        }
2255
                                                        else
2256
                                                        {
2257
                                                                if (pLoopPlot->getBonusType() != NO_BONUS)
2258
                                                                {
2259
                                                                        iOtherCount++;
2260
                                                                }
2261
                                                        }
2262
                                                }
2263
                                        }
2264
                                }
2265
 
2266
                            bool bLandBias = (iWaterCount > NUM_CITY_PLOTS / 2);
2267
 
2268
                shuffleArray(aiShuffle, NUM_CITY_PLOTS, getMapRand());                
2269
 
2270
                                for (iJ = 0; iJ < NUM_CITY_PLOTS; iJ++)
2271
                                {
2272
                                    CvPlot* pLoopPlot = plotCity(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), aiShuffle[iJ]);
2273
 
2274
                    if ((pLoopPlot != NULL) && (pLoopPlot != pStartingPlot))
2275
                    {
2276
                        if (getSorenRandNum(((bLandBias && pLoopPlot->isWater()) ? 2 : 1), "Placing Bonuses") == 0)
2277
                        {
2278
                                if ((iOtherCount * 3 + iOceanFoodCount * 2 + iCoastFoodCount * 2) >= 12)
2279
                                {
2280
                                        break;
2281
                                }
2282
 
2283
                            if (GET_PLAYER((PlayerTypes)iI).AI_foundValue(pStartingPlot->getX_INLINE(), pStartingPlot->getY_INLINE(), -1, true) >= iTargetValue)
2284
                            {
2285
                                break;
2286
                            }
2287
 
2288
                                                    bool bCoast = (pLoopPlot->isWater() && pLoopPlot->isAdjacentToLand());
2289
                                                    bool bOcean = (pLoopPlot->isWater() && !bCoast);
2290
                                                        if ((pLoopPlot != pStartingPlot)
2291
                                && !(bCoast && (iCoastFoodCount > 2))
2292
                                && !(bOcean && (iOceanFoodCount > 2)))
2293
                                                        {
2294
                                                                for (int iPass = 0; iPass < 2; iPass++)
2295
                                                                {
2296
                                                                        if (pLoopPlot->getBonusType() == NO_BONUS)
2297
                                                                        {
2298
                                                                                for (iK = 0; iK < GC.getNumBonusInfos(); iK++)
2299
                                                                                {
2300
                                                                                        if (GC.getBonusInfo((BonusTypes)iK).isNormalize())
2301
                                                                                        {
2302
                                                                                            //???no bonuses with negative yields?
2303
                                                                                                if ((GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_FOOD) >= 0) &&
2304
                                                                                                          (GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_PRODUCTION) >= 0))
2305
                                                                                                {
2306
                                                                                                        if ((GC.getBonusInfo((BonusTypes)iK).getTechCityTrade() == NO_TECH) || (GC.getTechInfo((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechCityTrade())).getEra() <= getStartEra()))
2307
                                                                                                        {
2308
                                                                                                                if (GET_TEAM(GET_PLAYER((PlayerTypes)iI).getTeam()).isHasTech((TechTypes)(GC.getBonusInfo((BonusTypes)iK).getTechReveal())))
2309
                                                                                                                {
2310
                                                                                                                        if ((iPass == 0) ? CvMapGenerator::GetInstance().canPlaceBonusAt(((BonusTypes)iK), pLoopPlot->getX(), pLoopPlot->getY(), bIgnoreLatitude) : pLoopPlot->canHaveBonus(((BonusTypes)iK), bIgnoreLatitude))
2311
                                                                                                                        {
2312
                                                                                                                                pLoopPlot->setBonusType((BonusTypes)iK);
2313
                                                                                                                                iCoastFoodCount += bCoast ? 1 : 0;
2314
                                                                                                                                iOceanFoodCount += bOcean ? 1 : 0;
2315
                                                                                                                                iOtherCount += !(bCoast || bOcean) ? 1 : 0;
2316
                                                                                                                                break;
2317
                                                                                                                        }
2318
                                                                                                                }
2319
                                                                                                        }
2320
                                                                                                }
2321
                                                                                        }
2322
                                                                                }
2323
 
2324
                                                                                if (bLandBias && !pLoopPlot->isWater() && pLoopPlot->getBonusType() == NO_BONUS)
2325
                                                                                {
2326
                                                                                        if (((iFeatureCount > 4) && (pLoopPlot->getFeatureType() != NO_FEATURE))
2327
                                                                                                && ((iCoastFoodCount + iOceanFoodCount) > 2))
2328
                                                                                        {
2329
                                                                                                if (getSorenRandNum(2, "Clear feature to add bonus") == 0)
2330
                                                                                                {
2331
                                                                                                        pLoopPlot->setFeatureType(NO_FEATURE);
2332
 
2333
                                                                                                        for (iK = 0; iK < GC.getNumBonusInfos(); iK++)
2334
                                                                                                        {
2335
                                                                                                                if (GC.getBonusInfo((BonusTypes)iK).isNormalize())
2336
                                                                                                                {
2337
                                                                                                                        //???no bonuses with negative yields?
2338
                                                                                                                        if ((GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_FOOD) >= 0) &&
2339
                                                                                                                                  (GC.getBonusInfo((BonusTypes)iK).getYieldChange(YIELD_PRODUCTION) >= 0))
2340
                                                                                                                        {
2341
                                                                                                                                if ((GC.getBonusInfo((BonusTypes)iK).getTechCityTrade() == NO_TECH) || (GC.getTechInfo&