~ubuntu-app-review-contributors/ubuntu-app-reviews/conquests

« back to all changes in this revision

Viewing changes to conquests/city.cpp

  • Committer: Andrew Mitchell
  • Author(s): Mark Harman
  • Date: 2012-09-22 08:42:00 UTC
  • Revision ID: ajmitch@ubuntu.com-20120922084200-okn4hegosnhkdnej
Tags: 1.2.1
* Fixed makefile for Ubuntu 12.04.
* Mousewheel zoom wasn't working when mouse was over minimap.
* Application icon.
* Display history for military strength too, under F5 scores screens.
* Improved method of not displaying the movement buttons (wasn't working
  right for high resolutions).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "conquests_stdafx.h"
 
2
 
 
3
#include "city.h"
 
4
#include "citywindow.h"
 
5
#include "civilization.h"
 
6
#include "buildable.h"
 
7
#include "technology.h"
 
8
#include "unit.h"
 
9
#include "maingamestate.h"
 
10
#include "map.h"
 
11
#include "infowindow.h"
 
12
 
 
13
#include "../Vision/VisionIface.h"
 
14
 
 
15
#include <cstring> // needed for Linux at least
 
16
 
 
17
#include <sstream>
 
18
using std::stringstream;
 
19
 
 
20
#include <map>
 
21
using std::multimap;
 
22
using std::pair;
 
23
 
 
24
int populations[] = {
 
25
        10000, // 1
 
26
        12500, // 2
 
27
        16000, // 3
 
28
        20000, // 4
 
29
        25000, // 5
 
30
        31000, // 6
 
31
        38000, // 7
 
32
        48000, // 8
 
33
        60000, // 9
 
34
        75000, // 10
 
35
        95000, // 11
 
36
        120000, // 12
 
37
        150000, // 13
 
38
        185000, // 14
 
39
        225000, // 15
 
40
        280000, // 16
 
41
        350000, // 17
 
42
        440000, // 18
 
43
        550000, // 19
 
44
        700000, // 20
 
45
        860000, // 21
 
46
        1100000, // 22
 
47
        1350000, // 23
 
48
        1700000, // 24
 
49
        2100000, // 25
 
50
        2650000, // 26
 
51
        3300000, // 27
 
52
        4000000 // 28
 
53
};
 
54
/*int populations[] = {
 
55
        10000, // 1
 
56
        14000, // 2
 
57
        20000, // 3
 
58
        27000, // 4
 
59
        38000, // 5
 
60
        54000, // 6
 
61
        75000, // 7
 
62
        100000  // 8
 
63
};*/
 
64
const int n_size_c = sizeof(populations)/sizeof(populations[0]);
 
65
 
 
66
City::City(MainGamestate *mainGamestate, Civilization *civilization, const char *name, int x, int y, int size) :
 
67
mainGamestate(mainGamestate), civilization(civilization), name(name), pos(x, y), size(size),
 
68
is_resisting(false), resisting_civilization(NULL), resistance(0),
 
69
needs_update(false),
 
70
progress_population(0),
 
71
progress_buildable(0), buildable(NULL),
 
72
counter_barracks(0) {
 
73
        //this->name = civilization->makeCityName();
 
74
        VI_log("New %s city of %s at %d, %d\n", civilization->getNameAdjective(), this->getName(), pos.x, pos.y);
 
75
        ASSERT( mainGamestate->getMap() != NULL );
 
76
        MapSquare *square = mainGamestate->getMap()->getSquare(x, y);
 
77
        ASSERT( square->getCity() == NULL );
 
78
        ASSERT( square->isLand() );
 
79
        ASSERT( square->canBuildCity() );
 
80
 
 
81
        civilization->addCity(this);
 
82
        square->setCity(this, true);
 
83
        if( square->getType() == TYPE_FOREST ) {
 
84
                square->setType(TYPE_GRASSLAND);
 
85
        }
 
86
        if( square->getBonusResource() != NULL ) {
 
87
                square->setBonusResource(NULL);
 
88
        }
 
89
        // initial element stocks
 
90
        for(size_t i=0;i<game_g->getGameData()->getNElements();i++) {
 
91
                const Element *element = game_g->getGameData()->getElement(i);
 
92
                this->element_stocks[element] = 0;
 
93
                if( element->getRequiresTechnology() != NULL && !this->civilization->hasTechnology(element->getRequiresTechnology()) ) {
 
94
                        continue;
 
95
                }
 
96
                if( element->getInitialAmount() > 0 ) {
 
97
                        this->element_stocks[element] = element->getInitialAmount();
 
98
                }
 
99
        }
 
100
        //this->civilization->uncover(this->pos.x, this->pos.y, 1); // normally shouldn't be needed, but just in case - also makes things easier for test suite
 
101
        // -> Now done in addCity(), above
 
102
        if( civilization != mainGamestate->getPlayer() ) {
 
103
                this->chooseAndSetBuildAI();
 
104
        }
 
105
        else {
 
106
                //const Buildable *buildable = game->findBuildable("Peasants");
 
107
                //this->setBuildable(buildable);
 
108
                this->setDefaultBuildable();
 
109
        }
 
110
}
 
111
 
 
112
City::City(MainGamestate *mainGamestate, Civilization *civilization) :
 
113
mainGamestate(mainGamestate), civilization(civilization), is_resisting(false), resisting_civilization(NULL), resistance(0), pos(-1, -1), size(-1),
 
114
needs_update(false),
 
115
progress_population(-1),
 
116
progress_buildable(-1), buildable(NULL),
 
117
counter_barracks(-1) {
 
118
        // create dummy city, used by City::load()
 
119
 
 
120
        // initialise just to fill up the entries (so don't have to worry about find() failing)
 
121
        for(size_t i=0;i<game_g->getGameData()->getNElements();i++) {
 
122
                const Element *element = game_g->getGameData()->getElement(i);
 
123
                this->element_stocks[element] = 0;
 
124
        }
 
125
}
 
126
 
 
127
City::~City() {
 
128
        VI_log("Destroy city of %s\n", this->getName());
 
129
        // Don't delete improvements, as they are not copies!
 
130
        if( civilization != NULL ) {
 
131
                civilization->removeCity(this);
 
132
        }
 
133
        ASSERT( mainGamestate->getMap() != NULL );
 
134
        MapSquare *square = mainGamestate->getMap()->getSquare(pos.x, pos.y);
 
135
        ASSERT( square->getCity() != NULL );
 
136
        square->setCity(NULL, true);
 
137
        /*if( square->getCity() != NULL ) {
 
138
                // n.b., square info may already have been cleared
 
139
                square->setCity(NULL);
 
140
        }*/
 
141
}
 
142
 
 
143
City *City::load(MainGamestate *mainGamestate, Civilization *civilization, FILE *file) {
 
144
        const int max_line_c = 4095;
 
145
        char line[max_line_c+1] = "";
 
146
        char word[max_line_c+1] = "";
 
147
        bool found_end = false;
 
148
        bool ok = true;
 
149
        const char field_xpos_c[] = "xpos=";
 
150
        const char field_ypos_c[] = "ypos=";
 
151
        const char field_name_c[] = "name=";
 
152
        const char field_size_c[] = "size=";
 
153
        const char field_progress_population_c[] = "progress_population=";
 
154
        const char field_progress_buildable_c[] = "progress_buildable=";
 
155
        const char field_buildable_c[] = "buildable=";
 
156
        const char field_improvement_c[] = "improvement=";
 
157
        const char field_element_stocks_c[] = "element_stocks=";
 
158
        const char field_amount_c[] = "amount=";
 
159
        const char field_counter_barracks_c[] = "counter_barracks=";
 
160
 
 
161
        City *city = new City(mainGamestate, civilization);
 
162
 
 
163
        while( ok && fgets(line, max_line_c, file) != NULL ) {
 
164
                //if( strcmp(line, "[/city]\n") == 0 ) {
 
165
                if( matchFileLine(line, "[/city]") ) {
 
166
                        found_end = true;
 
167
                        break;
 
168
                }
 
169
                if( line[0] == '[' ) {
 
170
                        VI_log("City::load: Unexpected '[' start of new section!\n");
 
171
                        ok = false;
 
172
                        break;
 
173
                }
 
174
                if( matchFileLine(line, field_xpos_c) ) {
 
175
                        parseFileLine(word, line, field_xpos_c);
 
176
                        city->pos.x = atoi(word);
 
177
                }
 
178
                else if( matchFileLine(line, field_ypos_c) ) {
 
179
                        parseFileLine(word, line, field_ypos_c);
 
180
                        city->pos.y = atoi(word);
 
181
                }
 
182
                else if( matchFileLine(line, field_name_c) ) {
 
183
                        parseFileLine(word, line, field_name_c);
 
184
                        city->name = word;
 
185
                }
 
186
                else if( matchFileLine(line, field_size_c) ) {
 
187
                        parseFileLine(word, line, field_size_c);
 
188
                        city->size = atoi(word);
 
189
                }
 
190
                else if( matchFileLine(line, field_progress_population_c) ) {
 
191
                        parseFileLine(word, line, field_progress_population_c);
 
192
                        city->progress_population = atoi(word);
 
193
                }
 
194
                else if( matchFileLine(line, field_progress_buildable_c) ) {
 
195
                        parseFileLine(word, line, field_progress_buildable_c);
 
196
                        city->progress_buildable = atoi(word);
 
197
                }
 
198
                else if( matchFileLine(line, field_buildable_c) ) {
 
199
                        parseFileLine(word, line, field_buildable_c);
 
200
                        if( strcmp(word, "null") == 0 ) {
 
201
                                city->buildable = NULL;
 
202
                        }
 
203
                        else {
 
204
                                city->buildable = game_g->findBuildable(word);
 
205
                                if( city->buildable == NULL ) {
 
206
                                        VI_log("City::load: can't find buildable: %s\n", word);
 
207
                                        ok = false;
 
208
                                }
 
209
                        }
 
210
                }
 
211
                else if( matchFileLine(line, field_improvement_c) ) {
 
212
                        parseFileLine(word, line, field_improvement_c);
 
213
                        const Improvement *improvement = game_g->findImprovement(word);
 
214
                        if( improvement == NULL ) {
 
215
                                VI_log("City::load: can't find improvement: %s\n", word);
 
216
                                ok = false;
 
217
                        }
 
218
                        else {
 
219
                                city->improvements.push_back(improvement); // don't copy, just pass a pointer
 
220
                        }
 
221
                }
 
222
                else if( matchFileLine(line, field_element_stocks_c) ) {
 
223
                        parseFileLine(word, line, field_element_stocks_c);
 
224
                        const Element *element = game_g->getGameData()->findElement(word);
 
225
                        if( element == NULL ) {
 
226
                                VI_log("City::load: can't find element: %s\n", word);
 
227
                                ok = false;
 
228
                        }
 
229
                        else {
 
230
                                if( fgets(line, max_line_c, file) == NULL ) {
 
231
                                        VI_log("unexpected eof after element %s\n", word);
 
232
                                        ok = false;
 
233
                                }
 
234
                                else {
 
235
                                        if( matchFileLine(line, field_amount_c) ) {
 
236
                                                parseFileLine(word, line, field_amount_c);
 
237
                                                city->element_stocks[element] = atoi(word);
 
238
                                        }
 
239
                                        else {
 
240
                                                VI_log("failed to find amount for element %s\n", word);
 
241
                                                ok = false;
 
242
                                        }
 
243
                                }
 
244
                        }
 
245
                }
 
246
                else if( matchFileLine(line, field_counter_barracks_c) ) {
 
247
                        parseFileLine(word, line, field_counter_barracks_c);
 
248
                        city->counter_barracks = atoi(word);
 
249
                }
 
250
        }
 
251
        if( !found_end ) {
 
252
                VI_log("City::load: didn't find end section\n");
 
253
                ok = false;
 
254
        }
 
255
        else if( city->pos.x == -1 || city->pos.y == -1 ) {
 
256
                VI_log("City::load: didn't find position\n");
 
257
                ok = false;
 
258
        }
 
259
        // TODO: check all fields have been set
 
260
 
 
261
        if( ok ) {
 
262
                civilization->addCity(city);
 
263
                MapSquare *square = mainGamestate->getMap()->getSquare(city->pos);
 
264
                ASSERT( square->getCity() == NULL );
 
265
                square->setCity(city, false); // territory is updated at end of loading
 
266
        }
 
267
        else {
 
268
                delete city;
 
269
                city = NULL;
 
270
        }
 
271
        return city;
 
272
}
 
273
 
 
274
void City::save(FILE *file) const {
 
275
        fprintf(file, "[city]\n");
 
276
        fprintf(file, "xpos=%d\n", pos.x);
 
277
        fprintf(file, "ypos=%d\n", pos.y);
 
278
        fprintf(file, "name=%s\n", name.c_str());
 
279
        fprintf(file, "size=%d\n", size);
 
280
        fprintf(file, "progress_population=%d\n", progress_population);
 
281
        fprintf(file, "progress_buildable=%d\n", progress_buildable);
 
282
        fprintf(file, "buildable=%s\n", buildable == NULL ? "null" : buildable->getName());
 
283
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
284
                const Improvement *improvement = *iter;
 
285
                fprintf(file, "improvement=%s\n", improvement->getName());
 
286
        }
 
287
        fprintf(file, "counter_barracks=%d\n", counter_barracks);
 
288
        for(map<const Element *, int>::const_iterator iter = this->element_stocks.begin(); iter != this->element_stocks.end(); ++iter) {
 
289
                fprintf(file, "element_stocks=%s\n", iter->first->getName());
 
290
                fprintf(file, "amount=%d\n", iter->second);
 
291
        }
 
292
        fprintf(file, "[/city]\n");
 
293
}
 
294
 
 
295
void City::modifyForResistance(int *value) const {
 
296
        if( this->is_resisting ) {
 
297
                ASSERT( resistance > 0 && resistance <= 100 );
 
298
                int mult = 100 - resistance;
 
299
                int new_value = (mult * (*value)) / 100;
 
300
                *value = new_value;
 
301
        }
 
302
}
 
303
 
 
304
void City::modifyForDifficulty(int *value, bool science) const {
 
305
        if( this->civilization == mainGamestate->getPlayer() ) {
 
306
                return;
 
307
        }
 
308
        //const int min_value = science ? 3 : 2;
 
309
        int min_value = 3;
 
310
        /*if( !science && mainGamestate->getDifficulty() != MainGamestate::DIFFICULTY_EASY && mainGamestate->getDifficulty() != MainGamestate::DIFFICULTY_MEDIUM ) {
 
311
                min_value = 2;
 
312
        }*/
 
313
        if( *value < min_value ) {
 
314
                // try to hide the obviousness of this, by only introducing the change when civilizations are a non-trivial size
 
315
                return;
 
316
        }
 
317
        int mult = 100;
 
318
        switch( mainGamestate->getDifficulty() ) {
 
319
                case MainGamestate::DIFFICULTY_EASY:
 
320
                        mult = 75;
 
321
                        break;
 
322
                case MainGamestate::DIFFICULTY_MEDIUM:
 
323
                        mult = 100;
 
324
                        break;
 
325
                case MainGamestate::DIFFICULTY_HARD:
 
326
                        //mult = 150;
 
327
                        // production needs a higher value, to make the increase comparable
 
328
                        mult = science ? 150 : 165;
 
329
                        break;
 
330
                case MainGamestate::DIFFICULTY_INSANE:
 
331
                        mult = 200;
 
332
                        break;
 
333
                default:
 
334
                        ASSERT( false );
 
335
                        break;
 
336
        }
 
337
        int new_value = (mult * (*value)) / 100;
 
338
        /*if( *value > 0 && new_value == 0 ) {
 
339
                // don't round down to 0
 
340
                new_value = 1;
 
341
        }*/
 
342
        if( *value < min_value ) {
 
343
                *value = min_value; // don't go below the min value
 
344
        }
 
345
        *value = new_value;
 
346
}
 
347
 
 
348
const int n_city_squares_c = 21;
 
349
const int centre_city_square_c = 10;
 
350
 
 
351
// remember to check if isValid before using it!
 
352
Pos2D City::getCitySquare(const Map *map, int i, Pos2D pos) {
 
353
        ASSERT( i >= 0 && i < n_city_squares_c );
 
354
        Pos2D npos;
 
355
        switch( i ) {
 
356
                case 0:
 
357
                        npos = Pos2D(pos.x - 1, pos.y - 2);
 
358
                        break;
 
359
                case 1:
 
360
                        npos = Pos2D(pos.x, pos.y - 2);
 
361
                        break;
 
362
                case 2:
 
363
                        npos = Pos2D(pos.x + 1, pos.y - 2);
 
364
                        break;
 
365
                case 3:
 
366
                        npos = Pos2D(pos.x - 2, pos.y - 1);
 
367
                        break;
 
368
                case 4:
 
369
                        npos = Pos2D(pos.x - 1, pos.y - 1);
 
370
                        break;
 
371
                case 5:
 
372
                        npos = Pos2D(pos.x, pos.y - 1);
 
373
                        break;
 
374
                case 6:
 
375
                        npos = Pos2D(pos.x + 1, pos.y - 1);
 
376
                        break;
 
377
                case 7:
 
378
                        npos = Pos2D(pos.x + 2, pos.y - 1);
 
379
                        break;
 
380
                case 8:
 
381
                        npos = Pos2D(pos.x - 2, pos.y);
 
382
                        break;
 
383
                case 9:
 
384
                        npos = Pos2D(pos.x - 1, pos.y);
 
385
                        break;
 
386
                case 10:
 
387
                        npos = Pos2D(pos.x, pos.y);
 
388
                        break;
 
389
                case 11:
 
390
                        npos = Pos2D(pos.x + 1, pos.y);
 
391
                        break;
 
392
                case 12:
 
393
                        npos = Pos2D(pos.x + 2, pos.y);
 
394
                        break;
 
395
                case 13:
 
396
                        npos = Pos2D(pos.x - 2, pos.y + 1);
 
397
                        break;
 
398
                case 14:
 
399
                        npos = Pos2D(pos.x - 1, pos.y + 1);
 
400
                        break;
 
401
                case 15:
 
402
                        npos = Pos2D(pos.x, pos.y + 1);
 
403
                        break;
 
404
                case 16:
 
405
                        npos = Pos2D(pos.x + 1, pos.y + 1);
 
406
                        break;
 
407
                case 17:
 
408
                        npos = Pos2D(pos.x + 2, pos.y + 1);
 
409
                        break;
 
410
                case 18:
 
411
                        npos = Pos2D(pos.x - 1, pos.y + 2);
 
412
                        break;
 
413
                case 19:
 
414
                        npos = Pos2D(pos.x, pos.y + 2);
 
415
                        break;
 
416
                case 20:
 
417
                        npos = Pos2D(pos.x + 1, pos.y + 2);
 
418
                        break;
 
419
                default:
 
420
                        ASSERT( false );
 
421
                        break;
 
422
        }
 
423
        map->reduceToBase(&npos.x, &npos.y);
 
424
        return npos;
 
425
}
 
