1 // Brain Party
2 // Copyright (C) 2010 Paul Hudson (http://www.tuxradar.com/brainparty)
3 
4 // Brain Party is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 3
7 // of the License, or (at your option) any later version.
8 
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 
18 #include <ctime>
19 #include "BPGame.h"
20 #include "SDL.h"
21 #include "SDL_opengl.h"
22 #include "SDL_ttf.h"
23 #include <string>
24 
25 
26 #include "bombhunt.h"
27 #include "balloonblaster.h"
28 #include "bpsays.h"
29 #include "bubbletrouble.h"
30 #include "cardmatch.h"
31 #include "connex.h"
32 #include "cupsnballs.h"
33 #include "diceoff.h"
34 #include "flashcounting.h"
35 #include "flashlight.h"
36 #include "iqtest.h"
37 #include "jewelflip.h"
38 #include "jeweljam.h"
39 #include "marbledrop.h"
40 #include "memoryblox.h"
41 #include "memorybox.h"
42 #include "memorymaths.h"
43 #include "minesweep.h"
44 #include "moonjump.h"
45 #include "nextinline.h"
46 #include "numbersnake.h"
47 #include "oddoneout.h"
48 #include "patchmatch.h"
49 #include "perfectpaths.h"
50 #include "routefinder.h"
51 #include "rps.h"
52 #include "scrambled.h"
53 #include "setfinder.h"
54 #include "sharpshooter.h"
55 #include "shortcircuitsudoku.h"
56 #include "shufflepuzzler.h"
57 #include "strangerdanger.h"
58 #include "symboliclogic.h"
59 #include "underthehat.h"
60 #include "untangler.h"
61 #include "wordsmash.h"
62 
63 Texture* BPGame::sfcLogo;
64 bool BPGame::ShowingMessageBox;
65 bool BPGame::ShowingClearScores;
66 SpriteFont* BPGame::sfcMessageBoxText;
67 SpriteFont* BPGame::sfcMessageBoxTitle;
68 
Init(int width,int height)69 void BPGame::Init(int width, int height) {
70 	srand(time(0));
71 
72 	EnableSound = true;
73 	EnableMusic = true;
74 
75 	EmptyPoint = BPPoint(0,0);
76 	LastStateChange = 0;
77 
78 	LastBGObject = 0;
79 
80 	Black = new Colour(0.0f, 0.0f, 0.0f, 1.0f);
81 	White = new Colour(1.0f, 1.0f, 1.0f, 1.0f);
82 	TransparentWhite = new Colour(1.0f, 1.0f, 1.0f, 0.0f);
83 
84 	Blue = new Colour(0.0f, 0.0f, 1.0f, 1.0f);
85 	Cyan = new Colour(0.0f, 1.0f, 1.0f, 1.0f);
86 	Green = new Colour(0.0f, 1.0f, 0.0f, 1.0f);
87 	Orange = new Colour(1.0f, 0.75f, 0.0f, 1.0f);
88 	Red = new Colour(1.0f, 0.0f, 0.0f, 1.0f);
89 	LightRed = new Colour(1.0f, 0.5f, 0.6f, 1.0f);
90 	DarkRed = new Colour(0.5f, 0.0f, 0.0f, 1.0f);
91 	Yellow = new Colour(1.0f, 1.0f, 0.0f, 1.0f);
92 	DarkGrey = new Colour(0.5f, 0.5f, 0.5f, 1.0f);
93 	ConnexGreen = new Colour(0.0f, 0.8f, 0.0f, 0.7f);
94 
95 	CheatMainTaps = CheatOptionsTaps = 0;
96 
97 	InTestMode = false;
98 
99 	TickCount = 0;
100 	ElapsedSeconds = 0;
101 	AnimCounter = 0.0f;
102 	PractiseAnimCounter = 0.0f;
103 
104 	PractisePageNumber = 0;
105 	PractisePageMoveLeft = true;
106 
107 	sfcTestWeight = NULL;
108 	sfcTestJob = NULL;
109 	sfcHighestBrainWeight = NULL;
110 
111 	HighestBrainWeight = -1;
112 	CurrentBrainWeight = -1;
113 
114 	TestBrainJobs.Add("Fast Food Assistant");
115 	TestBrainJobs.Add("Fast Food Manager");
116 	TestBrainJobs.Add("Bingo Club Manager");
117 	TestBrainJobs.Add("Web Designer");
118 	TestBrainJobs.Add("Personal Shopper");
119 	TestBrainJobs.Add("Aromatherapist");
120 	TestBrainJobs.Add("Solicitor");
121 	TestBrainJobs.Add("Psychotherapist");
122 	TestBrainJobs.Add("Lifestyle Consultant");
123 	TestBrainJobs.Add("Librarian");
124 	TestBrainJobs.Add("Acupuncturist");
125 	TestBrainJobs.Add("Insurance Broker");
126 	TestBrainJobs.Add("Bank Manager");
127 	TestBrainJobs.Add("Fashion Stylist");
128 	TestBrainJobs.Add("Interior Designer");
129 	TestBrainJobs.Add("Fashion Consultant");
130 	TestBrainJobs.Add("Sales Assistant");
131 	TestBrainJobs.Add("Actor");
132 	TestBrainJobs.Add("Sales Executive");
133 	TestBrainJobs.Add("Movie Director");
134 	TestBrainJobs.Add("Hotel Manager");
135 	TestBrainJobs.Add("Botanist");
136 	TestBrainJobs.Add("Marketing Executive");
137 	TestBrainJobs.Add("Economist");
138 	TestBrainJobs.Add("Statistician");
139 	TestBrainJobs.Add("Theatre Director");
140 	TestBrainJobs.Add("Nurse");
141 	TestBrainJobs.Add("Police Officer");
142 	TestBrainJobs.Add("Meteorologist");
143 	TestBrainJobs.Add("Art Valuer");
144 	TestBrainJobs.Add("Museum Curator");
145 	TestBrainJobs.Add("Marine Biologist");
146 	TestBrainJobs.Add("School Teacher");
147 	TestBrainJobs.Add("Dentist");
148 	TestBrainJobs.Add("Software Engineer");
149 	TestBrainJobs.Add("Forensic Scientist");
150 	TestBrainJobs.Add("Psychiatrist");
151 	TestBrainJobs.Add("Archaeologist");
152 	TestBrainJobs.Add("Engineer");
153 	TestBrainJobs.Add("Investment Analyst");
154 	TestBrainJobs.Add("Physicist");
155 	TestBrainJobs.Add("Sculptor");
156 	TestBrainJobs.Add("Painter");
157 	TestBrainJobs.Add("Poet");
158 	TestBrainJobs.Add("Doctor");
159 	TestBrainJobs.Add("Composer");
160 	TestBrainJobs.Add("Fighter Pilot");
161 	TestBrainJobs.Add("Architect");
162 	TestBrainJobs.Add("Brain Surgeon");
163 	TestBrainJobs.Add("Professor");
164 	TestBrainJobs.Add("Philosopher");
165 	TestBrainJobs.Add("Astronaut");
166 	TestBrainJobs.Add("Nobel Prize Winner");
167 	TestBrainJobs.Add("Genius");
168 	TestBrainJobs.Add("Super Genius");
169 	TestBrainJobs.Add("Albert Einstein");
170 
171 	PeopleNames.Add("Andrea");
172 	PeopleNames.Add("Andrew");
173 	PeopleNames.Add("Bob");
174 	PeopleNames.Add("Catherine");
175 	PeopleNames.Add("Dawn");
176 	PeopleNames.Add("Diana");
177 	PeopleNames.Add("Esther");
178 	PeopleNames.Add("Graham");
179 	PeopleNames.Add("Hannah");
180 	PeopleNames.Add("Jack");
181 	PeopleNames.Add("James");
182 	PeopleNames.Add("Jeff");
183 	PeopleNames.Add("Jeremy");
184 	PeopleNames.Add("John");
185 	PeopleNames.Add("Kathryn");
186 	PeopleNames.Add("Laura");
187 	PeopleNames.Add("Louise");
188 	PeopleNames.Add("Lyn");
189 	PeopleNames.Add("Mark");
190 	PeopleNames.Add("Matthew");
191 	PeopleNames.Add("Mike");
192 	PeopleNames.Add("Paul");
193 	PeopleNames.Add("Rebecca");
194 	PeopleNames.Add("Richard");
195 	PeopleNames.Add("Sandra");
196 	PeopleNames.Add("Scott");
197 	PeopleNames.Add("Tanya");
198 	PeopleNames.Add("Terry");
199 	PeopleNames.Add("Tim");
200 	PeopleNames.Add("William");
201 
202 
203 	sfcMiniGameUnknown = LoadBitmap("minigame_unknown", 90, 90);
204 	MiniGames[BALLOONBLASTER] = new BPMiniGame_Container(BALLOONBLASTER, "balloonblaster", "Balloon Blaster!", LoadBitmap("minigame_balloonblaster", 90, 90), false);
205 	MiniGames[BOMBHUNT] = new BPMiniGame_Container(BOMBHUNT, "bombhunt", "Bomb Hunt", LoadBitmap("minigame_bombhunt", 90, 90), false);
206 	MiniGames[BPSAYS] = new BPMiniGame_Container(BPSAYS, "bpsays", "Brain Party says...", LoadBitmap("minigame_bpsays", 90, 90), false);
207 	MiniGames[BUBBLETROUBLE] = new BPMiniGame_Container(BUBBLETROUBLE, "bubbletrouble", "Bubble Trouble", LoadBitmap("minigame_bubbletrouble", 90, 90), false);
208 	MiniGames[CARDMATCH] = new BPMiniGame_Container(CARDMATCH, "cardmatch", "Card Match", LoadBitmap("minigame_cardmatch", 90, 90), false);
209 	MiniGames[CUPSNBALLS] = new BPMiniGame_Container(CUPSNBALLS, "cupsnballs", "Cups 'n' Balls", LoadBitmap("minigame_cupsnballs", 90, 90), false);
210 	MiniGames[CONNEX] = new BPMiniGame_Container(CONNEX, "connex", "Connex", LoadBitmap("minigame_connex", 90, 90), false);
211 	MiniGames[DICEOFF] = new BPMiniGame_Container(DICEOFF, "diceoff", "Dice Off", LoadBitmap("minigame_unknown", 90, 90), true);
212 	MiniGames[FLASHCOUNTING] = new BPMiniGame_Container(FLASHCOUNTING, "flashcounting", "Flash Counting", LoadBitmap("minigame_flashcounting", 90, 90), false);
213 	MiniGames[FLASHLIGHT] = new BPMiniGame_Container(FLASHLIGHT, "flashlight", "Flashlight", LoadBitmap("minigame_flashlight", 90, 90), false);
214 	MiniGames[IQTEST] = new BPMiniGame_Container(IQTEST, "iqtest", "IQ Test", LoadBitmap("minigame_iqtest", 90, 90), false);
215 	MiniGames[JEWELFLIP] = new BPMiniGame_Container(JEWELFLIP, "jewelflip", "Jewel Flip", LoadBitmap("minigame_jewelflip", 90, 90), false);
216 	MiniGames[JEWELJAM] = new BPMiniGame_Container(JEWELJAM, "jeweljam", "Jewel Jam", LoadBitmap("minigame_jeweljam", 90, 90), false);
217 	MiniGames[MARBLEDROP] = new BPMiniGame_Container(MARBLEDROP, "marbledrop", "Marble Drop", LoadBitmap("minigame_marbledrop", 90, 90), false);
218 	MiniGames[MEMORYBLOX] = new BPMiniGame_Container(MEMORYBLOX, "memoryblox", "MemoryBlox", LoadBitmap("minigame_memoryblox", 90, 90), false);
219 	MiniGames[MEMORYBOX] = new BPMiniGame_Container(MEMORYBOX, "memorybox", "Memory Box", LoadBitmap("minigame_memorybox", 90, 90), false);
220 	MiniGames[MEMORYMATHS] = new BPMiniGame_Container(MEMORYMATHS, "memorymaths", "Memory Maths", LoadBitmap("minigame_memorymaths", 90, 90), false);
221 	MiniGames[MINESWEEP] = new BPMiniGame_Container(MINESWEEP, "minesweep", "Mine Sweep", LoadBitmap("minigame_minesweep", 90, 90), false);
222 	MiniGames[MOONJUMP] = new BPMiniGame_Container(MOONJUMP, "moonjump", "Moon Jump", LoadBitmap("minigame_moonjump", 90, 90), false);
223 	MiniGames[NEXTINLINE] = new BPMiniGame_Container(NEXTINLINE, "nextinline", "Next in Line", LoadBitmap("minigame_nextinline", 90, 90), false);
224 	MiniGames[NUMBERSNAKE] = new BPMiniGame_Container(NUMBERSNAKE, "numbersnake", "Number Snake", LoadBitmap("minigame_numbersnake", 90, 90), false);
225 	MiniGames[ODDONEOUT] = new BPMiniGame_Container(ODDONEOUT, "oddoneout", "Odd One Out", LoadBitmap("minigame_oddoneout", 90, 90), false);
226 	MiniGames[PATCHMATCH] = new BPMiniGame_Container(PATCHMATCH, "patchmatch", "Patch Match", LoadBitmap("minigame_patchmatch", 90, 90), false);
227 	MiniGames[PERFECTPATHS] = new BPMiniGame_Container(PERFECTPATHS, "perfectpaths", "Perfect Paths", LoadBitmap("minigame_perfectpaths", 90, 90), false);
228 	MiniGames[ROUTEFINDER] = new BPMiniGame_Container(ROUTEFINDER, "routefinder", "Route Finder", LoadBitmap("minigame_routefinder", 90, 90), false);
229 	MiniGames[RPS] = new BPMiniGame_Container(RPS, "rockpaperscissors", "Rock, Paper, Scissors", LoadBitmap("minigame_rps", 90, 90), false);
230 	MiniGames[SCRAMBLED] = new BPMiniGame_Container(SCRAMBLED, "scrambled", "Scrambled", LoadBitmap("minigame_scrambled", 90, 90), false);
231 	MiniGames[SETFINDER] = new BPMiniGame_Container(SETFINDER, "setfinder", "Set Finder", LoadBitmap("minigame_setfinder", 90, 90), false);
232 	MiniGames[SHARPSHOOTER] = new BPMiniGame_Container(SHARPSHOOTER, "sharpshooter", "Sharpshooter", LoadBitmap("minigame_sharpshooter", 90, 90), true);
233 	MiniGames[SHORTCIRCUITSUDOKU] = new BPMiniGame_Container(SHORTCIRCUITSUDOKU, "shortcircuitsudoku", "Short-circuit Sudoku", LoadBitmap("minigame_shortcircuitsudoku", 90, 90), false);
234 	MiniGames[SHUFFLEPUZZLER] = new BPMiniGame_Container(SHUFFLEPUZZLER, "shufflepuzzler", "Shuffle Puzzler", LoadBitmap("minigame_shufflepuzzler", 90, 90), true);
235 	MiniGames[STRANGERDANGER] = new BPMiniGame_Container(STRANGERDANGER, "strangerdanger", "Stranger Danger", LoadBitmap("minigame_unknown", 90, 90), true);
236 	MiniGames[SYMBOLICLOGIC] = new BPMiniGame_Container(SYMBOLICLOGIC, "symboliclogic", "Symbolic Logic", LoadBitmap("minigame_symboliclogic", 90, 90),  false);
237 	MiniGames[UNDERTHEHAT] = new BPMiniGame_Container(UNDERTHEHAT, "underthehat", "Under the Hat", LoadBitmap("minigame_underthehat", 90, 90), true);
238 	MiniGames[UNTANGLER] = new BPMiniGame_Container(UNTANGLER, "untangler", "Untangler", LoadBitmap("minigame_untangler", 90, 90), false);
239 	MiniGames[WORDSMASH] = new BPMiniGame_Container(WORDSMASH, "wordsmash", "Word Smash", LoadBitmap("minigame_unknown", 90, 90), true);
240 
241 	sfcLogo = LoadBitmap("brainparty", 312, 227);
242 	ShowingMessageBox = false;
243 	ShowingClearScores = false;
244 	sfcMessageBoxTitle = NULL;
245 	sfcMessageBoxText = NULL;
246 
247 	sfcTestStatus.Add(LoadBitmap("teststatus1", 320, 75));
248 	sfcTestStatus.Add(LoadBitmap("teststatus2", 320, 75));
249 	sfcTestStatus.Add(LoadBitmap("teststatus3", 320, 75));
250 	sfcTestStatus.Add(LoadBitmap("teststatus4", 320, 75));
251 	sfcTestStatus.Add(LoadBitmap("teststatus5", 320, 75));
252 
253 	sfcResults90[FAIL] = LoadBitmap("results_fail_90", 90, 90);
254 	sfcResults90[BRONZE] = LoadBitmap("results_bronze_90", 90, 90);
255 	sfcResults90[SILVER] = LoadBitmap("results_silver_90", 90, 90);
256 	sfcResults90[GOLD] = LoadBitmap("results_gold_90", 90, 90);
257 	sfcResults90[PLATINUM] = LoadBitmap("results_platinum_90", 90, 90);
258 
259 	sfcFirstRun = LoadBitmap("firstrun", 320, 480);
260 	sfcHelp = LoadBitmap("menu_help", 320, 480);
261 	sfcLoading = LoadBitmap("loading", 320, 480);
262 
263 	sfcOptions = LoadBitmap("menu_options", 320, 480);
264 	sfcOptionsSoundsOff = LoadBitmap("sound_off", 320, 48);
265 	sfcOptionsMusicOff = LoadBitmap("music_off", 320, 48);
266 
267 	sfcTestBackground = LoadBitmap("bg_test", 512, 512);
268 	sfcResultsBackground = LoadBitmap("bg_results", 512, 512);
269 	sfcResultsBackground2 = LoadBitmap("bg_results2", 320, 480);
270 	sfcHistoryBackground = LoadBitmap("history", 320, 480);
271 
272 	sfcMarathonMode = LoadBitmap("menu_marathonmode", 320, 480);
273 	sfcBrainBoost = LoadBitmap("menu_brainboost", 320, 480);
274 
275 	sfcBGObjectTypes.Add(LoadBitmap("emptycircle", 256, 256));
276 	sfcBGObjectTypes.Add(LoadBitmap("doubleemptycircle", 256, 256));
277 	sfcBGObjectTypes.Add(LoadBitmap("doublecircle", 256, 256));
278 	sfcBGObjectTypes.Add(LoadBitmap("circlering", 256, 256));
279 	sfcBGObjectTypes.Add(LoadBitmap("filledcircle", 256, 256));
280 
281 	sfcSecretLo = LoadBitmap("secret_lo", 71, 66);
282 	sfcSecretHi = LoadBitmap("secret_hi", 71, 66);
283 
284 	sfcStarTypes.Add(LoadBitmap("star_dark", 3, 3));
285 	sfcStarTypes.Add(LoadBitmap("star_medium", 3, 3));
286 	sfcStarTypes.Add(LoadBitmap("star_bright", 3, 3));
287 
288 	Sounds["baa"] = LoadSound("baa");
289 	Sounds["baa2"] = LoadSound("baa2");
290 	Sounds["baa3"] = LoadSound("baa3");
291 	Sounds["balloon_pop"] = LoadSound("balloon_pop");
292 	Sounds["beep_hi"] = LoadSound("beep_hi");
293 	Sounds["bubble"] = LoadSound("bubble");
294 	Sounds["card_flip"] = LoadSound("card_flip");
295 	Sounds["card_flip2"] = LoadSound("card_flip2");
296 	Sounds["click"] = LoadSound("click");
297 	Sounds["correct"] = LoadSound("correct");
298 	Sounds["down"] = LoadSound("down");
299 	Sounds["explosion"] = LoadSound("explosion");
300 	Sounds["gem_select"] = LoadSound("gem_select");
301 	Sounds["glass_break"] = LoadSound("glass_break");
302 	Sounds["gun1"] = LoadSound("gun1");
303 	Sounds["gun2"] = LoadSound("gun2");
304 	Sounds["happy_ring"] = LoadSound("happy_ring");
305 	Sounds["meow"] = LoadSound("meow");
306 	Sounds["mouse_click"] = LoadSound("mouse_click");
307 	Sounds["result"] = LoadSound("result");
308 	Sounds["slide"] = LoadSound("slide");
309 	Sounds["soft_boom"] = LoadSound("soft_boom");
310 	Sounds["swoosh_long"] = LoadSound("swoosh_long");
311 	Sounds["whack"] = LoadSound("whack");
312 	Sounds["wrong"] = LoadSound("wrong");
313 	Sounds["wrong2"] = LoadSound("wrong2");
314 	Sounds["wrong3"] = LoadSound("wrong3");
315 	Sounds["zap"] = LoadSound("zap");
316 
317 	PlaySound("mouse_click", true, false);
318 
319 	Music = NULL;
320 
321 	sfcMainMenu = LoadBitmap("menu_main", 320, 480);
322 	sfcPlayMenu = LoadBitmap("menu_play", 320, 480);
323 	sfcPractiseMenu = LoadBitmap("menu_practise", 320, 480);
324 	sfcPractiseMenuHider = LoadBitmap("menu_practise_hider", 134, 34);
325 	sfcProfessorTalk = LoadBitmap("professor_talk", 320, 480);
326 	sfcCredits = LoadBitmap("menu_credits", 320, 480);
327 
328 	sfcBottomBar = LoadBitmap("bottombar", 320, 64);
329 
330 	sfcQuitTest = LoadBitmap("quit_test", 320, 480);
331 
332 	sfcResultsFail = LoadBitmap("results_fail", 320, 480);
333 	sfcResultsBronze = LoadBitmap("results_bronze", 320, 480);
334 	sfcResultsSilver = LoadBitmap("results_silver", 320, 480);
335 	sfcResultsGold = LoadBitmap("results_gold", 320, 480);
336 	sfcResultsPlatinum = LoadBitmap("results_platinum", 320, 480);
337 
338 	sfcWhite = LoadBitmap("white", 64, 64);
339 
340 	sfcCorrect = LoadBitmap("correct", 320, 92);
341 	sfcWrong = LoadBitmap("wrong", 320, 92);
342 
343 	ActiveMiniGame = NULL;
344 
345 	LoadSettings();
346 
347 	if (FirstRun) {
348 		SetGameState(FIRST_RUN);
349 	} else {
350 		SetGameState(MAIN_MENU);
351 	}
352 
353 	PlayMusic("theme");
354 
355 
356 	// Hackage for stress testing!
357 
358 //	for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
359 //		for (int i = 0; i < 1000000; ++i) {
360 //			NSLog("Creating %", it->second->ShortName);
361 //			CreateMiniGame(UNTANGLER, false, true);
362 //			ActiveMiniGame->Start();
363 //		}
364 //	}
365 }
366 
Update(float elapsed)367 void BPGame::Update(float elapsed) {
368 	ElapsedSeconds = elapsed;
369 	ElapsedTickCount = floor(elapsed * 1000);
370 	TickCount += ElapsedTickCount;
371 
372 	if (ShowingMessageBox) {
373 		return;
374 	}
375 
376 	if (!GameStateJustChanged) {
377 		// some gamestates need to increment the animcounter - do that now!
378 		switch (GameState) {
379 			case MAIN_MENU_PLAY:
380 			case PLAY_MAIN_MENU:
381 			case PRACTISE_PROFESSOR:
382 			case MAIN_MENU_OPTIONS:
383 			case OPTIONS_MAIN_MENU:
384 			case PLAY_HISTORY:
385 			case HISTORY_CREDITS:
386 			case CREDITS_HISTORY:
387 			case HISTORY_PLAY:
388 			case TEST_RESULTS_PLAY:
389 			case MAIN_MENU_HELP:
390 			case HELP_MAIN_MENU:
391 				if (AnimCounter < 1.0f) {
392 					AnimCounter += 3.5f * elapsed;
393 					if (AnimCounter > 1.0f) {
394 						AnimCounter = 1.0f;
395 					}
396 				}
397 
398 				break;
399 
400 			case PLAY_PRACTISE:
401 			case PRACTISE_PLAY:
402 				if (AnimCounter < 1.0f) {
403 					AnimCounter += 3.5f * elapsed;
404 					if (AnimCounter > 1.0f) {
405 						AnimCounter = 1.0f;
406 					}
407 				}
408 
409 				// don't break - we need to execute the following one too!
410 
411 			case PRACTISE_MENU:
412 				if (PractiseAnimCounter < 1.0f) {
413 					PractiseAnimCounter += 3.5f * elapsed;
414 					if (PractiseAnimCounter > 1.0f) {
415 						PractiseAnimCounter = 1.0f;
416 					}
417 				}
418 
419 				break;
420 
421 			case TEST_STATUS:
422 				if (LastStateChange + 5000 < TickCount) {
423 					NextTest();
424 				}
425 
426 				if (LastBGObject + 1000 < TickCount) {
427 					BGObject* obj = new BGObject();
428 					obj->Scale = 0.0f;
429 					obj->Pos = BPPoint(RandomRange(0, 320), RandomRange(0, 480));
430 
431 					switch (RandomRange(0, 17)) {
432 					case 0:
433 					case 1:
434 					case 2:
435 					case 3:
436 					case 4:
437 					case 5:
438 					case 6:
439 					case 7:
440 						obj->Type = sfcBGObjectTypes[0];
441 						break;
442 
443 					case 8:
444 					case 9:
445 					case 10:
446 					case 11:
447 						obj->Type = sfcBGObjectTypes[1];
448 						break;
449 
450 					case 12:
451 					case 13:
452 					case 14:
453 						obj->Type = sfcBGObjectTypes[2];
454 						break;
455 
456 					case 15:
457 					case 16:
458 						obj->Type = sfcBGObjectTypes[3];
459 						break;
460 
461 					default:
462 						obj->Type = sfcBGObjectTypes[4];
463 						break;
464 					}
465 
466 					BackgroundObjects.Add(obj);
467 					LastBGObject = TickCount;
468 				}
469 
470 
471 				for (int i = BackgroundObjects.Count - 1; i >= 0; --i) {
472 					BackgroundObjects[i]->Scale += 0.3f * ElapsedSeconds;
473 
474 					if (BackgroundObjects[i]->Scale >= 1.0f) {
475 						BackgroundObjects.RemoveAt(i);
476 					}
477 				}
478 
479 
480 				break;
481 
482 			case TEST_RESULTS:
483 				for (int i = 0; i < TestResultContainers.Count; ++i) {
484 					TestResultContainer* result = TestResultContainers[i];
485 
486 					if (result->GoingUp) {
487 						result->FadeUpAnim += 0.2f * ElapsedSeconds;
488 						if (result->FadeUpAnim > 1.0f) {
489 							result->FadeUpAnim = 1.0f;
490 							result->GoingUp = false;
491 						}
492 					} else {
493 						result->FadeUpAnim -= 0.4f * ElapsedSeconds;
494 						if (result->FadeUpAnim < -1.0f) {
495 							result->FadeUpAnim = -1.0f;
496 							result->GoingUp = true;
497 						}
498 					}
499 				}
500 
501 				break;
502 
503 		}
504 	} else {
505 		GameStateJustChanged = false; // we skipped our animcounter update - now continue as normal
506 	}
507 
508 	switch (GameState) {
509 		case PLAY_PRACTISE:
510 		case PRACTISE_PLAY:
511 			if (AnimCounter == 1.0f) {
512 				if (GameState == PLAY_PRACTISE) {
513 					SetGameState(PRACTISE_MENU);
514 				} else {
515 					SetGameState(PLAY_MENU);
516 				}
517 			}
518 			// don't break - we need to update the practise screen behind the scenes too
519 
520 		case PRACTISE_MENU:
521 				for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
522 					it->second->X = SmoothStep(it->second->StartX, it->second->DestX, PractiseAnimCounter);
523 					it->second->Y = SmoothStep(it->second->StartY, it->second->DestY, PractiseAnimCounter);
524 				}
525 
526 				break;
527 
528 		case PLAYING:
529 			ActiveMiniGame->TickMiniGame();
530 			break;
531 
532 		case MAIN_MENU_PLAY:
533 			if (AnimCounter == 1.0f) SetGameState(PLAY_MENU);
534 			break;
535 
536 		case PLAY_MAIN_MENU:
537 			if (AnimCounter == 1.0f) SetGameState(MAIN_MENU);
538 			break;
539 
540 		case PLAY_HISTORY:
541 			if (AnimCounter == 1.0f) SetGameState(HISTORY);
542 			break;
543 
544 		case HISTORY_CREDITS:
545 			if (AnimCounter == 1.0f) SetGameState(CREDITS);
546 			break;
547 
548 		case CREDITS_HISTORY:
549 			if (AnimCounter == 1.0f) SetGameState(HISTORY);
550 			break;
551 
552 		case HISTORY_PLAY:
553 			if (AnimCounter == 1.0f) SetGameState(PLAY_MENU);
554 			break;
555 
556 		case PRACTISE_PROFESSOR:
557 			if (AnimCounter == 1.0f) SetGameState(PROFESSOR);
558 			break;
559 
560 		case MAIN_MENU_OPTIONS:
561 			if (AnimCounter == 1.0f) SetGameState(OPTIONS);
562 			break;
563 
564 		case OPTIONS_MAIN_MENU:
565 			if (AnimCounter == 1.0f) SetGameState(MAIN_MENU);
566 			break;
567 
568 		case TEST_RESULTS_PLAY:
569 			if (AnimCounter == 1.0f) SetGameState(PLAY_MENU);
570 			break;
571 
572 		case MAIN_MENU_HELP:
573 			if (AnimCounter == 1.0f) SetGameState(HELP);
574 			break;
575 
576 		case HELP_MAIN_MENU:
577 			if (AnimCounter == 1.0f) SetGameState(MAIN_MENU);
578 			break;
579 	}
580 }
581 
Draw()582 void BPGame::Draw() {
583 	Clear(Black);
584 
585 	switch (GameState) {
586 		case FIRST_RUN:
587 			sfcFirstRun->Draw(0, 0);
588 			break;
589 
590 		case MAIN_MENU:
591 			RenderMainMenu(0, 0);
592 			break;
593 
594 		case MAIN_MENU_PLAY:
595 			{
596 				float offval = SmoothStep(0, -320, AnimCounter);
597 				float onval = SmoothStep(320, 0, AnimCounter);
598 
599 				RenderMainMenu(offval, 0.0f);
600 				RenderPlayMenu(onval, 0.0f);
601 			}
602 
603 			break;
604 
605 		case PLAY_MAIN_MENU:
606 			{
607 				float offval = SmoothStep(-320, 0, AnimCounter);
608 				float onval = SmoothStep(0, 320, AnimCounter);
609 
610 				RenderMainMenu(offval, 0.0f);
611 				RenderPlayMenu(onval, 0.0f);
612 			}
613 
614 			break;
615 
616 		case PLAY_HISTORY:
617 			{
618 				float offval = SmoothStep(0, -480, AnimCounter);
619 				float onval = SmoothStep(480, 0, AnimCounter);
620 
621 				RenderPlayMenu(0.0f, offval);
622 				RenderHistory(0.0f, onval);
623 			}
624 
625 			break;
626 
627 		case HISTORY_CREDITS:
628 			{
629 				float offval = SmoothStep(0, -480, AnimCounter);
630 				float onval = SmoothStep(480, 0, AnimCounter);
631 
632 				RenderHistory(0.0f, offval);
633 				RenderCredits(0.0f, onval);
634 			}
635 
636 			break;
637 
638 		case CREDITS_HISTORY:
639 			{
640 				float offval = SmoothStep(0, 480, AnimCounter);
641 				float onval = SmoothStep(-480, 0, AnimCounter);
642 
643 				RenderCredits(0.0f, offval);
644 				RenderHistory(0.0f, onval);
645 			}
646 
647 			break;
648 
649 		case HISTORY_PLAY:
650 			{
651 				float offval = SmoothStep(0, 480, AnimCounter);
652 				float onval = SmoothStep(-480, 0, AnimCounter);
653 
654 				RenderHistory(0.0f, offval);
655 				RenderPlayMenu(0.0f, onval);
656 			}
657 
658 			break;
659 
660 		case MAIN_MENU_OPTIONS:
661 			RenderOptionsMenu();
662 
663 			glColor4f(1.0f, 1.0f, 1.0f, 1 - AnimCounter);
664 			RenderMainMenu(0.0f, 0.0f);
665 			glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
666 
667 			break;
668 
669 		case OPTIONS_MAIN_MENU:
670 			RenderMainMenu(0.0f, 0.0f);
671 
672 			glColor4f(1.0f, 1.0f, 1.0f, 1 - AnimCounter);
673 			RenderOptionsMenu();
674 			glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
675 
676 			break;
677 
678 		case MAIN_MENU_HELP:
679 		{
680 			float onval = SmoothStep(480, 0, AnimCounter);
681 
682 			RenderMainMenu(0.0f, 0.0f);
683 			RenderHelp(0.0f, onval);
684 		}
685 
686 			break;
687 
688 		case HELP_MAIN_MENU:
689 		{
690 			float offval = SmoothStep(0, 480, AnimCounter);
691 
692 			RenderMainMenu(0.0f, 0.0f);
693 			RenderHelp(0.0f, offval);
694 		}
695 
696 			break;
697 
698 		case TEST_RESULTS_PLAY:
699 			{
700 				float offval = SmoothStep(0, 480, AnimCounter);
701 				float onval = SmoothStep(-480, 0, AnimCounter);
702 
703 				RenderTestResults(0.0f, offval);
704 				RenderPlayMenu(0.0f, onval);
705 			}
706 
707 			break;
708 
709 		case PLAY_MENU:
710 			RenderPlayMenu(0.0f, 0.0f);
711 			break;
712 
713 		case PRACTISE_PLAY:
714 			RenderPractiseMenu();
715 
716 			glColor4f(1.0f, 1.0f, 1.0f, AnimCounter);
717 			RenderPlayMenu(0.0f, 0.0f);
718 			glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
719 
720 			break;
721 
722 		case PLAY_PRACTISE:
723 			RenderPractiseMenu();
724 
725 			glColor4f(1.0f, 1.0f, 1.0f, 1 - AnimCounter);
726 			RenderPlayMenu(0.0f, 0.0f);
727 			glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
728 
729 			break;
730 
731 		case PRACTISE_MENU:
732 			RenderPractiseMenu();
733 			break;
734 
735 		case PROFESSOR:
736 			RenderProfessor();
737 			break;
738 
739 		case PRACTISE_PROFESSOR:
740 			RenderPractiseMenu();
741 
742 			glColor4f(1.0f, 1.0f, 1.0f, AnimCounter);
743 			RenderProfessor();
744 			glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
745 			break;
746 
747 		case PLAYING:
748 			RenderPlaying();
749 			break;
750 
751 		case TEST_STATUS:
752 			RenderTestStatus();
753 			break;
754 
755 		case TEST_RESULTS:
756 			RenderTestResults(0.0f, 0.0f);
757 			break;
758 
759 		case OPTIONS:
760 			RenderOptionsMenu();
761 			break;
762 
763 		case HISTORY:
764 			RenderHistory(0.0f, 0.0f);
765 			break;
766 
767 		case BRAINBOOST:
768 			RenderBrainBoost();
769 			break;
770 
771 		case MARATHON:
772 			RenderMarathon();
773 			break;
774 
775 		case CREDITS:
776 			RenderCredits(0.0f, 0.0f);
777 			break;
778 
779 		case HELP:
780 			RenderHelp(0.0f, 0.0f);
781 			break;
782 	}
783 
784 	if (ShowingMessageBox) {
785 		FillRectangle(Colour(0.0f, 0.0f, 0.0f, 0.85f), 0, 0, 320, 480);
786 
787 		Colour col = Colour(1.0f, 1.0f, 1.0f, 1.0f);
788 		sfcLogo->Draw(160, 90, 0.0f, 0.6f, col);
789 		sfcMessageBoxTitle->drawAtPoint(0, 170);
790 
791 		glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
792 		sfcMessageBoxText->drawAtPoint(10, 205);
793 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
794 	}
795 }
796 
LoadBitmap(const char * filename,int actualwidth,int actualheight)797 Texture* BPGame::LoadBitmap(const char*	 filename, int actualwidth, int actualheight) {
798 	return new Texture(filename, actualwidth, actualheight);
799 }
800 
AddTestScore(int score)801 void BPGame::AddTestScore(int score) {
802 	if (InTestMode) {
803 		TestScores.Add(score);
804 
805 		if (TestScores.Count == TestMiniGames.Count) {
806 			// that was the last game in this test run!
807 			CalculateTestResults();
808 			SetGameState(TEST_RESULTS);
809 			InTestMode = false;
810 			PlayMusic("results");
811 		} else {
812 			SetGameState(TEST_STATUS);
813 		}
814 	}
815 }
816 
FillRectangle(Colour col,float x,float y,float width,float height)817 void BPGame::FillRectangle(Colour col, float x, float y, float width, float height) {
818 	glColor4f(col.R, col.G, col.B, col.A);
819 	sfcWhite->Draw(x, y, width, height);
820 	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
821 }
822 
DrawImage(Texture * tex,float x,float y)823 void BPGame::DrawImage(Texture* tex, float x, float y) {
824 	tex->Draw(x, y);
825 }
826 
DrawImage(Texture * tex,float x,float y,Colour & col)827 void BPGame::DrawImage(Texture* tex, float x, float y, Colour &col) {
828 	tex->Draw(x, y, col);
829 }
830 
831 
DrawImage(Texture * tex,float x,float y,float rotation,float scale,Colour & col)832 void BPGame::DrawImage(Texture* tex, float x, float y, float rotation, float scale, Colour &col) {
833 	tex->Draw(x, y, rotation, scale, col);
834 }
835 
Clear(Colour * col)836 void BPGame::Clear(Colour* col) {
837 	glClearColor(col->R, col->G, col->B, col->A);
838 	glClear(GL_COLOR_BUFFER_BIT);
839 }
840 
PointOverRect(int x1,int y1,int x2,int y2,int width,int height)841 bool BPGame::PointOverRect(int x1, int y1, int x2, int y2, int width, int height) {
842 	if (x1 >= x2 && x1 <= x2 + width) {
843 		if (y1 >= y2 && y1 <= y2 + height) {
844 			return true;
845 		}
846 	}
847 
848 	return false;
849 }
850 
RectOverRect(int x1,int y1,int width1,int height1,int x2,int y2,int width2,int height2)851 bool BPGame::RectOverRect(int x1, int y1, int width1, int height1, int x2, int y2, int width2, int height2) {
852 	if (x1 + width1 < x2) return false;
853 	if (x1 > x2 + width2) return false;
854 	if (y1 + height1 < y2) return false;
855 	if (y1 > y2 + height2) return false;
856 
857 	return true;
858 }
859 
TouchStart(float x,float y)860 void BPGame::TouchStart(float x, float y) {
861 	if (ShowingMessageBox) {
862 		return;
863 	}
864 
865 	TouchEvent.X = x;
866 	TouchEvent.Y = y;
867 
868 	switch (GameState) {
869 		case PLAYING:
870 			if (ActiveMiniGame != NULL) {
871 				ActiveMiniGame->HandleMouseDown(TouchEvent);
872 			}
873 
874 			break;
875 	}
876 }
877 
TouchStop(float x,float y)878 void BPGame::TouchStop(float x, float y) {
879 	if (ShowingMessageBox) {
880 		ShowingMessageBox = false;
881 		ShowingClearScores = false;
882 		return;
883 	}
884 
885 	TouchEvent.X = x;
886 	TouchEvent.Y = y;
887 
888 	switch (GameState) {
889 		case FIRST_RUN:
890 			SetGameState(MAIN_MENU);
891 			PlaySound("mouse_click");
892 			break;
893 
894 		case MAIN_MENU:
895 			if (PointOverRect(TouchEvent.X, TouchEvent.Y, 37, 207, 248, 78)) {
896 				SetGameState(MAIN_MENU_PLAY);
897 				PlaySound("mouse_click");
898 			} else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 22, 309, 272, 58)) {
899 				SetGameState(MAIN_MENU_OPTIONS);
900 				PlaySound("mouse_click");
901 			} else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 73, 370, 170, 58)) {
902 				SetGameState(MAIN_MENU_HELP);
903 				PlaySound("mouse_click");
904 			} else if (TouchEvent.Y < 207) {
905 				++CheatMainTaps;
906 			}
907 
908 			break;
909 
910 		case PLAY_MENU:
911 			if (PointOverRect(TouchEvent.X, TouchEvent.Y, 0, 48, 320, 128)) {
912 				if (AllTestScores.Count == 0) {
913 					MessageBox::Show("Once you have completed your first test, this will show your brain weight.", "Brain weight");
914 				} else {
915 					MessageBox::Show("This is your current brain weight, as measured by the last test you did.", "Brain weight");
916 				}
917 			} else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 16, 192, 288, 48)) {
918 				RunTest();
919 			} else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 15, 252, 289, 48)) {
920 				if (NumUnlockedGames > 0) {
921 					SetGameState(PLAY_PRACTISE);
922 					PlaySound("mouse_click");
923 				} else {
924 					MessageBox::Show("You can't practise any games until you have completed at least one test. Go on, it won't take long!", "No games to practise");
925 				}
926 			} else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 28, 312, 264, 48)) {
927 				SetGameState(PLAY_HISTORY);
928 				PlaySound("mouse_click");
929 			} else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 74, 410, 172, 48)) {
930 				SetGameState(PLAY_MAIN_MENU);
931 				PlaySound("mouse_click");
932 			}
933 			break;
934 
935 		case PRACTISE_MENU:
936 			if (PointOverRect(TouchEvent.X, TouchEvent.Y, 91, 437, 137, 27)) {
937 				SetGameState(PRACTISE_PLAY);
938 				PlaySound("mouse_click");
939 			} else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 15, 384, 134, 34)) {
940 				// back
941 				if (PractiseAnimCounter == 1.0f) {
942 					if (PractisePageNumber != 0) {
943 						PractisePageNumber -= 9;
944 						if (PractisePageNumber < 0) PractisePageNumber = 0;
945 						PractisePageMoveLeft = false;
946 						PositionPractiseGames();
947 						PlaySound("mouse_click");
948 					}
949 				}
950 			} else if (PointOverRect(TouchEvent.X, TouchEvent.Y, 173, 383, 134, 34)) {
951 				// more
952 				if (PractiseAnimCounter == 1.0f) {
953 					if (PractisePageNumber + 9 < NumUnlockedGames) {
954 						PractisePageNumber += 9;
955 						PractisePageMoveLeft = true;
956 						PositionPractiseGames();
957 						PlaySound("mouse_click");
958 					}
959 				}
960 			} else {
961 				// did the player ask to play a minigame?
962 				int i = 0;
963 				int j = 0;
964 				int xpos = 0;
965 
966 				for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
967 					if (it->second->IsSecret) continue;
968 					if (!it->second->Unlocked) continue;
969 
970 					if (i < PractisePageNumber) {
971 						++i;
972 						continue;
973 					}
974 
975 					xpos = i - PractisePageNumber;
976 
977 					y = 75 + (xpos * 100);
978 					x = 15 + (j * 100);
979 
980 					if (PointOverRect(TouchEvent.X, TouchEvent.Y, x, y, 90, 90)) {
981 						if (it->second->Unlocked) {
982 							PlaySound("mouse_click");
983 							CreateMiniGame((MiniGameType)it->second->GameCode, false, true);
984 						}
985 
986 						break;
987 					}
988 
989 					++j;
990 
991 					if (j == 3) {
992 						j = 0;
993 						++i;
994 					}
995 
996 					if (i > PractisePageNumber + 2) break;
997 				}
998 			}
999 			break;
1000 
1001 		case PROFESSOR:
1002 			ActiveMiniGame->PlayMusic();
1003 			ActiveMiniGame->Start();
1004 			SetGameState(PLAYING);
1005 			break;
1006 
1007 		case PLAYING:
1008 			ActiveMiniGame->HandleMouseUp(TouchEvent);
1009 			break;
1010 
1011 		case TEST_STATUS:
1012 			NextTest();
1013 			break;
1014 
1015 		case TEST_RESULTS:
1016 			if (LastStateChange + 1600 < TickCount) {
1017 				SetGameState(TEST_RESULTS_PLAY);
1018 				PlayMusic("theme");
1019 			}
1020 
1021 			break;
1022 
1023 		case OPTIONS:
1024 			if (PointOverRect(x, y, 21, 193, 277, 39)) {
1025 				EnableSound = !EnableSound;
1026 				PlaySound("click", false, true);
1027 				SaveSettings();
1028 			} else if (PointOverRect(x, y, 29, 259, 262, 37)) {
1029 				EnableMusic = !EnableMusic;
1030 				PlaySound("click");
1031 
1032 				if (EnableMusic == false) {
1033 					StopMusic();
1034 				} else {
1035 					PlayMusic("theme");
1036 				}
1037 
1038 				SaveSettings();
1039 			} else if (PointOverRect(x, y, 15, 353, 290, 31)) {
1040 				PromptResetScores();
1041 				PlaySound("click");
1042 
1043 			} else if (PointOverRect(x, y, 0, 416, 320, 64)) {
1044 				SetGameState(OPTIONS_MAIN_MENU);
1045 				PlaySound("mouse_click");
1046 			} else if (TouchEvent.Y < 193) {
1047 				++CheatOptionsTaps;
1048 			}
1049 
1050 			break;
1051 
1052 		case HISTORY:
1053 			if (PointOverRect(x, y, 17, 45, 285, 161)) {
1054 				MessageBox::Show("This graph shows your most recent test results.", "Your test history");
1055 			} else if (PointOverRect(x, y, 21, 251, 285, 57)) {
1056 				MessageBox::Show("This is the highest brain weight you have scored in any test. Each minigame is worth up to 500g, and you get five in a test, so the maximum brain weight is 2500g.", "Highest Brain Weight");
1057 			} else if (PointOverRect(x, y, 0, 349, 74, 66)) {
1058 				if (Secret1) {
1059 					CreateMiniGame(DICEOFF, false, false);
1060 				} else {
1061 					MessageBox::Show("This secret game is unlocked when you get a Platinum score in Balloon Blaster.", "Secret locked!");
1062 				}
1063 			} else if (PointOverRect(x, y, 82, 349, 74, 66)) {
1064 				if (Secret2) {
1065 					CreateMiniGame(WORDSMASH, false, false);
1066 				} else {
1067 					MessageBox::Show("This secret game is unlocked when you get a Platinum score in Jewel Jam.", "Secret locked!");
1068 				}
1069 			} else if (PointOverRect(x, y, 162, 349, 74, 66)) {
1070 				if (Secret3) {
1071 					SetGameState(MARATHON);
1072 					PlaySound("mouse_click");
1073 				} else {
1074 					MessageBox::Show("This secret area is unlocked when you get a Platinum score in Odd One Out.", "Secret locked!");
1075 				}
1076 			} else if (PointOverRect(x, y, 245, 349, 74, 66)) {
1077 				if (Secret4) {
1078 					SetGameState(BRAINBOOST);
1079 					PlaySound("mouse_click");
1080 				} else {
1081 					MessageBox::Show("This secret area is unlocked when you get a Platinum score in Untangler.", "Secret locked!");
1082 				}
1083 			} else if (PointOverRect(x, y, 2, 418, 110, 54)) {
1084 				SetGameState(HISTORY_PLAY);
1085 				PlaySound("mouse_click");
1086 			} else if (PointOverRect(x, y, 182, 418, 136, 54)) {
1087 				SetGameState(HISTORY_CREDITS);
1088 				PlaySound("mouse_click");
1089 			}
1090 
1091 			break;
1092 
1093 		case CREDITS:
1094 			if (PointOverRect(x, y, 193, 203, 126, 148)) {
1095 				// clicked on the professor!
1096 				if (CheatMainTaps >= 5 && CheatOptionsTaps >= 5) {
1097 					MessageBox::Show("Hey, it looks like you activated the cheat code - all the minigames and secrets have been unlocked. We hope you're proud of yourself!", "Cheat activated!");
1098 
1099 					for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
1100 						it->second->Unlocked = true;
1101 					}
1102 
1103 					Secret1 = Secret2 = Secret3 = Secret4 = true;
1104 
1105 					SaveSettings();
1106 
1107 					PlaySound("meow");
1108 				}
1109 			}
1110 
1111 			SetGameState(CREDITS_HISTORY);
1112 			PlaySound("mouse_click");
1113 			break;
1114 
1115 		case MARATHON:
1116 			if (PointOverRect(x, y, 12, 201, 90, 90)) {
1117 				CreateMiniGame(BALLOONBLASTER, true, false);
1118 			} else if (PointOverRect(x, y, 116, 201, 90, 90)) {
1119 				CreateMiniGame(BPSAYS, true, false);
1120 			} else if (PointOverRect(x, y, 220, 201, 90, 90)) {
1121 				CreateMiniGame(JEWELJAM, true, false);
1122 			} else if (PointOverRect(x, y, 12, 305, 90, 90)) {
1123 				CreateMiniGame(SHORTCIRCUITSUDOKU, true, false);
1124 			} else if (PointOverRect(x, y, 116, 305, 90, 90)) {
1125 				CreateMiniGame(SYMBOLICLOGIC, true, false);
1126 			} else if (PointOverRect(x, y, 220, 305, 90, 90)) {
1127 				CreateMiniGame(UNTANGLER, true, false);
1128 			} else if (PointOverRect(x, y, 0, 423, 320, 64)) {
1129 				SetGameState(HISTORY);
1130 				PlaySound("mouse_click");
1131 			}
1132 
1133 			break;
1134 
1135 		case BRAINBOOST:
1136 			if (PointOverRect(x, y, 53, 184, 90, 90)) {
1137 				CreateMiniGame(SHARPSHOOTER, true, false);
1138 			} else if (PointOverRect(x, y, 179, 184, 90, 90)) {
1139 				CreateMiniGame(SHUFFLEPUZZLER, true, false);
1140 			} else if (PointOverRect(x, y, 53, 305, 90, 90)) {
1141 				CreateMiniGame(STRANGERDANGER, true, false);
1142 			} else if (PointOverRect(x, y, 179, 305, 90, 90)) {
1143 				CreateMiniGame(UNDERTHEHAT, true, false);
1144 			} else if (PointOverRect(x, y, 0, 423, 320, 64)) {
1145 				SetGameState(HISTORY);
1146 				PlaySound("mouse_click");
1147 			}
1148 
1149 			break;
1150 
1151 		case HELP:
1152 			SetGameState(HELP_MAIN_MENU);
1153 			PlaySound("mouse_click");
1154 			break;
1155 	}
1156 }
1157 
TouchDrag(float x,float y)1158 void BPGame::TouchDrag(float x, float y) {
1159 	if (ShowingMessageBox) {
1160 		return;
1161 	}
1162 
1163 	TouchEvent.X = x;
1164 	TouchEvent.Y = y;
1165 
1166 	switch (GameState) {
1167 		case PLAYING:
1168 			if (ActiveMiniGame != NULL) {
1169 				ActiveMiniGame->HandleMouseMove(TouchEvent);
1170 			}
1171 
1172 			break;
1173 	}
1174 }
1175 
TrimString(const std::string & str)1176 const string TrimString(const std::string& str) {
1177 	string::size_type First = str.find_first_not_of( ' ' );
1178 
1179 	if (First == string::npos) {
1180 		First = 0;
1181 	}
1182 
1183 	string::size_type Last = str.find_last_not_of( ' ' );
1184 	if (Last != string::npos) {
1185 		Last = (Last + 1) - First;
1186 	}
1187 
1188   	return str.substr(First, Last);
1189 }
1190 
1191 
AllocString(SpriteFont ** tex,const char * str,FontSizes size,float width,float height,Alignments align,bool bold)1192 void BPGame::AllocString(SpriteFont** tex, const char* str, FontSizes size, float width, float height, Alignments align, bool bold) {
1193 	SAFE_DELETE((*tex));
1194 
1195 	// it's incredibly lazy to open and close the font each time - hurray!
1196 	TTF_Font* fnt = TTF_OpenFont("/usr/local/share/brainparty/freesans.ttf", size - 3); // NB: the -3 is here because the freesans.ttf font we're using is a big chunkier than the iPhone font
1197 
1198 	static SDL_Color white = { 255, 255, 255, 255 };
1199 
1200 	vector<string> lines; // we'll store the split lines here
1201 	string temp(str); // the current text we're working on
1202 	temp += " ";  // always add a space to the end of the text to enable wrapping - this gets removed later
1203 	int n = 0; // current index
1204 	int p = 0; // previous space
1205 
1206 	while (n != -1) {
1207 		std::string strSub;
1208 		n = temp.find(" ", p + 1 );		// -- Find the next " "
1209 
1210 		std::string line_so_far = temp.substr(0, n);
1211 		int w,h;
1212 
1213 		const char* c_str = line_so_far.c_str();
1214 		TTF_SizeText(fnt, c_str, &w, &h);
1215 
1216 		if (w >= width)	{
1217 			strSub = temp.substr(0, p);
1218 			lines.push_back(strSub);
1219 
1220 			if (n != -1) temp = temp.substr( p+1, string::npos );
1221 			p = 0;
1222 		} else {
1223 			p = n;
1224 		}
1225 	}
1226 
1227 	// do the last line too
1228 	string strSub = temp.substr(0, p);
1229 	lines.push_back(strSub);
1230 
1231 
1232 	// create a SpriteFont to hold all the information - this is used for drawing later
1233 	(*tex) = new SpriteFont();
1234 	(*tex)->Width = width;
1235 	(*tex)->Height = height;
1236 	(*tex)->Align = align;
1237 
1238 	// render all the text
1239 	for (int i = 0; i < lines.size(); ++i) {
1240 		SDL_Surface* sfc = TTF_RenderText_Blended(fnt, TrimString(lines[i]).c_str(), white);
1241 
1242 		if (sfc != NULL) {
1243 			(*tex)->Surfaces.Add(new Texture(sfc));
1244 			SDL_FreeSurface(sfc);
1245 		}
1246 	}
1247 
1248 	TTF_CloseFont(fnt);
1249 }
1250 
DrawString(SpriteFont * tex,Colour & col,float x,float y)1251 void BPGame::DrawString(SpriteFont* tex, Colour &col, float x, float y) {
1252 	if (tex == NULL) return;
1253 
1254 	glColor4f(col.R, col.G, col.B, col.A);
1255 	tex->drawAtPoint(x,y);
1256 	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1257 }
1258 
DrawString(SpriteFont * tex,Colours col,float x,float y)1259 void BPGame::DrawString(SpriteFont* tex, Colours col, float x, float y) {
1260 	if (tex == NULL) return;
1261 
1262 	if (col == WHITE) {
1263 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1264 	} else if (col == BLACK) {
1265 		glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1266 	}
1267 
1268 	tex->drawAtPoint(x,y);
1269 
1270 	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1271 }
1272 
DrawString(SpriteFont * tex,float x,float y)1273 void BPGame::DrawString(SpriteFont* tex, float x, float y) {
1274 	if (tex == NULL) return;
1275 
1276 	tex->drawAtPoint(x,y);
1277 }
1278 
RandomRange(int min,int max)1279 int BPGame::RandomRange(int min, int max) {
1280 	if (max < min) return min;
1281 
1282 	int value = rand();
1283 	return (value % ((max - min) + 1) + min);
1284 }
1285 
RandomRangeExcept(int min,int max,int except)1286 int BPGame::RandomRangeExcept(int min, int max, int except) {
1287 	int val = RandomRange(min, max);
1288 
1289 	while (val == except) {
1290 		val = RandomRange(min, max);
1291 	}
1292 
1293 	return val;
1294 }
1295 
LoadSettings()1296 void BPGame::LoadSettings() {
1297 	Secret1 = Secret2 = Secret3 = Secret4 = false;
1298 	NumUnlockedGames = 0;
1299 
1300 	ifstream ifs;
1301 	ifs.open((string(getenv("HOME")) + "/.brainparty").c_str());
1302 
1303 	FirstRun = false;
1304 
1305 	if (ifs.is_open()) {
1306 		string temp;
1307 
1308 		int loading_stage = 0;
1309 		int line_number = 0;
1310 		int secret_num = 1;
1311 
1312 		while (getline(ifs, temp)) {
1313 			++line_number;
1314 
1315 			if (temp.size() == 0) {
1316 				++loading_stage;
1317 			} else {
1318 				switch (loading_stage) {
1319 					case 0:
1320 						// loading whether we have music and sound
1321 						if (line_number == 1) {
1322 							if (temp.compare("1") == 0) {
1323 								EnableSound = true;
1324 							} else {
1325 								EnableSound = false;
1326 							}
1327 						} else {
1328 							if (temp.compare("1") == 0) {
1329 								EnableMusic = true;
1330 							} else {
1331 								EnableMusic = false;
1332 							}
1333 						}
1334 						break;
1335 
1336 					case 1:
1337 						// loading secrets
1338 						switch (secret_num) {
1339 							case 1:
1340 								if (temp.compare("1") == 0) {
1341 									Secret1 = true;
1342 								} else {
1343 									Secret1 = false;
1344 								}
1345 
1346 								break;
1347 
1348 							case 2:
1349 								if (temp.compare("1") == 0) {
1350 									Secret2 = true;
1351 								} else {
1352 									Secret2 = false;
1353 								}
1354 								break;
1355 
1356 							case 3:
1357 								if (temp.compare("1") == 0) {
1358 									Secret3 = true;
1359 								} else {
1360 									Secret3 = false;
1361 								}
1362 								break;
1363 
1364 							case 4:
1365 								if (temp.compare("1") == 0) {;
1366 
1367 									Secret4 = true;
1368 								} else {
1369 									Secret4 = false;
1370 								}
1371 								break;
1372 						}
1373 
1374 						++secret_num;
1375 
1376 						break;
1377 
1378 					case 2:
1379 					{
1380 						// loading test scores
1381 						CurrentBrainWeight = atoi(temp.c_str());
1382 						AllTestScores.Add(CurrentBrainWeight);
1383 
1384 						if (CurrentBrainWeight > HighestBrainWeight) {
1385 							HighestBrainWeight = CurrentBrainWeight;
1386 						}
1387 
1388 						break;
1389 					}
1390 
1391 
1392 					case 3:
1393 						const char* gamename = temp.c_str();
1394 
1395 						for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
1396 							if (it->second->IsSecret) continue;
1397 
1398 							if (strcmp(gamename, it->second->ShortName) == 0) {
1399 								it->second->Unlocked = true;
1400 								++NumUnlockedGames;
1401 								continue;
1402 							}
1403 						}
1404 
1405 						break;
1406 				}
1407 			}
1408 		}
1409 	} else {
1410 		FirstRun = true;
1411 	}
1412 
1413 	if (CurrentBrainWeight != -1) {
1414 		ostringstream output;
1415 		output << CurrentBrainWeight << "g";
1416 		AllocString(&sfcTestWeight, output.str().c_str(), BRAINWEIGHT, 320, 100, CENTRED, true);
1417 	} else {
1418 		AllocString(&sfcTestWeight, "???", BRAINWEIGHT, 320, 100, CENTRED, true);
1419 	}
1420 
1421 	if (HighestBrainWeight != -1) {
1422 		ostringstream output;
1423 		output << HighestBrainWeight << "g";
1424 		AllocString(&sfcHighestBrainWeight, output.str().c_str(), XXLARGE, 320, 100, CENTRED, true);
1425 	} else {
1426 		AllocString(&sfcHighestBrainWeight, "N/A", XXLARGE, 320, 100, CENTRED, true);
1427 	}
1428 }
1429 
SaveSettings()1430 void BPGame::SaveSettings() {
1431  	ofstream savefile;
1432  	savefile.open((string(getenv("HOME")) + "/.brainparty").c_str());
1433 	savefile << EnableSound << endl;
1434 	savefile << EnableMusic << endl;
1435 	savefile << endl;
1436 
1437 	savefile << Secret1 << endl;
1438 	savefile << Secret2 << endl;
1439 	savefile << Secret3 << endl;
1440 	savefile << Secret4 << endl;
1441 	savefile << endl;
1442 
1443 	for (int i = 0; i < AllTestScores.Count; ++i) {
1444 		savefile << AllTestScores[i] << endl;
1445 	}
1446 
1447 	savefile << endl;
1448 
1449 	for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
1450 		if (it->second->Unlocked) {
1451 			savefile << it->second->ShortName << endl;
1452 		}
1453 	}
1454 
1455  	savefile.close();
1456 
1457 	LoadSettings();
1458 }
1459 
SeparateThousands(int number)1460 string BPGame::SeparateThousands(int number) {
1461 	char buffer[20];
1462 
1463 	int i, digit, out_index = 0;
1464 
1465 	for (i = number; i != 0; i /= 10) {
1466 		digit = i % 10;
1467 
1468 		if ((out_index + 1) % 4 == 0) {
1469 			buffer[out_index++] = ',';
1470 		}
1471 
1472 		buffer[out_index++] = digit + '0';
1473 	}
1474 
1475 	buffer[out_index] = '\0';
1476 
1477 	string retval = string(buffer);
1478 	reverse(retval.begin(), retval.end());
1479 	return retval;
1480 }
1481 
TicksToTime(int ticks)1482 string* BPGame::TicksToTime(int ticks) {
1483 	int seconds_elapsed = floor(ticks / 1000);
1484 	int minutes = floor(seconds_elapsed / 60.0);
1485 	int seconds = seconds_elapsed % 60;
1486 
1487 	ostringstream output;
1488 
1489 	if (seconds < 10) {
1490 		output << minutes << ":0" << seconds;
1491 	} else {
1492 		output << minutes << ":" << seconds;
1493 	}
1494 
1495 	string* retval = new string(output.str());
1496 	return retval;
1497 }
1498 
DivRem(int Num,int Div,int * Rem)1499 int BPGame::DivRem(int Num, int Div, int* Rem) {
1500 	(*Rem) = Num % Div;
1501 	return floor(Num / Div);
1502 }
1503 
DrawLine(int fromx,int fromy,int tox,int toy,Colour * col,float width)1504 void BPGame::DrawLine(int fromx, int fromy, int tox, int toy, Colour* col, float width) {
1505 	GLfloat vertices[] = { fromx, fromy, tox, toy };
1506 
1507 	glDisable(GL_TEXTURE_2D);
1508 	glLineWidth(width);
1509 	glColor4f(col->R, col->G, col->B, col->A);
1510 	glLoadIdentity();
1511 
1512 	glVertexPointer(2, GL_FLOAT, 0, vertices);
1513 	glDrawArrays(GL_LINES, 0, 2);
1514 
1515 	glEnable(GL_TEXTURE_2D);
1516 	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1517 }
1518 
Clamp(float value,float minval,float maxval)1519 float BPGame::Clamp(float value, float minval, float maxval) {
1520 	if (value > maxval) {
1521 		value = maxval;
1522 	} else if (value < minval) {
1523 		value = minval;
1524 	}
1525 
1526 	return value;
1527 }
1528 
Hermite(float value1,float tangent1,float value2,float tangent2,float amount)1529 float BPGame::Hermite(float value1, float tangent1, float value2, float tangent2, float amount) {
1530 	float AmountSquared = amount * amount;
1531 	float AmountCubed = AmountSquared * amount;
1532 
1533 	float result = 0.0f;
1534 
1535 	if (amount == 0.0f) {
1536 		result = value1;
1537 	} else if (amount == 1.0f) {
1538 		result = value2;
1539 	} else {
1540 		result = (2 * value1 - 2 * value2 + tangent2 + tangent1) * AmountCubed + (3 * value2 - 3 * value1 - 2 * tangent1 - tangent2) * AmountSquared + tangent1 * amount + value1;
1541 	}
1542 
1543 	return result;
1544 }
1545 
Lerp(float value1,float value2,float amount)1546 float BPGame::Lerp(float value1, float value2, float amount) {
1547 	float result = Clamp(amount, 0.0f, 1.0f);
1548 	return value1 + (value2 - value1) * result;
1549 }
1550 
SmoothStep(float value1,float value2,float amount)1551 float BPGame::SmoothStep(float value1, float value2, float amount) {
1552 	float result = Clamp(amount, 0.0f, 1.0f);
1553 	result = Hermite(value1, 0.0, value2, 0.0, result);
1554 	return result;
1555 }
1556 
SmoothStep2(float value1,float value2,float amount)1557 float BPGame::SmoothStep2(float value1, float value2, float amount) {
1558 	float result = Clamp(amount, 0.0f, 1.0f);
1559 
1560 	if (result > 0.5f) {
1561 		result = Hermite(value2, 0.0f, value1, 0.0f, (result - 0.5f) * 2.0f);
1562 	} else {
1563 		result = Hermite(value1, 0.0f, value2, 0.0f, result * 2.0f);
1564 	}
1565 
1566 	return result;
1567 }
1568 
ColourSmoothStep(Colour & from,Colour & to,float amount)1569 Colour BPGame::ColourSmoothStep(Colour &from, Colour &to, float amount) {
1570 	return Colour(SmoothStep(from.R, to.R, amount), SmoothStep(from.G, to.G, amount), SmoothStep(from.B, to.B, amount), SmoothStep(from.A, to.A, amount));
1571 }
1572 
1573 
StartsWithVowel(string * word)1574 bool BPGame::StartsWithVowel(string* word) {
1575 	char chr = (*word)[0];
1576 	if (chr == 'a' || chr == 'e' || chr == 'i' || chr == 'o' || chr == 'u'){
1577 		return true;
1578 	}
1579 
1580 	return false;
1581 }
1582 
GetName()1583 const char* BPGame::GetName() {
1584 	return PeopleNames[RandomRange(0, PeopleNames.Count - 1)];
1585 }
1586 
RenderMainMenu(float xoff,float yoff)1587 void BPGame::RenderMainMenu(float xoff, float yoff) {
1588 	DrawImage(sfcMainMenu, xoff, yoff);
1589 }
1590 
RenderOptionsMenu()1591 void BPGame::RenderOptionsMenu() {
1592 	DrawImage(sfcOptions, 0, 0);
1593 
1594 	if (!EnableSound) {
1595 		DrawImage(sfcOptionsSoundsOff, 0, 188);
1596 	}
1597 
1598 	if (!EnableMusic) {
1599 		DrawImage(sfcOptionsMusicOff, 0, 254);
1600 	}
1601 }
1602 
RenderPlayMenu(float xoff,float yoff)1603 void BPGame::RenderPlayMenu(float xoff, float yoff) {
1604 	DrawImage(sfcPlayMenu, xoff, yoff);
1605 	DrawString(sfcTestWeight, xoff, yoff + 58.0f);
1606 }
1607 
RenderPractiseMenu()1608 void BPGame::RenderPractiseMenu() {
1609 	DrawImage(sfcPractiseMenu, 0, 0);
1610 
1611 	for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
1612 		if (!it->second->IsShowing) {
1613 			glColor4f(1.0f, 1.0f, 1.0f, 1.0f - PractiseAnimCounter);
1614 		}
1615 
1616 		if (it->second->Pic == NULL) {
1617 			DrawImage(sfcMiniGameUnknown, it->second->X, it->second->Y);
1618 		} else {
1619 			DrawImage(it->second->Pic, it->second->X, it->second->Y);
1620 		}
1621 
1622 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1623 	}
1624 
1625 	if (PractisePageNumber == 0) {
1626 		// hide Back
1627 		glColor4f(1.0f, 1.0f, 1.0f, 0.85f);
1628 		DrawImage(sfcPractiseMenuHider, 15, 384);
1629 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1630 	}
1631 
1632 	if (PractisePageNumber + 9 >= NumUnlockedGames) {
1633 		glColor4f(1.0f, 1.0f, 1.0f, 0.85f);
1634 		DrawImage(sfcPractiseMenuHider, 173, 383);
1635 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1636 	}
1637 }
1638 
RenderProfessor()1639 void BPGame::RenderProfessor() {
1640 	DrawImage(sfcProfessorTalk, 0, 0);
1641 
1642 	ActiveMiniGame->DrawProfessorText();
1643 }
1644 
RenderPlaying()1645 void BPGame::RenderPlaying() {
1646 	ActiveMiniGame->RenderMiniGame();
1647 }
1648 
RenderTestStatus()1649 void BPGame::RenderTestStatus() {
1650 	static float rotation = 0.0f;
1651 	rotation += 15 * ElapsedSeconds;
1652 
1653 	Clear(Black);
1654 	DrawImage(sfcTestBackground, 160.0f, 240.0f, rotation, 1.2f, (*White));
1655 	Colour col = Colour(1.0f, 1.0f, 1.0f, 0.2f);
1656 	DrawImage(sfcTestBackground, 160.0f, 240.0f, -rotation, 1.2f, col);
1657 
1658 	for (int i = 0; i < BackgroundObjects.Count; ++i) {
1659 		BGObject* obj = BackgroundObjects[i];
1660 
1661 		float alpha;
1662 
1663 		if (obj->Scale < 0.5f) {
1664 			// fading in
1665 			alpha = (obj->Scale / 2.5f);
1666 		} else {
1667 			// fading out
1668 			alpha = 0.4f - (obj->Scale / 2.5f);
1669 		}
1670 
1671 		alpha = Clamp(alpha, 0.0f, 1.0f);
1672 		Colour col = Colour(1.0f, 1.0f, 1.0f, alpha);
1673 
1674 		DrawImage(obj->Type, obj->Pos.X, obj->Pos.Y, 0.0f, obj->Scale, col);
1675 	}
1676 
1677 	DrawImage(sfcTestStatus[TestPosition], 0.0f, 208.0f);
1678 }
1679 
RenderTestResults(float xoff,float yoff)1680 void BPGame::RenderTestResults(float xoff, float yoff) {
1681 	if (LastStateChange + 200 > TickCount) {
1682 		// plain background
1683 		DrawImage(sfcResultsBackground, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, (*White));
1684 	} else if (LastStateChange + 1000 > TickCount) {
1685 		// fade in Your Brain Weighs text
1686 		DrawImage(sfcResultsBackground, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, (*White));
1687 		Colour col = Colour(1.0f, 1.0, 1.0f, 1 - (((LastStateChange + 1000) - TickCount) / 800.0f));
1688 		DrawImage(sfcResultsBackground2, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, col);
1689 	} else if (LastStateChange + 1600 > TickCount) {
1690 		// fade in brain weight
1691 		DrawImage(sfcResultsBackground2, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, (*White));
1692 		float alpha = 1 - (((LastStateChange + 1600) - TickCount) / 600.0f);
1693 
1694 		glColor4f(1.0f, 1.0f, 1.0f, alpha);
1695 		DrawString(sfcTestWeight, xoff + 0.0f, yoff + 93.0f);
1696 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1697 	} else {
1698 		// show everything
1699 		DrawImage(sfcResultsBackground2, xoff + 160.0f, yoff + 240.0f, 0.0f, 1.0f, (*White));
1700 		DrawString(sfcTestWeight, xoff + 0.0f, yoff + 93.0f);
1701 		DrawString(sfcTestJob, xoff + 0.0f, yoff + 200.0f);
1702 	}
1703 
1704 	float diff = 1 - (((LastStateChange + 500) - TickCount) / 500.0f);
1705 
1706 	for (int i = 0; i < TestResultContainers.Count; ++i) {
1707 		TestResultContainer* result = TestResultContainers[i];
1708 
1709 		int x, y, rot;
1710 
1711 		if (LastStateChange + 500 > TickCount) {
1712 			// fading in
1713 			x = SmoothStep(160, result->Pos.X, diff);
1714 			y = SmoothStep(525, result->Pos.Y, diff);
1715 			rot = SmoothStep(60 + (i * 60), 0, diff);
1716 			Colour col = Colour(1.0f, 1.0f, 1.0f, SmoothStep(0.0f, 1.0f, diff));
1717 			DrawImage(MiniGames[(MiniGameType)result->MiniGame]->Pic, xoff + x, yoff + y, rot, 1.0f, col);
1718 		} else {
1719 			x = result->Pos.X;
1720 			y = result->Pos.Y;
1721 			rot = 0;
1722 			DrawImage(MiniGames[(MiniGameType)result->MiniGame]->Pic, xoff + x, yoff + y, rot, 1.0f, (*White));
1723 			Colour col = Colour(1.0f, 1.0f, 1.0f, SmoothStep(0.0f, 1.0f, result->FadeUpAnim));
1724 			DrawImage(sfcResults90[result->Rank], xoff + x, yoff + y, 0.0f, 1.0f, col);
1725 		}
1726 	}
1727 }
1728 
RenderHistory(float xoff,float yoff)1729 void BPGame::RenderHistory(float xoff, float yoff) {
1730 	DrawImage(sfcHistoryBackground, xoff, yoff);
1731 
1732 	DrawString(sfcHighestBrainWeight, xoff, 246.0f + yoff);
1733 
1734 	if (Secret1) {
1735 		DrawImage(sfcSecretHi, 2 + xoff, 349 + yoff);
1736 	} else {
1737 		DrawImage(sfcSecretLo, 2 + xoff, 349 + yoff);
1738 	}
1739 
1740 	if (Secret2) {
1741 		DrawImage(sfcSecretHi, 83 + xoff, 349 + yoff);
1742 	} else {
1743 		DrawImage(sfcSecretLo, 83 + xoff, 349 + yoff);
1744 	}
1745 
1746 	if (Secret3) {
1747 		DrawImage(sfcSecretHi, 164 + xoff, 349 + yoff);
1748 	} else {
1749 		DrawImage(sfcSecretLo, 164 + xoff, 349 + yoff);
1750 	}
1751 
1752 	if (Secret4) {
1753 		DrawImage(sfcSecretHi, 246 + xoff, 349 + yoff);
1754 	} else {
1755 		DrawImage(sfcSecretLo, 246 + xoff, 349 + yoff);
1756 	}
1757 
1758 	int graph_height = 148;
1759 	int last_score = -1;
1760 
1761 	if (ShowScores.Count == 1) {
1762 		// just one score - draw a dot!
1763 		int this_score = round(ShowScores[0] / 2500.0f * graph_height);
1764 		DrawLine(52 + xoff, 201 - this_score + yoff, 56 + xoff, 201 - this_score + yoff, Red, 4.0f);
1765 	} else {
1766 		for (int i = 0; i < ShowScores.Count; ++i) {
1767 			int this_score = round(ShowScores[i] / 2500.0f * graph_height);
1768 
1769 			if (last_score != -1) {
1770 				// connect the last dot to this dot
1771 				DrawLine(54 + ((i - 1) * 30) + xoff, 201 - last_score + yoff, 54 + (i * 30) + xoff, 201 - this_score + yoff, Red, 3.0f);
1772 			}
1773 
1774 			last_score = this_score;
1775 		}
1776 	}
1777 }
1778 
RenderBrainBoost()1779 void BPGame::RenderBrainBoost() {
1780 	DrawImage(sfcBrainBoost, 0, 0);
1781 }
1782 
RenderMarathon()1783 void BPGame::RenderMarathon() {
1784 	DrawImage(sfcMarathonMode, 0, 0);
1785 }
1786 
RenderHelp(float xoff,float yoff)1787 void BPGame::RenderHelp(float xoff, float yoff) {
1788 	DrawImage(sfcHelp, xoff, yoff);
1789 }
1790 
RenderCredits(float xoff,float yoff)1791 void BPGame::RenderCredits(float xoff, float yoff) {
1792 	DrawImage(sfcCredits, xoff, yoff);
1793 }
1794 
CalculateTestResults()1795 void BPGame::CalculateTestResults() {
1796 	// add up all our scores and see how well we did...
1797 	TestBrainWeight = 0;
1798 
1799 	for (int i = 0; i < TestScores.Count; ++i) {
1800 		TestBrainWeight += TestScores[i];
1801 	}
1802 
1803 	if (TestBrainWeight < 500) {
1804 		TestBrainJob = TestBrainJobs[0];
1805 	} else if (TestBrainWeight < 600) {
1806 		TestBrainJob = TestBrainJobs[1];
1807 	} else if (TestBrainWeight < 650) {
1808 		TestBrainJob = TestBrainJobs[2];
1809 	} else if (TestBrainWeight < 700) {
1810 		TestBrainJob = TestBrainJobs[3];
1811 	} else if (TestBrainWeight < 750) {
1812 		TestBrainJob = TestBrainJobs[4];
1813 	} else if (TestBrainWeight < 800) {
1814 		TestBrainJob = TestBrainJobs[5];
1815 	} else if (TestBrainWeight < 850) {
1816 		TestBrainJob = TestBrainJobs[6];
1817 	} else if (TestBrainWeight < 900) {
1818 		TestBrainJob = TestBrainJobs[7];
1819 	} else if (TestBrainWeight < 950) {
1820 		TestBrainJob = TestBrainJobs[8];
1821 	} else if (TestBrainWeight < 1000) {
1822 		TestBrainJob = TestBrainJobs[9];
1823 	} else if (TestBrainWeight < 1050) {
1824 		TestBrainJob = TestBrainJobs[10];
1825 	} else if (TestBrainWeight < 1100) {
1826 		TestBrainJob = TestBrainJobs[11];
1827 	} else if (TestBrainWeight < 1150) {
1828 		TestBrainJob = TestBrainJobs[12];
1829 	} else if (TestBrainWeight < 1175) {
1830 		TestBrainJob = TestBrainJobs[13];
1831 	} else if (TestBrainWeight < 1200) {
1832 		TestBrainJob = TestBrainJobs[14];
1833 	} else if (TestBrainWeight < 1225) {
1834 		TestBrainJob = TestBrainJobs[15];
1835 	} else if (TestBrainWeight < 1250) {
1836 		TestBrainJob = TestBrainJobs[16];
1837 	} else if (TestBrainWeight < 1275) {
1838 		TestBrainJob = TestBrainJobs[17];
1839 	} else if (TestBrainWeight < 1300) {
1840 		TestBrainJob = TestBrainJobs[18];
1841 	} else if (TestBrainWeight < 1325) {
1842 		TestBrainJob = TestBrainJobs[19];
1843 	} else if (TestBrainWeight < 1350) {
1844 		TestBrainJob = TestBrainJobs[20];
1845 	} else if (TestBrainWeight < 1375) {
1846 		TestBrainJob = TestBrainJobs[21];
1847 	} else if (TestBrainWeight < 1400) {
1848 		TestBrainJob = TestBrainJobs[22];
1849 	} else if (TestBrainWeight < 1425) {
1850 		TestBrainJob = TestBrainJobs[23];
1851 	} else if (TestBrainWeight < 1450) {
1852 		TestBrainJob = TestBrainJobs[24];
1853 	} else if (TestBrainWeight < 1475) {
1854 		TestBrainJob = TestBrainJobs[25];
1855 	} else if (TestBrainWeight < 1500) {
1856 		TestBrainJob = TestBrainJobs[26];
1857 	} else if (TestBrainWeight < 1525) {
1858 		TestBrainJob = TestBrainJobs[27];
1859 	} else if (TestBrainWeight < 1550) {
1860 		TestBrainJob = TestBrainJobs[28];
1861 	} else if (TestBrainWeight < 1575) {
1862 		TestBrainJob = TestBrainJobs[29];
1863 	} else if (TestBrainWeight < 1600) {
1864 		TestBrainJob = TestBrainJobs[30];
1865 	} else if (TestBrainWeight < 1625) {
1866 		TestBrainJob = TestBrainJobs[31];
1867 	} else if (TestBrainWeight < 1650) {
1868 		TestBrainJob = TestBrainJobs[32];
1869 	} else if (TestBrainWeight < 1675) {
1870 		TestBrainJob = TestBrainJobs[33];
1871 	} else if (TestBrainWeight < 1700) {
1872 		TestBrainJob = TestBrainJobs[34];
1873 	} else if (TestBrainWeight < 1725) {
1874 		TestBrainJob = TestBrainJobs[35];
1875 	} else if (TestBrainWeight < 1750) {
1876 		TestBrainJob = TestBrainJobs[36];
1877 	} else if (TestBrainWeight < 1775) {
1878 		TestBrainJob = TestBrainJobs[37];
1879 	} else if (TestBrainWeight < 1800) {
1880 		TestBrainJob = TestBrainJobs[38];
1881 	} else if (TestBrainWeight < 1825) {
1882 		TestBrainJob = TestBrainJobs[39];
1883 	} else if (TestBrainWeight < 1850) {
1884 		TestBrainJob = TestBrainJobs[40];
1885 	} else if (TestBrainWeight < 1875) {
1886 		TestBrainJob = TestBrainJobs[41];
1887 	} else if (TestBrainWeight < 1900) {
1888 		TestBrainJob = TestBrainJobs[42];
1889 	} else if (TestBrainWeight < 1925) {
1890 		TestBrainJob = TestBrainJobs[43];
1891 	} else if (TestBrainWeight < 1950) {
1892 		TestBrainJob = TestBrainJobs[44];
1893 	} else if (TestBrainWeight < 1975) {
1894 		TestBrainJob = TestBrainJobs[45];
1895 	} else if (TestBrainWeight < 2000) {
1896 		TestBrainJob = TestBrainJobs[46];
1897 	} else if (TestBrainWeight < 2025) {
1898 		TestBrainJob = TestBrainJobs[47];
1899 	} else if (TestBrainWeight < 2050) {
1900 		TestBrainJob = TestBrainJobs[48];
1901 	} else if (TestBrainWeight < 2075) {
1902 		TestBrainJob = TestBrainJobs[49];
1903 	} else if (TestBrainWeight < 2100) {
1904 		TestBrainJob = TestBrainJobs[50];
1905 	} else if (TestBrainWeight < 2125) {
1906 		TestBrainJob = TestBrainJobs[51];
1907 	} else if (TestBrainWeight < 2150) {
1908 		TestBrainJob = TestBrainJobs[52];
1909 	} else if (TestBrainWeight < 2175) {
1910 		TestBrainJob = TestBrainJobs[53];
1911 	} else if (TestBrainWeight < 2200) {
1912 		TestBrainJob = TestBrainJobs[54];
1913 	} else {
1914 		TestBrainJob = TestBrainJobs[55];
1915 	}
1916 
1917 	AllocString(&sfcTestJob, TestBrainJob, NORMAL, 320.0f, 80.0f, CENTRED, false);
1918 
1919 	// add the new score to the array
1920 	AllTestScores.Add(TestBrainWeight);
1921 	CurrentBrainWeight = TestBrainWeight;
1922 
1923 	// unlock the games we just played
1924 	for (int i = 0; i < TestMiniGames.Count; ++i) {
1925 		MiniGames[TestMiniGames[i]]->Unlocked = true;
1926 	}
1927 
1928 	// now prepare the results screen
1929 	TestResultContainers.Clear();
1930 
1931 	for (int i = 0; i < TestMiniGames.Count; ++i) {
1932 		TestResultContainer* result = new TestResultContainer();
1933 
1934 		ostringstream brainweight;
1935 		brainweight << TestScores[i] << "g";
1936 		AllocString(&result->sfcBrainWeight, brainweight.str().c_str(), NORMAL, 90.0f, 30.0f, CENTRED, true);
1937 
1938 		result->MiniGame = TestMiniGames[i];
1939 		result->Rank = BPMiniGame::GetRank(TestScores[i]);
1940 		result->GoingUp = false;
1941 
1942 		if (i < 2) {
1943 			// first row
1944 			result->Pos = BPPoint(110 + (i * 100), 325);
1945 		} else {
1946 			// second row
1947 			result->Pos = BPPoint(60 + ((i - 2) * 100), 425);
1948 		}
1949 
1950 		result->FadeUpAnim = Lerp(-1.0f, 0.0f, i / (float)(TestMiniGames.Count - 1));
1951 		TestResultContainers.Add(result);
1952 	}
1953 
1954 	SaveSettings();
1955 }
1956 
CreateMiniGame(MiniGameType game,bool marathon,bool practise)1957 void BPGame::CreateMiniGame(MiniGameType game, bool marathon, bool practise) {
1958 	if (ActiveMiniGame != NULL) {
1959 		SAFE_DELETE(ActiveMiniGame);
1960 	}
1961 
1962 	switch (game) {
1963 		case BALLOONBLASTER:
1964 			ActiveMiniGame = new BPMiniGame_BalloonBlaster(this);
1965 			break;
1966 
1967 		case BOMBHUNT:
1968 			ActiveMiniGame = new BPMiniGame_BombHunt(this);
1969 			break;
1970 
1971 		case BPSAYS:
1972 			ActiveMiniGame = new BPMiniGame_BPSays(this);
1973 			break;
1974 
1975 		case BUBBLETROUBLE:
1976 			ActiveMiniGame = new BPMiniGame_BubbleTrouble(this);
1977 			break;
1978 
1979 		case CARDMATCH:
1980 			ActiveMiniGame = new BPMiniGame_CardMatch(this);
1981 			break;
1982 
1983 		case CONNEX:
1984 			ActiveMiniGame = new BPMiniGame_Connex(this);
1985 			break;
1986 
1987 		case CUPSNBALLS:
1988 			ActiveMiniGame = new BPMiniGame_CupsNBalls(this);
1989 			break;
1990 
1991 		case DICEOFF:
1992 			ActiveMiniGame = new BPMiniGame_DiceOff(this);
1993 			break;
1994 
1995 		case FLASHCOUNTING:
1996 			ActiveMiniGame = new BPMiniGame_FlashCounting(this);
1997 			break;
1998 
1999 		case FLASHLIGHT:
2000 			ActiveMiniGame = new BPMiniGame_Flashlight(this);
2001 			break;
2002 
2003 		case IQTEST:
2004 			ActiveMiniGame = new BPMiniGame_IQTest(this);
2005 			break;
2006 
2007 		case JEWELFLIP:
2008 			ActiveMiniGame = new BPMiniGame_JewelFlip(this);
2009 			break;
2010 
2011 		case JEWELJAM:
2012 			ActiveMiniGame = new BPMiniGame_JewelJam(this);
2013 			break;
2014 
2015 		case MARBLEDROP:
2016 			ActiveMiniGame = new BPMiniGame_MarbleDrop(this);
2017 			break;
2018 
2019 		case MEMORYBLOX:
2020 			ActiveMiniGame = new BPMiniGame_MemoryBlox(this);
2021 			break;
2022 
2023 		case MEMORYBOX:
2024 			ActiveMiniGame = new BPMiniGame_MemoryBox(this);
2025 			break;
2026 
2027 		case MEMORYMATHS:
2028 			ActiveMiniGame = new BPMiniGame_MemoryMaths(this);
2029 			break;
2030 
2031 		case MINESWEEP:
2032 			ActiveMiniGame = new BPMiniGame_MineSweep(this);
2033 			break;
2034 
2035 		case MOONJUMP:
2036 			ActiveMiniGame = new BPMiniGame_MoonJump(this);
2037 			break;
2038 
2039 		case NEXTINLINE:
2040 			ActiveMiniGame = new BPMiniGame_NextInLine(this);
2041 			break;
2042 
2043 		case NUMBERSNAKE:
2044 			ActiveMiniGame = new BPMiniGame_NumberSnake(this);
2045 			break;
2046 
2047 		case ODDONEOUT:
2048 			ActiveMiniGame = new BPMiniGame_OddOneOut(this);
2049 			break;
2050 
2051 		case PATCHMATCH:
2052 			ActiveMiniGame = new BPMiniGame_PatchMatch(this);
2053 			break;
2054 
2055 		case PERFECTPATHS:
2056 			ActiveMiniGame = new BPMiniGame_PerfectPaths(this);
2057 			break;
2058 
2059 		case ROUTEFINDER:
2060 			ActiveMiniGame = new BPMiniGame_RouteFinder(this);
2061 			break;
2062 
2063 		case RPS:
2064 			ActiveMiniGame = new BPMiniGame_RPS(this);
2065 			break;
2066 
2067 		case SCRAMBLED:
2068 			ActiveMiniGame = new BPMiniGame_Scrambled(this);
2069 			break;
2070 
2071 		case SETFINDER:
2072 			ActiveMiniGame = new BPMiniGame_SetFinder(this);
2073 			break;
2074 
2075 		case SHARPSHOOTER:
2076 			ActiveMiniGame = new BPMiniGame_Sharpshooter(this);
2077 			break;
2078 
2079 		case SHORTCIRCUITSUDOKU:
2080 			ActiveMiniGame = new BPMiniGame_ShortCircuitSudoku(this);
2081 			break;
2082 
2083 		case SHUFFLEPUZZLER:
2084 			ActiveMiniGame = new BPMiniGame_ShufflePuzzler(this);
2085 			break;
2086 
2087 		case STRANGERDANGER:
2088 			ActiveMiniGame = new BPMiniGame_StrangerDanger(this);
2089 			break;
2090 
2091 		case SYMBOLICLOGIC:
2092 			ActiveMiniGame = new BPMiniGame_SymbolicLogic(this);
2093 			break;
2094 
2095 		case UNDERTHEHAT:
2096 			ActiveMiniGame = new BPMiniGame_UnderTheHat(this);
2097 			break;
2098 
2099 		case UNTANGLER:
2100 			ActiveMiniGame = new BPMiniGame_Untangler(this);
2101 			break;
2102 
2103 		case WORDSMASH:
2104 			ActiveMiniGame = new BPMiniGame_WordSmash(this);
2105 			break;
2106 	}
2107 
2108 	ActiveMiniGame->Init();
2109 
2110 	if (marathon) ActiveMiniGame->SetMarathon();
2111 
2112 	if (GameState == HISTORY) {
2113 		ActiveMiniGame->ReturnType = RT_SECRET;
2114 	} else if (GameState == BRAINBOOST) {
2115 		ActiveMiniGame->ReturnType = RT_BRAINBOOST;
2116 	}
2117 
2118 	if (practise) {
2119 		SetGameState(PRACTISE_PROFESSOR);
2120 	} else {
2121 		SetGameState(PROFESSOR);
2122 	}
2123 }
2124 
SetGameState(GameStates state)2125 void BPGame::SetGameState(GameStates state) {
2126 	GameState = state;
2127 	AnimCounter = 0.0f;
2128 	GameStateJustChanged = true;
2129 
2130 	if (state != TEST_RESULTS_PLAY) {
2131 		// don't reset LastStateChange when going from test results back to the play menu, as that resets the
2132 		// animation on the results screen
2133 		LastStateChange = TickCount;
2134 	}
2135 
2136 	switch (state) {
2137 		case PLAY_PRACTISE:
2138 			PractisePageNumber = 0;
2139 			PractisePageMoveLeft = true;
2140 
2141 			for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
2142 				it->second->IsShowing = false;
2143 			}
2144 
2145 			PositionPractiseGames();
2146 
2147 			break;
2148 
2149 		case HISTORY:
2150 			ShowScores.Clear();
2151 
2152 			if (AllTestScores.Count > 8) {
2153 				for (int i = AllTestScores.Count - 8; i < AllTestScores.Count; ++i) {
2154 					ShowScores.Add(AllTestScores[i]);
2155 				}
2156 			} else {
2157 				for (int i = 0; i < AllTestScores.Count; ++i) {
2158 					ShowScores.Add(AllTestScores[i]);
2159 				}
2160 			}
2161 
2162 			break;
2163 
2164 		case PROFESSOR:
2165 			PlayMusic("professor");
2166 			break;
2167 
2168 		case TEST_STATUS:
2169 			PlaySound("happy_ring");
2170 			break;
2171 	}
2172 }
2173 
PositionPractiseGames()2174 void BPGame::PositionPractiseGames() {
2175 	PractiseAnimCounter = 0.0f;
2176 
2177 	// get all minigames off the screen
2178 	for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
2179 		if (it->second->IsShowing) {
2180 			// these are visible - make them scroll offscreen neatly
2181 			it->second->StartX = it->second->X;
2182 			it->second->StartY = it->second->Y;
2183 
2184 			if (PractisePageMoveLeft) {
2185 				it->second->DestX = -100;
2186 			} else {
2187 				it->second->DestX = 320;
2188 			}
2189 
2190 			it->second->DestY = 175;
2191 		} else {
2192 			it->second->Y = it->second->StartY = it->second->DestY = 175;
2193 
2194 			if (PractisePageMoveLeft) {
2195 				it->second->X = it->second->StartX = it->second->DestX = -100;
2196 			} else {
2197 				it->second->X = it->second->StartX = it->second->DestX = 320;
2198 			}
2199 		}
2200 
2201 		it->second->IsShowing = false;
2202 	}
2203 
2204 	BPPList<BPPoint*> PractisePositions;
2205 
2206 	for (int row = 0; row < 3; ++row) {
2207 		for (int col = 0; col < 3; ++col) {
2208 			PractisePositions.Add(new BPPoint(15 + (col * 100), 75 + (row * 100)));
2209 		}
2210 	}
2211 
2212 	int i = 0;
2213 	int j = 0;
2214 
2215 	for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
2216 		if (it->second->IsSecret) continue;
2217 		if (!it->second->Unlocked) continue;
2218 
2219 		if (i < PractisePageNumber) {
2220 			++i;
2221 			it->second->IsShowing = false;
2222 			continue;
2223 		}
2224 
2225 		it->second->DestX = PractisePositions[j]->X;
2226 		it->second->DestY = PractisePositions[j]->Y;
2227 
2228 		it->second->StartY = PractisePositions[j]->Y;
2229 
2230 		if (PractisePageMoveLeft) {
2231 			it->second->StartX = 320;
2232 		} else {
2233 			it->second->StartX = -100;
2234 		}
2235 
2236 		it->second->IsShowing = true;
2237 
2238 		++i;
2239 		++j;
2240 
2241 		if (i >= PractisePageNumber + 9) break;
2242 	}
2243 
2244 	PractisePositions.Clear();
2245 }
2246 
RunTest()2247 void BPGame::RunTest() {
2248 	StopMusic();
2249 
2250 	TestMiniGames.Clear();
2251 	TestScores.Clear();
2252 	TestPosition = 0;
2253 
2254 	BPList<MiniGameType> SeenMiniGames;
2255 	BPList<MiniGameType> UnseenMiniGames;
2256 
2257 	// add them all to an array, then shuffle the array
2258 	for (map<MiniGameType, BPMiniGame_Container*>::const_iterator it = MiniGames.begin(); it != MiniGames.end(); ++it) {
2259 		if (it->second->IsSecret) continue; // don't allow hidden minigames into the test
2260 
2261 		if (it->second->Unlocked) {
2262 			SeenMiniGames.Add(it->first);
2263 		} else {
2264 			UnseenMiniGames.Add(it->first);
2265 		}
2266 	}
2267 
2268 	SeenMiniGames.Shuffle();
2269 	UnseenMiniGames.Shuffle();
2270 
2271 	int to_add;
2272 
2273 	if (SeenMiniGames.Count == 0) {
2274 		// we've seen no games yet; add five unseen games
2275 		to_add = 5;
2276 	} else {
2277 		to_add = min(UnseenMiniGames.Count, 4);
2278 	}
2279 
2280 	for (int i = 0; i < to_add; ++i) {
2281 		TestMiniGames.Add(UnseenMiniGames[i]);
2282 	}
2283 
2284 	// figure out how many seen games we need to add, and add them
2285 	to_add = 5 - to_add;
2286 	for (int i = 0; i < to_add; ++i) {
2287 		TestMiniGames.Add(SeenMiniGames[i]);
2288 	}
2289 
2290 	// shuffle the list so that the seen/unseen games come in any order
2291 	TestMiniGames.Shuffle();
2292 
2293 	InTestMode = true;
2294 	SetGameState(TEST_STATUS);
2295 }
2296 
NextTest()2297 void BPGame::NextTest() {
2298 	if (TestPosition == TestMiniGames.Count) {
2299 		// use this for quick testing
2300 //	if (true) {
2301 //		TestScores.Add(150);
2302 //		TestScores.Add(250);
2303 //		TestScores.Add(350);
2304 //		TestScores.Add(450);
2305 //		TestScores.Add(500);
2306 		CalculateTestResults();
2307 		SetGameState(TEST_RESULTS);
2308 
2309 		InTestMode = false;
2310 
2311 		PlayMusic("results");
2312 
2313 		return;
2314 	}
2315 
2316 	CreateMiniGame(TestMiniGames[TestPosition], false, false);
2317 	++TestPosition;
2318 }
2319 
PlaySound(const char * sound,bool preload_only,bool force_play)2320 void BPGame::PlaySound(const char* sound, bool preload_only, bool force_play) {
2321 
2322 	if (!EnableSound && !force_play) return;
2323 
2324 	if (Sounds.find(sound) != Sounds.end()) {
2325 		if (preload_only) {
2326 			// do nothing - this is only for iPhone
2327 		} else {
2328 			Mix_PlayChannel(-1, Sounds[sound], 0);
2329 		}
2330 	} else {
2331 		printf("Error: sound %s doesn't exist.\n", sound);
2332 	}
2333 }
2334 
PlayMusic(const char * name)2335 void BPGame::PlayMusic(const char* name) {
2336 	if (!EnableMusic) return;
2337 
2338 	if (Music != NULL) {
2339 		Mix_HaltMusic();
2340 		Mix_FreeMusic(Music);
2341 		Music = NULL;
2342 	}
2343 
2344 	string* file = new string(name);
2345 	file->insert(0, "/usr/local/share/brainparty/");
2346 	file->append(".ogg");
2347 
2348 	Music = Mix_LoadMUS(file->c_str());
2349 	Mix_PlayMusic(Music, -1);
2350 
2351 	delete(file);
2352 }
2353 
StopMusic()2354 void BPGame::StopMusic() {
2355 	if (Music != NULL) {
2356 		Mix_HaltMusic();
2357 		Mix_FreeMusic(Music);
2358 		Music = NULL;
2359 	}
2360 }
2361 
FileExists(const char * filename)2362 bool BPGame::FileExists(const char * filename) {
2363     if (FILE * file = fopen(filename, "r")) {
2364         fclose(file);
2365         return true;
2366     }
2367     return false;
2368 }
2369 
LoadSound(const char * filename,const char * extension)2370 Mix_Chunk* BPGame::LoadSound(const char* filename, const char* extension) {
2371 	string* file = new string(filename);
2372 	file->insert(0, "/usr/local/share/brainparty/");
2373 	file->append(".wav");
2374 
2375 	Mix_Chunk* retval = Mix_LoadWAV(file->c_str());
2376 	if (retval == NULL) printf("Warning: couldn't load file %s.\n", filename);
2377 	delete file;
2378 
2379 	return retval;
2380 }
2381 
CancelTest()2382 void BPGame::CancelTest() {
2383 	GameState = PLAY_MENU;
2384 	TestMiniGames.Clear();
2385 	TestScores.Clear();
2386 	TestPosition = 0;
2387 
2388 	InTestMode = false;
2389 
2390 	PlayMusic("theme");
2391 }
2392 
Accelerate(float x,float y,float z)2393 void BPGame::Accelerate(float x, float y, float z) {
2394 	Acceleration[0] = x;
2395 	Acceleration[1] = y;
2396 	Acceleration[2] = z;
2397 }
2398 
PromptResetScores()2399 void BPGame::PromptResetScores() {
2400 	ShowingClearScores = true;
2401 	MessageBox::Show("Are you sure you want to wipe all your test scores so far? Press Y on your keyboard now to wipe your scores. Click the mouse or press any other key cancel.", "Clear scores?");
2402 }
2403 
ExecuteResetScores()2404 void BPGame::ExecuteResetScores() {
2405 	AllTestScores.Clear();
2406 	SaveSettings();
2407 	MessageBox::Show("Your test scores have been wiped and you have a clean slate - good luck!", "Scores wiped!");
2408 }
2409 
ColorLerp(Colour * from,Colour * to,float amount)2410 Colour* BPGame::ColorLerp(Colour* from, Colour* to, float amount) {
2411 	Colour* col = new Colour(Lerp(from->R, to->R, amount), Lerp(from->G, to->G, amount), Lerp(from->B, to->B, amount), Lerp(from->A, to->A, amount));
2412 	return col;
2413 }
2414