1 #include "stdafx.h"
2 
3 #include "tutorial.h"
4 #include "game.h"
5 #include "gamestate.h"
6 #include "gui.h"
7 #include "utils.h"
8 
getTutorialInfo()9 vector<TutorialInfo> TutorialManager::getTutorialInfo() {
10 	vector<TutorialInfo> infos;
11 	infos.push_back( TutorialInfo("intro", "play your first island") );
12 	infos.push_back( TutorialInfo("army_maneuvers", "army maneuvers") );
13 	infos.push_back( TutorialInfo("build_manufacture", "learn to build and manufacture") );
14 	return infos;
15 }
16 
setupTutorial(const string & id)17 Tutorial *TutorialManager::setupTutorial(const string &id) {
18 	Tutorial *tutorial = NULL;
19 	if( id == "intro" )
20 		tutorial = new Tutorial1(id);
21 	else if( id == "army_maneuvers" )
22 		tutorial = new Tutorial2(id);
23 	else if( id == "build_manufacture" )
24 		tutorial = new Tutorial3(id);
25 	return tutorial;
26 }
27 
resetGUI(PlayingGameState * playing_gamestate)28 void GUIHandler::resetGUI(PlayingGameState *playing_gamestate) {
29 	playing_gamestate->getGamePanel()->setEnabled(true);
30 	playing_gamestate->getScreenPage()->setEnabled(true);
31 }
32 
setGUI(PlayingGameState * playing_gamestate) const33 void GUIHandlerBlockAll::setGUI(PlayingGameState *playing_gamestate) const {
34 	playing_gamestate->getGamePanel()->setEnabled(false);
35 	playing_gamestate->getScreenPage()->setEnabled(false);
36 	for(vector<string>::const_iterator iter = exceptions.begin(); iter != exceptions.end(); ++iter) {
37 		const string exception = *iter;
38 		PanelPage *panel = playing_gamestate->getGamePanel()->findById(exception);
39 		if( panel != NULL ) {
40 			panel->setEnabled(true);
41 		}
42 		else {
43 			panel = playing_gamestate->getScreenPage()->findById(exception);
44 			if( panel != NULL ) {
45 				panel->setEnabled(true);
46 			}
47 		}
48 	}
49 	// the following are always exceptions
50 	PanelPage *pause_button = playing_gamestate->getScreenPage()->findById("pause_button");
51 	T_ASSERT( pause_button != NULL );
52 	if( pause_button != NULL ) {
53 		pause_button->setEnabled(true);
54 	}
55 	PanelPage *quit_button = playing_gamestate->getScreenPage()->findById("quit_button");
56 	T_ASSERT( quit_button != NULL );
57 	if( quit_button != NULL ) {
58 		quit_button->setEnabled(true);
59 	}
60 	PanelPage *speed_button = playing_gamestate->getScreenPage()->findById("speed_button");
61 	T_ASSERT( speed_button != NULL );
62 	if( speed_button != NULL ) {
63 		speed_button->setEnabled(true);
64 	}
65 }
66 
hasArrow(PlayingGameState * playing_gamestate) const67 bool TutorialCard::hasArrow(PlayingGameState *playing_gamestate) const {
68 	if( this->show_arrow_on_page && playing_gamestate->getGamePanel()->getPage() != this->show_arrow_page )
69 		return false;
70 	if( this->show_arrow_on_sector && ( playing_gamestate->getCurrentSector()->getXPos() != this->show_arrow_sector_x || playing_gamestate->getCurrentSector()->getYPos() != this->show_arrow_sector_y ) )
71 		return false;
72 	return has_arrow;
73 }
74 
setGUI(PlayingGameState * playing_gamestate) const75 void TutorialCard::setGUI(PlayingGameState *playing_gamestate) const {
76 	playing_gamestate->getGamePanel()->setEnabled(true);
77 	playing_gamestate->getScreenPage()->setEnabled(true);
78 	if( gui_handler != NULL ) {
79 		gui_handler->setGUI(playing_gamestate);
80 	}
81 }
82 
canProceed(PlayingGameState * playing_gamestate) const83 bool TutorialCardWaitForPanelPage::canProceed(PlayingGameState *playing_gamestate) const {
84 	int c_page = playing_gamestate->getGamePanel()->getPage();
85 	return c_page == wait_page;
86 }
87 
canProceed(PlayingGameState * playing_gamestate) const88 bool TutorialCardWaitForDesign::canProceed(PlayingGameState *playing_gamestate) const {
89 	if( wait_type == WAITTYPE_CURRENT_DESIGN || wait_type == WAITTYPE_CURRENT_MANUFACTURE ) {
90 		const Design *current_design = wait_type == WAITTYPE_CURRENT_DESIGN ? sector->getCurrentDesign() : sector->getCurrentManufacture();
91 		if( current_design == NULL )
92 			return false;
93 		const Invention *invention = current_design->getInvention();
94 		if( require_type && invention->getType() != invention_type )
95 			return false;
96 		if( require_epoch && invention->getEpoch() != invention_epoch )
97 			return false;
98 		return true;
99 	}
100 	else if( wait_type == WAITTYPE_HAS_DESIGNED || wait_type == WAITTYPE_HAS_MANUFACTURED ) {
101 		for(int i=0;i<Invention::N_TYPES;i++) {
102 			if( require_type && i != invention_type )
103 				continue;
104 			int n_j = i == Invention::SHIELD ? n_shields_c : n_epochs_c;
105 			for(int j=0;j<n_j;j++) {
106 				if( require_epoch && j != invention_epoch )
107 					continue;
108 				if( wait_type == WAITTYPE_HAS_DESIGNED && sector->inventionKnown(static_cast<Invention::Type>(i), j) ) {
109 					return true;
110 				}
111 				else if( wait_type == WAITTYPE_HAS_MANUFACTURED && i == Invention::SHIELD && sector->getStoredShields(j) > 0 ) {
112 					return true;
113 				}
114 				else if( wait_type == WAITTYPE_HAS_MANUFACTURED && i == Invention::DEFENCE && sector->getStoredDefenders(j) > 0 ) {
115 					return true;
116 				}
117 				else if( wait_type == WAITTYPE_HAS_MANUFACTURED && i == Invention::WEAPON && sector->getStoredArmy()->getSoldiers(j) > 0 ) {
118 					return true;
119 				}
120 			}
121 		}
122 		return false;
123 	}
124 	ASSERT(false);
125 	return true;
126 }
127 
canProceed(PlayingGameState * playing_gamestate) const128 bool TutorialCardWaitForBuilding::canProceed(PlayingGameState *playing_gamestate) const {
129 	if( sector->getBuilding(building_type) != NULL ) {
130 		return true;
131 	}
132 	return false;
133 }
134 
canProceed(PlayingGameState * playing_gamestate) const135 bool TutorialCardWaitForDeployedArmy::canProceed(PlayingGameState *playing_gamestate) const {
136 	if( !inverse ) {
137 		int str = require_bombard ? deploy_sector->getArmy(playing_gamestate->getClientPlayer())->getBombardStrength() : deploy_sector->getArmy(playing_gamestate->getClientPlayer())->getTotal();
138 		if( require_unoccupied && deploy_sector->getPlayer() != PLAYER_NONE ) {
139 			return false;
140 		}
141 		if( require_empty && str == 0 )
142 			return true;
143 		else if( !require_empty && str > 0 )
144 			return true;
145 	}
146 	else {
147 		for(int y=0;y<map_height_c;y++) {
148 			for(int x=0;x<map_width_c;x++) {
149 				if( game_g->getMap()->isSectorAt(x, y) ) {
150 					const Sector *sector = game_g->getMap()->getSector(x, y);
151 					if( sector == deploy_sector )
152 						continue;
153 					if( require_unoccupied && sector->getPlayer() != PLAYER_NONE ) {
154 						continue;
155 					}
156 					int str = require_bombard ? sector->getArmy(playing_gamestate->getClientPlayer())->getBombardStrength() : sector->getArmy(playing_gamestate->getClientPlayer())->getTotal();
157 					if( require_empty && str > 0 )
158 						return false;
159 					else if( !require_empty && str > 0 )
160 						return true;
161 				}
162 			}
163 		}
164 		if( require_empty )
165 			return true;
166 	}
167 	return false;
168 }
169 
canProceed(PlayingGameState * playing_gamestate) const170 bool TutorialCardWaitForNewTower::canProceed(PlayingGameState *playing_gamestate) const {
171 	if( !inverse ) {
172 		bool has_tower = tower_sector->getPlayer() == playing_gamestate->getClientPlayer();
173 		if( has_tower )
174 			return true;
175 	}
176 	else {
177 		for(int y=0;y<map_height_c;y++) {
178 			for(int x=0;x<map_width_c;x++) {
179 				if( game_g->getMap()->isSectorAt(x, y) ) {
180 					const Sector *sector = game_g->getMap()->getSector(x, y);
181 					if( sector == tower_sector )
182 						continue;
183 					bool has_tower = sector->getPlayer() == playing_gamestate->getClientPlayer();
184 					if( has_tower )
185 						return true;
186 				}
187 			}
188 		}
189 	}
190 	return false;
191 }
192 
~Tutorial()193 Tutorial::~Tutorial() {
194 	for(vector<TutorialCard *>::const_iterator iter = cards.begin(); iter != cards.end(); ++iter) {
195 		TutorialCard *card = *iter;
196 		delete card;
197 	}
198 }
199 
jumpTo(const string & id)200 bool Tutorial::jumpTo(const string &id) {
201 	int index = 0;
202 	for(vector<TutorialCard *>::const_iterator iter = cards.begin(); iter != cards.end(); ++iter, index++) {
203 		TutorialCard *card = *iter;
204 		if( card->getId() == id ) {
205 			card_index = index;
206 			return true;
207 		}
208 	}
209 	return false;
210 }
211 
Tutorial1(const string & id)212 Tutorial1::Tutorial1(const string &id) : Tutorial(id) {
213 	start_epoch = 0;
214 	island = 0;
215 	start_map_x = 1;
216 	start_map_y = 2;
217 	n_men = 20;
218 	ai_allow_growth = false;
219 	ai_allow_design = false;
220 	ai_allow_ask_alliance = false;
221 	ai_allow_deploy = false;
222 }
223 
initCards()224 void Tutorial1::initCards() {
225 	Sector *start_sector = game_g->getMap()->getSector(start_map_x, start_map_y);
226 	ASSERT(start_sector != NULL);
227 	Sector *enemy_sector = game_g->getMap()->getSector(2, 2);
228 	ASSERT(enemy_sector != NULL);
229 
230 	TutorialCard *card = NULL;
231 
232 #if defined(__ANDROID__)
233 	card = new TutorialCard("0", "Welcome to Gigalomania!\nThis tutorial will introduce you to the game,\nand show you how to win your first island.\nUse the volume keys on your device to control the music volume.\nClick 'next' to continue when you're ready.");
234 #else
235 	card = new TutorialCard("0", "Welcome to Gigalomania!\nThis tutorial will introduce you to the game,\nand show you how to win your first island.\nClick 'next' to continue when you're ready.");
236 #endif
237 	card->setGUIHandler(new GUIHandlerBlockAll());
238 	cards.push_back(card);
239 
240 	card = new TutorialCard("1", "At the top left you can see a map of the current island.\nThe island is split up into sectors.\nThe coloured squares represent sectors controlled by a player.");
241 	card->setArrow(40, 56);
242 	card->setGUIHandler(new GUIHandlerBlockAll());
243 	cards.push_back(card);
244 
245 	card = new TutorialCard("2", "The age of this sector is 10,000 bc.\nThis represents the state of technology. \nIt's possible for different sectors to be in different ages.");
246 	card->setArrow(80, 110);
247 	card->setGUIHandler(new GUIHandlerBlockAll());
248 	cards.push_back(card);
249 
250 	card = new TutorialCard("3", "Next we'll go over the control panel, which\nallows you to control your sector.");
251 	card->setGUIHandler(new GUIHandlerBlockAll());
252 	cards.push_back(card);
253 
254 	card = new TutorialCard("4", "The number below the person icon shows the number of people in your\nsector that are available.\nThe population will grow gradually with time.");
255 	card->setArrow(16, 136);
256 	card->setGUIHandler(new GUIHandlerBlockAll());
257 	cards.push_back(card);
258 
259 	card = new TutorialCardWaitForPanelPage("5", "Now let's design a weapon!\nClick on the lightbulb icon to start researching.", (int)GamePanel::STATE_DESIGN);
260 	card->setArrow(36, 156);
261 	{
262 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
263 		gui_handler->addException("button_design");
264 		card->setGUIHandler(gui_handler);
265 	}
266 	cards.push_back(card);
267 
268 	card = new TutorialCard("6", "This page allows you to design new inventions:\nThe left hand column shows shields, which are used to repair buildings.\nThe middle shows defences for your sector.\nThe right shows weapons to attack the enemy!");
269 	card->setGUIHandler(new GUIHandlerBlockAll());
270 	cards.push_back(card);
271 
272 	card = new TutorialCardWaitForDesign("7", "For this tutorial, we're going to design a weapon.\nClick on one of the weapons.\nI recommend the Rock weapon, but any will do.", start_sector, TutorialCardWaitForDesign::WAITTYPE_CURRENT_DESIGN, true, Invention::WEAPON, false, -1);
273 	card->setArrow(90, 168);
274 	{
275 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
276 		gui_handler->addException("button_weapons_0");
277 		gui_handler->addException("button_weapons_1");
278 		gui_handler->addException("button_weapons_2");
279 		gui_handler->addException("button_weapons_3");
280 		card->setGUIHandler(gui_handler);
281 	}
282 	cards.push_back(card);
283 
284 	if( game_g->isOneMouseButton() ) {
285 		card = new TutorialCard("8", "Now put some of your people to work designing the weapon.\nClick on the number, then use the arrows to increase or decrease\nthe number of designers.");
286 	}
287 	else {
288 		card = new TutorialCard("8", "Now put some of your people to work designing the weapon.\nUsing the right mouse button, click on the number to increase\nthe number of designers, left mouse button to decrease.");
289 	}
290 	card->setArrow(50, 130);
291 	{
292 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
293 		gui_handler->addException("button_weapons_0");
294 		gui_handler->addException("button_weapons_1");
295 		gui_handler->addException("button_weapons_2");
296 		gui_handler->addException("button_weapons_3");
297 		gui_handler->addException("button_designers");
298 		card->setGUIHandler(gui_handler);
299 	}
300 	cards.push_back(card);
301 
302 	card = new TutorialCard("9", "While your designers are working, the clock shows the remaining time\nuntil the invention is ready.");
303 	card->setArrow(86, 130);
304 	{
305 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
306 		gui_handler->addException("button_weapons_0");
307 		gui_handler->addException("button_weapons_1");
308 		gui_handler->addException("button_weapons_2");
309 		gui_handler->addException("button_weapons_3");
310 		gui_handler->addException("button_designers");
311 		card->setGUIHandler(gui_handler);
312 	}
313 	cards.push_back(card);
314 
315 	if( game_g->isOneMouseButton() ) {
316 		card = new TutorialCardWaitForDesign("10", "To hurry things up, you can make time go faster.\nClick the 1x icon to cycle through different time rates.", start_sector, TutorialCardWaitForDesign::WAITTYPE_HAS_DESIGNED, true, Invention::WEAPON, false, -1);
317 	}
318 	else {
319 		card = new TutorialCardWaitForDesign("10", "To hurry things up, you can make time go faster.\nRight click on the 1x icon to speed time up.\nLeft click slows time back down.", start_sector, TutorialCardWaitForDesign::WAITTYPE_HAS_DESIGNED, true, Invention::WEAPON, false, -1);
320 	}
321 	card->setArrow(100, 10);
322 	{
323 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
324 		gui_handler->addException("button_weapons_0");
325 		gui_handler->addException("button_weapons_1");
326 		gui_handler->addException("button_weapons_2");
327 		gui_handler->addException("button_weapons_3");
328 		gui_handler->addException("button_designers");
329 		card->setGUIHandler(gui_handler);
330 	}
331 	cards.push_back(card);
332 
333 	card = new TutorialCardWaitForPanelPage("11", "Great! Now click on the lightbulb to go back to the main interface.", (int)GamePanel::STATE_SECTORCONTROL);
334 	card->setArrow(50, 110);
335 	{
336 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
337 		gui_handler->addException("button_weapons_0");
338 		gui_handler->addException("button_weapons_1");
339 		gui_handler->addException("button_weapons_2");
340 		gui_handler->addException("button_weapons_3");
341 		gui_handler->addException("button_designers");
342 		gui_handler->addException("button_bigdesign");
343 		card->setGUIHandler(gui_handler);
344 	}
345 	cards.push_back(card);
346 
347 	card = new TutorialCardWaitForPanelPage("11", "Time to attack our enemy. The shield and sword icon allows you to\nassemble your army.", (int)GamePanel::STATE_ATTACK);
348 	card->setArrow(80, 125);
349 	{
350 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
351 		gui_handler->addException("button_attack");
352 		card->setGUIHandler(gui_handler);
353 	}
354 	cards.push_back(card);
355 
356 	card = new TutorialCard("12", "This page shows you the available soldiers to deploy.\nThey can be unarmed or, preferably, armed with weapons\nyou have invented.");
357 	card->setGUIHandler(new GUIHandlerBlockAll());
358 	cards.push_back(card);
359 
360 	card = new TutorialCard("13", "Not only are armed soldiers stronger, but they are required to destroy\nan enemy's buildings. Unarmed soldiers can fight other soldiers,\nbut won't knock down the enemy tower.");
361 	card->setGUIHandler(new GUIHandlerBlockAll());
362 	cards.push_back(card);
363 
364 	card = new TutorialCard("14", "Click on the weapon icon to assemble soldiers with the weapon\nyou've just invented.\nAssemble as many soldiers as we have people available!");
365 	card->setArrow(15, 170);
366 	{
367 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
368 		gui_handler->addException("button_deploy_attackers_0");
369 		gui_handler->addException("button_deploy_attackers_1");
370 		gui_handler->addException("button_deploy_attackers_2");
371 		gui_handler->addException("button_deploy_attackers_3");
372 		card->setGUIHandler(gui_handler);
373 	}
374 	cards.push_back(card);
375 
376 	card = new TutorialCardWaitForDeployedArmy("15", "Then click on the enemy's sector in the map - that's the\nright hand square - to send your army to attack.", enemy_sector, true);
377 	card->setArrow(48, 56);
378 	card->setArrowShowPage((int)GamePanel::STATE_ATTACK);
379 	{
380 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
381 		gui_handler->addException("button_deploy_attackers_0");
382 		gui_handler->addException("button_deploy_attackers_1");
383 		gui_handler->addException("button_deploy_attackers_2");
384 		gui_handler->addException("button_deploy_attackers_3");
385 		gui_handler->addException("map_1_2"); // need to allow the user to return to the player sector if necessary (as user can switch to the other sector without sending men)
386 		gui_handler->addException("map_2_2");
387 		gui_handler->addException("button_attack"); // allow the user to get back to the attack screen (a GUI resets to main if user switches current sector)
388 		gui_handler->addException("button_bigattack"); // ...and for consistency, allow the user to go back to the main screen
389 		// and in case the user wants to design some more:
390 		gui_handler->addException("button_design");
391 		gui_handler->addException("button_weapons_0");
392 		gui_handler->addException("button_weapons_1");
393 		gui_handler->addException("button_weapons_2");
394 		gui_handler->addException("button_weapons_3");
395 		gui_handler->addException("button_designers");
396 		gui_handler->addException("button_bigdesign");
397 		card->setGUIHandler(gui_handler);
398 	}
399 	cards.push_back(card);
400 
401 	card = new TutorialCard("16", "Now wait until the battle is won!\nRemember to speed up the time rate if you prefer.");
402 	card->setNextText("Done");
403 	cards.push_back(card);
404 
405 	// for debugging
406 	//this->card_index = 13;
407 }
408 
Tutorial2(const string & id)409 Tutorial2::Tutorial2(const string &id) : Tutorial(id) {
410 	start_epoch = 0;
411 	island = 2;
412 	start_map_x = 2;
413 	start_map_y = 2;
414 	n_men = 25;
415 	auto_end = true;
416 	ai_allow_growth = false;
417 	ai_allow_design = false;
418 	ai_allow_ask_alliance = false;
419 	ai_allow_deploy = false;
420 	allow_retreat_loss = false;
421 }
422 
initCards()423 void Tutorial2::initCards() {
424 	Sector *start_sector = game_g->getMap()->getSector(start_map_x, start_map_y);
425 	ASSERT(start_sector != NULL);
426 
427 	TutorialCard *card = NULL;
428 
429 	card = new TutorialCardWaitForPanelPage("0", "In this tutorial we'll learn some army maneuvers.\nSelect the shield and sword icon to deploy some soldiers.", (int)GamePanel::STATE_ATTACK);
430 	card->setPlayerAllowBuildTower(false);
431 	card->setArrow(80, 125);
432 	{
433 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
434 		gui_handler->addException("button_attack");
435 		card->setGUIHandler(gui_handler);
436 	}
437 	cards.push_back(card);
438 
439 	card = new TutorialCard("1", "In the first tutorial you learnt how to design weapons.\nHere you'll be learning how to deploy and move your soldiers,\nso unarmed men will do.");
440 	card->setPlayerAllowBuildTower(false);
441 	card->setGUIHandler(new GUIHandlerBlockAll());
442 	cards.push_back(card);
443 
444 	card = new TutorialCard("2", "Click to assemble some unarmed men.");
445 	card->setPlayerAllowBuildTower(false);
446 	card->setArrow(15, 145);
447 	{
448 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
449 		gui_handler->addException("button_deploy_unarmedmen");
450 		gui_handler->addException("button_deploy_attackers_0");
451 		gui_handler->addException("button_deploy_attackers_1");
452 		gui_handler->addException("button_deploy_attackers_2");
453 		gui_handler->addException("button_deploy_attackers_3");
454 		gui_handler->addException("button_return_attackers");
455 		card->setGUIHandler(gui_handler);
456 	}
457 	cards.push_back(card);
458 
459 	card = new TutorialCard("3", "Note that if you make a mistake assembling your army,\nyou can cancel by clicking the shield and sword icon at the bottom.");
460 	card->setPlayerAllowBuildTower(false);
461 	card->setArrow(87, 195);
462 	{
463 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
464 		gui_handler->addException("button_deploy_unarmedmen");
465 		gui_handler->addException("button_deploy_attackers_0");
466 		gui_handler->addException("button_deploy_attackers_1");
467 		gui_handler->addException("button_deploy_attackers_2");
468 		gui_handler->addException("button_deploy_attackers_3");
469 		gui_handler->addException("button_return_attackers");
470 		card->setGUIHandler(gui_handler);
471 	}
472 	cards.push_back(card);
473 
474 	card = new TutorialCardWaitForDeployedArmy("4", "Assemble some unarmed men, and send them to a\nsector by clicking on a new map square of your choice.", start_sector, false);
475 	card->setPlayerAllowBuildTower(false);
476 	static_cast<TutorialCardWaitForDeployedArmy *>(card)->setInverse(true);
477 	card->setArrow(60, 70);
478 	card->setArrowShowPage((int)GamePanel::STATE_ATTACK);
479 	{
480 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
481 		gui_handler->addException("button_deploy_unarmedmen");
482 		gui_handler->addException("button_deploy_attackers_0");
483 		gui_handler->addException("button_deploy_attackers_1");
484 		gui_handler->addException("button_deploy_attackers_2");
485 		gui_handler->addException("button_deploy_attackers_3");
486 		gui_handler->addException("button_return_attackers");
487 		gui_handler->addException("button_attack");
488 		for(int y=0;y<map_height_c;y++) {
489 			for(int x=0;x<map_width_c;x++) {
490 				// enable the current square too, as we need to allow getting back if the user clicks another square without an assembled army!
491 				if( game_g->getMap()->isSectorAt(x, y) ) {
492 					char buffer[256] = "";
493 					sprintf(buffer, "map_%d_%d", x, y);
494 					gui_handler->addException(buffer);
495 				}
496 			}
497 		}
498 		card->setGUIHandler(gui_handler);
499 	}
500 	cards.push_back(card);
501 
502 	if( game_g->isOneMouseButton() ) {
503 		card = new TutorialCard("5", "Now see if you can return them to the home sector.\nYou can select an army by clicking\non the main area to the right of the map.");
504 	}
505 	else {
506 		card = new TutorialCard("5", "Now see if you can return them to the home sector.\nYou can select an army by right clicking,\neither on the current map square,\nor right clicking on the main area to the right.");
507 	}
508 	card->setPlayerAllowBuildTower(false);
509 	cards.push_back(card);
510 
511 	card = new TutorialCardWaitForDeployedArmy("6", "When the army is selected, the shield icon will show,\nor a bloody sword icon if retreating from an enemy sector.\nMove the army back home by clicking on the square of your sector", start_sector, false);
512 	card->setPlayerAllowBuildTower(false);
513 	card->setArrow(47, 54);
514 	cards.push_back(card);
515 
516 	// return back home
517 
518 	if( game_g->isOneMouseButton() ) {
519 		card = new TutorialCardWaitForDeployedArmy("7", "Now let's return our men back to the tower.\nClick to select the army as before, then\nclick on your tower.", NULL, false);
520 	}
521 	else {
522 		card = new TutorialCardWaitForDeployedArmy("7", "Now let's return our men back to the tower.\nRight click to select the army as before, then\nleft click on your tower.", NULL, false);
523 	}
524 	static_cast<TutorialCardWaitForDeployedArmy *>(card)->setInverse(true);
525 	static_cast<TutorialCardWaitForDeployedArmy *>(card)->setRequireEmpty(true);
526 	card->setPlayerAllowBuildTower(false);
527 	card->setArrow(260, 80);
528 	card->setArrowShowSector(start_map_x, start_map_y);
529 	cards.push_back(card);
530 
531 	// build new tower
532 
533 	card = new TutorialCard("8", "So far you've only had a single tower,\nbut you can build new towers.");
534 	card->setPlayerAllowBuildTower(false);
535 	cards.push_back(card);
536 
537 	card = new TutorialCard("9", "Each tower can act independently, researching and\nconstructing different weapons.\nEach tower needs to invent its own weapons.");
538 	card->setPlayerAllowBuildTower(false);
539 	cards.push_back(card);
540 
541 	card = new TutorialCardWaitForDeployedArmy("10", "Assemble some unarmed men again, and this time\nsend them to a square that isn't occupied by the enemy", start_sector, false);
542 	static_cast<TutorialCardWaitForDeployedArmy *>(card)->setInverse(true);
543 	static_cast<TutorialCardWaitForDeployedArmy *>(card)->setRequireUnoccupied(true);
544 	cards.push_back(card);
545 
546 	card = new TutorialCardWaitForNewTower("11", "Now sit back and wait until your new tower is constructed.\nRemember to speed up the rate of time if you want.", start_sector);
547 	static_cast<TutorialCardWaitForNewTower *>(card)->setInverse(true);
548 	cards.push_back(card);
549 
550 	card = new TutorialCard("12", "You have completed this tutorial!");
551 	cards.push_back(card);
552 
553 	// for debugging
554 	//this->card_index = 5;
555 }
556 
Tutorial3(const string & id)557 Tutorial3::Tutorial3(const string &id) : Tutorial(id) {
558 	start_epoch = 3;
559 	island = 1;
560 	start_map_x = 3;
561 	start_map_y = 3;
562 	n_men = 50;
563 	//auto_end = true;
564 	ai_allow_growth = false;
565 	ai_allow_design = false;
566 	ai_allow_ask_alliance = false;
567 	ai_allow_deploy = false;
568 	//allow_retreat_loss = false;
569 }
570 
initCards()571 void Tutorial3::initCards() {
572 	Sector *start_sector = game_g->getMap()->getSector(start_map_x, start_map_y);
573 	ASSERT(start_sector != NULL);
574 
575 	TutorialCard *card = NULL;
576 
577 	card = new TutorialCard("0", "We're now thousands of years into the future since the last tutorial.\nIn this tutorial, you'll learn how to make use of newer technology\nto build weapons to destroy your enemies!");
578 	card->setGUIHandler(new GUIHandlerBlockAll());
579 	cards.push_back(card);
580 
581 	card = new TutorialCardWaitForPanelPage("1", "From the fourth age onwards, you can construct an additional building\nin your sector - a mine.\nSelect the pickaxe icon at the bottom left to build a mine.", (int)GamePanel::STATE_BUILD);
582 	card->setArrow(25, 210);
583 	{
584 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
585 		gui_handler->addException("button_build_mine");
586 		card->setGUIHandler(gui_handler);
587 	}
588 	cards.push_back(card);
589 
590 	card = new TutorialCardWaitForBuilding("2", "Assign some men to start building a mine, and then\nwait for it to be constructed.", start_sector, BUILDING_MINE);
591 	card->setArrow(60, 130);
592 	{
593 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
594 		gui_handler->addException("button_nbuilders2_mine");
595 		card->setGUIHandler(gui_handler);
596 	}
597 	cards.push_back(card);
598 
599 	card = new TutorialCardWaitForPanelPage("3", "Now click the bricks icon to go back to the main interface.", (int)GamePanel::STATE_SECTORCONTROL);
600 	{
601 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
602 		gui_handler->addException("button_bigbuild");
603 		card->setGUIHandler(gui_handler);
604 	}
605 	card->setArrow(50, 110);
606 	cards.push_back(card);
607 
608 	card = new TutorialCardWaitForPanelPage("4", "Your mine can extract elements from the ground, in order to\ncreate new inventions. To do this, click on any of the elements.", (int)GamePanel::STATE_ELEMENTSTOCKS);
609 	card->setArrow(45, 185);
610 	{
611 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
612 		gui_handler->addException("button_elements_0");
613 		gui_handler->addException("button_elements_1");
614 		gui_handler->addException("button_elements_2");
615 		gui_handler->addException("button_elements_3");
616 		card->setGUIHandler(gui_handler);
617 	}
618 	cards.push_back(card);
619 
620 	card = new TutorialCard("5", "This page shows you the sector's current element stocks.\nSo far you've worked with gatherables, that your men automatically\npick up, without the need for a mine.");
621 	card->setGUIHandler(new GUIHandlerBlockAll());
622 	card->setArrow(80, 150);
623 	cards.push_back(card);
624 
625 	card = new TutorialCard("6", "But more advanced elements require you to assign miners to them.\nClick on the 0 number to add some miners now, and wait\nuntil we have at least 1 unit.\nOnly use a few of your men for this.");
626 	{
627 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
628 		gui_handler->addException("button_nminers2_0");
629 		gui_handler->addException("button_nminers2_1");
630 		gui_handler->addException("button_nminers2_2");
631 		gui_handler->addException("button_nminers2_3");
632 		card->setGUIHandler(gui_handler);
633 	}
634 	card->setArrow(52, 183);
635 	cards.push_back(card);
636 
637 	card = new TutorialCardWaitForPanelPage("7", "Now click the pickaxe icon to go back to the main screen.", (int)GamePanel::STATE_SECTORCONTROL);
638 	{
639 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
640 		gui_handler->addException("button_nminers2_0");
641 		gui_handler->addException("button_nminers2_1");
642 		gui_handler->addException("button_nminers2_2");
643 		gui_handler->addException("button_nminers2_3");
644 		gui_handler->addException("button_bigelementstocks");
645 		card->setGUIHandler(gui_handler);
646 	}
647 	card->setArrow(50, 110);
648 	cards.push_back(card);
649 
650 	card = new TutorialCardWaitForPanelPage("8", "Now let's design a weapon!\nClick on the lightbulb icon to start researching.", (int)GamePanel::STATE_DESIGN);
651 	card->setArrow(36, 156);
652 	card->setArrowShowPage((int)GamePanel::STATE_SECTORCONTROL);
653 	{
654 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
655 		gui_handler->addException("button_elements_0");
656 		gui_handler->addException("button_elements_1");
657 		gui_handler->addException("button_elements_2");
658 		gui_handler->addException("button_elements_3");
659 		gui_handler->addException("button_nminers2_0");
660 		gui_handler->addException("button_nminers2_1");
661 		gui_handler->addException("button_nminers2_2");
662 		gui_handler->addException("button_nminers2_3");
663 		gui_handler->addException("button_bigelementstocks");
664 		gui_handler->addException("button_design");
665 		card->setGUIHandler(gui_handler);
666 	}
667 	cards.push_back(card);
668 
669 	card = new TutorialCardWaitForDesign("9", "First, design a longbow", start_sector, TutorialCardWaitForDesign::WAITTYPE_HAS_DESIGNED, true, Invention::WEAPON, true, 3);
670 	card->setArrow(90, 168);
671 	card->setArrowShowPage((int)GamePanel::STATE_DESIGN);
672 	{
673 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
674 		gui_handler->addException("button_elements_0");
675 		gui_handler->addException("button_elements_1");
676 		gui_handler->addException("button_elements_2");
677 		gui_handler->addException("button_elements_3");
678 		gui_handler->addException("button_nminers2_0");
679 		gui_handler->addException("button_nminers2_1");
680 		gui_handler->addException("button_nminers2_2");
681 		gui_handler->addException("button_nminers2_3");
682 		gui_handler->addException("button_bigelementstocks");
683 		gui_handler->addException("button_design");
684 		gui_handler->addException("button_bigdesign");
685 		gui_handler->addException("button_weapons_0");
686 		gui_handler->addException("button_designers");
687 		card->setGUIHandler(gui_handler);
688 	}
689 	cards.push_back(card);
690 
691 	card = new TutorialCardWaitForDesign("10", "Now design a trebuchet", start_sector, TutorialCardWaitForDesign::WAITTYPE_HAS_DESIGNED, true, Invention::WEAPON, true, 4);
692 	card->setArrow(90, 188);
693 	card->setArrowShowPage((int)GamePanel::STATE_DESIGN);
694 	{
695 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
696 		gui_handler->addException("button_elements_0");
697 		gui_handler->addException("button_elements_1");
698 		gui_handler->addException("button_elements_2");
699 		gui_handler->addException("button_elements_3");
700 		gui_handler->addException("button_nminers2_0");
701 		gui_handler->addException("button_nminers2_1");
702 		gui_handler->addException("button_nminers2_2");
703 		gui_handler->addException("button_nminers2_3");
704 		gui_handler->addException("button_bigelementstocks");
705 		gui_handler->addException("button_design");
706 		gui_handler->addException("button_bigdesign");
707 		gui_handler->addException("button_weapons_1");
708 		gui_handler->addException("button_designers");
709 		card->setGUIHandler(gui_handler);
710 	}
711 	cards.push_back(card);
712 
713 	card = new TutorialCardWaitForPanelPage("11", "Now click the lightbulb icon to go back to the main screen.", (int)GamePanel::STATE_SECTORCONTROL);
714 	card->setArrow(50, 110);
715 	card->setArrowShowPage((int)GamePanel::STATE_DESIGN);
716 	{
717 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
718 		gui_handler->addException("button_elements_0");
719 		gui_handler->addException("button_elements_1");
720 		gui_handler->addException("button_elements_2");
721 		gui_handler->addException("button_elements_3");
722 		gui_handler->addException("button_nminers2_0");
723 		gui_handler->addException("button_nminers2_1");
724 		gui_handler->addException("button_nminers2_2");
725 		gui_handler->addException("button_nminers2_3");
726 		gui_handler->addException("button_bigelementstocks");
727 		gui_handler->addException("button_bigdesign");
728 		card->setGUIHandler(gui_handler);
729 	}
730 	cards.push_back(card);
731 
732 	card = new TutorialCardWaitForPanelPage("12", "As a result of your two inventions, we've moved forward to a new age.\nThis means we can build a factory, which is necessary to construct\ntrebuchets. Click the factory icon at the bottom to build a factory.",  (int)GamePanel::STATE_BUILD);
733 	card->setArrow(45, 210);
734 	card->setArrowShowPage((int)GamePanel::STATE_SECTORCONTROL);
735 	{
736 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
737 		gui_handler->addException("button_elements_0");
738 		gui_handler->addException("button_elements_1");
739 		gui_handler->addException("button_elements_2");
740 		gui_handler->addException("button_elements_3");
741 		gui_handler->addException("button_nminers2_0");
742 		gui_handler->addException("button_nminers2_1");
743 		gui_handler->addException("button_nminers2_2");
744 		gui_handler->addException("button_nminers2_3");
745 		gui_handler->addException("button_bigelementstocks");
746 		gui_handler->addException("button_build_factory");
747 		card->setGUIHandler(gui_handler);
748 	}
749 	cards.push_back(card);
750 
751 	card = new TutorialCardWaitForBuilding("13", "Now assign some men to build a factory, as you did with the mine,\nand wait for it to be constructed.", start_sector, BUILDING_FACTORY);
752 	card->setArrow(60, 160);
753 	card->setArrowShowPage((int)GamePanel::STATE_BUILD);
754 	{
755 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
756 		gui_handler->addException("button_elements_0");
757 		gui_handler->addException("button_elements_1");
758 		gui_handler->addException("button_elements_2");
759 		gui_handler->addException("button_elements_3");
760 		gui_handler->addException("button_nminers2_0");
761 		gui_handler->addException("button_nminers2_1");
762 		gui_handler->addException("button_nminers2_2");
763 		gui_handler->addException("button_nminers2_3");
764 		gui_handler->addException("button_bigelementstocks");
765 		gui_handler->addException("button_build_factory");
766 		gui_handler->addException("button_bigbuild");
767 		gui_handler->addException("button_nbuilders2_factory");
768 		card->setGUIHandler(gui_handler);
769 	}
770 	cards.push_back(card);
771 
772 	card = new TutorialCardWaitForPanelPage("14", "Now click the bricks icon to go back to the main interface.", (int)GamePanel::STATE_SECTORCONTROL);
773 	{
774 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
775 		gui_handler->addException("button_elements_0");
776 		gui_handler->addException("button_elements_1");
777 		gui_handler->addException("button_elements_2");
778 		gui_handler->addException("button_elements_3");
779 		gui_handler->addException("button_nminers2_0");
780 		gui_handler->addException("button_nminers2_1");
781 		gui_handler->addException("button_nminers2_2");
782 		gui_handler->addException("button_nminers2_3");
783 		gui_handler->addException("button_bigelementstocks");
784 		gui_handler->addException("button_bigbuild");
785 		card->setGUIHandler(gui_handler);
786 	}
787 	card->setArrow(50, 110);
788 	cards.push_back(card);
789 
790 	card = new TutorialCardWaitForPanelPage("15", "Click on the factory icon to start manufacturing.", (int)GamePanel::STATE_FACTORY);
791 	card->setArrow(65, 156);
792 	card->setArrowShowPage((int)GamePanel::STATE_SECTORCONTROL);
793 	{
794 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
795 		gui_handler->addException("button_elements_0");
796 		gui_handler->addException("button_elements_1");
797 		gui_handler->addException("button_elements_2");
798 		gui_handler->addException("button_elements_3");
799 		gui_handler->addException("button_nminers2_0");
800 		gui_handler->addException("button_nminers2_1");
801 		gui_handler->addException("button_nminers2_2");
802 		gui_handler->addException("button_nminers2_3");
803 		gui_handler->addException("button_bigelementstocks");
804 		gui_handler->addException("button_factory");
805 		card->setGUIHandler(gui_handler);
806 	}
807 	cards.push_back(card);
808 
809 	card = new TutorialCardWaitForDesign("16", "Select the trebuchet to start manufacturing", start_sector, TutorialCardWaitForDesign::WAITTYPE_CURRENT_MANUFACTURE, true, Invention::WEAPON, false, -1);
810 	card->setArrow(90, 205);
811 	card->setArrowShowPage((int)GamePanel::STATE_FACTORY);
812 	{
813 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
814 		gui_handler->addException("button_elements_0");
815 		gui_handler->addException("button_elements_1");
816 		gui_handler->addException("button_elements_2");
817 		gui_handler->addException("button_elements_3");
818 		gui_handler->addException("button_nminers2_0");
819 		gui_handler->addException("button_nminers2_1");
820 		gui_handler->addException("button_nminers2_2");
821 		gui_handler->addException("button_nminers2_3");
822 		gui_handler->addException("button_bigelementstocks");
823 		gui_handler->addException("button_factory");
824 		gui_handler->addException("button_bigfactory");
825 		gui_handler->addException("button_fweapons_1");
826 		card->setGUIHandler(gui_handler);
827 	}
828 	cards.push_back(card);
829 
830 	card = new TutorialCardWaitForDesign("17", "The top number shows the assigned number of workers,\nthe bottom shows the number of trebuchets to be manufactured.\nAssign workers by increasing the top number, then wait!", start_sector, TutorialCardWaitForDesign::WAITTYPE_HAS_MANUFACTURED, true, Invention::WEAPON, false, -1);
831 	card->setArrow(90, 135);
832 	card->setArrowShowPage((int)GamePanel::STATE_FACTORY);
833 	{
834 		GUIHandlerBlockAll *gui_handler = new GUIHandlerBlockAll();
835 		gui_handler->addException("button_elements_0");
836 		gui_handler->addException("button_elements_1");
837 		gui_handler->addException("button_elements_2");
838 		gui_handler->addException("button_elements_3");
839 		gui_handler->addException("button_nminers2_0");
840 		gui_handler->addException("button_nminers2_1");
841 		gui_handler->addException("button_nminers2_2");
842 		gui_handler->addException("button_nminers2_3");
843 		gui_handler->addException("button_bigelementstocks");
844 		gui_handler->addException("button_factory");
845 		gui_handler->addException("button_bigfactory");
846 		gui_handler->addException("button_fweapons_1");
847 		gui_handler->addException("button_workers");
848 		gui_handler->addException("button_famount");
849 		card->setGUIHandler(gui_handler);
850 	}
851 	cards.push_back(card);
852 
853 	card = new TutorialCard("18", "You now have your first trebchet! Now manufacture some more,\nand use them to defeat your enemies. Good luck!");
854 	card->setNextText("Done");
855 	cards.push_back(card);
856 }
857