426
 
 
427
// remember to check if isValid before using it!
 
428
Pos2D City::getCitySquare(int i) const {
 
429
        return getCitySquare(mainGamestate->getMap(), i, pos);
 
430
}
 
431
 
 
432
int City::getCentreCitySquareIndex() {
 
433
        return centre_city_square_c;
 
434
}
 
435
 
 
436
int City::getNCitySquares() {
 
437
        return n_city_squares_c;
 
438
}
 
439
 
 
440
/*Pos2D City::getAdjacentSquare(int i) const {
 
441
        ASSERT( i >= 0 && i < 8 );
 
442
        switch( i ) {
 
443
                case 0:
 
444
                        return Pos2D(pos.x - 1, pos.y - 1);
 
445
                        break;
 
446
                case 1:
 
447
                        return Pos2D(pos.x, pos.y - 1);
 
448
                        break;
 
449
                case 2:
 
450
                        return Pos2D(pos.x + 1, pos.y - 1);
 
451
                        break;
 
452
                case 3:
 
453
                        return Pos2D(pos.x - 1, pos.y);
 
454
                        break;
 
455
                case 4:
 
456
                        return Pos2D(pos.x + 1, pos.y);
 
457
                        break;
 
458
                case 5:
 
459
                        return Pos2D(pos.x - 1, pos.y + 1);
 
460
                        break;
 
461
                case 6:
 
462
                        return Pos2D(pos.x, pos.y + 1);
 
463
                        break;
 
464
                case 7:
 
465
                        return Pos2D(pos.x + 1, pos.y + 1);
 
466
                        break;
 
467
        }
 
468
        ASSERT( false );
 
469
        return Pos2D(-1, -1); // won't actually reach here
 
470
}*/
 
471
 
 
472
bool City::isOnOrAdjacent(Type mapType) const {
 
473
        /*for(int i=0;i<8;i++) {
 
474
                MapSquare *square = game->getMap()->getSquare( getAdjacentSquare(i) );
 
475
                if( square->getType() == mapType ) {
 
476
                        return true;
 
477
                }
 
478
        }
 
479
        return false;*/
 
480
        return mainGamestate->getMap()->isOnOrAdjacent(pos, mapType);
 
481
}
 
482
 
 
483
string City::getStatsInfo() const {
 
484
        stringstream str;
 
485
        const Map *map = mainGamestate->getMap();
 
486
        const MapSquare *square = map->getSquare(this->pos);
 
487
        if( square->getType() == TYPE_DESERT || square->getType() == TYPE_ARTIC ) {
 
488
                str << "Slower growth due to " << square->getName() << ".\n";
 
489
        }
 
490
        if( map->isWithinCityRadius(this->pos, TYPE_FOREST, false) ) {
 
491
                str << "+1 city production due to Forest.\n";
 
492
        }
 
493
        int road_railways_bonus = calculateRoadRailwaysScienceBonus();
 
494
        if( road_railways_bonus > 0 ) {
 
495
                str << "+" << road_railways_bonus << " science due to Roads/Railways.\n";
 
496
        }
 
497
        for(int i=0;i<this->getNCitySquares();i++) {
 
498
                if( i == centre_city_square_c ) {
 
499
                        continue;
 
500
                }
 
501
                Pos2D sq_pos = this->getCitySquare(i);
 
502
                if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
 
503
                        continue;
 
504
                }
 
505
                const MapSquare *square = mainGamestate->getMap()->getSquare(sq_pos);
 
506
                const BonusResource *bonus_resource = square->getBonusResource();
 
507
                if( bonus_resource != NULL && bonus_resource->canUse(this) ) {
 
508
                        int bonus_production = bonus_resource->getBonusProduction();
 
509
                        int bonus_growth = bonus_resource->getBonusReduceGrowthTime();
 
510
                        if( bonus_production > 0 ) {
 
511
                                str << "+" << bonus_production << " production due to " << bonus_resource->getName() << " production bonus.\n";
 
512
                        }
 
513
                        if( bonus_growth > 0 ) {
 
514
                                str << "Faster growth due to " << bonus_resource->getName() << " trade bonus.\n";
 
515
                        }
 
516
                }
 
517
        }
 
518
        return str.str();
 
519
}
 
520
 
 
521
void City::capture(Civilization *new_civilization) {
 
522
        VI_log("%s city of %s captured by %s\n", this->civilization->getNameAdjective(), this->getName(), new_civilization->getName());
 
523
        const int init_resistance_c = 100;
 
524
        if( is_resisting && new_civilization == resisting_civilization ) {
 
525
                VI_log("city reclaimed back - stop resisting\n");
 
526
                this->is_resisting = false;
 
527
                this->resisting_civilization = NULL;
 
528
                this->resistance = 0;
 
529
        }
 
530
        else if( is_resisting ) {
 
531
                VI_log("reset resistance\n");
 
532
                // captured by someone else - city still identifies as the original civilization, but we reset the year
 
533
                this->resistance = init_resistance_c;
 
534
        }
 
535
        else if( this->size > 1 ) {
 
536
                VI_log("start resistance\n");
 
537
                this->is_resisting = true;
 
538
                this->resisting_civilization = civilization;
 
539
                this->resistance = init_resistance_c;
 
540
        }
 
541
        civilization->removeCity(this);
 
542
        // need to update territory as soon as the city is removed, so that it's valid when calling addCity (needed for when we make contact - otherwise we assertion fail if the civ is now wiped out, because their territory still exists
 
543
        this->mainGamestate->calculateTerritory();
 
544
        civilization = new_civilization;
 
545
        new_civilization->addCity(this);
 
546
        this->mainGamestate->calculateTerritory(); // now recalculate again, with the city belonging to the new civilization
 
547
        this->mainGamestate->refreshMapDisplay();
 
548
        this->civilization->uncover(this->pos.x, this->pos.y, 1);
 
549
        this->civilization->updateFogOfWarCity(this);
 
550
        this->initTravel(true, NULL); // reveal squares from harbour etc
 
551
        this->setBuildable(NULL); // always call this, to reset the production progress
 
552
        if( civilization == mainGamestate->getPlayer() ) {
 
553
                if( this->is_resisting && this->size > 1 && this->size < 10 ) {
 
554
                        string text = "The citizens are resisting our rule! Shall we use our troops to crush the resistance?";
 
555
                        if( InfoWindow::confirm(game_g->getGraphicsEnvironment(), mainGamestate->getPanel(), game_g->getFont(), game_g->getPanelTexture(), text.c_str(), "Yes", "No") ) {
 
556
                                this->resistance /= 2;
 
557
                                this->setSize( size-1 );
 
558
                        }
 
559
                }
 
560
                this->setDefaultBuildable();
 
561
                new CityWindow(mainGamestate, this);
 
562
        }
 
563
        else {
 
564
                this->chooseAndSetBuildAI();
 
565
        }
 
566
}
 
567
 
 
568
void City::setSize(int size) {
 
569
        this->size = size;
 
570
        VI_log("%s city of %s: size changed to %d\n", this->civilization->getNameAdjective(), this->getName(), size);
 
571
        ASSERT( size > 0 );
 
572
}
 
573
 
 
574
int City::getPopulation() const {
 
575
        /*int pop = 10000;
 
576
        for(int i=1;i<size;i++) {
 
577
                pop *= 1.1;
 
578
        }*/
 
579
        ASSERT( size >= 1 && size <= n_size_c );
 
580
        int population = populations[size-1];
 
581
        return population;
 
582
}
 
583
 
 
584
string City::getPopulationString() const {
 
585
        /*int pop = this->getPopulation();
 
586
        if( pop == 0 ) {
 
587
                return "0";
 
588
        }
 
589
        stringstream str;
 
590
        bool first = true;
 
591
        while( pop > 0 ) {
 
592
                stringstream temp;
 
593
                int mod_pop = pop % 1000;
 
594
                if( pop >= 1000 ) {
 
595
                        if( mod_pop < 10 )
 
596
                                temp << "00";
 
597
                        else if( mod_pop < 100 )
 
598
                                temp << "0";
 
599
                }
 
600
                temp <<  mod_pop;
 
601
                VI_log("temp: %s\n", temp.str().c_str());
 
602
                if( !first ) {
 
603
                        temp << ",";
 
604
                }
 
605
                else
 
606
                        first = false;
 
607
                str.str(temp.str() + str.str());
 
608
                VI_log("str: %s\n", str.str().c_str());
 
609
                pop /= 1000;
 
610
        }
 
611
        return str.str();*/
 
612
        int pop = this->getPopulation();
 
613
        T_ASSERT( pop > 0 );
 
614
        //stringstream str;
 
615
        //str << pop;
 
616
        /*int n = 0;
 
617
        int temp_pop = pop;
 
618
        while( temp_pop > 0 ) {
 
619
                temp_pop /= 10;
 
620
                n++;
 
621
        }*/
 
622
        /*stringstream base_str;
 
623
        base_str << pop;
 
624
        int n = 3 - (base_str.str().length() % 3);
 
625
        bool first = true;
 
626
        for(int i=0;i<base_str.str().length();i++) {
 
627
                if( !first && n % 3 == 0 ) {
 
628
                        str << ",";
 
629
                }
 
630
                first = false;
 
631
                n++;
 
632
                str << base_str.str().at(i);
 
633
        }
 
634
        return str.str();*/
 
635
        return formatNumber(pop);
 
636
}
 
637
 
 
638
int City::calculateProduction() const {
 
639
        // todo: cache the value?
 
640
        int production = getPopulation() / 10000;
 
641
        // improvements
 
642
        production += this->civilization->getCivBonusProduction();
 
643
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
644
                const Improvement *improvement = *iter;
 
645
                if( !this->improvementHasEffect(improvement) ) {
 
646
                        continue;
 
647
                }
 
648
                if( !improvement->getProductionBonusAllCities() ) {
 
649
                        production += improvement->getProductionBonus();
 
650
                }
 
651
        }
 
652
        // bonuses
 
653
        bool done_forest = false;
 
654
        for(int i=0;i<this->getNCitySquares();i++) {
 
655
                if( i == centre_city_square_c ) {
 
656
                        continue;
 
657
                }
 
658
                Pos2D sq_pos = this->getCitySquare(i);
 
659
                if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
 
660
                        continue;
 
661
                }
 
662
                const MapSquare *square = mainGamestate->getMap()->getSquare(sq_pos);
 
663
                if( !done_forest && square->getType() == TYPE_FOREST ) {
 
664
                        production++;
 
665
                        done_forest = true;
 
666
                }
 
667
                const BonusResource *bonus_resource = square->getBonusResource();
 
668
                if( bonus_resource != NULL ) {
 
669
                        /*bool bonus_ok = true;
 
670
                        if( bonus_ok && bonus_resource->getRequiresImprovement() != NULL ) {
 
671
                                if( !this->hasImprovement( bonus_resource->getRequiresImprovement() ) ) {
 
672
                                        bonus_ok = false;
 
673
                                }
 
674
                        }
 
675
                        if( bonus_ok && bonus_resource->getRequiresTechnology() != NULL ) {
 
676
                                if( !this->civilization->hasTechnology( bonus_resource->getRequiresTechnology() ) ) {
 
677
                                        bonus_ok = false;
 
678
                                }
 
679
                        }
 
680
                        if( bonus_ok )*/
 
681
                        if( bonus_resource->canUse(this) )
 
682
                                production += bonus_resource->getBonusProduction();
 
683
                }
 
684
        }
 
685
        //if( this->civilization->hasTechnology( game_g->getGameData()->findTechnology("Agricultural Revolution") ) ) {
 
686
        if( this->civilization->hasTechnology("Agricultural Revolution") ) {
 
687
                production += 2;
 
688
        }
 
689
        //if( this->civilization->hasTechnology( game_g->getGameData()->findTechnology("Industrial Revolution") ) ) {
 
690
        if( this->civilization->hasTechnology("Industrial Revolution") ) {
 
691
                production += 4;
 
692
        }
 
693
        modifyForResistance(&production);
 
694
        modifyForDifficulty(&production, false);
 
695
        if( this->civilization->hasBonus(Civilization::BONUS_PRODUCTION) ) {
 
696
                //production *= 1.5;
 
697
                production = (int)(production * 1.5);
 
698
        }
 
699
        return production;
 
700
}
 
701
 
 
702
int City::calculateRoadRailwaysScienceBonus() const {
 
703
        int road_bonus = 0;
 
704
        int rail_bonus = 0;
 
705
        for(int i=0;i<this->getNCitySquares();i++) {
 
706
                if( i == centre_city_square_c ) {
 
707
                        continue;
 
708
                }
 
709
                Pos2D sq_pos = this->getCitySquare(i);
 
710
                if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
 
711
                        continue;
 
712
                }
 
713
                const MapSquare *square = mainGamestate->getMap()->getSquare(sq_pos);
 
714
                /*if( square->getRoad() != ROAD_NONE ) {
 
715
                        if( square->givesRoadBonus() ) {
 
716
                                road_bonus++;
 
717
                                if( road_bonus == max_road_bonus_c ) {
 
718
                                        break;
 
719
                                }
 
720
                        }
 
721
                }*/
 
722
                if( square->givesRoadBonus() ) {
 
723
                        if( square->getRoad() == ROAD_BASIC ) {
 
724
                                road_bonus++;
 
725
                        }
 
726
                        else if( square->getRoad() == ROAD_RAILWAYS ) {
 
727
                                rail_bonus++;
 
728
                                //road_bonus++;
 
729
                        }
 
730
                }
 
731
        }
 
732
        rail_bonus = min(rail_bonus, max_road_bonus_c);
 
733
        road_bonus = min(road_bonus, max_road_bonus_c - rail_bonus);
 
734
        ASSERT( rail_bonus >= 0 );
 
735
        ASSERT( road_bonus >= 0 );
 
736
        int bonus = 2 * rail_bonus + road_bonus;
 
737
        return bonus;
 
738
}
 
739
 
 
740
int City::calculateScience() const {
 
741
        // todo: cache the value?
 
742
        int science = getPopulation() / 20000;
 
743
        if( science == 0 )
 
744
                science = 1;
 
745
        // bonuses
 
746
        /*int road_bonus = 0;
 
747
        int rail_bonus = 0;
 
748
        for(int i=0;i<this->getNCitySquares();i++) {
 
749
                if( i == centre_city_square_c ) {
 
750
                        continue;
 
751
                }
 
752
                Pos2D sq_pos = this->getCitySquare(i);
 
753
                if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
 
754
                        continue;
 
755
                }
 
756
                const MapSquare *square = mainGamestate->getMap()->getSquare(sq_pos);
 
757
                if( square->givesRoadBonus() ) {
 
758
                        if( square->getRoad() == ROAD_BASIC ) {
 
759
                                road_bonus++;
 
760
                        }
 
761
                        else if( square->getRoad() == ROAD_RAILWAYS ) {
 
762
                                rail_bonus++;
 
763
                                //road_bonus++;
 
764
                        }
 
765
                }
 
766
        }
 
767
        rail_bonus = min(rail_bonus, max_road_bonus_c);
 
768
        road_bonus = min(road_bonus, max_road_bonus_c - rail_bonus);
 
769
        ASSERT( rail_bonus >= 0 );
 
770
        ASSERT( road_bonus >= 0 );
 
771
        science += 2 * rail_bonus;
 
772
        science += road_bonus;*/
 
773
        science += calculateRoadRailwaysScienceBonus();
 
774
 
 
775
        if( this->hasImprovement("School") ) {
 
776
                // increases base, so do before multiplier modifiers
 
777
                science += 2;
 
778
        }
 
779
 
 
780
        int base_science = science;
 
781
 
 
782
        // improvements
 
783
        science += (base_science*this->civilization->getCivBonusResearchMultiplier())/100;
 
784
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
785
                const Improvement *improvement = *iter;
 
786
                if( !this->improvementHasEffect(improvement) ) {
 
787
                        continue;
 
788
                }
 
789
                if( !improvement->getResearchMultiplierBonusAllCities() ) {
 
790
                        science += (base_science*improvement->getResearchMultiplierBonus())/100;
 
791
                }
 
792
        }
 
793
        // hardcoded improvements
 
794
        /*if( this->hasImprovement("Library") ) {
 
795
                science += base_science/2;
 
796
        }*/
 
