1
#include "conquests_stdafx.h"
4
#include "citywindow.h"
5
#include "civilization.h"
7
#include "technology.h"
9
#include "maingamestate.h"
11
#include "infowindow.h"
13
#include "../Vision/VisionIface.h"
15
#include <cstring> // needed for Linux at least
18
using std::stringstream;
54
/*int populations[] = {
64
const int n_size_c = sizeof(populations)/sizeof(populations[0]);
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),
70
progress_population(0),
71
progress_buildable(0), buildable(NULL),
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() );
81
civilization->addCity(this);
82
square->setCity(this, true);
83
if( square->getType() == TYPE_FOREST ) {
84
square->setType(TYPE_GRASSLAND);
86
if( square->getBonusResource() != NULL ) {
87
square->setBonusResource(NULL);
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()) ) {
96
if( element->getInitialAmount() > 0 ) {
97
this->element_stocks[element] = element->getInitialAmount();
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();
106
//const Buildable *buildable = game->findBuildable("Peasants");
107
//this->setBuildable(buildable);
108
this->setDefaultBuildable();
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),
115
progress_population(-1),
116
progress_buildable(-1), buildable(NULL),
117
counter_barracks(-1) {
118
// create dummy city, used by City::load()
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;
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);
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);
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;
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=";
161
City *city = new City(mainGamestate, civilization);
163
while( ok && fgets(line, max_line_c, file) != NULL ) {
164
//if( strcmp(line, "[/city]\n") == 0 ) {
165
if( matchFileLine(line, "[/city]") ) {
169
if( line[0] == '[' ) {
170
VI_log("City::load: Unexpected '[' start of new section!\n");
174
if( matchFileLine(line, field_xpos_c) ) {
175
parseFileLine(word, line, field_xpos_c);
176
city->pos.x = atoi(word);
178
else if( matchFileLine(line, field_ypos_c) ) {
179
parseFileLine(word, line, field_ypos_c);
180
city->pos.y = atoi(word);
182
else if( matchFileLine(line, field_name_c) ) {
183
parseFileLine(word, line, field_name_c);
186
else if( matchFileLine(line, field_size_c) ) {
187
parseFileLine(word, line, field_size_c);
188
city->size = atoi(word);
190
else if( matchFileLine(line, field_progress_population_c) ) {
191
parseFileLine(word, line, field_progress_population_c);
192
city->progress_population = atoi(word);
194
else if( matchFileLine(line, field_progress_buildable_c) ) {
195
parseFileLine(word, line, field_progress_buildable_c);
196
city->progress_buildable = atoi(word);
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;
204
city->buildable = game_g->findBuildable(word);
205
if( city->buildable == NULL ) {
206
VI_log("City::load: can't find buildable: %s\n", word);
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);
219
city->improvements.push_back(improvement); // don't copy, just pass a pointer
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);
230
if( fgets(line, max_line_c, file) == NULL ) {
231
VI_log("unexpected eof after element %s\n", word);
235
if( matchFileLine(line, field_amount_c) ) {
236
parseFileLine(word, line, field_amount_c);
237
city->element_stocks[element] = atoi(word);
240
VI_log("failed to find amount for element %s\n", word);
246
else if( matchFileLine(line, field_counter_barracks_c) ) {
247
parseFileLine(word, line, field_counter_barracks_c);
248
city->counter_barracks = atoi(word);
252
VI_log("City::load: didn't find end section\n");
255
else if( city->pos.x == -1 || city->pos.y == -1 ) {
256
VI_log("City::load: didn't find position\n");
259
// TODO: check all fields have been set
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
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());
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);
292
fprintf(file, "[/city]\n");
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;
304
void City::modifyForDifficulty(int *value, bool science) const {
305
if( this->civilization == mainGamestate->getPlayer() ) {
308
//const int min_value = science ? 3 : 2;
310
/*if( !science && mainGamestate->getDifficulty() != MainGamestate::DIFFICULTY_EASY && mainGamestate->getDifficulty() != MainGamestate::DIFFICULTY_MEDIUM ) {
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
318
switch( mainGamestate->getDifficulty() ) {
319
case MainGamestate::DIFFICULTY_EASY:
322
case MainGamestate::DIFFICULTY_MEDIUM:
325
case MainGamestate::DIFFICULTY_HARD:
327
// production needs a higher value, to make the increase comparable
328
mult = science ? 150 : 165;
330
case MainGamestate::DIFFICULTY_INSANE:
337
int new_value = (mult * (*value)) / 100;
338
/*if( *value > 0 && new_value == 0 ) {
339
// don't round down to 0
342
if( *value < min_value ) {
343
*value = min_value; // don't go below the min value
348
const int n_city_squares_c = 21;
349
const int centre_city_square_c = 10;
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 );
357
npos = Pos2D(pos.x - 1, pos.y - 2);
360
npos = Pos2D(pos.x, pos.y - 2);
363
npos = Pos2D(pos.x + 1, pos.y - 2);
366
npos = Pos2D(pos.x - 2, pos.y - 1);
369
npos = Pos2D(pos.x - 1, pos.y - 1);
372
npos = Pos2D(pos.x, pos.y - 1);
375
npos = Pos2D(pos.x + 1, pos.y - 1);
378
npos = Pos2D(pos.x + 2, pos.y - 1);
381
npos = Pos2D(pos.x - 2, pos.y);
384
npos = Pos2D(pos.x - 1, pos.y);
387
npos = Pos2D(pos.x, pos.y);
390
npos = Pos2D(pos.x + 1, pos.y);
393
npos = Pos2D(pos.x + 2, pos.y);
396
npos = Pos2D(pos.x - 2, pos.y + 1);
399
npos = Pos2D(pos.x - 1, pos.y + 1);
402
npos = Pos2D(pos.x, pos.y + 1);
405
npos = Pos2D(pos.x + 1, pos.y + 1);
408
npos = Pos2D(pos.x + 2, pos.y + 1);
411
npos = Pos2D(pos.x - 1, pos.y + 2);
414
npos = Pos2D(pos.x, pos.y + 2);
417
npos = Pos2D(pos.x + 1, pos.y + 2);
423
map->reduceToBase(&npos.x, &npos.y);
427
// remember to check if isValid before using it!
428
Pos2D City::getCitySquare(int i) const {
429
return getCitySquare(mainGamestate->getMap(), i, pos);
432
int City::getCentreCitySquareIndex() {
433
return centre_city_square_c;
436
int City::getNCitySquares() {
437
return n_city_squares_c;
440
/*Pos2D City::getAdjacentSquare(int i) const {
441
ASSERT( i >= 0 && i < 8 );
444
return Pos2D(pos.x - 1, pos.y - 1);
447
return Pos2D(pos.x, pos.y - 1);
450
return Pos2D(pos.x + 1, pos.y - 1);
453
return Pos2D(pos.x - 1, pos.y);
456
return Pos2D(pos.x + 1, pos.y);
459
return Pos2D(pos.x - 1, pos.y + 1);
462
return Pos2D(pos.x, pos.y + 1);
465
return Pos2D(pos.x + 1, pos.y + 1);
469
return Pos2D(-1, -1); // won't actually reach here
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 ) {
480
return mainGamestate->getMap()->isOnOrAdjacent(pos, mapType);
483
string City::getStatsInfo() const {
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";
490
if( map->isWithinCityRadius(this->pos, TYPE_FOREST, false) ) {
491
str << "+1 city production due to Forest.\n";
493
int road_railways_bonus = calculateRoadRailwaysScienceBonus();
494
if( road_railways_bonus > 0 ) {
495
str << "+" << road_railways_bonus << " science due to Roads/Railways.\n";
497
for(int i=0;i<this->getNCitySquares();i++) {
498
if( i == centre_city_square_c ) {
501
Pos2D sq_pos = this->getCitySquare(i);
502
if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
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";
513
if( bonus_growth > 0 ) {
514
str << "Faster growth due to " << bonus_resource->getName() << " trade bonus.\n";
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;
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;
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;
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 );
560
this->setDefaultBuildable();
561
new CityWindow(mainGamestate, this);
564
this->chooseAndSetBuildAI();
568
void City::setSize(int size) {
570
VI_log("%s city of %s: size changed to %d\n", this->civilization->getNameAdjective(), this->getName(), size);
574
int City::getPopulation() const {
576
for(int i=1;i<size;i++) {
579
ASSERT( size >= 1 && size <= n_size_c );
580
int population = populations[size-1];
584
string City::getPopulationString() const {
585
/*int pop = this->getPopulation();
593
int mod_pop = pop % 1000;
597
else if( mod_pop < 100 )
601
VI_log("temp: %s\n", temp.str().c_str());
607
str.str(temp.str() + str.str());
608
VI_log("str: %s\n", str.str().c_str());
612
int pop = this->getPopulation();
618
while( temp_pop > 0 ) {
622
/*stringstream base_str;
624
int n = 3 - (base_str.str().length() % 3);
626
for(int i=0;i<base_str.str().length();i++) {
627
if( !first && n % 3 == 0 ) {
632
str << base_str.str().at(i);
635
return formatNumber(pop);
638
int City::calculateProduction() const {
639
// todo: cache the value?
640
int production = getPopulation() / 10000;
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) ) {
648
if( !improvement->getProductionBonusAllCities() ) {
649
production += improvement->getProductionBonus();
653
bool done_forest = false;
654
for(int i=0;i<this->getNCitySquares();i++) {
655
if( i == centre_city_square_c ) {
658
Pos2D sq_pos = this->getCitySquare(i);
659
if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
662
const MapSquare *square = mainGamestate->getMap()->getSquare(sq_pos);
663
if( !done_forest && square->getType() == TYPE_FOREST ) {
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() ) ) {
675
if( bonus_ok && bonus_resource->getRequiresTechnology() != NULL ) {
676
if( !this->civilization->hasTechnology( bonus_resource->getRequiresTechnology() ) ) {
681
if( bonus_resource->canUse(this) )
682
production += bonus_resource->getBonusProduction();
685
//if( this->civilization->hasTechnology( game_g->getGameData()->findTechnology("Agricultural Revolution") ) ) {
686
if( this->civilization->hasTechnology("Agricultural Revolution") ) {
689
//if( this->civilization->hasTechnology( game_g->getGameData()->findTechnology("Industrial Revolution") ) ) {
690
if( this->civilization->hasTechnology("Industrial Revolution") ) {
693
modifyForResistance(&production);
694
modifyForDifficulty(&production, false);
695
if( this->civilization->hasBonus(Civilization::BONUS_PRODUCTION) ) {
697
production = (int)(production * 1.5);
702
int City::calculateRoadRailwaysScienceBonus() const {
705
for(int i=0;i<this->getNCitySquares();i++) {
706
if( i == centre_city_square_c ) {
709
Pos2D sq_pos = this->getCitySquare(i);
710
if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
713
const MapSquare *square = mainGamestate->getMap()->getSquare(sq_pos);
714
/*if( square->getRoad() != ROAD_NONE ) {
715
if( square->givesRoadBonus() ) {
717
if( road_bonus == max_road_bonus_c ) {
722
if( square->givesRoadBonus() ) {
723
if( square->getRoad() == ROAD_BASIC ) {
726
else if( square->getRoad() == ROAD_RAILWAYS ) {
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;
740
int City::calculateScience() const {
741
// todo: cache the value?
742
int science = getPopulation() / 20000;
746
/*int road_bonus = 0;
748
for(int i=0;i<this->getNCitySquares();i++) {
749
if( i == centre_city_square_c ) {
752
Pos2D sq_pos = this->getCitySquare(i);
753
if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
756
const MapSquare *square = mainGamestate->getMap()->getSquare(sq_pos);
757
if( square->givesRoadBonus() ) {
758
if( square->getRoad() == ROAD_BASIC ) {
761
else if( square->getRoad() == ROAD_RAILWAYS ) {
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();
775
if( this->hasImprovement("School") ) {
776
// increases base, so do before multiplier modifiers
780
int base_science = science;
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) ) {
789
if( !improvement->getResearchMultiplierBonusAllCities() ) {
790
science += (base_science*improvement->getResearchMultiplierBonus())/100;
793
// hardcoded improvements
794
/*if( this->hasImprovement("Library") ) {
795
science += base_science/2;
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;
806
modifyForResistance(&science);
807
modifyForDifficulty(&science, true);
808
if( this->civilization->hasBonus(Civilization::BONUS_TECH) ) {
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) ) {
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) ) {
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 )
836
for(vector<const Improvement *>::const_iterator iter = improvements.begin();iter != improvements.end(); ++iter) {
837
const Improvement *improvement = *iter;
838
if( !this->improvementHasEffect(improvement) ) {
842
power_per_turn += improvement->getPowerPerTurn();
844
return power_per_turn;
847
int City::getResistance() const {
848
ASSERT( this->is_resisting );
849
return this->resistance;
852
int City::getPopulationCost() const {
854
MapSquare *square = mainGamestate->getMap()->getSquare(pos);
855
if( square->getType() == TYPE_ARTIC || square->getType() == TYPE_DESERT ) {
857
cost = (int)(cost * 1.5);
859
/*if( this->hasImprovement("Hospital") ) {
861
cost = (int)(cost * 0.8);
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();
869
//if( this->civilization->hasTechnology( mainGamestate->findTechnology("Genetics") ) ) {
870
if( this->civilization->hasTechnology("Genetics") ) {
872
cost = (int)(cost * 0.8);
874
for(int i=0;i<this->getNCitySquares();i++) {
875
if( i == centre_city_square_c ) {
878
Pos2D sq_pos = this->getCitySquare(i);
879
if( !mainGamestate->getMap()->isValid(sq_pos.x, sq_pos.y) ) {
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() ) ) {
891
if( bonus_ok && bonus_resource->getRequiresTechnology() != NULL ) {
892
if( !this->civilization->hasTechnology( bonus_resource->getRequiresTechnology() ) ) {
897
if( bonus_resource->canUse(this) )
898
cost -= bonus_resource->getBonusReduceGrowthTime();
905
void City::addImprovement(const Improvement *improvement) {
906
this->improvements.push_back(improvement); // don't copy, just pass a pointer
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);
913
if( this->civilization == mainGamestate->getPlayer() ) {
914
mainGamestate->centre(this->pos);
916
if( improvement->getRaceSpecific() != NULL ) {
917
text << this->getName() << " has built a great project!: " << buildable->getName() << ".";
920
text << this->getName() << " has built: " << buildable->getName() << ".";
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);
927
else if( improvement->getRaceSpecific() != NULL ) {
928
// n.b., notify player even if we haven't made contact with the civilization
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);
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;
947
void City::update() {
948
/*if( !needs_update ) {
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;
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()) ) {
961
if( element->getRequiresImprovement() != NULL && !this->hasImprovementOrNewer(element->getRequiresImprovement()) ) {
964
this->element_stocks[element] += element->getBaseRate();
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;
979
VI_log("%s city of %s receives %d of %s\n", this->civilization->getNameAdjective(), this->getName(), total, element->getName());
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") ) ) {
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);
993
if( city != this && city->element_stocks[element] < max_stock_c ) {
994
cities.insert(pair<int, City *>(city->element_stocks[element], city));
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]);
1005
while( this->element_stocks[element] > max_stock_c ) {
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]++;
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");
1024
/*while( this->element_stocks[element] > max_stock_c ) {
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);
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]++;
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");
1047
this->element_stocks[element] = min(this->element_stocks[element], max_stock_c);
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"));
1059
if( !this->canBuild(unit_template) ) {
1060
unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Riflemen"));
1062
if( !this->canBuild(unit_template) ) {
1063
unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Musketeers"));
1065
if( !this->canBuild(unit_template) ) {
1066
unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Men-At-Arms"));
1068
if( !this->canBuild(unit_template) ) {
1069
unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Swordsmen"));
1071
if( !this->canBuild(unit_template) ) {
1072
unit_template = static_cast<const UnitTemplate *>(game_g->findBuildable("Peasants"));
1075
VI_log("The %s city of %s produces barracks unit: %s\n", this->civilization->getNameAdjective(), this->getName(), unit_template->getName());
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;
1084
/*if( this->buildable == NULL ) {
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);
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);
1108
useUpElements(this->buildable);
1111
this->progress_buildable += calculateProduction();
1113
if( this->progress_buildable >= buildable->getCost() ) {
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();
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) ) {
1139
if( improvement->getAutoVeteranBonus() ) {
1140
auto_veteran = true;
1143
if( auto_veteran ) {
1144
unit->setVeteran(true);
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();
1156
VI_log("Unknown type: %s\n", this->buildable->getName());
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();
1169
if( civilization != mainGamestate->getPlayer() ) {
1171
this->chooseAndSetBuildAI();
1176
if( civilization->getTechnology() == NULL ) {
1177
if( civilization == mainGamestate->getPlayer() ) {
1178
mainGamestate->askTechnology();
1181
civilization->chooseTechnologyAI();
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() ) {
1190
Age age = civilization->getAge();
1191
if( (int)age >= (int)AGE_INDUSTRIAL )
1192
text << "Our scientists have discovered the secrets of ";
1194
text << "Our wise men have discovered the secrets of ";
1195
text << was_researching->getName();
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);
1203
mainGamestate->askTechnology();
1206
civilization->chooseTechnologyAI();
1211
this->civilization->updatePower( this->calculatePowerPerTurn() );
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;
1225
max_size = n_size_c;
1226
if( this->size <= max_size ) {
1228
if( this->civilization->hasBonus(Civilization::BONUS_GROWTH) )
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;
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();
1244
this->progress_population = population_cost;
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;
1255
this->setSize( size-1 );
1256
VI_log("%s city of %s shrinks to size %d\n", this->civilization->getNameAdjective(), this->getName(), this->size);
1260
// update resistance
1261
if( this->is_resisting ) {
1262
const vector<Unit *> *units = mainGamestate->getMap()->findUnitsAt( this->pos );
1264
for(vector<Unit *>::const_iterator iter = units->begin(); iter != units->end(); ++iter) {
1265
const Unit *unit = *iter;
1266
if( unit->getTemplate()->getAttack() > 0 ) {
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;
1277
VI_log("resistance of %s falls to %d\n", this->getName(), this->resistance);
1280
needs_update = false;
1281
if( open_citywindow ) {
1282
new CityWindow(mainGamestate, this);
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);
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);
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() ) {
1305
const Improvement *improvement = unit_template->getRequiresImprovement();
1306
if( improvement == NULL ) {
1309
else if( this->hasImprovement(improvement) ) {
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
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 )
1326
int this_range = this_improvement->getTravelRange();
1327
if( this_range > 0 )
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 )
1339
int this_range = this_improvement->getTravelRange();
1340
if( this_range > 0 )
1346
int City::getTravelRange(bool by_air) const {
1347
// travel range for land units, by sea or air
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 )
1354
if( this_improvement->isTravelByAir() != by_air )
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") ) {
1362
else if( this->civilization->hasTechnology("Magnetism") ) {
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;
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;
1377
if( this_range > range )
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
1387
if( unit_template != NULL && unit_template->isMissile() ) {
1388
return; // no travel for missiles, for now
1390
if( unit_template != NULL && unit_template->isAir() ) {
1391
// air units travel according to their own range, and can only travel by air
1393
if( this->canLaunch(unit_template) ) {
1394
*air_range = unit_template->getAirRange();
1397
// no longer an airport!
1402
*sea_range = this->getTravelRange(false);
1403
*air_range = this->getTravelRange(true);
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());
1411
ASSERT( unit_template == NULL );
1413
/*if( unit_template != NULL && unit_template->isSea() ) { // test
1414
sea_defending = true;
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() );
1423
if( sea_defending ) {
1424
sea_range = unit_template->getSeaDefenceRange();
1427
this->getTravelRanges(&sea_range, &air_range, unit_template);
1429
/*if( unit_template != NULL && unit_template->isAir() ) {
1431
air_range = unit_template->getAirRange();
1432
ASSERT( this->getTravelRange(true) > 0 );
1435
sea_range = this->getTravelRange(false);
1436
air_range = this->getTravelRange(true);
1440
//ASSERT( civilization == game->getPlayer() );
1441
mainGamestate->getMap()->resetTargets();
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.
1452
if( reveal && this->civilization == mainGamestate->getPlayer() && game_g->getGraphicsEnvironment()->getWorld() != NULL && game_g->getGraphicsEnvironment()->getWorld()->getTerrain() != NULL ) {
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() ) {
1463
//this->civilization->setMapVisible(x, y, true);
1464
this->civilization->uncover(x, y, 1);
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!
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) ) ) ) {
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);
1490
square->setTarget(true);
1505
if( air_range > 0 ) {
1507
this->civilization->uncover(pos.x, pos.y, air_range);
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!
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);
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;
1551
void City::setBuildable(const Buildable *buildable) {
1552
if( this->buildable == buildable )
1554
if( buildable != NULL ) {
1555
ASSERT( this->canBuild( buildable ) );
1557
this->buildable = buildable;
1558
this->progress_buildable = 0;
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) ) {
1569
if( defensiveUnit == NULL || unit_template->getDefence() > defensiveUnit->getDefence() ||
1570
( unit_template->getDefence() == defensiveUnit->getDefence() && unit_template->getCost() < defensiveUnit->getCost() )
1572
defensiveUnit = unit_template;
1575
if( defensiveUnit != NULL ) {
1576
this->setBuildable(defensiveUnit);
1580
bool City::hasImprovement(const Improvement *improvement) const {
1581
// TODO: improvements should be a set?
1582
ASSERT( improvement != NULL );
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) ) {
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;
1608
return has_improvement;
1611
bool City::hasImprovement(const char *improvement) const {
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) ) {
1622
/*bool City::hasImprovement(ImprovementType improvementType) const {
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 ) {
1633
bool City::canBuild(const Buildable *candidate_buildable) const {
1634
bool can_build = false;
1635
if( candidate_buildable->getType() == Buildable::TYPE_UNIT ) {
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
1642
else if( candidate_buildable->getType() == Buildable::TYPE_IMPROVEMENT ) {
1643
const Improvement *improvement = static_cast<const Improvement *>(candidate_buildable);
1644
if( !hasImprovement(improvement) ) {
1648
if( can_build && improvement->requiresCoastal() && !this->isOnOrAdjacent(TYPE_OCEAN) ) {
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)
1658
// obsoleted checks now done below
1660
if( improvement->getImprovementType() == IMPROVEMENT_FORT && hasImprovement(IMPROVEMENT_WALLS) ) {
1661
// walls replaces fort
1671
const Race *race_specific = candidate_buildable->getRaceSpecific();
1672
if( race_specific != NULL && race_specific != this->civilization->getRace() ) {
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);
1683
if( city->hasImprovement(improvement) ) {
1686
else if( city->getBuildable() == improvement ) {
1695
const Technology *obsoleted_by = candidate_buildable->getObsoletedBy();
1696
if( obsoleted_by != NULL && this->civilization->hasTechnology(obsoleted_by) ) {
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) ) {
1709
else if( requires_technology != NULL && !civilization->hasTechnology(requires_technology) ) {
1712
/*else if( replaced_by != NULL && ( this->hasImprovement(replaced_by) || this->canBuild(replaced_by) ) ) {
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) ) ) {
1722
while( can_build && replaced_by != NULL ) {
1723
if( this->canBuild(replaced_by) )
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) ) {
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();
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) ) {
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 ) {
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);
1759
int stock = this->element_stocks.find(element)->second;
1760
if( stock < amount ) {
1765
// now check bonus_resource
1766
if( can_build && candidate_buildable->getRequiresBonusResource() != NULL ) {
1767
const BonusResource *requires_bonus_resource = candidate_buildable->getRequiresBonusResource();
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()) ) {
1786
int City::getDefenceBonus(const Unit *attacker) const {
1789
const Civilization *attacker_civ = attacker->getCivilization();
1790
if( !attacker_civ->hasTechnology("Gunpowder") ) {
1791
// gunpowder makes these obsolete
1792
if( this->hasImprovement("Walls") ) {
1795
else if( this->hasImprovement("Castle") ) {
1798
else if( this->hasImprovement("Fort") ) {
1799
// n.b. Fort is replaced by Walls, so isn't cumulative
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) ) {
1810
if( !improvement->getDefenceBonusAllCities() ) {
1811
bonus = max(bonus, improvement->getDefenceBonus());
1817
bool City::losePopulation() const {
1818
if( this->size <= size_limit_aqueduct_c && this->hasImprovement("Walls") ) {
1825
ASSERT( this->civilization != mainGamestate->getPlayer() );
1826
if( this->buildable == NULL ) {
1827
this->chooseAndSetBuildAI();
1831
//const int min_defenders_c = 1;
1833
bool City::needDefendersAI(bool *undefended, const Unit *this_unit, int min_defence) const {
1834
ASSERT( this->civilization != mainGamestate->getPlayer() );
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
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 )
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
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
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;
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)
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
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 )
1887
vector<Civilization *> civilizations = AIInterface::getCivilizations(AIInterface::GETCIVILIZATIONS_WAR);
1888
if( civilizations.size() > 0 ) {
1892
// a capital medium sized city, or large city; and we're at war!
1893
min_defenders_c = 3;
1897
if( n_defenders < min_defenders_c ) {
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
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()) ) {
1917
#ifndef USE_LUA_CITY_AI
1919
bool City::chooseBuildPopLimits() {
1920
// need improvements for city growth
1921
if(mainGamestate->getYear() <= 50 ) {
1922
return false; // prefer to focus on Settlers
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());
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());
1945
const Improvement *City::chooseImprovementAI() {
1946
vector<const Improvement *> candidates;
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;
1954
if( this_value > 0 && b->getAIHint() == Improvement::AIHINT_RESEARCH ) {
1955
if( this->civilization->hasAllTechnology() ) {
1956
// no point building if we have all technology
1961
if( this_value <= 0 ) {
1964
else if( this_value > max_value ) {
1966
candidates.push_back(b);
1967
max_value = this_value;
1969
else if( this_value == max_value ) {
1970
candidates.push_back(b);
1974
if( candidates.size() > 0 ) {
1975
int r = rand() % candidates.size();
1976
return candidates.at(r);
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");
1999
/*for(int i=0;i<this->mainGamestate->getNCivilizations();i++) {
2000
const Civilization *civ = this->mainGamestate->getCivilization(i);
2001
if( civ == civilization )
2006
const Relationship *relationship = mainGamestate->findRelationship(this->civilization, civ);
2007
if( relationship->getStatus() == Relationship::STATUS_PEACE )
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;
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) )
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());
2036
void City::chooseAndSetBuildAI() {
2037
ASSERT( this->progress_buildable == 0 );
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());
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());
2049
const Buildable *City::getBuildChoiceAI() {
2050
const Buildable *choice = NULL;
2052
AIInterface::setMainGamestate(this->mainGamestate);
2053
AIInterface::setAICivilization(this->civilization);
2055
#ifdef USE_LUA_CITY_AI
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) ) {
2064
AIInterface::setMainGamestate(NULL);
2065
AIInterface::setAICivilization(NULL);
2070
if( !lua_islightuserdata(game_g->getLuaState(), arg_index) ) {
2071
VI_log("City::getBuildChoiceAI(): script return argument %d not a pointer\n", arg_index);
2074
void *ptr = lua_touserdata(game_g->getLuaState(), arg_index);
2075
choice = static_cast<const Buildable *>(ptr);
2079
lua_settop(game_g->getLuaState(), 0); // important - clear the stack!
2086
int n_production = this->getProduction();
2087
const int ignore_dist_c = 16;
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);
2110
if( unit_template->canBuildCity() ) {
2111
ASSERT( potentialSettlersUnit == NULL ); // should only be one
2112
potentialSettlersUnit = unit_template;
2115
if( !this->canBuild(unit_template) ) {
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() )
2122
bestUnit = unit_template;
2124
if( defensiveUnit == NULL || unit_template->getDefence() > defensiveUnit->getDefence() ||
2125
( unit_template->getDefence() == defensiveUnit->getDefence() && unit_template->getCost() < defensiveUnit->getCost() )
2127
defensiveUnit = unit_template;
2129
if( fastestUnit == NULL || unit_template->getMoves() > fastestUnit->getMoves() ||
2130
( unit_template->getMoves() == fastestUnit->getMoves() && unit_template->getCost() < fastestUnit->getCost() )
2132
fastestUnit = unit_template;
2134
if( cheapestUnit == NULL || unit_template->getCost() < cheapestUnit->getCost() ||
2135
( unit_template->getCost() == cheapestUnit->getCost() && unit_template->getAttack() > cheapestUnit->getAttack() )
2137
cheapestUnit = unit_template;
2140
if( unit_template->isAir() && !unit_template->isMissile() ) {
2141
if( bestFighterAirUnit == NULL || unit_template->getAirDefence() > bestFighterAirUnit->getAirDefence() ) {
2142
bestFighterAirUnit = unit_template;
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() )
2149
bestBomberAirUnit = unit_template;
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() )
2156
bestConventionalMissileUnit = unit_template;
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;
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() )
2169
bestWorkerUnit = unit_template;
2171
if( workerUnit == NULL || unit_template->getCost() < workerUnit->getCost() ||
2172
( unit_template->getCost() == workerUnit->getCost() && unit_template->getDefence() > workerUnit->getDefence() )
2174
workerUnit = unit_template;
2177
if( unit_template->canBuildCity() ) {
2178
ASSERT( settlersUnit == NULL ); // should only be one
2179
settlersUnit = unit_template;
2182
/*if( bestUnit == NULL && fastestUnit != NULL ) {
2183
bestUnit = fastestUnit;
2185
else if( bestUnit == NULL && cheapestUnit != NULL ) {
2186
bestUnit = cheapestUnit;
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
2192
bestUnit = fastestUnit;
2195
ASSERT( bestUnit != NULL );
2196
ASSERT( fastestUnit != NULL );
2197
//ASSERT( bestWorkerUnit != NULL );
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
2202
if( r == 0 || r == 1 ) {
2206
bestUnit = fastestUnit;
2207
VI_log("AI: %s: best unit is fastest\n", this->getName());
2209
/*else if( r == 2 ) {
2210
bestUnit = fastestUnit;
2211
VI_log("AI: %s: best unit is fastest\n", this->getName());
2214
bestUnit = bestWorkerUnit;
2215
VI_log("AI: %s: best unit is worker\n", this->getName());
2220
int n_explorers = 0;
2221
//int n_workers = 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() ) {
2229
if( bestNuclearMissileUnit != NULL && unit_template->getNuclearType() == bestNuclearMissileUnit->getNuclearType() ) {
2232
//if( mainGamestate->getMap()->findCity(unit->getX(), unit->getY()) != NULL ) {
2233
if( AIInterface::getCity(unit->getX(), unit->getY()) != NULL ) {
2234
// ignore units defending cities
2237
if( unit_template == fastestUnit ) {
2240
/*if( unit_template == workerUnit ) {
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;
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;
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++;
2269
if( unit_template->getMoves() >= fastestUnit->getMoves() ) {
2270
n_explorers_being_built++;
2272
if( bestNuclearMissileUnit != NULL && unit_template->getNuclearType() == bestNuclearMissileUnit->getNuclearType() ) {
2273
n_nukes_being_built++;
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);
2302
if( this->chooseBuildPopLimits() ) {
2303
// and only do this if the growth improvement is cheaper!
2304
if( defensiveUnit->getCost() > this->buildable->getCost() ) {
2306
VI_log("(too long to build defensive unit)\n");
2307
AIInterface::setMainGamestate(NULL);
2308
AIInterface::setAICivilization(NULL);
2313
this->buildable = NULL;
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());
2321
AIInterface::setMainGamestate(NULL);
2322
AIInterface::setAICivilization(NULL);
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);
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);
2349
bool tried_improvements = false;
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;
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);
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 )
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 )
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) )
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
2401
/*MapSquare *mapsq = map->get(x,y);
2402
if( !game->validCitySquare(x,y) )
2404
//if( !game->getMap()->canBuildCity(x,y) )
2405
/*if( !mainGamestate->getMap()->getSquare(x, y)->canBuildCity() )
2407
if( !AIInterface::canBuildCity(x, y) )
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;
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());
2421
AIInterface::setMainGamestate(NULL);
2422
AIInterface::setAICivilization(NULL);
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 )
2433
Pos2D pos = this->getCitySquare(i);
2434
if( !mainGamestate->getMap()->isValid(pos.x, pos.y) ) {
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;
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;
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() ) {
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 ) {
2470
//if( is_improved && i != this->getCentreCitySquareIndex() ) {
2472
n_improved_squares++;
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)
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());
2483
AIInterface::setMainGamestate(NULL);
2484
AIInterface::setAICivilization(NULL);
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) )
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 )
2504
// need to look at adjacent squares for dist!
2505
bool found_dist = false;
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 ) {
2514
this_dist = adj_dist;
2519
// the square is surrounded by unexplored squares, so there must be another one closer
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) )
2527
build_explorer = true;
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());
2537
AIInterface::setMainGamestate(NULL);
2538
AIInterface::setAICivilization(NULL);
2543
if( this->chooseBuildPopLimits() ) {
2545
AIInterface::setMainGamestate(NULL);
2546
AIInterface::setAICivilization(NULL);
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());
2559
AIInterface::setMainGamestate(NULL);
2560
AIInterface::setAICivilization(NULL);
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());
2570
AIInterface::setMainGamestate(NULL);
2571
AIInterface::setAICivilization(NULL);
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());
2582
AIInterface::setMainGamestate(NULL);
2583
AIInterface::setAICivilization(NULL);
2587
// check already build enough air units
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 ) {
2598
if( bestBomberAirUnit != NULL && unit->getTemplate() == bestBomberAirUnit ) {
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;
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;
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
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());
2621
AIInterface::setMainGamestate(NULL);
2622
AIInterface::setAICivilization(NULL);
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 )
2635
const Relationship *relationship = mainGamestate->findRelationship(this->civilization, civ);
2636
if( relationship->getStatus() == Relationship::STATUS_PEACE )
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;
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) )
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 )
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());
2662
AIInterface::setMainGamestate(NULL);
2663
AIInterface::setAICivilization(NULL);
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) )
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 )
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());
2687
AIInterface::setMainGamestate(NULL);
2688
AIInterface::setAICivilization(NULL);
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 ) {
2704
cheapest_b_cost = b->getCost();
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());
2712
AIInterface::setMainGamestate(NULL);
2713
AIInterface::setAICivilization(NULL);
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());
2723
AIInterface::setMainGamestate(NULL);
2724
AIInterface::setAICivilization(NULL);
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
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());
2738
AIInterface::setMainGamestate(NULL);
2739
AIInterface::setAICivilization(NULL);
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());
2749
AIInterface::setMainGamestate(NULL);
2750
AIInterface::setAICivilization(NULL);
2755
AIInterface::setMainGamestate(NULL);
2756
AIInterface::setAICivilization(NULL);