1 //---------------------------------------------------------------------------
2 #include "stdafx.h"
3 
4 #include <cassert>
5 #include <cstdlib>
6 
7 #include <stdexcept> // needed for Android at least
8 
9 #include <sstream>
10 
11 #include "player.h"
12 #include "game.h"
13 #include "gamestate.h"
14 #include "utils.h"
15 #include "sector.h"
16 #include "tutorial.h"
17 //---------------------------------------------------------------------------
18 
19 bool Player::alliances[n_players_c][n_players_c];
20 int Player::alliance_last_asked[n_players_c][n_players_c];
21 
getName(PlayerTypeID id)22 const char *PlayerType::getName(PlayerTypeID id) {
23 	if( id == PLAYER_RED )
24 		return "RED TEAM";
25 	else if( id == PLAYER_GREEN )
26 		return "GREEN TEAM";
27 	else if( id == PLAYER_YELLOW )
28 		return "YELLOW TEAM";
29 	else if( id == PLAYER_BLUE )
30 		return "BLUE TEAM";
31 	ASSERT(false);
32 	return NULL;
33 }
34 
getColour(int * r,int * g,int * b,PlayerTypeID id)35 void PlayerType::getColour(int *r,int *g,int *b,PlayerTypeID id) {
36 	*r = *g = *b = 0;
37 	if( id == PLAYER_RED ) {
38 		*r = 145;
39 		*g = 36;
40 		*b = 34;
41 	}
42 	else if( id == PLAYER_GREEN ) {
43 		*r = 67;
44 		*g = 160;
45 		*b = 71;
46 	}
47 	else if( id == PLAYER_YELLOW ) {
48 		*r = 209;
49 		*g = 184;
50 		*b = 0;
51 	}
52 	else if( id == PLAYER_BLUE ) {
53 		*r = 63;
54 		*g = 81;
55 		*b = 181;
56 	}
57 	else {
58 		ASSERT(false);
59 	}
60 }
61 
62 //Player::Player(int index, char *name) {
63 //Player::Player(int index, int personality) {
Player(bool is_human,int index)64 Player::Player(bool is_human, int index) :
65 index(index), dead(false), n_births(0), n_deaths(0), n_men_for_this_island(0), n_suspended(0), is_human(is_human), alliance_last_asked_human(-1)
66 {
67 	for(int i=0;i<n_players_c;i++) {
68 		if( i != index && game_g->players[i] != NULL && !game_g->players[i]->isDead() ) {
69 			setAlliance(index, i, false);
70 			setAllianceLastAsked(index, i, -1);
71 		}
72 	}
73 }
74 
~Player()75 Player::~Player() {
76 }
77 
saveState(stringstream & stream) const78 void Player::saveState(stringstream &stream) const {
79 	stream << "<player ";
80 	stream << "player_id=\"" << index << "\" ";
81 	stream << "dead=\"" << (dead?1:0) << "\" ";
82 	stream << "n_births=\"" << n_births << "\" ";
83 	stream << "n_deaths=\"" << n_deaths << "\" ";
84 	stream << "n_men_for_this_island=\"" << n_men_for_this_island << "\" ";
85 	stream << "n_suspended=\"" << n_suspended << "\" ";
86 	stream << "alliance_last_asked_human=\"" << alliance_last_asked_human << "\" ";
87 	stream << ">\n";
88 	stream << "</player>\n";
89 }
90 
loadStateParseXMLNode(const TiXmlNode * parent)91 void Player::loadStateParseXMLNode(const TiXmlNode *parent) {
92 	if( parent == NULL ) {
93 		return;
94 	}
95 	bool read_children = true;
96 
97 	switch( parent->Type() ) {
98 		case TiXmlNode::TINYXML_DOCUMENT:
99 			break;
100 		case TiXmlNode::TINYXML_ELEMENT:
101 			{
102 				const char *element_name = parent->Value();
103 				const TiXmlElement *element = parent->ToElement();
104 				const TiXmlAttribute *attribute = element->FirstAttribute();
105 				if( strcmp(element_name, "player") == 0 ) {
106 					while( attribute != NULL ) {
107 						const char *attribute_name = attribute->Name();
108 						if( strcmp(attribute_name, "player_id") == 0 ) {
109 							// handled by caller
110 						}
111 						else if( strcmp(attribute_name, "dead") == 0 ) {
112 							dead = atoi(attribute->Value())==1;
113 						}
114 						else if( strcmp(attribute_name, "n_births") == 0 ) {
115 							n_births = atoi(attribute->Value());
116 						}
117 						else if( strcmp(attribute_name, "n_deaths") == 0 ) {
118 							n_deaths = atoi(attribute->Value());
119 						}
120 						else if( strcmp(attribute_name, "n_men_for_this_island") == 0 ) {
121 							n_men_for_this_island = atoi(attribute->Value());
122 						}
123 						else if( strcmp(attribute_name, "n_suspended") == 0 ) {
124 							n_suspended = atoi(attribute->Value());
125 						}
126 						else if( strcmp(attribute_name, "alliance_last_asked_human") == 0 ) {
127 							alliance_last_asked_human = atoi(attribute->Value());
128 						}
129 						else {
130 							// don't throw an error here, to help backwards compatibility, but should throw an error in debug mode in case this is a sign of not loading something that we've saved
131 							LOG("unknown player/player attribute: %s\n", attribute_name);
132 							ASSERT(false);
133 						}
134 						attribute = attribute->Next();
135 					}
136 				}
137 				else {
138 					// don't throw an error here, to help backwards compatibility, but should throw an error in debug mode in case this is a sign of not loading something that we've saved
139 					LOG("unknown player tag: %s\n", element_name);
140 					ASSERT(false);
141 				}
142 			}
143 			break;
144 		case TiXmlNode::TINYXML_COMMENT:
145 			break;
146 		case TiXmlNode::TINYXML_UNKNOWN:
147 			break;
148 		case TiXmlNode::TINYXML_TEXT:
149 			{
150 			}
151 			break;
152 		case TiXmlNode::TINYXML_DECLARATION:
153 			break;
154 	}
155 
156 	for(const TiXmlNode *child=parent->FirstChild();child!=NULL && read_children;child=child->NextSibling())  {
157 		loadStateParseXMLNode(child);
158 	}
159 }
160 
saveStateAlliances(stringstream & stream)161 void Player::saveStateAlliances(stringstream &stream) {
162 	stream << "<player_alliances>\n";
163 	for(int i=0;i<n_players_c;i++) {
164 		for(int j=i+1;j<n_players_c;j++) {
165 			stream << "<player_alliance ";
166 			stream << "player_id_i=\"" << i << "\" ";
167 			stream << "player_id_j=\"" << j << "\" ";
168 			stream << "alliances=\"" << (alliances[i][j] ? 1 : 0) << "\" ";
169 			stream << "alliance_last_asked=\"" << alliance_last_asked[i][j] << "\" ";
170 			stream << "/>\n";
171 		}
172 	}
173 	stream << "</player_alliances>\n";
174 }
175 
loadStateParseXMLNodeAlliances(const TiXmlNode * parent)176 void Player::loadStateParseXMLNodeAlliances(const TiXmlNode *parent) {
177 	if( parent == NULL ) {
178 		return;
179 	}
180 	bool read_children = true;
181 
182 	switch( parent->Type() ) {
183 		case TiXmlNode::TINYXML_DOCUMENT:
184 			break;
185 		case TiXmlNode::TINYXML_ELEMENT:
186 			{
187 				const char *element_name = parent->Value();
188 				const TiXmlElement *element = parent->ToElement();
189 				const TiXmlAttribute *attribute = element->FirstAttribute();
190 				if( strcmp(element_name, "player_alliances") == 0 ) {
191 					// handled entirely by caller
192 				}
193 				else if( strcmp(element_name, "player_alliance") == 0 ) {
194 					int player_id_i = -1;
195 					int player_id_j = -1;
196 					bool alliance = false;
197 					int last_asked = -1;
198 					while( attribute != NULL ) {
199 						const char *attribute_name = attribute->Name();
200 						if( strcmp(attribute_name, "player_id_i") == 0 ) {
201 							player_id_i = atoi(attribute->Value());
202 						}
203 						else if( strcmp(attribute_name, "player_id_j") == 0 ) {
204 							player_id_j = atoi(attribute->Value());
205 						}
206 						else if( strcmp(attribute_name, "alliances") == 0 ) {
207 							alliance = atoi(attribute->Value())==1;
208 						}
209 						else if( strcmp(attribute_name, "alliance_last_asked") == 0 ) {
210 							last_asked = atoi(attribute->Value());
211 						}
212 						else {
213 							// don't throw an error here, to help backwards compatibility, but should throw an error in debug mode in case this is a sign of not loading something that we've saved
214 							LOG("unknown player_alliances/player_alliance attribute: %s\n", attribute_name);
215 							ASSERT(false);
216 						}
217 						attribute = attribute->Next();
218 					}
219 					if( player_id_i < 0 || player_id_i >= n_players_c ) {
220 						throw std::runtime_error("player_alliance invalid player_id_i");
221 					}
222 					else if( player_id_j < 0 || player_id_j >= n_players_c ) {
223 						throw std::runtime_error("player_alliance invalid player_id_j");
224 					}
225 					alliances[player_id_i][player_id_j] = alliance;
226 					alliance_last_asked[player_id_i][player_id_j] = last_asked;
227 				}
228 				else {
229 					// don't throw an error here, to help backwards compatibility, but should throw an error in debug mode in case this is a sign of not loading something that we've saved
230 					LOG("unknown player_alliances tag: %s\n", element_name);
231 					ASSERT(false);
232 				}
233 			}
234 			break;
235 		case TiXmlNode::TINYXML_COMMENT:
236 			break;
237 		case TiXmlNode::TINYXML_UNKNOWN:
238 			break;
239 		case TiXmlNode::TINYXML_TEXT:
240 			{
241 			}
242 			break;
243 		case TiXmlNode::TINYXML_DECLARATION:
244 			break;
245 	}
246 
247 	for(const TiXmlNode *child=parent->FirstChild();child!=NULL && read_children;child=child->NextSibling())  {
248 		loadStateParseXMLNodeAlliances(child);
249 	}
250 }
251 
setAlliance(int a,int b,bool alliance)252 void Player::setAlliance(int a, int b, bool alliance) {
253 	LOG("Alliance %s between players %d and %d\n", alliance?"MADE":"BROKEN", a, b);
254 	ASSERT(a != b);
255 	ASSERT_PLAYER(a);
256 	ASSERT_PLAYER(b);
257 	if( a > b ) {
258 		int dummy = a;
259 		a = b;
260 		b = dummy;
261 	}
262 	alliances[a][b] = alliance;
263 }
264 
isAlliance(int a,int b)265 bool Player::isAlliance(int a, int b) {
266 	ASSERT(a != b);
267 	ASSERT_PLAYER(a);
268 	ASSERT_PLAYER(b);
269 	if( a > b ) {
270 		int dummy = a;
271 		a = b;
272 		b = dummy;
273 	}
274 	return alliances[a][b];
275 }
276 
resetAllAlliances()277 void Player::resetAllAlliances() {
278 	for(int i=0;i<n_players_c;i++) {
279 		for(int j=i+1;j<n_players_c;j++) {
280 			setAlliance(i, j, false);
281 			setAllianceLastAsked(i, j, -1);
282 		}
283 	}
284 }
285 
setAllianceLastAsked(int a,int b,int time)286 void Player::setAllianceLastAsked(int a, int b,int time) {
287 	ASSERT(a != b);
288 	ASSERT_PLAYER(a);
289 	ASSERT_PLAYER(b);
290 	if( a > b ) {
291 		int dummy = a;
292 		a = b;
293 		b = dummy;
294 	}
295 	alliance_last_asked[a][b] = time;
296 }
297 
allianceLastAsked(int a,int b)298 int Player::allianceLastAsked(int a, int b) {
299 	ASSERT(a != b);
300 	ASSERT_PLAYER(a);
301 	ASSERT_PLAYER(b);
302 	if( a > b ) {
303 		int dummy = a;
304 		a = b;
305 		b = dummy;
306 	}
307 	return alliance_last_asked[a][b];
308 }
309 
askHuman()310 bool Player::askHuman() {
311 	const int wait_time_human_c = 5000;
312 	//ASSERT( !isAlliance(index, human_player) );
313 	//ASSERT( index != human_player );
314 	ASSERT( !this->is_human );
315 	// whether to _consider_ asking the human player - we still have to go through the requestAlliance test afterwards
316 	if( game_g->getTutorial() != NULL && !game_g->getTutorial()->aiAllowAskAlliance() ) {
317 		return false;
318 	}
319 	int time = game_g->getGameTime();
320 	if( alliance_last_asked_human == -1 ) {
321 		// note - don't ask if alliance_last_asked_human==-1, to avoid being asked straight away
322 		alliance_last_asked_human = time;
323 	}
324 	else if( time >= alliance_last_asked_human + wait_time_human_c ) {
325 		alliance_last_asked_human = time;
326 		if( rand() % 2 == 0 )
327 		{
328 			return true;
329 		}
330 	}
331 	return false;
332 }
333 
requestAlliance(int player)334 bool Player::requestAlliance(int player) {
335 	// 'player' requests alliance with 'this'
336 	const int wait_time_c = 5000;
337 	ASSERT( !isAlliance(index, player) );
338 	//ASSERT( index != player );
339 	//ASSERT(this->index != human_player);
340 	ASSERT( !this->is_human );
341 	int last_asked = Player::allianceLastAsked(index, player);
342 	int time = game_g->getGameTime();
343 	if( last_asked == -1 || time >= last_asked + wait_time_c ) {
344 		Player::setAllianceLastAsked(index, player, time);
345 		bool has_diplomatic_bonus = player == PlayerType::PLAYER_YELLOW;
346 		if( has_diplomatic_bonus ? (rand() % 2 == 0)  : (rand() % 3 == 0) )
347 		{
348 			return true;
349 		}
350 		//return true;
351 	}
352 	return false;
353 }
354 
355 //int Player::getShieldIndex() {
getShieldIndex(bool allied[n_players_c])356 int Player::getShieldIndex(bool allied[n_players_c]) {
357 	int rtn = 0;
358 	/*if(personality == 0)
359 	rtn = 2;
360 	else if(personality == 1)
361 	rtn = 1;
362 	else if(personality == 2)
363 	rtn = 4;
364 	else if(personality == 3)
365 	rtn = 3;*/
366 	int index = 0;
367 	for(int i=0,c=1;i<n_players_c;i++,c*=2) {
368 		if( allied[i] ) {
369 			index += c;
370 		}
371 	}
372 	/*if(index == 0)
373 	rtn = 2;
374 	else if(index == 1)
375 	rtn = 1;
376 	else if(index == 2)
377 	rtn = 4;
378 	else if(index == 3)
379 	rtn = 3;*/
380 	if( index == 0 )
381 		rtn = 0;
382 	else if( index == 1 )
383 		rtn = 2;
384 	else if( index == 2 )
385 		rtn = 1;
386 	else if( index == 3 )
387 		rtn = 8;
388 	else if( index == 4 )
389 		rtn = 4;
390 	else if( index == 5 )
391 		rtn = 7;
392 	else if( index == 6 )
393 		rtn = 9;
394 	else if( index == 7 )
395 		rtn = 11;
396 	else if( index == 8 )
397 		rtn = 3;
398 	else if( index == 9 )
399 		rtn = 5;
400 	else if( index == 10 )
401 		rtn = 6;
402 	else if( index == 11 )
403 		rtn = 13;
404 	else if( index == 12 )
405 		rtn = 10;
406 	else if( index == 13 )
407 		rtn = 12;
408 	else if( index == 14 )
409 		rtn = 14;
410 	else {
411 		ASSERT(false);
412 	}
413 	return rtn;
414 }
415 
kill(PlayingGameState * gamestate)416 void Player::kill(PlayingGameState *gamestate) {
417 	// break alliances
418 	for(int i=0;i<n_players_c;i++) {
419 		if( i != this->index )
420 			Player::setAlliance(i, index, false);
421 	}
422 
423 	/*if( ((PlayingGameState *)gamestate)->getPlayerAskingAlliance() == this->index ) {
424 		((PlayingGameState *)gamestate)->cancelPlayerAskingAlliance();
425 	}*/
426 	if( gamestate->getPlayerAskingAlliance() == this->index ) {
427 		gamestate->cancelPlayerAskingAlliance();
428 	}
429 
430 	this->dead = true;
431 
432 	// check for only being one side
433 	bool one_side = true;
434 	for(int i=0;i<n_players_c && one_side;i++) {
435 		if( game_g->players[i] != NULL && !game_g->players[i]->isDead() ) {
436 			for(int j=0;j<n_players_c && one_side;j++) {
437 				if( game_g->players[j] != NULL && !game_g->players[j]->isDead() ) {
438 					if( i != j && !Player::isAlliance(i,j) ) {
439 						one_side = false;
440 					}
441 				}
442 			}
443 		}
444 	}
445 	if( one_side ) {
446 		// break all alliances
447 		for(int i=0;i<n_players_c;i++) {
448 			if( game_g->players[i] != NULL && !game_g->players[i]->isDead() ) {
449 				for(int j=0;j<n_players_c && one_side;j++) {
450 					if( game_g->players[j] != NULL && !game_g->players[j]->isDead() ) {
451 						if( i != j ) {
452 							Player::setAlliance(i, j, false);
453 						}
454 					}
455 				}
456 			}
457 		}
458 	}
459 
460 	//gamestate->reset(); // needed to update player shield buttons
461 	//((PlayingGameState *)gamestate)->resetShieldButtons(); // needed to update player shield buttons
462 	gamestate->resetShieldButtons(); // needed to update player shield buttons
463 }
464 
doSectorAI(int client_player,PlayingGameState * gamestate,Sector * sector)465 void Player::doSectorAI(int client_player, PlayingGameState *gamestate, Sector *sector) {
466 	const int MIN_POP = 5;
467 	const int EVACUATE_LEVEL = 3;
468 
469 	ASSERT( this->index == sector->getPlayer() );
470 
471 	// reset to zero
472 	sector->setDesigners( 0 );
473 	for(int i=0;i<N_ID;i++) {
474 		if( game_g->elements[i]->getType() != Element::GATHERABLE )
475 			sector->setMiners((Id)i, 0);
476 	}
477 	sector->setWorkers( 0 );
478 	for(int i=0;i<N_BUILDINGS;i++) {
479 		sector->setBuilders((Type)i, 0);
480 	}
481 
482 	bool enemiesPresent = sector->enemiesPresent();
483 	bool enemiesPresentWithBombardment = sector->enemiesPresentWithBombardment();
484 
485 	int attack_pref[n_players_c];
486 	{
487 		int attack_order[n_players_c-1];
488 		int choose_from[n_players_c-1];
489 		for(int i=0,indx=0;i<n_players_c;i++) {
490 			if( i != index ) {
491 				choose_from[indx++] = i;
492 			}
493 		}
494 		for(int i=0;i<n_players_c-1;i++) {
495 			int n_choose_from = n_players_c - 1 - i;
496 			int c = rand() % n_choose_from;
497 			attack_order[i] = choose_from[c];
498 			choose_from[c] = choose_from[n_choose_from-1];
499 		}
500 		attack_pref[index] = 0;
501 		for(int i=0;i<n_players_c-1;i++) {
502 			attack_pref[ attack_order[i] ] = i+1;
503 		}
504 	}
505 
506 	if( enemiesPresentWithBombardment && sector->getBuilding(BUILDING_TOWER)->getHealth() <= EVACUATE_LEVEL ) {
507 		// evacuate!
508 		sector->evacuate();
509 		/*for(int i=0;i<N_BUILDINGS;i++) {
510 			Building *building = sector->getBuilding((Type)i);
511 			if( building != NULL ) {
512 				for(int j=0;j<building->getNTurrets();j++) {
513 					if( building->getTurretMan(j) != -1 )
514 						sector->returnDefender(building, j);
515 				}
516 			}
517 		}
518 		int men = sector->getAvailablePopulation();
519 		if( men > 0 ) {
520 			sector->getAssembledArmy()->add(n_epochs_c, men);
521 			int n_pop = sector->getPopulation() - men;
522 			sector->setPopulation(n_pop);
523 		}
524 		sector->getArmy(this->index)->add(sector->getAssembledArmy());*/
525 	}
526 
527 	// recall army
528 	if( !enemiesPresent && sector->getArmy(this->index)->getTotal() > 0 ) {
529 		sector->returnArmy();
530 	}
531 
532 	if( sector->getPopulation() < MIN_POP && !enemiesPresent )
533 		return; // reproduce
534 
535 	// defenders
536 	for(int i=n_epochs_c-1;i>=0 /*&& enemiesPresent*/;i--) {
537 		/*if( i == nuclear_epoch_c )
538 		continue;*/
539 		if( !enemiesPresentWithBombardment && i != nuclear_epoch_c && i != laser_epoch_c )
540 			continue; // don't put out defenders if no enemies present, except for nuclear defence or laser
541 		if( enemiesPresent && i == nuclear_epoch_c )
542 			continue; // don't put out new nuclear defences if under attack
543 		/*if( i == laser_epoch_c ) // test - disable lasers to test nuke defence
544 		continue;*/
545 		for(;;) {
546 			if( i == nuclear_epoch_c ) {
547 				int n_lasers = sector->getNDefenders(laser_epoch_c);
548 				int n_nuke_defs = sector->getNDefenders(nuclear_epoch_c);
549 				ASSERT(n_nuke_defs <= 1);
550 				if( n_lasers > 0 || n_nuke_defs > 0 )
551 					break; // don't need a nuclear defence
552 			}
553 			Design *design = NULL;
554 			if( sector->getStoredDefenders(i) == 0 ) {
555 				design = sector->canBuildDesign(Invention::DEFENCE, i);
556 				if( design == NULL )
557 					break;
558 			}
559 			// we can make this defence
560 			bool placed = false;
561 			for(int j=0;j<N_BUILDINGS && !placed && sector->getAvailablePopulation() > MIN_POP;j++) {
562 				Building *building = sector->getBuilding((Type)j);
563 				if( building != NULL ) {
564 					for(int k=0;k<building->getNTurrets() && !placed;k++) {
565 						if( building->getTurretMan(k) == -1 ) {
566 							// new defender
567 							placed = sector->deployDefender(building, k, i);
568 						}
569 					}
570 				}
571 			}
572 			// try again, replacing poorer defences this time
573 			for(int j=0;j<N_BUILDINGS && !placed;j++) {
574 				Building *building = sector->getBuilding((Type)j);
575 				if( building != NULL ) {
576 					for(int k=0;k<building->getNTurrets() && !placed;k++) {
577 						if( building->getTurretMan(k) != -1 && building->getTurretMan(k) < i ) {
578 							// replace defender
579 							placed = sector->deployDefender(building, k, i);
580 						}
581 					}
582 				}
583 			}
584 			if( !placed ) {
585 				// couldn't place it
586 				if( i >= factory_epoch_c && sector->getStoredDefenders(i) == 0 &&
587 					sector->getCurrentManufacture() == NULL ) {
588 						// manufacture one
589 						sector->setCurrentManufacture(design);
590 						sector->setFAmount(1);
591 
592 				}
593 				break;
594 			}
595 		}
596 	}
597 
598 	if( !enemiesPresentWithBombardment ) {
599 		// return defenders (except nuclear defence and lasers)
600 		for(int j=0;j<N_BUILDINGS;j++) {
601 			Building *building = sector->getBuilding((Type)j);
602 			if( building != NULL ) {
603 				//for(int k=0;k<max_building_turrets_c;k++) {
604 				for(int k=0;k<building->getNTurrets();k++) {
605 					if( building->getTurretMan(k) != -1 && building->getTurretMan(k) != nuclear_epoch_c && building->getTurretMan(k) != laser_epoch_c ) {
606 						/*sector->stored_defenders[ building->turret_man[k] ]++;
607 						building->turret_man[k] = -1;
608 						int n_pop = sector->getPopulation() + 1;
609 						sector->setPopulation(n_pop);*/
610 						sector->returnDefender(building, k);
611 					}
612 				}
613 			}
614 		}
615 	}
616 
617 	if( sector->getCurrentManufacture() == NULL ) {
618 		// defences handled already, above
619 		for(int i=game_g->getNSubEpochs()-1;i>=0;i--) {
620 			if( game_g->getStartEpoch() + i == nuclear_epoch_c )
621 				continue; // nuclear weapons handled later
622 			if( game_g->getStartEpoch() + i >= factory_epoch_c ) {
623 				Design *design = sector->canBuildDesign(Invention::WEAPON, game_g->getStartEpoch() + i);
624 				if( design != NULL ) {
625 					sector->setCurrentManufacture(design);
626 					sector->setFAmount(1);
627 					break;
628 				}
629 			}
630 		}
631 	}
632 
633 	// use shields?
634 	for(int i=0;i<N_BUILDINGS;i++) {
635 		Building *building = sector->getBuilding((Type)i);
636 		if( building == NULL )
637 			continue;
638 		if( building->getHealth() < 30 ) {
639 			bool healed = false;
640 			for(int j=3;j>=0 && !healed;j--) {
641 				healed = sector->useShield(building, j);
642 			}
643 			if( !healed && sector->getCurrentManufacture() != NULL ) {
644 				// manufacture a shield
645 				for(int j=game_g->getNSubEpochs()-1;j>=0;j--) {
646 					Design *design = sector->canBuildDesign(Invention::SHIELD, game_g->getStartEpoch() + j);
647 					if( design != NULL ) {
648 						sector->setCurrentManufacture(design);
649 						sector->setFAmount(1);
650 						break;
651 					}
652 				}
653 			}
654 		}
655 	}
656 
657 	// nuke a sector?
658     while( sector->getStoredArmy()->getSoldiers(nuclear_epoch_c) > 0 || sector->getCurrentManufacture() == NULL ) {
659 		// look for tower to nuke
660 		Sector *nuke_sector = NULL;
661 		bool found_tower = false;
662 		for(int x=0;x<map_width_c;x++) {
663 			for(int y=0;y<map_height_c;y++) {
664 				if( game_g->getMap()->isSectorAt(x, y) ) {
665 					Sector *c_sector = game_g->getMap()->getSector(x, y);
666 					int this_strength = c_sector->getArmy(sector->getPlayer())->getStrength();
667 					if( this_strength > 0 && ( !enemiesPresentWithBombardment || sector->getBuilding(BUILDING_TOWER)->getHealth() > EVACUATE_LEVEL ) ) {
668 						// only nuke our own men if this tower is under attack and nearly destroyed
669 						continue;
670 					}
671 					// prefer nuking towers to men
672 					if( c_sector->getActivePlayer() != -1 && c_sector->getPlayer() != sector->getPlayer() && !Player::isAlliance(c_sector->getPlayer(), sector->getPlayer()) ) {
673 						if( nuke_sector == NULL || !found_tower || attack_pref[c_sector->getPlayer()] > attack_pref[nuke_sector->getPlayer()] ) {
674 							nuke_sector = c_sector;
675 							found_tower = true;
676 						}
677 					}
678 					else if( !found_tower && c_sector->getActivePlayer() == -1 && c_sector->enemiesPresent(sector->getPlayer()) && !c_sector->getArmy(sector->getPlayer())->any(true) ) {
679 						if( nuke_sector == NULL || attack_pref[c_sector->getPlayer()] > attack_pref[nuke_sector->getPlayer()] ) {
680 							nuke_sector = c_sector;
681 						}
682 					}
683 				}
684 			}
685 		}
686 		if( nuke_sector == NULL ) {
687 			break;
688 		}
689 		if( sector->getStoredArmy()->getSoldiers(nuclear_epoch_c) > 0 && !sector->isBeingNuked() ) {
690 			// nuke
691 			nuke_sector->nukeSector(sector);
692 			sector->getStoredArmy()->remove(nuclear_epoch_c, 1);
693 		}
694 		else {
695 			// start making a nuke, only if not already making something
696             Design *design = sector->canBuildDesign(Invention::WEAPON, nuclear_epoch_c);
697             if( design != NULL ) {
698                 sector->setCurrentManufacture(design);
699                 sector->setFAmount(1);
700             }
701 			break;
702 		}
703 	}
704 
705 	// trash designs?
706 	sector->autoTrashDesigns();
707 
708 	if( game_g->getTutorial() != NULL && !game_g->getTutorial()->aiAllowDesign() ) {
709 		// don't allow designs
710 	}
711 	else if( sector->getCurrentDesign() == NULL ) {
712 		// set new invention?
713 		int best_weapon = -1;
714 		int best_defence = -1;
715 		int best_shield = -1;
716 		for(int i=game_g->getNSubEpochs()-1;i>=0;i--) {
717 			if( best_weapon == -1 && sector->inventionKnown(Invention::WEAPON, game_g->getStartEpoch() + i) )
718 				best_weapon = game_g->getStartEpoch() + i;
719 			if( best_defence == -1 && sector->inventionKnown(Invention::DEFENCE, game_g->getStartEpoch() + i) )
720 				best_defence = game_g->getStartEpoch() + i;
721 			if( best_shield == -1 && sector->inventionKnown(Invention::SHIELD, game_g->getStartEpoch() + i) )
722 				best_shield = game_g->getStartEpoch() + i;
723 		}
724 		Design *design = NULL;
725 		Design *reserve_design = NULL;
726 		// prefer nuke!
727 		design = sector->canResearch(Invention::WEAPON, nuclear_epoch_c);
728 
729 		bool try_mining_more = sector->tryMiningMore();
730 		for(int i=0;i<game_g->getNSubEpochs() && design == NULL;i++) {
731 			int eph = game_g->getStartEpoch() + i;
732 			Design *this_design = NULL;
733 
734 			this_design = sector->canResearch(Invention::WEAPON, eph);
735 			if( eph > best_weapon )
736 				design = this_design;
737 			else if( reserve_design == NULL )
738 				reserve_design = this_design;
739 
740 			if( design == NULL ) {
741 				this_design = sector->canResearch(Invention::DEFENCE, eph);
742 				if( eph > best_defence )
743 					design = this_design;
744 				else if( reserve_design == NULL )
745 					reserve_design = this_design;
746 			}
747 			if( design == NULL && ( best_weapon != -1 || best_defence != -1 || !try_mining_more ) ) {
748 				// (only design shield if we've already designed either a weapon or a defence, or there's no point waiting)
749 				this_design = sector->canResearch(Invention::SHIELD, eph);
750 				if( eph > best_shield )
751 					design = this_design;
752 				else if( reserve_design == NULL )
753 					reserve_design = this_design;
754 			}
755 		}
756 
757 		if( design == NULL && sector->getEpoch() < game_g->getStartEpoch() + 3 )
758 			design = reserve_design;
759 
760 		if( design != NULL ) {
761 			sector->setCurrentDesign(design);
762 		}
763 	}
764 
765 	bool used_up = game_g->getStartEpoch() != end_epoch_c && sector->usedUp();
766 	bool can_design = sector->getCurrentDesign() != NULL;
767 	bool can_mine = false;
768 	if( !used_up ) {
769 		// even if there are elements remaining to mine, we might still consider a sector "used up" if we've already mined at least 6 of that element, and we still can't design anything
770 		//
771 		for(int i=0;i<N_ID && !can_mine;i++) {
772 			if( sector->canMine((Id)i) && game_g->elements[i]->getType() != Element::GATHERABLE )
773 				can_mine = true;
774 		}
775 	}
776 	bool build_mine = sector->canBuild(BUILDING_MINE);
777 	bool build_factory = sector->canBuild(BUILDING_FACTORY);
778 	bool build_lab = sector->canBuild(BUILDING_LAB);
779 	bool need_workers = sector->getCurrentManufacture() != NULL;
780 
781 	if( enemiesPresentWithBombardment && sector->getBuilding(BUILDING_TOWER)->getHealth() <= EVACUATE_LEVEL+1 )
782 		can_design = false;
783 	if( enemiesPresentWithBombardment && sector->getBuilding(BUILDING_TOWER)->getHealth() <= EVACUATE_LEVEL+1 )
784 		can_mine = false;
785 	if( enemiesPresentWithBombardment && sector->getBuilding(BUILDING_TOWER)->getHealth() <= EVACUATE_LEVEL+1 )
786 		need_workers = false;
787 
788 	if( enemiesPresentWithBombardment && sector->getBuilding(BUILDING_TOWER)->getHealth() <= EVACUATE_LEVEL+1 ) {
789 		build_mine = false;
790 		build_factory = false;
791 		build_lab = false;
792 	}
793 
794 	int split = 1;
795 	int design_weight = 0;
796 	int work_weight = 0;
797 	if( can_design  ) {
798 		design_weight = 1;
799 		if( sector->getCurrentDesign()->getInvention()->getEpoch() == nuclear_epoch_c )
800 			design_weight = 4; // rush!
801 		split += design_weight;
802 	}
803 	if( can_mine )
804 		split++;
805 	if( build_mine )
806 		split++;
807 	if( build_factory )
808 		split++;
809 	if( build_lab )
810 		split++;
811 	if( need_workers  ) {
812 		work_weight = 1;
813 		if( sector->getCurrentManufacture()->getInvention()->getEpoch() == nuclear_epoch_c )
814 			work_weight = 4; // rush!
815 		split += work_weight;
816 	}
817 
818 	int pop = sector->getAvailablePopulation();
819 
820 	if( can_design ) {
821 		sector->setDesigners((design_weight * pop) / split);
822 	}
823 	if( can_mine ) {
824 		int n_miners = 0;
825 		while( n_miners < pop/split ) {
826 			for(int i=0;i<N_ID && n_miners < pop/split;i++) {
827 				if( sector->canMine((Id)i) && game_g->elements[i]->getType() != Element::GATHERABLE ) {
828 					int n = sector->getMiners((Id)i) + 1;
829 					sector->setMiners((Id)i, n);
830 					n_miners++;
831 				}
832 			}
833 		}
834 	}
835 	if( build_mine ) {
836 		sector->setBuilders(BUILDING_MINE, pop / split);
837 	}
838 	if( build_factory ) {
839 		sector->setBuilders(BUILDING_FACTORY, pop / split);
840 	}
841 	if( build_lab ) {
842 		sector->setBuilders(BUILDING_LAB, pop / split);
843 	}
844 	if( need_workers ) {
845 		sector->setWorkers((work_weight * pop) / split);
846 	}
847 
848 
849 	if( game_g->getTutorial() != NULL && !game_g->getTutorial()->aiAllowDeploy() ) {
850 		// don't allow deployment
851 	}
852 	else if( sector->getCurrentDesign() == NULL || enemiesPresentWithBombardment ) {
853 		//if( used_up || enemiesPresentWithBombardment ) {
854 		// think about attacking?
855 		Sector *target_sector = NULL;
856 		bool by_land = false;
857 		bool new_sector = false;
858 		int strength = 0;
859 		bool temp[map_width_c][map_height_c];
860 		game_g->getMap()->canMoveTo(temp, sector->getXPos(),sector->getYPos(),sector->getPlayer());
861 
862 		// if used up, look for a new sector
863 		bool look_for_new_sector = used_up || ( rand() % 3 == 0 );
864 		if( look_for_new_sector ) {
865 			vector<Sector *> candidate_sectors;
866 			int max_n_men = 0;
867 			for(int x=0;x<map_width_c;x++) {
868 				for(int y=0;y<map_height_c;y++) {
869 					Sector *c_sector = game_g->getMap()->getSector(x, y);
870 					if( c_sector == NULL )
871 						continue;
872 					// Only worth moving to a sector that has no other players
873 					// If we were to move to a sector with an ally army, the army would then be immediately moved back to the tower by code in Player::doSectorAI() (this bug was fixed in 0.28)
874 					// No need to move to a sector with enemies - the decision to attack is done below
875 					if( c_sector->getActivePlayer() == -1 ) {
876 						if( temp[x][y] ) {
877 							bool has_others = false;
878 							for(int i=0;i<n_players_c && !has_others;i++) {
879 								if( i != index && c_sector->getArmy(i)->any(true) ) {
880 									has_others = true;
881 								}
882 							}
883 							if( !has_others ) {
884 								int n_men = c_sector->getArmy(index)->getTotal();
885 								// prefer sectors that already have our men - and pick the largest number
886 								if( n_men >= max_n_men ) {
887 									if( n_men > max_n_men ) {
888 										candidate_sectors.clear();
889 										max_n_men = n_men;
890 									}
891 									candidate_sectors.push_back(c_sector);
892 								}
893 							}
894 						}
895 					}
896 				}
897 			}
898 			if( candidate_sectors.size() > 0 ) {
899 				// randomly pick out of the candidate sectors
900 				int r = rand() % candidate_sectors.size();
901 				target_sector = candidate_sectors.at(r);
902 				by_land = true;
903 				new_sector = true;
904 			}
905 		}
906 
907 		// look for tower to attack
908 		for(int x=0;x<map_width_c;x++) {
909 			for(int y=0;y<map_height_c;y++) {
910 				Sector *c_sector = game_g->getMap()->getSector(x, y);
911 				if( c_sector == NULL )
912 					continue;
913 				if( c_sector->getActivePlayer() != -1 && c_sector->getPlayer() != sector->getPlayer()
914 					&& !Player::isAlliance(c_sector->getPlayer(), sector->getPlayer())
915 					&& !new_sector // only consider attacking if aren't moving to a new sector
916 					) {
917 						//int this_strength = c_sector->getArmy(sector->getPlayer())->getTotal();
918 						int this_strength = c_sector->getArmy(sector->getPlayer())->getStrength();
919 						if( target_sector == NULL // we haven't chosen anywhere yet
920 							|| ( temp[x][y] && !by_land ) // prefer by land over by air
921 							|| ( temp[x][y] == by_land && this_strength > strength ) // prefer where we're already attacking
922 							|| ( temp[x][y] == by_land && this_strength == strength && attack_pref[c_sector->getPlayer()] > attack_pref[target_sector->getPlayer()] ) // prefer a particular player
923 							) {
924 								target_sector = c_sector;
925 								strength = this_strength;
926 								by_land = temp[x][y];
927 						}
928 				}
929 			}
930 		}
931 		if( target_sector == NULL ) {
932 			// look for men to attack
933 			for(int x=0;x<map_width_c;x++) {
934 				for(int y=0;y<map_height_c;y++) {
935 					Sector *c_sector = game_g->getMap()->getSector(x, y);
936 					if( c_sector == NULL )
937 						continue;
938 					bool enemy = false;
939 					for(int i=0;i<n_players_c && !enemy;i++) {
940 						if( i != sector->getPlayer() && c_sector->getArmy(i)->getTotal() > 0 &&
941 							!Player::isAlliance(i, sector->getPlayer()) )
942 							enemy = true;
943 					}
944 					if( enemy ) {
945 						//int this_strength = c_sector->getArmy(sector->getPlayer())->getTotal();
946 						int this_strength = c_sector->getArmy(sector->getPlayer())->getStrength();
947 						if( target_sector == NULL ||
948 							( temp[x][y] && !by_land ) ||
949 							( temp[x][y] == by_land && this_strength > strength ) ) {
950 								target_sector = c_sector;
951 								by_land = temp[x][y];
952 								strength = this_strength;
953 						}
954 					}
955 				}
956 			}
957 		}
958 		if( enemiesPresentWithBombardment && !used_up ) {
959 			target_sector = sector;
960 			by_land = true;
961 			new_sector = false;
962 		}
963 
964 		if( target_sector != NULL ) {
965 			int min_pop = MIN_POP;
966 			//if( enemiesPresent && sector->getBuilding(BUILDING_TOWER)->health <= EVACUATE_LEVEL+1 )
967 			//if( enemiesPresent || new_sector )
968 			if( enemiesPresent || used_up )
969 				min_pop = 0;
970 			for(int i=n_epochs_c-1;i>=game_g->getStartEpoch();i--) {
971 				if( i == nuclear_epoch_c )
972 					continue;
973 				if( !by_land && !isAirUnit(i) )
974 					continue;
975 				while(sector->getAvailablePopulation() > min_pop) {
976 					if( !sector->assembleArmy(i, 1) )
977 						break;
978 				}
979 			}
980 			/*if( new_sector ) {
981 			// add unarmed men
982 			while(sector->getAvailablePopulation() > min_pop) {
983 			if( !sector->assembleArmy(n_epochs_c, 1) )
984 			break;
985 			}
986 			}*/
987 
988 			//int assembled_strength = sector->getAssembledArmy()->getTotal();
989 			int assembled_strength = sector->getAssembledArmy()->getStrength();
990 			//int min_req = 8;
991 			//int min_req = 4 * (game_g->getStartEpoch()+1);
992 			int min_req = 8 * (game_g->getStartEpoch()+1);
993 			min_req = std::min(min_req, 50);
994 			for(int i=0;i<=game_g->getStartEpoch();i++)
995 				min_req *= 2;
996 			if( used_up ) {
997 				// no point waiting
998 				min_req = 0;
999 			}
1000 
1001 			/*if( by_land && sector->getCurrentDesign() == NULL && sector->getCurrentManufacture() == NULL &&
1002 			( enemiesPresent || assembled_strength > min_req || game_g->getStartEpoch() == end_epoch_c ) ) {
1003 			// only use unarmed men if we aren't designing or manufacturing anything
1004 			// and either we are under attack, or we are able to destroy enemy buildings, or moving to a new sector
1005 			// assemble unarmed men*/
1006 			if( by_land && sector->getCurrentDesign() == NULL && sector->getCurrentManufacture() == NULL &&
1007 				( enemiesPresentWithBombardment || game_g->getStartEpoch() == end_epoch_c || new_sector ) ) {
1008 					// only use unarmed men if we aren't designing or manufacturing anything
1009 					// and either we are under attack, or we are able to destroy enemy buildings, or we are moving to a new sector
1010 					// assemble unarmed men
1011 					int n_unarmed = sector->getAvailablePopulation() - min_pop;
1012 					if( n_unarmed > 0 ) {
1013 						int n_population = sector->getPopulation();
1014 						sector->getAssembledArmy()->add(n_epochs_c, n_unarmed);
1015 						sector->setPopulation( n_population - n_unarmed );
1016 					}
1017 			}
1018 
1019 			if( sector->getAssembledArmy()->any(true) ) {
1020 				assembled_strength = sector->getAssembledArmy()->getStrength();
1021 
1022 				if( new_sector && used_up && sector->getStoredArmy()->any(false) && (sector->getSparePopulation() + sector->getAssembledArmy()->getTotalMen()) < 0.75f*max_grow_population_c ) {
1023 					// If moving to a new sector because the sector is used up, we don't want to leave weapons behind - if we didn't have enough men to use them, better to wait until the population grows.
1024 					// However we need to have the population not too close to the max_grow_population_c (otherwise we'll no longer be growing very much)
1025 					// Arguably this logic should apply even if sending an army to attack (when not used up), but have to be careful - we don't want to make the AI take ages to decide to attack even though it has a reasonable strength.
1026 					sector->returnAssembledArmy();
1027 				}
1028 				else if( strength + assembled_strength >= min_req || enemiesPresentWithBombardment ) {
1029 					ASSERT( !target_sector->isNuked() );
1030 					if( target_sector->getPlayer() == client_player && !target_sector->getArmy(this->index)->any(true) ) {
1031 						game_g->setTimeRate(1); // auto-slow if attacking a player sector (but not if already being attacked by this player)
1032 						gamestate->refreshTimeRate();
1033 					}
1034 					bool moved_all = target_sector->moveArmy(sector->getAssembledArmy());
1035 					ASSERT(moved_all);
1036 				}
1037 				else {
1038 					sector->returnAssembledArmy();
1039 				}
1040 			}
1041 		}
1042 	}
1043 }
1044 
1045 
doAIUpdate(int client_player,PlayingGameState * gamestate)1046 void Player::doAIUpdate(int client_player, PlayingGameState *gamestate) {
1047 	if( game_g->players[index]->isDead() ) {
1048 		return;
1049 	}
1050 	//LOG("Player::doAIUpdate()\n");
1051 
1052 	int loop_time = game_g->getLoopTime();
1053 
1054 	// TODO: currently breaking/making alliances is entirely random, should improve this...
1055 
1056 	// break alliances
1057 	int p_break_alliance = poisson(20000, loop_time);
1058 	bool break_alliance = false;
1059 	if( (rand() % RAND_MAX) <= p_break_alliance ) {
1060 		for(int i=0;i<n_players_c;i++) {
1061 			if( i != index && Player::isAlliance(i, index) ) {
1062 				Player::setAlliance(i, index, false);
1063 				break_alliance = true;
1064 			}
1065 		}
1066 	}
1067 	if( break_alliance ) {
1068 		//gamestate->reset(); // reset shield buttons
1069 		//((PlayingGameState *)gamestate)->resetShieldButtons(); // needed to update player shield buttons
1070 		gamestate->resetShieldButtons(); // needed to update player shield buttons
1071 	}
1072 
1073 	// make alliances
1074 	for(int i=0;i<n_players_c;i++) {
1075 		if( i != this->index && game_g->players[i] != NULL && !game_g->players[i]->isDead() /*&& i != human_player*/ ) {
1076 			//if( this->index == ((PlayingGameState *)gamestate)->getPlayerAskingAlliance() || i == ((PlayingGameState *)gamestate)->getPlayerAskingAlliance() ) {
1077 			if( this->index == gamestate->getPlayerAskingAlliance() || i == gamestate->getPlayerAskingAlliance() ) {
1078 				// one of these AIs is asking the player, so don't request
1079 				continue;
1080 			}
1081 			// request alliance
1082 			/*if( ((PlayingGameState *)gamestate)->canRequestAlliance(index, i) ) {
1083 				((PlayingGameState *)gamestate)->requestAlliance(index, i, false);
1084 			}*/
1085 			if( gamestate->canRequestAlliance(index, i) ) {
1086 				gamestate->requestAlliance(index, i, false);
1087 			}
1088 		}
1089 	}
1090 
1091 	// update sectors
1092 	for(int x=0;x<map_width_c;x++) {
1093 		for(int y=0;y<map_height_c;y++) {
1094 			Sector *sector = game_g->getMap()->getSector(x, y);
1095 			if( sector == NULL )
1096 				continue;
1097 			if( sector->getActivePlayer() == this->index ) {
1098 				//game_g->getMap()->sectors[x][y]->doAIUpdate();
1099 				doSectorAI(client_player, gamestate, sector);
1100 			}
1101 			else {
1102 				Army *army = sector->getArmy(index);
1103 				if( !army->any(true) ) {
1104 					// no army to move
1105 				}
1106 				else if( !army->canLeaveSafely() ) {
1107 					// can't retreat safely
1108 				}
1109 				else {
1110 					// at this point, we have an army, with no enemies present, so check if we can build here
1111 					bool move = false;
1112 					if( sector->isShutdown() )
1113 						move = true;
1114 					else if( sector->getPlayer() != -1 ) {
1115 						ASSERT( Player::isAlliance(sector->getPlayer(), index) ); // must be true, otherwise we should not be able to retreat safely
1116 						move = true;
1117 					}
1118 					for(int i=0;i<n_players_c && !move;i++) {
1119 						if( i != index && sector->getArmy(i)->any(true) ) {
1120 							ASSERT( Player::isAlliance(i, index) ); // must be true, otherwise we should not be able to retreat safely
1121 							move = true;
1122 						}
1123 					}
1124 					if( move ) {
1125 						// find somewhere to move
1126 						// TODO: move to attack players, if can't return to a tower
1127 						bool done = false;
1128 						for(int cx=0;cx<map_width_c && !done;cx++) {
1129 							for(int cy=0;cy<map_height_c && !done;cy++) {
1130 								Sector *c_sector = game_g->getMap()->getSector(cx, cy);
1131 								if( c_sector != NULL && c_sector->getActivePlayer() == this->index ) {
1132 									ASSERT( c_sector != sector );
1133 									done = c_sector->moveArmy(army);
1134 								}
1135 							}
1136 						}
1137 					}
1138 				}
1139 			}
1140 		}
1141 	}
1142 	//LOG("EXIT Player::doAIUpdate()\n");
1143 }
1144 
getFinalMen() const1145 int Player::getFinalMen() const {
1146 	int final_men = n_men_for_this_island + n_births - n_deaths;
1147 	ASSERT(final_men >= 0);
1148 	return final_men;
1149 }
1150