797
        if( this->hasImprovement("University") ) {
 
798
                // +50% is already handled, but still need to do Scientific Method
 
799
                //science += base_science/2;
 
800
                //if( this->civilization->hasTechnology( mainGamestate->findTechnology("Scientific Method") ) ) {
 
801
                if( this->civilization->hasTechnology("Scientific Method") ) {
 
802
                        science += base_science/20;
 
803
                }
 
804
        }
 
805
 
 
806
        modifyForResistance(&science);
 
807
        modifyForDifficulty(&science, true);
 
808
        if( this->civilization->hasBonus(Civilization::BONUS_TECH) ) {
 
809
                science *= 2;
 
810
        }
 
811
        return science;
 
812
}
 
813
 
 
814
bool City::improvementHasEffect(const Improvement *improvement) const {
 
815
        const Technology *obsoleted_by = improvement->getObsoletedBy();
 
816
        if( obsoleted_by != NULL && this->civilization->hasTechnology(obsoleted_by) ) {
 
817
                return false;
 
818
        }
 
819
        const Buildable *replaced_by = improvement->getReplacedBy();
 
820
        if( replaced_by != NULL ) {
 
821
                ASSERT( replaced_by->getType() == Buildable::TYPE_IMPROVEMENT );
 
822
                const Improvement *replaced_by_improvement = static_cast<const Improvement *>(replaced_by);
 
823
                if( this->hasImprovement(replaced_by_improvement) ) {
 
824
                        return false;
 
825
                }
 
826
        }
 
827
        return true;
 
828
}
 
829
 
 
830
int City::calculatePowerPerTurn() const {
 
831
        // n.b., should not be modified for AIs due to difficulty level!
 
832
        //int power_per_turn = 0;
 
833
        int power_per_turn = getPopulation() / 10000;
 
834
        if( power_per_turn > 0 )
 
835
                power_per_turn--;
 
836
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
837
                const Improvement *improvement = *iter;
 
838
                if( !this->improvementHasEffect(improvement) ) {
 
839
                        continue;
 
840
                }
 
841
 
 
842
                power_per_turn += improvement->getPowerPerTurn();
 
843
        }
 
844
        return power_per_turn;
 
845
}
 
846
 
 
847
int City::getResistance() const {
 
848
        ASSERT( this->is_resisting );
 
849
        return this->resistance;
 
850
}
 
851
 
 
852
int City::getPopulationCost() const {
 
853
        int cost = 10;
 
854
        MapSquare *square = mainGamestate->getMap()->getSquare(pos);
 
855
        if( square->getType() == TYPE_ARTIC || square->getType() == TYPE_DESERT ) {
 
856
                //cost *= 1.5;
 
857
                cost = (int)(cost * 1.5);
 
858
        }
 
859
        /*if( this->hasImprovement("Hospital") ) {
 
860
                //cost *= 0.8;
 
861
                cost = (int)(cost * 0.8);
 
862
        }*/
 
863
        for(vector<const Improvement *>::const_iterator iter = improvements.begin(); iter != improvements.end(); ++iter) {
 
864
                const Improvement *improvement = *iter;
 
865
                if( this->improvementHasEffect(improvement) ) {
 
866
                        cost += improvement->getGrowthRate();
 
867
                }
 
868
        }
 
869
        //if( this->civilization->hasTechnology( mainGamestate->findTechnology("Genetics") ) ) {
 
870
        if( this->civilization->hasTechnology("Genetics") ) {
 
871
                //cost *= 0.8;
 
872
                cost = (int)(cost * 0.8);
 
873
        }
 
874
        for(int i=0;i<this->getNCitySquares();i++) {
 
875
                if( i == centre_city_square_c ) {
 
876
                        continue;
 
877
                }
 
878
                Pos2D sq_pos = this->getCitySquare(i);
 
879
                if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
 
880
                        continue;
 
881
                }
 
882
                const MapSquare *square = mainGamestate->getMap()->getSquare(sq_pos);
 
883
                const BonusResource *bonus_resource = square->getBonusResource();
 
884
                if( bonus_resource != NULL ) {
 
885
                        /*bool bonus_ok = true;
 
886
                        if( bonus_ok && bonus_resource->getRequiresImprovement() != NULL ) {
 
887
                                if( !this->hasImprovement( bonus_resource->getRequiresImprovement() ) ) {
 
888
                                        bonus_ok = false;
 
889
                                }
 
890
                        }
 
891
                        if( bonus_ok && bonus_resource->getRequiresTechnology() != NULL ) {
 
892
                                if( !this->civilization->hasTechnology( bonus_resource->getRequiresTechnology() ) ) {
 
893
                                        bonus_ok = false;
 
894
                                }
 
895
                        }
 
896
                        if( bonus_ok )*/
 
897
                        if( bonus_resource->canUse(this) )
 
898
                                cost -= bonus_resource->getBonusReduceGrowthTime();
 
899
                }
 
900
        }
 
901
        cost = max(cost, 2);
 
902
        return cost;
 
903
}
 
904
 
 
905
void City::addImprovement(const Improvement *improvement) {
 
906
        this->improvements.push_back(improvement); // don't copy, just pass a pointer
 
907
 
 
908
        //if( improvement->getImprovementType() == IMPROVEMENT_HARBOUR ) { // test not necessary, but just to help performance
 
909
        if( improvement->getTravelRange() > 0 ) { // test not necessary, but just to help performance
 
910
                initTravel(true, NULL);
 
911
        }
 
912
 
 
913
        if( this->civilization == mainGamestate->getPlayer() ) {
 
914
                mainGamestate->centre(this->pos);
 
915
                stringstream text;
 
916
                if( improvement->getRaceSpecific() != NULL ) {
 
917
                        text << this->getName() << " has built a great project!: " << buildable->getName() << ".";
 
918
                }
 
919
                else {
 
920
                        text << this->getName() << " has built: " << buildable->getName() << ".";
 
921
                }
 
922
                mainGamestate->playSound(MainGamestate::SOUND_COMPLETE);
 
923
                InfoWindow *window = new InfoWindow(game_g->getGraphicsEnvironment(), mainGamestate->getPanel(), text.str(), game_g->getFont(), game_g->getPanelTexture(), infowindow_def_x_c, infowindow_def_y_c, infowindow_def_w_c, 128);
 
924
                window->doModal();
 
925
                delete window;
 
926
        }
 
927
        else if( improvement->getRaceSpecific() != NULL ) {
 
928
                // n.b., notify player even if we haven't made contact with the civilization
 
929
                stringstream text;
 
930
                text << "The " << improvement->getRaceSpecific()->getNameAdjective() << " city of " << this->getName() << " has built a great project!: " << buildable->getName() << ".";
 
931
                InfoWindow *window = new InfoWindow(game_g->getGraphicsEnvironment(), mainGamestate->getPanel(), text.str(), game_g->getFont(), game_g->getPanelTexture(), infowindow_def_x_c, infowindow_def_y_c, infowindow_def_w_c, 128);
 
932
                window->doModal();
 
933
                delete window;
 
934
        }
 
935
}
 
936
 
 
937
// Called by the Test routines - this resets the current buildable if it's the improvement being added, but doesn't choose or ask for a new buildable.
 
938
void City::addImprovementTest(const Improvement *improvement) {
 
939
        this->addImprovement(improvement);
 
940
        if( this->buildable == improvement ) {
 
941
                // can't build this anymore
 
942
                this->buildable = NULL;
 
943
                this->progress_buildable = 0;
 
944
        }
 
945
}
 
946
 
 
947
void City::update() {
 
948
        /*if( !needs_update ) {
 
949
                return;
 
950
        }*/
 
951
        //VI_log("Updating the city of %s ( %d )\n", getName(), this);
 
952
        ASSERT( needs_update ); // should only be called if update is needed!
 
953
        bool open_citywindow = false;
 
954
 
 
955
        // update element stocks
 
956
        for(size_t i=0;i<game_g->getGameData()->getNElements();i++) {
 
957
                const Element *element = game_g->getGameData()->getElement(i);
 
958
                if( element->getRequiresTechnology() != NULL && !this->civilization->hasTechnology(element->getRequiresTechnology()) ) {
 
959
                        continue;
 
960
                }
 
961
                if( element->getRequiresImprovement() != NULL && !this->hasImprovementOrNewer(element->getRequiresImprovement()) ) {
 
962
                        continue;
 
963
                }
 
964
                this->element_stocks[element] += element->getBaseRate();
 
965
                int total = 0;
 
966
                for(int j=0;j<this->getNCitySquares();j++) {
 
967
                        Pos2D pos = this->getCitySquare(j);
 
968
                        if( this->mainGamestate->getMap()->isValid(pos.x, pos.y) ) {
 
969
                                const MapSquare *square = this->mainGamestate->getMap()->getSquare(pos);
 
970
                                int terrain_rate = element->getTerrainRate( square->getType() );
 
971
                                this->element_stocks[element] += terrain_rate;
 
972
                                int bonus_rate = element->getBonusRate( square->getBonusResource() );
 
973
                                this->element_stocks[element] += bonus_rate;
 
974
                                total += terrain_rate;
 
975
                                total += bonus_rate;
 
976
                        }
 
977
                }
 
978
                /*if( total > 0 ) {
 
979
                        VI_log("%s city of %s receives %d of %s\n", this->civilization->getNameAdjective(), this->getName(), total, element->getName());
 
980
                }*/
 
981
 
 
982
                const int max_stock_c = 200;
 
983
                if( this->element_stocks[element] > max_stock_c ) {
 
984
                        if( this->civilization->hasTechnology( game_g->findTechnology("Steam Power") ) ) {
 
985
                                //set<City *, 
 
986
                                //VI_log("%s city of %s distributes %s:\n", this->civilization->getNameAdjective(), this->getName(), element->getName());
 
987
                                // we use a multimap, to sort the Cities by the stocks for this element, so we give to the cities with smaller stock first
 
988
                                multimap<int, City *> cities;
 
989
                                for(size_t j=0;j<this->civilization->getNCities() && this->element_stocks[element] > max_stock_c;j++) {
 
990
                                        City *city = this->civilization->getCity(j);
 
991
                                        if( city == this )
 
992
                                                continue;
 
993
                                        if( city != this && city->element_stocks[element] < max_stock_c ) {
 
994
                                                cities.insert(pair<int, City *>(city->element_stocks[element], city));
 
995
                                        }
 
996
                                }
 
997
                                /*{
 
998
                                        // debug
 
999
                                        VI_log("candidate cities:\n");
 
1000
                                        for(multimap<int, City *>::iterator iter = cities.begin(); iter != cities.end(); ++iter) {
 
1001
                                                City *city = iter->second;
 
1002
                                                VI_log("    %s : %d\n", city->getName(), city->element_stocks[element]);
 
1003
                                        }
 
1004
                                }*/
 
1005
                                while( this->element_stocks[element] > max_stock_c ) {
 
1006
                                        bool any = false;
 
1007
                                        for(multimap<int, City *>::iterator iter = cities.begin(); iter != cities.end() && this->element_stocks[element] > max_stock_c; ++iter) {
 
1008
                                                City *city = iter->second;
 
1009
                                                if( city->element_stocks[element] < max_stock_c ) {
 
1010
                                                        // need to check again, as it may have increased to the maximum
 
1011
                                                        // also note that increasing stocks won't change its ordering in the cities multimap (as we don't change a key), but this is intended behaviour
 
1012
                                                        //VI_log("%s city of %s gave 1 of %s to %s\n", this->civilization->getNameAdjective(), this->getName(), element->getName(), city->getName());
 
1013
                                                        this->element_stocks[element]--;
 
1014
                                                        city->element_stocks[element]++;
 
1015
                                                        any = true;
 
1016
                                                }
 
1017
                                        }
 
1018
                                        if( !any ) {
 
1019
                                                // no more cities with spare stock space to give to!
 
1020
                                                //VI_log("no more cities with spare stock space to give to\n");
 
1021
                                                break;
 
1022
                                        }
 
1023
                                }
 
1024
                                /*while( this->element_stocks[element] > max_stock_c ) {
 
1025
                                        VI_log(">>>>\n");
 
1026
                                        bool any = false;
 
1027
                                        for(size_t j=0;j<this->civilization->getNCities() && this->element_stocks[element] > max_stock_c;j++) {
 
1028
                                                City *city = this->civilization->getCity(j);
 
1029
                                                if( city == this )
 
1030
                                                        continue;
 
1031
                                                if( city->element_stocks[element] < max_stock_c ) {
 
1032
                                                        VI_log("%s city of %s gave 1 of %s to %s\n", this->civilization->getName(), this->getName(), element->getName(), city->getName());
 
1033
                                                        this->element_stocks[element]--;
 
1034
                                                        city->element_stocks[element]++;
 
1035
                                                        any = true;
 
1036
                                                }
 
1037
                                        }
 
1038
                                        if( !any ) {
 
1039
                                                // no more cities with spare stock space to give to!
 
1040
                                                VI_log("no more cities with spare stock space to give to\n");
 
1041
                                                break;
 
1042
                                        }
 
1043
                                        VI_log("<<<<\n");
 
1044
                                }*/
 
1045
                                //VI_log("done\n");
 
1046
                        }
 
1047
                        this->element_stocks[element] = min(this->element_stocks[element], max_stock_c);
 
1048
                }
 
1049
        }
 
1050
 
 
1051
        if( this->hasImprovement("Barracks") ) {
 
1052
                this->counter_barracks++;
 
1053
                if( this->counter_barracks >= barracks_turns_per_unit_c ) {
 
1054
                        const UnitTemplate *unit_template = NULL;
 
1055
                        unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Modern Infantry"));
 
1056
                        if( !this->canBuild(unit_template) ) {
 
1057
                                unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Infantry"));
 
1058
                        }
 
1059
                        if( !this->canBuild(unit_template) ) {
 
1060
                                unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Riflemen"));
 
1061
                        }
 
1062
                        if( !this->canBuild(unit_template) ) {
 
1063
                                unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Musketeers"));
 
1064
                        }
 
1065
                        if( !this->canBuild(unit_template) ) {
 
1066
                                unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Men-At-Arms"));
 
1067
                        }
 
1068
                        if( !this->canBuild(unit_template) ) {
 
1069
                                unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Swordsmen"));
 
1070
                        }
 
1071
                        if( !this->canBuild(unit_template) ) {
 
1072
                                unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Peasants"));
 
1073
                        }
 
1074
 
 
1075
                        VI_log("The %s city of %s produces barracks unit: %s\n", this->civilization->getNameAdjective(), this->getName(), unit_template->getName());
 
1076
 
 
1077
                        new Unit(mainGamestate, this->civilization, unit_template, this->getPos());
 
1078
                        // n.b., units produced from barracks aren't ever veterans, even if we have auto_veteran bonus
 
1079
                        useUpElements(unit_template);
 
1080
                        this->counter_barracks = 0;
 
1081
                }
 
1082
        }
 
1083
 
 
1084
        /*if( this->buildable == NULL ) {
 
1085
                new CityView(this);
 
1086
        }
 
1087
        else*/
 
1088
        if( this->buildable != NULL ) {
 
1089
                // first check if we can build a replacement
 
1090
                const Buildable *replaced_by = this->buildable->getReplacedBy();
 
1091
                if( replaced_by != NULL && this->canBuild(replaced_by) ) {
 
1092
                        this->buildable = replaced_by;
 
1093
                        // also need to use up any elements!
 
1094
                        useUpElements(this->buildable);
 
1095
                }
 
1096
 
 
1097
                if( this->progress_buildable == 0 ) {
 
1098
                        // just started building, so use up the elements
 
1099
                        /*if( this->buildable->getRequiresElement() != NULL ) {
 
1100
                                const Element *element = this->buildable->getRequiresElement();
 
1101
                                int amount = this->buildable->getRequiresElementAmount();
 
1102
                                T_ASSERT( amount > 0 );
 
1103
                                // it's possible to have too little stock, e.g., if multiple cities are building the same thing, and the stock runs too low; or if loading a game from an old version, when the required elements have since changed
 
1104
                                // as a workaround, we simply allow the player this one for free...
 
1105
                                this->element_stocks[element] -= amount;
 
1106
                                this->element_stocks[element] = max(this->element_stocks[element], 0);
 
1107
                        }*/
 
1108
                        useUpElements(this->buildable);
 
1109
                }
 
1110
 
 
1111
                this->progress_buildable += calculateProduction();
 
1112
 
 
1113
                if( this->progress_buildable >= buildable->getCost() ) {
 
1114
                        // built
 
1115
                        VI_log("The %s city of %s builds %s\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
1116
                        if( this->buildable->getType() == Buildable::TYPE_IMPROVEMENT ) {
 
1117
                                const Improvement *improvement = static_cast<const Improvement *>(this->buildable);
 
1118
                                this->addImprovement(improvement);
 
1119
                                this->setBuildable(NULL); // can't build improvement anymore
 
1120
                                if( civilization == mainGamestate->getPlayer() ) {
 
1121
                                        // ask for new buildable
 
1122
                                        open_citywindow = true;
 
1123
                                        // if built an improvement, use the AI to pick a default next buildable
 
1124
                                        this->chooseAndSetBuildAI();
 
1125
                                        if( this->buildable == NULL ) {
 
1126
                                                this->setDefaultBuildable();
 
1127
                                        }
 
1128
                                }
 
1129
                        }
 
1130
                        else if( this->buildable->getType() == Buildable::TYPE_UNIT ) {
 
1131
                                const UnitTemplate *unit_template = static_cast<const UnitTemplate *>(this->buildable);
 
1132
                                Unit *unit = new Unit(mainGamestate, this->civilization, unit_template, this->getPos());
 
1133
                                bool auto_veteran = this->civilization->getCivBonusAutoVeteran();
 
1134
                                for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end() && !auto_veteran; ++iter) {
 
1135
                                        const Improvement *improvement = *iter;
 
1136
                                        if( !this->improvementHasEffect(improvement) ) {
 
1137
                                                continue;
 
1138
                                        }
 
1139
                                        if( improvement->getAutoVeteranBonus() ) {
 
1140
                                                auto_veteran = true;
 
1141
                                        }
 
1142
                                }
 
1143
                                if( auto_veteran ) {
 
1144
                                        unit->setVeteran(true);
 
1145
                                }
 
1146
                                if( !this->canBuild( this->buildable ) ) {
 
1147
                                        // can't build this anymore - could happen if necessary improvement destroyed, for example
 
1148
                                        this->buildable = NULL;
 
1149
                                        if( civilization == mainGamestate->getPlayer() ) {
 
1150
                                                // n.b., don't open a window for units
 
1151
                                                this->setDefaultBuildable();
 
1152
                                        }
 
1153
                                }
 
1154
                        }
 
1155
                        else {
 
1156
                                VI_log("Unknown type: %s\n", this->buildable->getName());
 
1157
                                ASSERT(false);
 
1158
                        }
 
1159
                        // reset
 
1160
                        this->progress_buildable = 0;
 
1161
                        /*if( !this->canBuild( this->buildable ) ) {
 
1162
                                // can't build this anymore (usually means it's an Improvement, but could apply to Units hypothetically...
 
1163
                                this->buildable = NULL;
 
1164
                                if( civilization == mainGamestate->getPlayer() ) {
 
1165
                                        open_citywindow = true;
 
1166
                                        this->setDefaultBuildable();
 
1167
                                }
 
1168
                        }*/
 
1169
                        if( civilization != mainGamestate->getPlayer() ) {
 
1170
                                // do AI
 
1171
                                this->chooseAndSetBuildAI();
 
1172
                        }
 
1173
                }
 
1174
        }
 
1175
 
 
1176
        if( civilization->getTechnology() == NULL ) {
 
1177
                if( civilization == mainGamestate->getPlayer() ) {
 
1178
                        mainGamestate->askTechnology();
 
1179
                }
 
1180
                else {
 
1181
                        civilization->chooseTechnologyAI();
 
1182
                }
 
1183
        }
 
1184
        if( civilization->getTechnology() != NULL ) {
 
1185
                const Technology *was_researching = civilization->getTechnology(); // need to save, as it will be made NULL if we discover it!
 
1186
                if( this->civilization->updateProgressTechnology( calculateScience() ) ) {
 
1187
                        VI_log("%s discover %s\n", civilization->getName(), was_researching->getName());
 
1188
                        if( civilization == mainGamestate->getPlayer() ) {
 
1189
                                stringstream text;
 
1190
                                Age age  = civilization->getAge();
 
1191
                                if( (int)age >= (int)AGE_INDUSTRIAL )
 
1192
                                        text << "Our scientists have discovered the secrets of ";
 
1193
                                else
 
1194
                                        text << "Our wise men have discovered the secrets of ";
 
1195
                                text << was_researching->getName();
 
1196
                                text << "!";
 
1197
                                text << "\n\n";
 
1198
                                text << was_researching->getInfo();
 
1199
                                mainGamestate->playSound(MainGamestate::SOUND_COMPLETE);
 
1200
                                InfoWindow *window = new InfoWindow(game_g->getGraphicsEnvironment(), mainGamestate->getPanel(), text.str(), game_g->getFont(), game_g->getPanelTexture(), infowindow_def_x_c, infowindow_def_y_c, infowindow_def_w_c, 320);
 
1201
                                window->doModal();
 
1202
                                delete window;
 
1203
                                mainGamestate->askTechnology();
 
1204
                        }
 
1205
                        else {
 
1206
                                civilization->chooseTechnologyAI();
 
1207
                        }
 
1208
                }
 
1209
        }
 
1210
 
 
1211
        this->civilization->updatePower( this->calculatePowerPerTurn() );
 
1212
 
 
1213
        int max_size = 0;
 
1214
        if( !this->hasImprovement("Farmland") )
 
1215
                max_size = size_limit_farmland_c;
 
1216
        else if( !this->hasImprovement("Aqueduct") )
 
1217
                max_size = size_limit_aqueduct_c;
 
1218
        //else if( !this->civilization->hasTechnology( mainGamestate->findTechnology("Agricultural Revolution") ) )
 
1219
        else if( !this->civilization->hasTechnology("Agricultural Revolution") )
 
1220
                max_size = size_limit_agriculture_c;
 
1221
        //else if( !this->hasImprovement("Factory") || !this->civilization->hasTechnology( mainGamestate->findTechnology("Combustion") ) )
 
1222
        else if( !this->hasImprovement("Factory") || !this->civilization->hasTechnology("Combustion") )
 
1223
                max_size = size_limit_combustion_c;
 
1224
        else
 
1225
                max_size = n_size_c;
 
1226
        if( this->size <= max_size ) {
 
1227
                int increase = 1;
 
1228
                if( this->civilization->hasBonus(Civilization::BONUS_GROWTH) )
 
1229
                        increase = 2;
 
1230
                this->progress_population += increase;
 
1231
                int population_cost = getPopulationCost();
 
1232
                if( this->progress_population >= population_cost ) {
 
1233
                        if( this->size < max_size ) {
 
1234
                                this->progress_population = 0;
 
1235
                                //this->size++;
 
1236
                                this->setSize( size+1 );
 
1237
                                VI_log("%s city of %s grows to size %d\n", this->civilization->getNameAdjective(), this->getName(), this->size);
 
1238
                                if( civilization != mainGamestate->getPlayer() && this->progress_buildable == 0 ) {
 
1239
                                        // call AI routine again, as different city size may change our decision
 
1240
                                        this->chooseAndSetBuildAI();
 
1241
                                }
 
1242
                        }
 
1243
                        else {
 
1244
                                this->progress_population = population_cost;
 
1245
                        }
 
1246
                }
 
1247
        }
 
1248
        else if( this->size > 1 ) {
 
1249
                // city reduces in size!
 
1250
                this->progress_population--;
 
1251
                if( this->progress_population < 0 ) {
 
1252
                        int population_cost = getPopulationCost();
 
1253
                        this->progress_population = population_cost - 1;
 
1254
                        //this->size--;
 
1255
                        this->setSize( size-1 );
 
1256
                        VI_log("%s city of %s shrinks to size %d\n", this->civilization->getNameAdjective(), this->getName(), this->size);
 
1257
                }
 
1258
        }
 
1259
 
 
1260
        // update resistance
 
1261
        if( this->is_resisting ) {
 
1262
                const vector<Unit *> *units = mainGamestate->getMap()->findUnitsAt( this->pos );
 
1263
                int count = 1;
 
1264
                for(vector<Unit *>::const_iterator iter = units->begin(); iter != units->end(); ++iter) {
 
1265
                        const Unit *unit = *iter;
 
1266
                        if( unit->getTemplate()->getAttack() > 0 ) {
 
1267
                                count++;
 
1268
                        }
 
1269
                }
 
1270
                count = min(count, 4);
 
1271
                this->resistance -= 10 * count;
 
1272
                if( this->resistance <= 0 ) {
 
1273
                        this->is_resisting = false;
 
1274
                        this->resisting_civilization = NULL;
 
1275
                        this->resistance = 0;
 
1276
                }
 
1277
                VI_log("resistance of %s falls to %d\n", this->getName(), this->resistance);
 
1278
        }
 
1279
 
 
1280
        needs_update = false;
 
1281
        if( open_citywindow ) {
 
1282
                new CityWindow(mainGamestate, this);
 
1283
        }
 
1284
}
 
1285
 
 
1286
void City::useUpElements(const Buildable *b) {
 
1287
        for(size_t i=0;i<game_g->getGameData()->getNElements();i++) {
 
1288
                const Element *element = game_g->getGameData()->getElement(i);
 
1289
                int amount = b->getRequiresElementAmount(element);
 
1290
                if( amount > 0 ) {
 
1291
                        this->element_stocks[element] -= amount;
 
1292
                        // theoretically the stock should never fall below 0 (we should only be calling this on buildables that the city can build!), but just in case, allow the player to get away with it...
 
1293
                        this->element_stocks[element] = max(this->element_stocks[element], 0);
 
1294
                }
 
1295
        }
 
1296
}
 
1297
 
 
1298
bool City::canLaunch(const UnitTemplate *unit_template) const {
 
1299
        // whether air/missile units can bomb from this city; whether fighter units can defend this city; whether air units can rebase from/to this city
 
1300
        // we go by whether the "required" improvement is present
 
1301
        //ASSERT( unit_template->isAir() );
 
1302
        if( !unit_template->isAir() ) {
 
1303
                return false;
 
1304
        }
 
1305
        const Improvement *improvement = unit_template->getRequiresImprovement();
 
1306
        if( improvement == NULL ) {
 
1307
                return true;
 
1308
        }
 
1309
        else if( this->hasImprovement(improvement) ) {
 
1310
                return true;
 
1311
        }
 
1312
        return false;
 
1313
}
 
1314
 
 
1315
/*bool City::canTravel(const UnitTemplate *unit_template) const {
 
1316
        // can this unit travel from/to this city?
 
1317
        // if unit_template==NULL, then consider a generic land unit
 
1318
        if( unit_template != NULL && unit_template->isMissile() ) {
 
1319
                return false; // disallow for now
 
1320
        }
 
1321
        bool by_air = unit_template != NULL && unit_template->isAir();
 
1322
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
1323
                const Improvement *this_improvement = *iter;
 
1324
                if( this_improvement->isTravelByAir() != by_air )
 
1325
                        continue;
 
1326
                int this_range = this_improvement->getTravelRange();
 
1327
                if( this_range > 0 )
 
1328
                        return true;
 
1329
        }
 
1330
        return false;
 
1331
}*/
 
1332
 
 
1333
/*bool City::canTravel(bool by_air) const {
 
1334
        // can we travel from/to this city?
 
1335
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
1336
                const Improvement *this_improvement = *iter;
 
1337
                if( this_improvement->isTravelByAir() != by_air )
 
1338
                        continue;
 
1339
                int this_range = this_improvement->getTravelRange();
 
1340
                if( this_range > 0 )
 
1341
                        return true;
 
1342
        }
 
1343
        return false;
 
1344
}*/
 
1345
 
 
1346
int City::getTravelRange(bool by_air) const {
 
1347
        // travel range for land units, by sea or air
 
1348
        int range = 0;
 
1349
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
1350
                const Improvement *this_improvement = *iter;
 
1351
                int this_range = this_improvement->getTravelRange();
 
1352
                if( this_range == 0 )
 
1353
                        continue;
 
1354
                if( this_improvement->isTravelByAir() != by_air )
 
1355
                        continue;
 
1356
                //if( this_improvement->getImprovementType() == IMPROVEMENT_PORT ) {
 
1357
                if( this_improvement->equals("Port") ) {
 
1358
                        //if( this->civilization->hasTechnology( mainGamestate->findTechnology("Steam Power") ) ) {
 
1359
                        if( this->civilization->hasTechnology("Steam Power") ) {
 
1360
                                this_range = 9999;
 
1361
                        }
 
1362
                        else if( this->civilization->hasTechnology("Magnetism") ) {
 
1363
                                this_range *= 4;
 
1364
                        }
 
1365
                }
 
1366
                //else if( this_improvement->getImprovementType() == IMPROVEMENT_AIRPORT ) {
 
1367
                else if( this_improvement->isTravelByAir() ) {
 
1368
                        //if( this->civilization->hasTechnology( mainGamestate->findTechnology("Rocketry") ) ) {
 
1369
                        if( this->civilization->hasTechnology("Rocketry") ) {
 
1370
                                this_range = jet_travel_range_c;
 
1371
                        }
 
1372
                        //else if( this->civilization->hasTechnology( mainGamestate->findTechnology("Advanced Flight") ) ) {
 
1373
                        else if( this->civilization->hasTechnology("Advanced Flight") ) {
 
1374
                                this_range = bombers_travel_range_c;
 
1375
                        }
 
1376
                }
 
1377
                if( this_range > range )
 
1378
                        range = this_range;
 
1379
        }
 
1380
        return range;
 
1381
}
 
1382
 
 
1383
void City::getTravelRanges(int *sea_range, int *air_range, const UnitTemplate *unit_template) const {
 
1384
        // unit_template may still be NULL, indicating a generic land unit
 
1385
        *sea_range = 0;
 
1386
        *air_range = 0;
 
1387
        if( unit_template != NULL && unit_template->isMissile() ) {
 
1388
                return; // no travel for missiles, for now
 
1389
        }
 
1390
        if( unit_template != NULL && unit_template->isAir() ) {
 
1391
                // air units travel according to their own range, and can only travel by air
 
1392
                *sea_range = 0;
 
1393
                if( this->canLaunch(unit_template) ) {
 
1394
                        *air_range = unit_template->getAirRange();
 
1395
                }
 
1396
                else {
 
1397
                        // no longer an airport!
 
1398
                        *air_range = 0;
 
1399
                }
 
1400
        }
 
1401
        else {
 
1402
                *sea_range = this->getTravelRange(false);
 
1403
                *air_range = this->getTravelRange(true);
 
1404
        }
 
1405
}
 
1406
 
 
1407
void City::initTravel(bool reveal, const UnitTemplate *unit_template, bool sea_defending) const {
 
1408
        // a good idea to lock, if reveal is true, and calling repeatedly
 
1409
        //VI_log("City::initTravel() for %s\n", this->getName());
 
1410
        if( reveal ) {
 
1411
                ASSERT( unit_template == NULL );
 
1412
        }
 
1413
        /*if( unit_template != NULL && unit_template->isSea() ) { // test
 
1414
                sea_defending = true;
 
1415
        }*/
 
1416
        // otherwise, unit_template may still be NULL, indicating a generic land unit (that's capable of attack)
 
1417
        if( sea_defending ) {
 
1418
                // if sea_defending is set to true, this is the special case where we're seeing what squares the sea unit can defend
 
1419
                ASSERT( unit_template != NULL && unit_template->isSea() );
 
1420
        }
 
1421
        int sea_range = 0;
 
1422
        int air_range = 0;
 
1423
        if( sea_defending ) {
 
1424
                sea_range = unit_template->getSeaDefenceRange();
 
1425
        }
 
1426
        else {
 
1427
                this->getTravelRanges(&sea_range, &air_range, unit_template);
 
1428
        }
 
1429
        /*if( unit_template != NULL && unit_template->isAir() ) {
 
1430
                sea_range = 0;
 
1431
                air_range = unit_template->getAirRange();
 
1432
                ASSERT( this->getTravelRange(true) > 0 );
 
1433
        }
 
1434
        else {
 
1435
                sea_range = this->getTravelRange(false);
 
1436
                air_range = this->getTravelRange(true);
 
1437
        }*/
 
1438
 
 
1439
        if( !reveal ) {
 
1440
                //ASSERT( civilization == game->getPlayer() );
 
1441
                mainGamestate->getMap()->resetTargets();
 
1442
        }
 
1443
 
 
1444
        if( sea_range > 0 ) {
 
1445
                bool ship_travel = !sea_defending && unit_template != NULL && unit_template->isSea();
 
1446
                bool can_invade = unit_template == NULL || ( !ship_travel && unit_template->getAttack() > 0 && unit_template->isFoot() );
 
1447
                // Invading means whether we can attack an enemy directly by sea.
 
1448
                // If unit_template == NULL, this should mean it's being called from the City AI, when deciding to build a unit. So we assume a unit that can invade.
 
1449
                // This does mean a risk that we end up building a unit that can't invade, but such a unit will still be useful, and could still in general attack the enemy by landing first.
 
1450
 
 
1451
                bool lock = false;
 
1452
                if( reveal && this->civilization == mainGamestate->getPlayer() && game_g->getGraphicsEnvironment()->getWorld() != NULL && game_g->getGraphicsEnvironment()->getWorld()->getTerrain() != NULL ) {
 
1453
                        lock = true;
 
1454
                        VI_lock();
 
1455
                }
 
1456
                const Distance *dists = mainGamestate->getMap()->calculateDistanceMap(civilization, NULL, false, true, pos.x, pos.y, -1, -1, true, true);
 
1457
                for(int y=0;y<mainGamestate->getMap()->getHeight();y++) {
 
1458
                        for(int x=0;x<mainGamestate->getMap()->getWidth();x++) {
 
1459
                                ASSERT( mainGamestate->getMap()->isValidBase(x, y) );
 
1460
                                int this_dist = dists[y * mainGamestate->getMap()->getWidth() + x].cost;
 
1461
                                if( this_dist >= 0 &&  this_dist < sea_range*road_move_scale_c && !mainGamestate->getMap()->getSquare(x, y)->isLand() ) {
 
1462
                                        if( reveal ) {
 
1463
                                                //this->civilization->setMapVisible(x, y, true);
 
1464
                                                this->civilization->uncover(x, y, 1);
 
1465
                                        }
 
1466
                                        else {
 
1467
                                                for(int cy=y-1;cy<=y+1;cy++) {
 
1468
                                                        for(int cx=x-1;cx<=x+1;cx++) {
 
1469
                                                                int base_cx = cx, base_cy = cy;
 
1470
                                                                mainGamestate->getMap()->reduceToBase(&base_cx, &base_cy);
 
1471
                                                                if( base_cx == this->pos.x && base_cy == this->pos.y ) {
 
1472
                                                                        continue; // no point travelling to same square!
 
1473
                                                                }
 
1474
                                                                if( mainGamestate->getMap()->isValid(base_cx, base_cy) ) {
 
1475
                                                                        ASSERT( civilization->isExplored(base_cx, base_cy) ); // should have been revealed when Harbour etc was built
 
1476
                                                                        MapSquare *square = mainGamestate->getMap()->getSquare(base_cx, base_cy);
 
1477
                                                                        if( ( sea_defending && square->isLand() ) || ( square->canMoveTo(unit_template) && ( can_invade || !square->hasForeignUnits(this->civilization) ) ) ) {
 
1478
                                                                                if( ship_travel ) {
 
1479
                                                                                        const City *city = square->getCity();
 
1480
                                                                                        if( city != NULL && city->getCivilization() == this->civilization ) {
 
1481
                                                                                                int targ_sea_range = 0;
 
1482
                                                                                                int targ_air_range = 0;
 
1483
                                                                                                city->getTravelRanges(&targ_sea_range, &targ_air_range, unit_template);
 
1484
                                                                                                if( targ_sea_range > 0 ) {
 
1485
                                                                                                        square->setTarget(true);
 
1486
                                                                                                }
 
1487
                                                                                        }
 
1488
                                                                                }
 
1489
                                                                                else {
 
1490
                                                                                        square->setTarget(true);
 
1491
                                                                                }
 
1492
                                                                        }
 
1493
                                                                }
 
1494
                                                        }
 
1495
                                                }
 
1496
                                        }
 
1497
                                }
 
1498
                        }
 
1499
                }
 
1500
                if( lock ) {
 
1501
                        VI_unlock();
 
1502
                }
 
1503
                delete [] dists;
 
1504
        }
 
1505
        if( air_range > 0 ) {
 
1506
                if( reveal ) {
 
1507
                        this->civilization->uncover(pos.x, pos.y, air_range);
 
1508
                }
 
1509
                else {
 
1510
                        for(int cy=pos.y-air_range;cy<=pos.y+air_range;cy++) {
 
1511
                                for(int cx=pos.x-air_range;cx<=pos.x+air_range;cx++) {
 
1512
                                        if( cx == this->pos.x && cy == this->pos.y ) {
 
1513
                                                continue; // no point travelling to same square!
 
1514
                                        }
 
1515
                                        if( mainGamestate->getMap()->isValid(cx, cy) ) {
 
1516
                                                ASSERT( civilization->isExplored(cx, cy) ); // should have been revealed when Airport etc was built
 
1517
                                                MapSquare *square = mainGamestate->getMap()->getSquare(cx, cy);
 
1518
                                                const City *city = square->getCity();
 
1519
                                                //if( square->canMoveTo(unit_template) && !square->hasForeignUnits(this->civilization) ) {
 
1520
                                                //if( city != NULL && city->getCivilization() == this->civilization && city->getTravelRange(true) > 0 && square->canMoveTo(unit_template) ) {
 
1521
                                                //if( city != NULL && city->getCivilization() == this->civilization && city->canTravel(true) > 0 && square->canMoveTo(unit_template) ) {
 
1522
                                                if( city != NULL && city->getCivilization() == this->civilization ) {
 
1523
                                                        int targ_sea_range = 0;
 
1524
                                                        int targ_air_range = 0;
 
1525
                                                        city->getTravelRanges(&targ_sea_range, &targ_air_range, unit_template);
 
1526
                                                        if( targ_air_range > 0 ) {
 
1527
                                                                square->setTarget(true);
 
1528
                                                        }
 
1529
                                                }
 
1530
                                        }
 
1531
                                }
 
1532
                        }
 
1533
                }
 
1534
        }
 
1535
}
 
1536
 
 
1537
const Improvement *City::getBestAirDefenceImprovement() const {
 
1538
        const Improvement *improvement = NULL;
 
1539
        int best_defence = 0;
 
1540
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
1541
                const Improvement *this_improvement = *iter;
 
1542
                int defence = this_improvement->getAirDefence();
 
1543
                if( defence > 0 && ( improvement == NULL || defence > best_defence ) ) {
 
1544
                        improvement = this_improvement;
 
1545
                        best_defence = defence;
 
1546
                }
 
1547
        }
 
1548
        return improvement;
 
1549
}
 
1550
 
 
1551
void City::setBuildable(const Buildable *buildable) {
 
1552
        if( this->buildable == buildable )
 
1553
                return;
 
1554
        if( buildable != NULL ) {
 
1555
                ASSERT( this->canBuild( buildable ) );
 
1556
        }
 
1557
        this->buildable = buildable;
 
1558
        this->progress_buildable = 0;
 
1559
}
 
1560
 
 
1561
void City::setDefaultBuildable() {
 
1562
        // start building best defensive unit
 
1563
        const UnitTemplate *defensiveUnit = NULL;
 
1564
        for(size_t i=0;i<mainGamestate->getNUnitTemplates();i++) {
 
1565
                const UnitTemplate *unit_template = mainGamestate->getUnitTemplate(i);
 
1566
                if( !this->canBuild(unit_template) ) {
 
1567
                        continue;
 
1568
                }
 
1569
                if( defensiveUnit == NULL || unit_template->getDefence() > defensiveUnit->getDefence() ||
 
1570
                        ( unit_template->getDefence() == defensiveUnit->getDefence() && unit_template->getCost() < defensiveUnit->getCost() )
 
1571
                        ) {
 
1572
                                defensiveUnit = unit_template;
 
1573
                }
 
1574
        }
 
1575
        if( defensiveUnit != NULL ) {
 
1576
                this->setBuildable(defensiveUnit);
 
1577
        }
 
1578
}
 
1579
 
 
1580
bool City::hasImprovement(const Improvement *improvement) const {
 
1581
        // TODO: improvements should be a set?
 
1582
        ASSERT( improvement != NULL );
 
1583
        bool found = false;
 
1584
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end() && !found; ++iter) {
 
1585
                const Improvement *this_improvement = *iter;
 
1586
                if( this_improvement->equals(improvement) ) {
 
1587
                        found = true;
 
1588
                }
 
1589
        }
 
1590
        return found;
 
1591
}
 
1592
 
 
1593
// whether a city has an improvement, or any improvement which replace the required improvement
 
1594
bool City::hasImprovementOrNewer(const Improvement *improvement) const {
 
1595
        ASSERT( improvement != NULL );
 
1596
        bool has_improvement = true;
 
1597
        if( !this->hasImprovement( improvement ) ) {
 
1598
                has_improvement = false;
 
1599
                // check for improvements which replace the required improvement
 
1600
                while( improvement->getReplacedBy() != NULL && !has_improvement ) {
 
1601
                        ASSERT( improvement->getReplacedBy()->getType() == Buildable::TYPE_IMPROVEMENT );
 
1602
                        improvement = static_cast<const Improvement *>(improvement->getReplacedBy());
 
1603
                        if( this->hasImprovement( improvement ) ) {
 
1604
                                has_improvement = true;
 
1605
                        }
 
1606
                }
 
1607
        }
 
1608
        return has_improvement;
 
1609
}
 
1610
 
 
1611
bool City::hasImprovement(const char *improvement) const {
 
1612
        bool found = false;
 
1613
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end() && !found; ++iter) {
 
1614
                const Improvement *this_improvement = *iter;
 
1615
                if( this_improvement->equals(improvement) ) {
 
1616
                        found = true;
 
1617
                }
 
1618
        }
 
1619
        return found;
 
1620
}
 
1621
 
 
1622
/*bool City::hasImprovement(ImprovementType improvementType) const {
 
1623
        bool found = false;
 
1624
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end() && !found; ++iter) {
 
1625
                const Improvement *this_improvement = *iter;
 
1626
                if( this_improvement->getImprovementType() == improvementType ) {
 
1627
                        found = true;
 
1628
                }
 
1629
        }
 
1630
        return found;
 
1631
}*/
 
1632
 
 
1633
bool City::canBuild(const Buildable *candidate_buildable) const {
 
1634
        bool can_build = false;
 
1635
        if( candidate_buildable->getType() == Buildable::TYPE_UNIT ) {
 
1636
                can_build = true;
 
1637
                const UnitTemplate *unit_template = static_cast<const UnitTemplate *>(candidate_buildable);
 
1638
                if( unit_template->canBuildCity() && this->getSize() <= 1 ) {
 
1639
                        can_build = false; // need at least size 2 city
 
1640
                }
 
1641
        }
 
1642
        else if( candidate_buildable->getType() == Buildable::TYPE_IMPROVEMENT ) {
 
1643
                const Improvement *improvement = static_cast<const Improvement *>(candidate_buildable);
 
1644
                if( !hasImprovement(improvement) ) {
 
1645
                        can_build = true;
 
1646
                }
 
1647
                // further checks
 
1648
                if( can_build && improvement->requiresCoastal() && !this->isOnOrAdjacent(TYPE_OCEAN) ) {
 
1649
                        can_build = false;
 
1650
                }
 
1651
                /*if( can_build && ( improvement->getImprovementType() == IMPROVEMENT_FORT || improvement->getImprovementType() == IMPROVEMENT_CASTLE || improvement->getImprovementType() == IMPROVEMENT_WALLS ) ) {
 
1652
                        const Technology *tech = game_g->getGameData()->findTechnology("Gunpowder");
 
1653
                        if( this->civilization->hasTechnology(tech) ) {
 
1654
                                // Gunpowder obsoletes these improvements (note, they still have an effect for cities that have built them, and cities already building them can do so - we just disallow the option to build new ones)
 
1655
                                can_build = false;
 
1656
                        }
 
1657
                }*/
 
1658
                // obsoleted checks now done below
 
1659
                /*if( can_build ) {
 
1660
                        if( improvement->getImprovementType() == IMPROVEMENT_FORT && hasImprovement(IMPROVEMENT_WALLS) ) {
 
1661
                                // walls replaces fort
 
1662
                                can_build = false;
 
1663
                        }
 
1664
                }*/
 
1665
        }
 
1666
        else {
 
1667
                ASSERT( false );
 
1668
        }
 
1669
 
 
1670
        if( can_build ) {
 
1671
                const Race *race_specific = candidate_buildable->getRaceSpecific();
 
1672
                if( race_specific != NULL && race_specific != this->civilization->getRace() ) {
 
1673
                        can_build = false;
 
1674
                }
 
1675
                else if( race_specific != NULL && race_specific == this->civilization->getRace() ) {
 
1676
                        if( candidate_buildable->getType() == Buildable::TYPE_IMPROVEMENT ) {
 
1677
                                const Improvement *improvement = static_cast<const Improvement *>(candidate_buildable);
 
1678
                                // check not already built, or not already building it
 
1679
                                for(size_t i=0;i<civilization->getNCities() && can_build;i++) {
 
1680
                                        const City *city = civilization->getCity(i);
 
1681
                                        if( city == this )
 
1682
                                                continue;
 
1683
                                        if( city->hasImprovement(improvement) ) {
 
1684
                                                can_build = false;
 
1685
                                        }
 
1686
                                        else if( city->getBuildable() == improvement ) {
 
1687
                                                can_build = false;
 
1688
                                        }
 
1689
                                }
 
1690
                        }
 
1691
                }
 
1692
        }
 
1693
 
 
1694
        if( can_build ) {
 
1695
                const Technology *obsoleted_by = candidate_buildable->getObsoletedBy();
 
1696
                if( obsoleted_by != NULL && this->civilization->hasTechnology(obsoleted_by) ) {
 
1697
                        can_build = false;
 
1698
                }
 
1699
        }
 
1700
 
 
1701
        if( can_build ) {
 
1702
                const Improvement *requires_improvement = candidate_buildable->getRequiresImprovement();
 
1703
                const Technology *requires_technology = candidate_buildable->getRequiresTechnology();
 
1704
                //const Improvement *replaced_by = static_cast<const Improvement *>(candidate_buildable->getReplacedBy()); // must be same type
 
1705
                const Buildable *replaced_by = candidate_buildable->getReplacedBy();
 
1706
                if( requires_improvement != NULL && !hasImprovement(requires_improvement) ) {
 
1707
                        can_build = false;
 
1708
                }
 
1709
                else if( requires_technology != NULL && !civilization->hasTechnology(requires_technology) ) {
 
1710
                        can_build = false;
 
1711
                }
 
1712
                /*else if( replaced_by != NULL && ( this->hasImprovement(replaced_by) || this->canBuild(replaced_by) ) ) {
 
1713
                        can_build = false;
 
1714
                }
 
1715
                while( can_build && replaced_by != NULL ) {
 
1716
                        // but we also need to look at if this unit has been replaced - e.g., Cuirassiers replaces Knights, which replaces Horsemen; if a Civ can build Cuirassiers, then that should replace Horsemen even if they can't build Knights (due to no Armoury)!
 
1717
                        replaced_by = static_cast<const Improvement *>(replaced_by->getReplacedBy());
 
1718
                        if( replaced_by != NULL && ( this->hasImprovement(replaced_by) || this->canBuild(replaced_by) ) ) {
 
1719
                                can_build = false;
 
1720
                        }
 
1721
                }*/
 
1722
                while( can_build && replaced_by != NULL ) {
 
1723
                        if( this->canBuild(replaced_by) )
 
1724
                                can_build = false;
 
1725
                        else if( replaced_by->getType() == Buildable::TYPE_IMPROVEMENT ) {
 
1726
                                const Improvement *replaced_by_improvement = static_cast<const Improvement *>(replaced_by);
 
1727
                                if( this->hasImprovement(replaced_by_improvement) ) {
 
1728
                                        can_build = false;
 
1729
                                }
 
1730
                        }
 
1731
                        // but we also need to look at if this unit has been replaced - e.g., Cuirassiers replaces Knights, which replaces Horsemen; if a Civ can build Cuirassiers, then that should replace Horsemen even if they can't build Knights (due to no Armoury)!
 
1732
                        replaced_by = replaced_by->getReplacedBy();
 
1733
                }
 
1734
                /*else if( replaced_by != NULL ) {
 
1735
                        const Technology *replaced_by_tech = replaced_by->getRequiresTechnology();
 
1736
                        ASSERT( replaced_by_tech != NULL );
 
1737
                        // A new technology will replace older units, even if the city can't build that unit (e.g., due to lacking the improvement).
 
1738
                        // Whilst seemingly a step backwards, this is to encourage to build those improvements, and to avoid anachronisms (e.g., cities still building chariots in medieval times, because the city doesn't have an armourer, to build knights).
 
1739
                        if( civilization->hasTechnology(replaced_by_tech) ) {
 
1740
                                can_build = false;
 
1741
                        }
 
1742
                }*/
 
1743
        }
 
1744
 
 
1745
        // now check element stocks
 
1746
        /*if( can_build && candidate_buildable->getRequiresElement() != NULL ) {
 
1747
                const Element *element = candidate_buildable->getRequiresElement();
 
1748
                int amount = candidate_buildable->getRequiresElementAmount();
 
1749
                T_ASSERT( amount > 0 );
 
1750
                int stock = this->element_stocks.find(element)->second;
 
1751
                if( stock < amount ) {
 
1752
                        can_build = false;
 
1753
                }
 
1754
        }*/
 
1755
        for(size_t i=0;i<game_g->getGameData()->getNElements() && can_build;i++) {
 
1756
                const Element *element = game_g->getGameData()->getElement(i);
 
1757
                int amount = candidate_buildable->getRequiresElementAmount(element);
 
1758
 
 
1759
                int stock = this->element_stocks.find(element)->second;
 
1760
                if( stock < amount ) {
 
1761
                        can_build = false;
 
1762
                }
 
1763
        }
 
1764
 
 
1765
        // now check bonus_resource
 
1766
        if( can_build && candidate_buildable->getRequiresBonusResource() != NULL ) {
 
1767
                const BonusResource *requires_bonus_resource = candidate_buildable->getRequiresBonusResource();
 
1768
                bool found = false;
 
1769
                for(int i=0;i<this->getNCitySquares() && !found;i++) {
 
1770
                        Pos2D pos = this->getCitySquare(i);
 
1771
                        if( this->mainGamestate->getMap()->isValid(pos.x, pos.y) ) {
 
1772
                                const MapSquare *square = this->mainGamestate->getMap()->getSquare(pos);
 
1773
                                const BonusResource *this_bonus_resource = square->getBonusResource();
 
1774
                                if( this_bonus_resource != NULL && requires_bonus_resource->equals(this_bonus_resource->getName()) ) {
 
1775
                                        found = true;
 
1776
                                }
 
1777
                        }
 
1778
                }
 
1779
                if( !found ) {
 
1780
                        can_build = false;
 
1781
                }
 
1782
        }
 
1783
        return can_build;
 
1784
}
 
1785
 
 
1786
int City::getDefenceBonus(const Unit *attacker) const {
 
1787
        // as a percentage
 
1788
        int bonus = 0;
 
1789
        const Civilization *attacker_civ = attacker->getCivilization();
 
1790
        if( !attacker_civ->hasTechnology("Gunpowder") ) {
 
1791
                // gunpowder makes these obsolete
 
1792
                if( this->hasImprovement("Walls") ) {
 
1793
                        bonus = 50;
 
1794
                }
 
1795
                else if( this->hasImprovement("Castle") ) {
 
1796
                        bonus = 50;
 
1797
                }
 
1798
                else if( this->hasImprovement("Fort") ) {
 
1799
                        // n.b. Fort is replaced by Walls, so isn't cumulative
 
1800
                        bonus = 25;
 
1801
                }
 
1802
        }
 
1803
        // improvements
 
1804
        bonus = max(bonus, this->civilization->getCivBonusDefence());
 
1805
        for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
 
1806
                const Improvement *improvement = *iter;
 
1807
                if( !this->improvementHasEffect(improvement) ) {
 
1808
                        continue;
 
1809
                }
 
1810
                if( !improvement->getDefenceBonusAllCities() ) {
 
1811
                        bonus = max(bonus, improvement->getDefenceBonus());
 
1812
                }
 
1813
        }
 
1814
        return bonus;
 
1815
}
 
1816
 
 
1817
bool City::losePopulation() const {
 
1818
        if( this->size <= size_limit_aqueduct_c && this->hasImprovement("Walls") ) {
 
1819
                return false;
 
1820
        }
 
1821
        return true;
 
1822
}
 
1823
 
 
1824
void City::doAI() {
 
1825
        ASSERT( this->civilization != mainGamestate->getPlayer() );
 
1826
        if( this->buildable == NULL ) {
 
1827
                this->chooseAndSetBuildAI();
 
1828
        }
 
1829
}
 
1830
 
 
1831
//const int min_defenders_c = 1;
 
1832
 
 
1833
bool City::needDefendersAI(bool *undefended, const Unit *this_unit, int min_defence) const {
 
1834
        ASSERT( this->civilization != mainGamestate->getPlayer() );
 
1835
        //return false;
 
1836
        // TODO: best defenders
 
1837
        /*Unit::Type def_type = city->bestBuildableUnit(City::DEFENCE);
 
1838
        Unit *best_defender = (Unit *)Buildable::getBuildable(Buildable::UNIT, def_type);
 
1839
        if( this->type == def_type || this->getBaseDefence() > best_defender->getBaseDefence() ) {*/
 
1840
        //const vector<Unit *> *units = mainGamestate->getMap()->findUnitsAt(pos.x, pos.y);
 
1841
        const vector<Unit *> *units = AIInterface::getUnits(pos.x, pos.y);
 
1842
        int n_defenders = 0;
 
1843
        if( undefended != NULL ) {
 
1844
                *undefended = true; // initialise
 
1845
        }
 
1846
        if( units != NULL ) {
 
1847
                for(vector<Unit *>::const_iterator iter = units->begin(); iter != units->end(); ++iter) {
 
1848
                        const Unit *unit = *iter;
 
1849
                        if( unit == this_unit )
 
1850
                                continue;
 
1851
                        if( this_unit != NULL && unit->getTemplate()->getDefence() < this_unit->getTemplate()->getDefence() ) {
 
1852
                                continue; // ignore units not as good as this_unit, so that we prefer to keep stronger units defending the city
 
1853
                        }
 
1854
                        if( this_unit != NULL && unit->getTemplate()->getDefence() == this_unit->getTemplate()->getDefence() && unit->getTemplate()->getAttack() > this_unit->getTemplate()->getAttack() ) {
 
1855
                                continue; // for units of equal defence, prefer to keep the units of weaker attack - so the stronger attack units can be used to leave the city
 
1856
                        }
 
1857
                        //if( unit->getType() == def_type || unit->getBaseDefence() > best_defender->getBaseDefence() ) {
 
1858
                        if( unit->getTemplate()->getAttack() > 0 && unit->getTemplate()->getDefence() > 0 ) {
 
1859
                                if( undefended != NULL ) {
 
1860
                                        *undefended = false;
 
1861
                                }
 
1862
                                if( unit->getTemplate()->getDefence() < min_defence ) {
 
1863
                                        // setting min_defence allows us to only look at defenders of a certain defence when counting (however, we still set the 'undefended' flag)
 
1864
                                        continue;
 
1865
                                }
 
1866
                                n_defenders++;
 
1867
                        }
 
1868
                }
 
1869
        }
 
1870
        int min_defenders_c = 0;
 
1871
        if( this->size <= 2 )
 
1872
                min_defenders_c = 1;
 
1873
        else if( this_unit == NULL && min_defence == 1 )
 
1874
                min_defenders_c = 1; // if we can only build Peasants, better to wait until we have better units
 
1875
        else {
 
1876
                min_defenders_c = 2;
 
1877
                if( ( this->size >= 6 && this == this->civilization->getCity(0) ) || this->size >= 8 ) {
 
1878
                        bool is_war = false;
 
1879
                        /*for(int i=0;i<mainGamestate->getNCivilizations() && !is_war;i++) {
 
1880
                                const Civilization *civ = mainGamestate->getCivilization(i);
 
1881
                                if( this->civilization != civ && !civ->isDead() ) {
 
1882
                                        const Relationship *relationship = mainGamestate->findRelationship(this->civilization, civ);
 
1883
                                        if( relationship->getStatus() == Relationship::STATUS_WAR )
 
1884
                                                is_war = true;
 
1885
                                }
 
1886
                        }*/
 
1887
                        vector<Civilization *> civilizations = AIInterface::getCivilizations(AIInterface::GETCIVILIZATIONS_WAR);
 
1888
                        if( civilizations.size() > 0 ) {
 
1889
                                is_war = true;
 
1890
                        }
 
1891
                        if( is_war ) {
 
1892
                                // a capital medium sized city, or large city; and we're at war!
 
1893
                                min_defenders_c = 3;
 
1894
                        }
 
1895
                }
 
1896
        }
 
1897
        if( n_defenders < min_defenders_c ) {
 
1898
                return true;
 
1899
        }
 
1900
        return false;
 
1901
}
 
1902
 
 
1903
/*bool City::wantWorkerAt(int indx, const Unit *unit) const {
 
1904
        Pos2D pos = this->getCitySquare(indx);
 
1905
        //if( !unit->canMoveTo(pos) ) {
 
1906
        //      // no point trying to move to it
 
1907
        //      return false;
 
1908
        //}
 
1909
        // no need to check if we can move here, as that should be tested separately!
 
1910
        const MapSquare *square = game->getMap()->getSquare(pos);
 
1911
        if( square->canBeImproved(unit->getTemplate()) ) {
 
1912
                return true;
 
1913
        }
 
1914
        return false;
 
1915
}*/
 
1916
 
 
1917
#ifndef USE_LUA_CITY_AI
 
1918
 
 
1919
bool City::chooseBuildPopLimits() {
 
1920
        // need improvements for city growth
 
1921
        if(mainGamestate->getYear() <= 50 ) {
 
1922
                return false; // prefer to focus on Settlers
 
1923
        }
 
1924
        //if( this->getSize() >= size_limit_farmland_c && !this->hasImprovement(IMPROVEMENT_FARMLAND) ) {
 
1925
        if( this->getSize() >= size_limit_farmland_c ) {
 
1926
                const Buildable *b = mainGamestate->findImprovement(IMPROVEMENT_FARMLAND);
 
1927
                if( this->canBuild(b) ) {
 
1928
                        this->buildable = b;
 
1929
                        VI_log("%s city of %s starts building %s [need farmland]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
1930
                        return true;
 
1931
                }
 
1932
        }
 
1933
        //if( this->getSize() >= size_limit_aqueduct_c && !this->hasImprovement(IMPROVEMENT_AQUEDUCT) ) {
 
1934
        if( this->getSize() >= size_limit_aqueduct_c ) {
 
1935
                const Buildable *b = mainGamestate->findImprovement(IMPROVEMENT_AQUEDUCT);
 
1936
                if( this->canBuild(b) ) {
 
1937
                        this->buildable = b;
 
1938
                        VI_log("%s city of %s starts building %s [need aqueduct]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
1939
                        return true;
 
1940
                }
 
1941
        }
 
1942
        return false;
 
1943
}
 
1944
 
 
1945
const Improvement *City::chooseImprovementAI() {
 
1946
        vector<const Improvement *> candidates;
 
1947
        int max_value = 0;
 
1948
        for(int i=0;i<mainGamestate->getNImprovements();i++) {
 
1949
                const Improvement *b = mainGamestate->getImprovement(i);
 
1950
                if( this->canBuild(b) ) {
 
1951
                        int r = rand() % 20;
 
1952
                        int this_value = b->getAIWeight() + r;
 
1953
 
 
1954
                        if( this_value > 0 && b->getAIHint() == Improvement::AIHINT_RESEARCH ) {
 
1955
                                if( this->civilization->hasAllTechnology() ) {
 
1956
                                        // no point building if we have all technology
 
1957
                                        this_value = 0;
 
1958
                                }
 
1959
                        }
 
1960
 
 
1961
                        if( this_value <= 0 ) {
 
1962
                                // don't build
 
1963
                        }
 
1964
                        else if( this_value > max_value ) {
 
1965
                                candidates.clear();
 
1966
                                candidates.push_back(b);
 
1967
                                max_value = this_value;
 
1968
                        }
 
1969
                        else if( this_value == max_value ) {
 
1970
                                candidates.push_back(b);
 
1971
                        }
 
1972
                }
 
1973
        }
 
1974
        if( candidates.size() > 0 ) {
 
1975
                int r = rand() % candidates.size();
 
1976
                return candidates.at(r);
 
1977
        }
 
1978
        return NULL;
 
1979
}
 
1980
 
 
1981
const UnitTemplate *City::chooseAirUnitAI(const UnitTemplate *bestFighterAirUnit, const UnitTemplate *bestBomberAirUnit, const UnitTemplate *bestConventionalMissileUnit, const UnitTemplate *bestNuclearMissileUnit, bool war_only) {
 
1982
        vector<const UnitTemplate *> choices;
 
1983
        if( bestFighterAirUnit != NULL )
 
1984
                choices.push_back(bestFighterAirUnit);
 
1985
        if( bestBomberAirUnit != NULL )
 
1986
                choices.push_back(bestBomberAirUnit);
 
1987
        if( bestConventionalMissileUnit != NULL )
 
1988
                choices.push_back(bestConventionalMissileUnit);
 
1989
        if( bestNuclearMissileUnit != NULL )
 
1990
                choices.push_back(bestNuclearMissileUnit);
 
1991
        ASSERT( choices.size() > 0 );
 
1992
        int r = rand() % choices.size();
 
1993
        const UnitTemplate *unit = choices.at(r);
 
1994
        if( unit == bestFighterAirUnit ) {
 
1995
                // defensive unit, so don't need to see if any cities to attack
 
1996
                VI_log("build a defensive air unit\n");
 
1997
                return unit;
 
1998
        }
 
1999
        /*for(int i=0;i<this->mainGamestate->getNCivilizations();i++) {
 
2000
                const Civilization *civ = this->mainGamestate->getCivilization(i);
 
2001
                if( civ == civilization )
 
2002
                        continue;
 
2003
                if( civ->isDead() )
 
2004
                        continue;
 
2005
                if( war_only ) {
 
2006
                        const Relationship *relationship = mainGamestate->findRelationship(this->civilization, civ);
 
2007
                        if( relationship->getStatus() == Relationship::STATUS_PEACE )
 
2008
                                continue;
 
2009
                }*/
 
2010
        vector<Civilization *> civs = AIInterface::getCivilizations(war_only ? AIInterface::GETCIVILIZATIONS_WAR : AIInterface::GETCIVILIZATIONS_ALL);
 
2011
        for(vector<Civilization *>::iterator iter = civs.begin(); iter != civs.end(); ++iter) {
 
2012
                Civilization *civ = *iter;
 
2013
                // bomb cities?
 
2014
                /*for(int j=0;j<civ->getNCities();j++) {
 
2015
                        const City *city = civ->getCity(j);
 
2016
                        Pos2D city_pos = city->getPos();
 
2017
                        if( !this->civilization->isExplored(city_pos.x, city_pos.y) )
 
2018
                                continue;*/
 
2019
                vector<City *> cities = AIInterface::getCities(civ);
 
2020
                for(vector<City *>::const_iterator iter2 = cities.begin(); iter2 != cities.end(); ++iter2) {
 
2021
                        const City *city = *iter2;
 
2022
                        Pos2D city_pos = city->getPos();
 
2023
                        /*int dist = mainGamestate->getMap()->distanceChebyshev(city_pos, this->pos);
 
2024
                        if( dist <= unit->getAirRange() ) {*/
 
2025
                        if( AIInterface::canBomb(unit, this, city_pos, true) ) {
 
2026
                                VI_log("%s: %s is within range %d\n", this->getName(), city->getName(), unit->getAirRange());
 
2027
                                return unit;
 
2028
                        }
 
2029
                }
 
2030
        }
 
2031
        return NULL;
 
2032
}
 
2033
 
 
2034
#endif
 
2035
 
 
2036
void City::chooseAndSetBuildAI() {
 
2037
        ASSERT( this->progress_buildable == 0 );
 
2038
 
 
2039
        this->buildable = getBuildChoiceAI();
 
2040
        /*if( this->buildable != NULL )
 
2041
                VI_log("AI: %s city of %s starts building %s\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2042
        else
 
2043
                VI_log("AI: %s city of %s isn't building anything!\n", this->civilization->getNameAdjective(), this->getName());*/
 
2044
        if( this->buildable == NULL ) {
 
2045
                VI_log("AI: %s city of %s isn't building anything!\n", this->civilization->getNameAdjective(), this->getName());
 
2046
        }
 
2047
}
 
2048
 
 
2049
const Buildable *City::getBuildChoiceAI() {
 
2050
        const Buildable *choice = NULL;
 
2051
 
 
2052
        AIInterface::setMainGamestate(this->mainGamestate);
 
2053
        AIInterface::setAICivilization(this->civilization);
 
2054
 
 
2055
#ifdef USE_LUA_CITY_AI
 
2056
        {
 
2057
                // Lua code
 
2058
                game_g->pushScriptFunction("chooseBuild");
 
2059
                lua_pushlightuserdata(game_g->getLuaState(), this);
 
2060
                //lua_pushnumber(game_g->getLuaState(), (int)this);
 
2061
                if( !game_g->runScriptFunction(1) ) {
 
2062
                        ASSERT(false);
 
2063
                }
 
2064
                AIInterface::setMainGamestate(NULL);
 
2065
                AIInterface::setAICivilization(NULL);
 
2066
                {
 
2067
                        // read result
 
2068
                        int arg_index = 1;
 
2069
 
 
2070
                        if( !lua_islightuserdata(game_g->getLuaState(), arg_index) ) {
 
2071
                                VI_log("City::getBuildChoiceAI(): script return argument %d not a pointer\n", arg_index);
 
2072
                        }
 
2073
                        else {
 
2074
                                void *ptr = lua_touserdata(game_g->getLuaState(), arg_index);
 
2075
                                choice = static_cast<const Buildable *>(ptr);
 
2076
                        }
 
2077
                        arg_index++;
 
2078
 
 
2079
                        lua_settop(game_g->getLuaState(), 0); // important - clear the stack!
 
2080
                }
 
2081
        }
 
2082
        return choice;
 
2083
 
 
2084
#else
 
2085
 
 
2086
        int n_production = this->getProduction();
 
2087
        const int ignore_dist_c = 16;
 
2088
 
 
2089
        // get unit templates
 
2090
        const UnitTemplate *bestUnit = NULL;
 
2091
        //const UnitTemplate *bestWorkerUnit = NULL; // best attacker unit that can also work
 
2092
        const UnitTemplate *defensiveUnit = NULL;
 
2093
        const UnitTemplate *fastestUnit = NULL;
 
2094
        const UnitTemplate *cheapestUnit = NULL;
 
2095
        const UnitTemplate *bestFighterAirUnit = NULL;
 
2096
        const UnitTemplate *bestBomberAirUnit = NULL;
 
2097
        const UnitTemplate *bestConventionalMissileUnit = NULL;
 
2098
        const UnitTemplate *bestNuclearMissileUnit = NULL;
 
2099
        const UnitTemplate *settlersUnit = NULL;
 
2100
        const UnitTemplate *potentialSettlersUnit = NULL; // the Settlers unit, even if we can't yet build it
 
2101
        const UnitTemplate *workerUnit = NULL;
 
2102
        vector<const Buildable *> buildables = AIInterface::cityGetBuildables(this, AIInterface::GETBUILDABLES_UNITS);
 
2103
        /*for(int i=0;i<mainGamestate->getNUnitTemplates();i++) {
 
2104
                const UnitTemplate *unit_template = mainGamestate->getUnitTemplate(i);*/
 
2105
        for(vector<const Buildable *>::const_iterator iter = buildables.begin(); iter != buildables.end(); ++iter) {
 
2106
                const Buildable *buildable = *iter;
 
2107
                ASSERT( buildable->getType() == Buildable::TYPE_UNIT );
 
2108
                const UnitTemplate *unit_template = static_cast<const UnitTemplate *>(buildable);
 
2109
 
 
2110
                if( unit_template->canBuildCity() ) {
 
2111
                        ASSERT( potentialSettlersUnit == NULL ); // should only be one
 
2112
                        potentialSettlersUnit = unit_template;
 
2113
                }
 
2114
 
 
2115
                if( !this->canBuild(unit_template) ) {
 
2116
                        continue;
 
2117
                }
 
2118
                if( !unit_template->isAir() ) {
 
2119
                        if( bestUnit == NULL || unit_template->getAttack() > bestUnit->getAttack() ||
 
2120
                                ( unit_template->getAttack() == bestUnit->getAttack() && unit_template->getCost() < bestUnit->getCost() )
 
2121
                                ) {
 
2122
                                        bestUnit = unit_template;
 
2123
                        }
 
2124
                        if( defensiveUnit == NULL || unit_template->getDefence() > defensiveUnit->getDefence() ||
 
2125
                                ( unit_template->getDefence() == defensiveUnit->getDefence() && unit_template->getCost() < defensiveUnit->getCost() )
 
2126
                                ) {
 
2127
                                        defensiveUnit = unit_template;
 
2128
                        }
 
2129
                        if( fastestUnit == NULL || unit_template->getMoves() > fastestUnit->getMoves() ||
 
2130
                                ( unit_template->getMoves() == fastestUnit->getMoves() && unit_template->getCost() < fastestUnit->getCost() )
 
2131
                                ) {
 
2132
                                        fastestUnit = unit_template;
 
2133
                        }
 
2134
                        if( cheapestUnit == NULL || unit_template->getCost() < cheapestUnit->getCost() ||
 
2135
                                ( unit_template->getCost() == cheapestUnit->getCost() && unit_template->getAttack() > cheapestUnit->getAttack() )
 
2136
                                ) {
 
2137
                                        cheapestUnit = unit_template;
 
2138
                        }
 
2139
                }
 
2140
                if( unit_template->isAir() && !unit_template->isMissile() ) {
 
2141
                        if( bestFighterAirUnit == NULL || unit_template->getAirDefence() > bestFighterAirUnit->getAirDefence() ) {
 
2142
                                bestFighterAirUnit = unit_template;
 
2143
                        }
 
2144
                }
 
2145
                if( unit_template->isAir() && !unit_template->isMissile() ) {
 
2146
                        if( bestBomberAirUnit == NULL || unit_template->getBombardPower() > bestBomberAirUnit->getBombardPower() ||
 
2147
                                ( unit_template->getBombardPower() == bestBomberAirUnit->getBombardPower() && unit_template->getBombard() > bestBomberAirUnit->getBombard() )
 
2148
                                ) {
 
2149
                                        bestBomberAirUnit = unit_template;
 
2150
                        }
 
2151
                }
 
2152
                if( unit_template->isAir() && unit_template->isMissile() && unit_template->getNuclearType() == UnitTemplate::NUCLEARTYPE_NONE ) {
 
2153
                        if( bestConventionalMissileUnit == NULL || unit_template->getBombardPower() > bestConventionalMissileUnit->getBombardPower() ||
 
2154
                                ( unit_template->getBombardPower() == bestConventionalMissileUnit->getBombardPower() && unit_template->getBombard() > bestConventionalMissileUnit->getBombard() )
 
2155
                                ) {
 
2156
                                        bestConventionalMissileUnit = unit_template;
 
2157
                        }
 
2158
                }
 
2159
                if( unit_template->isAir() && unit_template->isMissile() && unit_template->getNuclearType() != UnitTemplate::NUCLEARTYPE_NONE ) {
 
2160
                        if( bestNuclearMissileUnit == NULL ||
 
2161
                                ( bestNuclearMissileUnit->getNuclearType() == UnitTemplate::NUCLEARTYPE_FISSION && unit_template->getNuclearType() == UnitTemplate::NUCLEARTYPE_FUSION ) ) {
 
2162
                                        bestNuclearMissileUnit = unit_template;
 
2163
                        }
 
2164
                }
 
2165
                if( unit_template->canBuildRoads() ) {
 
2166
                        /*if( bestWorkerUnit == NULL || unit_template->getAttack() > bestWorkerUnit->getAttack() ||
 
2167
                                ( unit_template->getAttack() == bestWorkerUnit->getAttack() && unit_template->getCost() < bestWorkerUnit->getCost() )
 
2168
                                ) {
 
2169
                                        bestWorkerUnit = unit_template;
 
2170
                        }*/
 
2171
                        if( workerUnit == NULL || unit_template->getCost() < workerUnit->getCost() ||
 
2172
                                ( unit_template->getCost() == workerUnit->getCost() && unit_template->getDefence() > workerUnit->getDefence() )
 
2173
                                ) {
 
2174
                                        workerUnit = unit_template;
 
2175
                        }
 
2176
                }
 
2177
                if( unit_template->canBuildCity() ) {
 
2178
                        ASSERT( settlersUnit == NULL ); // should only be one
 
2179
                        settlersUnit = unit_template;
 
2180
                }
 
2181
        }
 
2182
        /*if( bestUnit == NULL && fastestUnit != NULL ) {
 
2183
                bestUnit = fastestUnit;
 
2184
        }
 
2185
        else if( bestUnit == NULL && cheapestUnit != NULL ) {
 
2186
                bestUnit = cheapestUnit;
 
2187
        }
 
2188
        else if( bestUnit != NULL && fastestUnit != NULL ) {
 
2189
                // we should mainly build the best attacker, but having a few fastest units is good too, so do a substitution
 
2190
                int r = rand() % 3;
 
2191
                if( r == 0 ) {
 
2192
                        bestUnit = fastestUnit;
 
2193
                }
 
2194
        }*/
 
2195
        ASSERT( bestUnit != NULL );
 
2196
        ASSERT( fastestUnit != NULL );
 
2197
        //ASSERT( bestWorkerUnit != NULL );
 
2198
        {
 
2199
                // having a few fastest and worker units is good too, so do a substitution
 
2200
                // update: we build enough worker units either directly, or through barracks - so need more faster units
 
2201
                int r = rand() % 4;
 
2202
                if( r == 0 || r == 1 ) {
 
2203
                        // keep with best
 
2204
                }
 
2205
                else {
 
2206
                        bestUnit = fastestUnit;
 
2207
                        VI_log("AI: %s: best unit is fastest\n", this->getName());
 
2208
                }
 
2209
                /*else if( r == 2 ) {
 
2210
                        bestUnit = fastestUnit;
 
2211
                        VI_log("AI: %s: best unit is fastest\n", this->getName());
 
2212
                }
 
2213
                else if( r == 3 ) {
 
2214
                        bestUnit = bestWorkerUnit;
 
2215
                        VI_log("AI: %s: best unit is worker\n", this->getName());
 
2216
                }*/
 
2217
        }
 
2218
 
 
2219
        int n_settlers = 0;
 
2220
        int n_explorers = 0;
 
2221
        //int n_workers = 0;
 
2222
        int n_nukes = 0;
 
2223
        for(int i=0;i<civilization->getNUnits();i++) {
 
2224
                const Unit *unit = civilization->getUnit(i);
 
2225
                const UnitTemplate *unit_template = unit->getTemplate();
 
2226
                if( unit_template->canBuildCity() ) {
 
2227
                        n_settlers++;
 
2228
                }
 
2229
                if( bestNuclearMissileUnit != NULL && unit_template->getNuclearType() == bestNuclearMissileUnit->getNuclearType() ) {
 
2230
                        n_nukes++;
 
2231
                }
 
2232
                //if( mainGamestate->getMap()->findCity(unit->getX(), unit->getY()) != NULL ) {
 
2233
                if( AIInterface::getCity(unit->getX(), unit->getY()) != NULL ) {
 
2234
                        // ignore units defending cities
 
2235
                        continue;
 
2236
                }
 
2237
                if( unit_template == fastestUnit ) {
 
2238
                        n_explorers++;
 
2239
                }
 
2240
                /*if( unit_template == workerUnit ) {
 
2241
                        n_workers++;
 
2242
                }*/
 
2243
        }
 
2244
 
 
2245
        //int max_explorers = 2 * civilization->getNCities();
 
2246
        //int max_explorers = 3 * civilization->getNCities();
 
2247
        int max_explorers = civilization->getNCities() + 4; // favour explorers when fewer cities
 
2248
        if( mainGamestate->getYear() > 100 && civilization->getNCities() > 4 ) {
 
2249
                max_explorers = 8 + ( civilization->getNCities() - 4 ) / 5;
 
2250
        }
 
2251
        //int max_workers = 2 * civilization->getNCities();
 
2252
        int max_settlers = civilization->getNCities()+1; // +1 so that a single City can still build a 2nd Settlers unit when we already have 1 Settlers unit
 
2253
        if( mainGamestate->getYear() > 100 && civilization->getNCities() > 8 ) {
 
2254
                max_settlers = 9 + ( civilization->getNCities() - 8 ) / 5;
 
2255
        }
 
2256
 
 
2257
        int n_settlers_being_built = 0;
 
2258
        int n_explorers_being_built = 0;
 
2259
        int n_nukes_being_built = 0;
 
2260
        for(int i=0;i<civilization->getNCities();i++) {
 
2261
                const City *city = civilization->getCity(i);
 
2262
                if( city != this ) {
 
2263
                        const Buildable *city_buildable = city->getBuildable();
 
2264
                        if( city_buildable != NULL && city_buildable->getType() == Buildable::TYPE_UNIT ) {
 
2265
                                const UnitTemplate *unit_template = static_cast<const UnitTemplate *>(city_buildable);
 
2266
                                if( unit_template->canBuildCity() ) {
 
2267
                                        n_settlers_being_built++;
 
2268
                                }
 
2269
                                if( unit_template->getMoves() >= fastestUnit->getMoves() ) {
 
2270
                                        n_explorers_being_built++;
 
2271
                                }
 
2272
                                if( bestNuclearMissileUnit != NULL && unit_template->getNuclearType() == bestNuclearMissileUnit->getNuclearType() ) {
 
2273
                                        n_nukes_being_built++;
 
2274
                                }
 
2275
                        }
 
2276
                }
 
2277
        }
 
2278
 
 
2279
        // build defensive units
 
2280
        if( defensiveUnit != NULL ) {
 
2281
                bool undefended = true;
 
2282
                int min_defence = this->civilization->getNCities() > 1 || n_settlers > 0 ? defensiveUnit->getDefence() : 0;
 
2283
                        // if only 1 city and 0 Settlers, we only care about getting a minimum defence, as building Settlers is better
 
2284
                if( needDefendersAI(&undefended, NULL, min_defence) ) {
 
2285
                        //int n_turns = n_production / defensiveUnit->getCost();
 
2286
                        if( n_production > 0 ) {
 
2287
                                int n_turns = defensiveUnit->getCost() / n_production;
 
2288
                                VI_log("n_turns = %d\n", n_turns);
 
2289
                                if( n_turns > ( undefended ? 40 : 20 ) ) {
 
2290
                                        VI_log("too long, try growing first?\n");
 
2291
                                        // too long to build this unit, try growing first (needed for later stages in game for small cities)
 
2292
                                        /*const Buildable *aqueduct = mainGamestate->findImprovement(IMPROVEMENT_AQUEDUCT);
 
2293
                                        if( defensiveUnit->getCost() > aqueduct->getCost() ) {
 
2294
                                                // and only do this if the growth improvement is cheaper!
 
2295
                                                if( this->chooseBuildPopLimits() ) {
 
2296
                                                        VI_log("(too long to build defensive unit)\n");
 
2297
                                                        AIInterface::setMainGamestate(NULL);
 
2298
                                                        AIInterface::setAICivilization(NULL);
 
2299
                                                        return;
 
2300
                                                }
 
2301
                                        }*/
 
2302
                                        if( this->chooseBuildPopLimits() ) {
 
2303
                                                // and only do this if the growth improvement is cheaper!
 
2304
                                                if( defensiveUnit->getCost() > this->buildable->getCost() ) {
 
2305
                                                        // okay
 
2306
                                                        VI_log("(too long to build defensive unit)\n");
 
2307
                                                        AIInterface::setMainGamestate(NULL);
 
2308
                                                        AIInterface::setAICivilization(NULL);
 
2309
                                                        return;
 
2310
                                                }
 
2311
                                                else {
 
2312
                                                        // cancel build
 
2313
                                                        this->buildable = NULL;
 
2314
                                                }
 
2315
                                        }
 
2316
                                }
 
2317
                        }
 
2318
                        this->buildable = defensiveUnit;
 
2319
                        VI_log("AI: %s city of %s starts building %s [defender]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2320
                        //delete [] dists;
 
2321
                        AIInterface::setMainGamestate(NULL);
 
2322
                        AIInterface::setAICivilization(NULL);
 
2323
                        return;
 
2324
                }
 
2325
 
 
2326
        }
 
2327
 
 
2328
        if( this->civilization->getNCities() > 1 || n_settlers > 0 ) {
 
2329
                // need improvements for city growth
 
2330
                if( this->chooseBuildPopLimits() ) {
 
2331
                        AIInterface::setMainGamestate(NULL);
 
2332
                        AIInterface::setAICivilization(NULL);
 
2333
                        return;
 
2334
                }
 
2335
        }
 
2336
 
 
2337
        if( bestNuclearMissileUnit != NULL && n_nukes + n_nukes_being_built < 5 && n_production > 0 ) {
 
2338
                // rush building for nukes
 
2339
                int n_turns = bestNuclearMissileUnit->getCost() / n_production;
 
2340
                if( n_turns <= 10 ) {
 
2341
                        this->buildable = bestNuclearMissileUnit;
 
2342
                        VI_log("%s city of %s starts building %s [rush build nukes]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2343
                        AIInterface::setMainGamestate(NULL);
 
2344
                        AIInterface::setAICivilization(NULL);
 
2345
                        return;
 
2346
                }
 
2347
        }
 
2348
 
 
2349
        bool tried_improvements = false;
 
2350
        // build settlers
 
2351
        // TODO: improve performance?
 
2352
        bool build_settler = false;
 
2353
        if( mainGamestate->getYear() <= 100 ) {
 
2354
                // prefer building Settlers in early game phase
 
2355
                // although note this does give the problem of overproduction, on Civs that are on small islands...
 
2356
                build_settler = true;
 
2357
        }
 
2358
        else {
 
2359
                // in later stages of game, for non-small cities, try doing city improvements before other choices, some of the time
 
2360
                if( this->size >= 3 && rand() % 2 == 0 ) {
 
2361
                        tried_improvements = true;
 
2362
                        const Improvement *improvement = chooseImprovementAI();
 
2363
                        if( improvement != NULL ) {
 
2364
                                this->buildable = improvement;
 
2365
                                VI_log("%s city of %s starts building %s [improvement] (1st phase)\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2366
                                AIInterface::setMainGamestate(NULL);
 
2367
                                AIInterface::setAICivilization(NULL);
 
2368
                                return;
 
2369
                        }
 
2370
                }
 
2371
        }
 
2372
 
 
2373
        const Map::Distance *dists = mainGamestate->getMap()->calculateDistanceMap(civilization, NULL, true, true, pos.x, pos.y);
 
2374
        //if( this->getSize() > 1 )
 
2375
        //if( settlersUnit != NULL )
 
2376
        // we try to see if we want settlers, even if we can't build them, because in such case, it's better to build a cheap unit rather than wasting time with an expensive improvement!
 
2377
        if( !build_settler && n_settlers + n_settlers_being_built < max_settlers )
 
2378
        {
 
2379
                for(int y=0;y<mainGamestate->getMap()->getHeight() && !build_settler;y++) {
 
2380
                        for(int x=0;x<mainGamestate->getMap()->getWidth() && !build_settler;x++) {
 
2381
                                /*int diffx = abs(x - pos.x);
 
2382
                                int diffy = abs(y - pos.y);
 
2383
                                if( diffx + diffy > ignore_dist_c )
 
2384
                                        continue; // don't bother considering*/
 
2385
                                ASSERT( mainGamestate->getMap()->isValidBase(x, y) );
 
2386
                                int this_dist = dists[y * mainGamestate->getMap()->getWidth() + x].cost;
 
2387
                                if( this_dist == -1 )
 
2388
                                        continue;
 
2389
                                if( this_dist > ignore_dist_c * road_move_scale_c )
 
2390
                                        continue; // don't bother considering
 
2391
                                const MapSquare *square = mainGamestate->getMap()->getSquare(x, y);
 
2392
                                /*if( !square->canMoveTo(potentialSettlersUnit) )
 
2393
                                        continue;*/
 
2394
                                ASSERT( square->canMoveTo(potentialSettlersUnit) );
 
2395
                                /*if( !this->civilization->isExplored(x, y) ) {
 
2396
                                        if( n_settlers == 0 && n_settlers_being_built == 0 ) {
 
2397
                                                build_settler = true; // if 0 settlers, always build 1 to try exploring unexplored area
 
2398
                                        }
 
2399
                                        continue;
 
2400
                                }*/
 
2401
                                /*MapSquare *mapsq = map->get(x,y);
 
2402
                                if( !game->validCitySquare(x,y) )
 
2403
                                continue;*/
 
2404
                                //if( !game->getMap()->canBuildCity(x,y) )
 
2405
                                /*if( !mainGamestate->getMap()->getSquare(x, y)->canBuildCity() )
 
2406
                                        continue;*/
 
2407
                                if( !AIInterface::canBuildCity(x, y) )
 
2408
                                        continue;
 
2409
                                /*if( diffx + diffy > ignore_dist_c )
 
2410
                                        continue; // don't bother considering*/
 
2411
                                /*if( this_dist > ignore_dist_c * road_move_scale_c )
 
2412
                                        continue; // don't bother considering*/
 
2413
                                build_settler = true;
 
2414
                        }
 
2415
                }
 
2416
        }
 
2417
        if( build_settler && settlersUnit != NULL ) {
 
2418
                this->buildable = settlersUnit;
 
2419
                VI_log("%s city of %s starts building %s [build a new city]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2420
                delete [] dists;
 
2421
                AIInterface::setMainGamestate(NULL);
 
2422
                AIInterface::setAICivilization(NULL);
 
2423
                return;
 
2424
        }
 
2425
 
 
2426
        // build workers
 
2427
        int n_nearby_workers = 0;
 
2428
        int n_improved_squares = 0; // also includes those currently being improved
 
2429
        bool need_workers = false;
 
2430
        /*for(int i=0;i<this->getNCitySquares();i++) {
 
2431
                if( i == centre_city_square_c )
 
2432
                        continue;
 
2433
                Pos2D pos = this->getCitySquare(i);
 
2434
                if( !mainGamestate->getMap()->isValid(pos.x, pos.y) ) {
 
2435
                        continue;
 
2436
                }*/
 
2437
        vector<Pos2D> city_squares = AIInterface::getCitySquares(this->pos.x, this->pos.y, false);
 
2438
        for(vector<Pos2D>::iterator iter = city_squares.begin(); iter != city_squares.end(); ++iter) {
 
2439
                Pos2D adj_pos = *iter;
 
2440
 
 
2441
                //const MapSquare *square = mainGamestate->getMap()->getSquare(adj_pos);
 
2442
                //bool can_be_improved = square->canBeImproved( this->getCivilization() );
 
2443
                bool can_be_improved = AIInterface::canBeImproved(adj_pos.x, adj_pos.y);
 
2444
                if( !need_workers && can_be_improved ) {
 
2445
                        ASSERT( mainGamestate->getMap()->isValidBase(adj_pos.x, adj_pos.y) );
 
2446
                        int this_dist = dists[adj_pos.y * mainGamestate->getMap()->getWidth() + adj_pos.x].cost;
 
2447
                        /*const MapSquare *square = mainGamestate->getMap()->getSquare(adj_pos);
 
2448
                        if( this_dist != -1 && square->canMoveTo( workerUnit ) ) {*/
 
2449
                        if( this_dist != -1 ) {
 
2450
                                need_workers = true;
 
2451
                        }
 
2452
                }
 
2453
                bool is_improved = false;
 
2454
                const vector<Unit *> *units = mainGamestate->getMap()->findUnitsAt(adj_pos.x, adj_pos.y);
 
2455
                for(vector<Unit *>::const_iterator iter2 = units->begin(); iter2 != units->end(); ++iter2) {
 
2456
                        const Unit *unit = *iter2;
 
2457
                        if( unit->getCivilization() == this->civilization && unit->getTemplate()->canBuildRoads() ) {
 
2458
                                n_nearby_workers++;
 
2459
                                is_improved = true;
 
2460
                        }
 
2461
                }
 
2462
                if( !is_improved ) {
 
2463
                        Road road = AIInterface::getRoad(adj_pos.x, adj_pos.y);
 
2464
                        //if( !can_be_improved && square->getRoad() != ROAD_NONE ) {
 
2465
                        if( !can_be_improved && road != ROAD_UNKNOWN && road != ROAD_NONE ) {
 
2466
                        //if( !can_be_improved ) {
 
2467
                                is_improved = true;
 
2468
                        }
 
2469
                }
 
2470
                //if( is_improved && i != this->getCentreCitySquareIndex() ) {
 
2471
                if( is_improved ) {
 
2472
                        n_improved_squares++;
 
2473
                }
 
2474
                //delete units;
 
2475
        }
 
2476
        if( this->size <= 2 && n_improved_squares >= max_road_bonus_c ) {
 
2477
                need_workers = false; // small cities need fewer improved squares - this allows us to start on settlers sooner (also see corresponding code for Unit AI)
 
2478
        }
 
2479
        if( n_nearby_workers == 0 && need_workers ) {
 
2480
                this->buildable = workerUnit;
 
2481
                VI_log("%s city of %s starts building %s [worker]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2482
                delete [] dists;
 
2483
                AIInterface::setMainGamestate(NULL);
 
2484
                AIInterface::setAICivilization(NULL);
 
2485
                return;
 
2486
        }
 
2487
 
 
2488
        // build explorers
 
2489
        bool build_explorer = false;
 
2490
        bool all_explored  = true;
 
2491
        for(int y=0;y<mainGamestate->getMap()->getHeight() && !build_explorer;y++) {
 
2492
                for(int x=0;x<mainGamestate->getMap()->getWidth() && !build_explorer;x++) {
 
2493
                        /*int diffx = abs(x - pos.x);
 
2494
                        int diffy = abs(y - pos.y);
 
2495
                        if( diffx + diffy > ignore_dist_c )
 
2496
                                continue; // don't bother considering*/
 
2497
                        if( this->civilization->isExplored(x, y) )
 
2498
                                continue;
 
2499
                        all_explored = false;
 
2500
                        ASSERT( mainGamestate->getMap()->isValidBase(x, y) );
 
2501
                        /*int this_dist = dists[y * mainGamestate->getMap()->getWidth() + x].cost;
 
2502
                        if( this_dist == -1 )
 
2503
                                continue;*/
 
2504
                        // need to look at adjacent squares for dist!
 
2505
                        bool found_dist = false;
 
2506
                        int this_dist = 0;
 
2507
                        vector<Pos2D> adjacent_squares = AIInterface::getAdjacentSquares(x, y, false);
 
2508
                        for(vector<Pos2D>::iterator iter = adjacent_squares.begin(); iter != adjacent_squares.end(); ++iter) {
 
2509
                                Pos2D adjacent_square = *iter;
 
2510
                                int adj_dist = dists[adjacent_square.y * mainGamestate->getMap()->getWidth() + adjacent_square.x].cost;
 
2511
                                if( adj_dist != -1 ) {
 
2512
                                        if( !found_dist || adj_dist < this_dist ) {
 
2513
                                                found_dist = true;
 
2514
                                                this_dist = adj_dist;
 
2515
                                        }
 
2516
                                }
 
2517
                        }
 
2518
                        if( !found_dist ) {
 
2519
                                // the square is surrounded by unexplored squares, so there must be another one closer
 
2520
                                continue;
 
2521
                        }
 
2522
                        if( this_dist > ignore_dist_c * road_move_scale_c )
 
2523
                                continue; // don't bother considering
 
2524
                        /*const MapSquare *square = mainGamestate->getMap()->getSquare(x, y);
 
2525
                        if( !square->canMoveTo(fastestUnit) )
 
2526
                                continue;*/
 
2527
                        build_explorer = true;
 
2528
                }
 
2529
        }
 
2530
        // don't build more explorers if we have lots of nearby workers who could do the job later (if the explorer unit can also work, we just end up building loads of explorers...)
 
2531
        if( n_nearby_workers < 2 && n_explorers + n_explorers_being_built < max_explorers && build_explorer ) {
 
2532
                /*Unit::Type move_type = this->bestBuildableUnit(MOVEMENT);
 
2533
                this->building = Buildable::getBuildable(Buildable::UNIT, move_type);*/
 
2534
                this->buildable = fastestUnit;
 
2535
                VI_log("%s city of %s starts building %s [explorer]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2536
                delete [] dists;
 
2537
                AIInterface::setMainGamestate(NULL);
 
2538
                AIInterface::setAICivilization(NULL);
 
2539
                return;
 
2540
        }
 
2541
 
 
2542
        // now try again
 
2543
        if( this->chooseBuildPopLimits() ) {
 
2544
                delete [] dists;
 
2545
                AIInterface::setMainGamestate(NULL);
 
2546
                AIInterface::setAICivilization(NULL);
 
2547
                return;
 
2548
        }
 
2549
 
 
2550
        if( !build_explorer && !all_explored ) {
 
2551
                // if build_explorer is false, it means there are no nearby squares left to explore - try building sea improvements
 
2552
                // if all explored, not as urgent to do this (still useful for travel, but we'll build them with the other improvements)
 
2553
                if( !this->hasImprovement(IMPROVEMENT_PORT) ) {
 
2554
                        const Buildable *b = mainGamestate->findImprovement(IMPROVEMENT_PORT);
 
2555
                        if( this->canBuild(b) ) {
 
2556
                                this->buildable = b;
 
2557
                                VI_log("%s city of %s starts building %s [port]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2558
                                delete [] dists;
 
2559
                                AIInterface::setMainGamestate(NULL);
 
2560
                                AIInterface::setAICivilization(NULL);
 
2561
                                return;
 
2562
                        }
 
2563
                }
 
2564
                if( !this->hasImprovement(IMPROVEMENT_HARBOUR) ) {
 
2565
                        const Buildable *b = mainGamestate->findImprovement(IMPROVEMENT_HARBOUR);
 
2566
                        if( this->canBuild(b) ) {
 
2567
                                this->buildable = b;
 
2568
                                VI_log("%s city of %s starts building %s [harbour]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2569
                                delete [] dists;
 
2570
                                AIInterface::setMainGamestate(NULL);
 
2571
                                AIInterface::setAICivilization(NULL);
 
2572
                                return;
 
2573
                        }
 
2574
                }
 
2575
        }
 
2576
 
 
2577
        if( this->size == 1 && build_settler ) {
 
2578
                // remember, only a viable tactic if the city is going to grow to size 2
 
2579
                this->buildable = cheapestUnit;
 
2580
                VI_log("%s city of %s starts building %s [cheap unit whilst growing]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2581
                delete [] dists;
 
2582
                AIInterface::setMainGamestate(NULL);
 
2583
                AIInterface::setAICivilization(NULL);
 
2584
                return;
 
2585
        }
 
2586
 
 
2587
        // check already build enough air units
 
2588
        {
 
2589
                /*const MapSquare *square = mainGamestate->getMap()->getSquare(pos);
 
2590
                const vector<Unit *> *units = square->getUnits();*/
 
2591
                const vector<Unit *> *units = AIInterface::getUnits(pos.x, pos.y);
 
2592
                int n_fighters = 0, n_bombers = 0;
 
2593
                for(vector<Unit *>::const_iterator iter = units->begin(); iter != units->end(); ++iter) {
 
2594
                        const Unit *unit = *iter;
 
2595
                        if( bestFighterAirUnit != NULL && unit->getTemplate() == bestFighterAirUnit ) {
 
2596
                                n_fighters++;
 
2597
                        }
 
2598
                        if( bestBomberAirUnit != NULL && unit->getTemplate() == bestBomberAirUnit ) {
 
2599
                                n_bombers++;
 
2600
                        }
 
2601
                }
 
2602
                if( n_fighters >= 4 ) {
 
2603
                        VI_log("%s city of %s: already have %d fighters\n", this->civilization->getNameAdjective(), this->getName(), n_fighters);
 
2604
                        bestFighterAirUnit = NULL;
 
2605
                }
 
2606
                if( n_bombers >= 4 ) {
 
2607
                        VI_log("%s city of %s: already have %d bombers\n", this->civilization->getNameAdjective(), this->getName(), n_bombers);
 
2608
                        bestBomberAirUnit = NULL;
 
2609
                }
 
2610
        }
 
2611
 
 
2612
        // air/missile units for civs at war
 
2613
        if( ( bestFighterAirUnit != NULL || bestBomberAirUnit != NULL || bestConventionalMissileUnit != NULL || bestNuclearMissileUnit != NULL )
 
2614
                && ( rand() % 2 == 0 ) // only build air/missile units some of the time
 
2615
                ) {
 
2616
                const UnitTemplate *unit = chooseAirUnitAI(bestFighterAirUnit, bestBomberAirUnit, bestConventionalMissileUnit, bestNuclearMissileUnit, true);
 
2617
                if( unit != NULL ) {
 
2618
                        this->buildable = unit;
 
2619
                        VI_log("%s city of %s starts building %s [bomb enemy city, at war]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2620
                        delete [] dists;
 
2621
                        AIInterface::setMainGamestate(NULL);
 
2622
                        AIInterface::setAICivilization(NULL);
 
2623
                        return;
 
2624
                }
 
2625
        }
 
2626
 
 
2627
        // build attackers for nearby enemies
 
2628
        if( bestUnit != NULL ) {
 
2629
                /*for(int i=0;i<mainGamestate->getNCivilizations();i++) {
 
2630
                        const Civilization *civ = mainGamestate->getCivilization(i);
 
2631
                        if( civ == this->civilization )
 
2632
                                continue;
 
2633
                        if( civ->isDead() )
 
2634
                                continue;
 
2635
                        const Relationship *relationship = mainGamestate->findRelationship(this->civilization, civ);
 
2636
                        if( relationship->getStatus() == Relationship::STATUS_PEACE )
 
2637
                                continue;*/
 
2638
                vector<Civilization *> civs = AIInterface::getCivilizations(AIInterface::GETCIVILIZATIONS_WAR);
 
2639
                for(vector<Civilization *>::iterator iter = civs.begin(); iter != civs.end(); ++iter) {
 
2640
                        Civilization *civ = *iter;
 
2641
                        // attack cities?
 
2642
                        /*for(int j=0;j<civ->getNCities();j++) {
 
2643
                                const City *city = civ->getCity(j);
 
2644
                                int c_xpos = city->getX();
 
2645
                                int c_ypos = city->getY();
 
2646
                                if( !this->civilization->isExplored(c_xpos, c_ypos) )
 
2647
                                        continue;*/
 
2648
                        vector<City *> cities = AIInterface::getCities(civ);
 
2649
                        for(vector<City *>::const_iterator iter2 = cities.begin(); iter2 != cities.end(); ++iter2) {
 
2650
                                const City *city = *iter2;
 
2651
                                int c_xpos = city->getX();
 
2652
                                int c_ypos = city->getY();
 
2653
                                ASSERT( mainGamestate->getMap()->isValidBase(c_xpos, c_ypos) );
 
2654
                                int this_dist = dists[c_ypos * mainGamestate->getMap()->getWidth() + c_xpos].cost;
 
2655
                                if( this_dist == -1 )
 
2656
                                        continue;
 
2657
                                if( this_dist > ignore_dist_c * road_move_scale_c )
 
2658
                                        continue; // don't bother considering
 
2659
                                this->buildable = bestUnit;
 
2660
                                VI_log("%s city of %s starts building %s [attack enemy city of %s]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName(), city->getName());
 
2661
                                delete [] dists;
 
2662
                                AIInterface::setMainGamestate(NULL);
 
2663
                                AIInterface::setAICivilization(NULL);
 
2664
                                return;
 
2665
                        }
 
2666
                        // attack units?
 
2667
                        vector<Unit *> units = AIInterface::getUnits(civ);
 
2668
                        /*for(int j=0;j<civ->getNUnits();j++) {
 
2669
                                const Unit *unit = civ->getUnit(j);
 
2670
                                int u_xpos = unit->getX();
 
2671
                                int u_ypos = unit->getY();
 
2672
                                if( !this->civilization->isExplored(u_xpos, u_ypos) )
 
2673
                                        continue;*/
 
2674
                        for(vector<Unit *>::const_iterator iter2 = units.begin(); iter2 != units.end(); ++iter2) {
 
2675
                                const Unit *unit = *iter2;
 
2676
                                int u_xpos = unit->getX();
 
2677
                                int u_ypos = unit->getY();
 
2678
                                ASSERT( mainGamestate->getMap()->isValidBase(u_xpos, u_ypos) );
 
2679
                                int this_dist = dists[u_ypos * mainGamestate->getMap()->getWidth() + u_xpos].cost;
 
2680
                                if( this_dist == -1 )
 
2681
                                        continue;
 
2682
                                if( this_dist > ignore_dist_c * road_move_scale_c )
 
2683
                                        continue; // don't bother considering
 
2684
                                this->buildable = bestUnit;
 
2685
                                VI_log("%s city of %s starts building %s [attack enemy unit]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2686
                                delete [] dists;
 
2687
                                AIInterface::setMainGamestate(NULL);
 
2688
                                AIInterface::setAICivilization(NULL);
 
2689
                                return;
 
2690
                        }
 
2691
                }
 
2692
        }
 
2693
 
 
2694
        // build improvements
 
2695
        //for(int i=0;i<N_IMPROVEMENTS;i++) {
 
2696
        /*const Improvement *cheapest_b = NULL;
 
2697
        int cheapest_b_cost = 0;
 
2698
        for(int i=0;i<game->getNImprovements();i++) {
 
2699
                //Improvement *b = (Improvement *)Improvement::getImprovement(static_cast<ImprovementType>(i));
 
2700
                const Improvement *b = game->getImprovement(i);
 
2701
                if( this->canBuild( b ) ) {
 
2702
                        if( cheapest_b == NULL || b->getCost() < cheapest_b_cost ) {
 
2703
                                cheapest_b = b;
 
2704
                                cheapest_b_cost = b->getCost();
 
2705
                        }
 
2706
                }
 
2707
        }
 
2708
        if( cheapest_b != NULL ) {
 
2709
                this->buildable = cheapest_b;
 
2710
                VI_log("%s city of %s starts building %s [improvement]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2711
                delete [] dists;
 
2712
                AIInterface::setMainGamestate(NULL);
 
2713
                AIInterface::setAICivilization(NULL);
 
2714
                return;
 
2715
        }*/
 
2716
 
 
2717
        if( !tried_improvements ) {
 
2718
                const Improvement *improvement = chooseImprovementAI();
 
2719
                if( improvement != NULL ) {
 
2720
                        this->buildable = improvement;
 
2721
                        VI_log("%s city of %s starts building %s [improvement] (2nd phase)\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2722
                        delete [] dists;
 
2723
                        AIInterface::setMainGamestate(NULL);
 
2724
                        AIInterface::setAICivilization(NULL);
 
2725
                        return;
 
2726
                }
 
2727
        }
 
2728
 
 
2729
        // air/missile units for civs at peace
 
2730
        if( ( bestFighterAirUnit != NULL || bestBomberAirUnit != NULL || bestConventionalMissileUnit != NULL || bestNuclearMissileUnit != NULL )
 
2731
                && ( bestUnit == NULL || rand() % 2 == 0 ) // only build air/missile units some of the time
 
2732
                ) {
 
2733
                const UnitTemplate *unit = chooseAirUnitAI(bestFighterAirUnit, bestBomberAirUnit, bestConventionalMissileUnit, bestNuclearMissileUnit, false);
 
2734
                if( unit != NULL ) {
 
2735
                        this->buildable = unit;
 
2736
                        VI_log("%s city of %s starts building %s [bomb enemy city, at peace]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2737
                        delete [] dists;
 
2738
                        AIInterface::setMainGamestate(NULL);
 
2739
                        AIInterface::setAICivilization(NULL);
 
2740
                        return;
 
2741
                }
 
2742
        }
 
2743
 
 
2744
        // build attackers
 
2745
        if( bestUnit != NULL ) {
 
2746
                this->buildable = bestUnit;
 
2747
                VI_log("%s city of %s starts building %s [attacker]\n", this->civilization->getNameAdjective(), this->getName(), this->buildable->getName());
 
2748
                delete [] dists;
 
2749
                AIInterface::setMainGamestate(NULL);
 
2750
                AIInterface::setAICivilization(NULL);
 
2751
                return;
 
2752
        }
 
2753
 
 
2754
        delete [] dists;
 
2755
        AIInterface::setMainGamestate(NULL);
 
2756
        AIInterface::setAICivilization(NULL);
 
2757
 
 
2758
#endif
 
2759
}