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 "symboliclogic.h"
19 #include "Minigame.h"
20 #include <algorithm>
21 #include <cctype>
22
BPMiniGame_SymbolicLogic(BPGame * game)23 BPMiniGame_SymbolicLogic::BPMiniGame_SymbolicLogic(BPGame* game) : BPMiniGame(game) {
24 sfcBackground = TheGame->LoadBitmap("symboliclogic", 320, 416);
25
26 LastStateChange = CurrentLevel = Score = NumTries = 0;
27 GameState = WAITING;
28
29 sfcText = NULL;
30
31 AnswerIsTrue = false;
32
33 TimeStarted = 0;
34
35 GameTitle = "Symbolic Logic";
36 GameHelp = "I'm going to give you two statements that I'd like you to accept as truth. Based on those two facts, are my conclusions true or false?";
37 GameHelp2 = "If you read the questions carefully, you should be OK, but remember: if the conclusion says \"A must be a B\" and you think \"A could be a B or it could not be a B; I don't know\", then clearly the conclusion is wrong!";
38
39 MiniGameType = PUZZLE;
40
41 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("can play the guitar", "can't play the guitar", "can play the guitar", "guitarists"));
42 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("can play the piano", "can't play the piano", "can play the piano", "pianists"));
43 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("can play the violin", "can't play the violin", "can play the violin", "violinists"));
44 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("can speak Chinese", "can't speak Chinese", "can speak Chinese", "Chinese speakers"));
45 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("can speak French", "can't speak French", "can speak French", "French speakers"));
46 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("can speak Japanese", "can't speak Japanese", "can speak Japanese", "Japanese speakers"));
47 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("can speak Latin", "can't speak Latin", "can speak Latin", "Latin speakers"));
48 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("can speak Spanish", "can't speak Spanish", "can speak Spanish", "Spanish speakers"));
49 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("drives a car", "can't drive a car", "drive a car", "car drivers"));
50 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("eats mashed potato", "doesn't eat mashed potato", "like mashed potato", "mashed potato eaters"));
51 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("enjoys cooking", "doesn't enjoy cooking", "enjoy cooking", "cooks"));
52 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("exercises regularly", "doesn't exercise regularly", "exercise regularly", "regular exercisers"));
53 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("goes to church", "doesn't go to church", "go to church", "churchgoers"));
54 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("has brown hair", "doesn't have brown hair", "have brown hair", "brown-haired people"));
55 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("has blue eyes", "doesn't have blue eyes", "have blue eyes", "blue-eyed people"));
56 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("has curly hair", "doesn't have curly hair", "have curly hair", "curly-haired people"));
57 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("hates computers", "doesn't hate computers", "hate computers", "computer haters"));
58 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("is very clever", "isn't very clever", "are very clever", "very clever people"));
59 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("is very popular", "isn't very popular", "are very popular", "very popular people"));
60 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("likes bowling", "doesn't like bowling", "like bowling", "bowlers"));
61 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("likes broccoli", "doesn't like broccoli", "like broccoli", "broccoli eaters"));
62 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("likes eating carrots", "doesn't like eating carrots", "like eating carrots", "carrot eaters"));
63 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("likes eating dessert", "doesn't like eating dessert", "like eating dessert", "dessert eaters"));
64 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("likes puzzles", "doesn't like puzzles", "like puzzles", "people who like puzzles"));
65 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("likes to sing", "doesn't like to sing", "like to sing", "singers"));
66 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("loves animals", "doesn't like animals", "like animals", "animal lovers"));
67 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("loves Shakespeare", "doesn't love Shakespeare", "love Shakespeare", "Shakespeare lovers"));
68 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("owns a mansion", "doesn't own a mansion", "own a mansion", "mansion owners"));
69 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("plays golf", "doesn't play golf", "play golf", "golfers"));
70 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("plays Sudoku", "doesn't play Sudoku", "play Sudoku", "Sudoku players"));
71 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("plays tennis", "doesn't play tennis", "play tennis", "tennis players"));
72 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("owns a cat", "doesn't own a cat", "own a cat", "cat owners"));
73 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("owns a cellphone", "doesn't own a cellphone", "own a cellphone", "cellphone owners"));
74 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("owns a dog", "doesn't own a dog", "own a dog", "dog owners"));
75 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("owns a goat", "doesn't own a goat", "own a goat", "goat owners"));
76 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("owns a hamster", "doesn't own a hamster", "own a hamster", "hamster owners"));
77 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("owns a parrot", "doesn't own a parrot", "own a parrot", "parrot owners"));
78 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("owns a rabbit", "doesn't own a rabbit", "own a rabbit", "rabbit owners"));
79 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("reads books", "doesn't read books", "read books", "people who read books"));
80 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("reads newspapers", "doesn't read newspapers", "read newspapers", "newspaper readers"));
81 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("rides a bike", "doesn't ride a bike", "ride a bike", "bicyclists"));
82 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("walks to work", "doesn't walk to work", "walk to work", "people who walk to work"));
83 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("watches TV", "doesn't watch TV", "watch TV", "TV watchers"));
84 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("wears glasses", "doesn't wear glasses", "wear glasses", "people who wear glasses"));
85 LogicItems.Add(new BPMiniGame_SymbolicLogic_Item("wrestles crocodiles", "doesn't wrestle crocodiles", "wrestle crocodiles", "crocodile wrestlers"));
86 }
87
~BPMiniGame_SymbolicLogic()88 BPMiniGame_SymbolicLogic::~BPMiniGame_SymbolicLogic() {
89 SAFE_DELETE(sfcBackground);
90
91 LogicItems.Clear();
92 Premises.Clear();
93
94 SAFE_DELETE(sfcText);
95 }
96
Start()97 void BPMiniGame_SymbolicLogic::Start() {
98 TimeStarted = TheGame->TickCount;
99 LevelUp();
100 }
101
GetWeight()102 int BPMiniGame_SymbolicLogic::GetWeight() {
103 float TimePassed = (TheGame->TickCount - TimeStarted) / 1000.0f;
104 return MinMax(Score - round(TimePassed));
105 }
106
Render()107 void BPMiniGame_SymbolicLogic::Render() {
108 TheGame->DrawImage(sfcBackground, 0, 0);
109
110 TheGame->DrawString(sfcText, WHITE, 20, 19);
111
112 if (GameState == CORRECT) {
113 RenderCorrect();
114 } else if (GameState == WRONG) {
115 RenderWrong();
116 }
117 }
118
FlattenPremise(BPMiniGame_SymbolicLogic_Premise * premise)119 const char* BPMiniGame_SymbolicLogic::FlattenPremise(BPMiniGame_SymbolicLogic_Premise* premise) {
120 ostringstream result;
121
122 switch (premise->Type) {
123 case ALL_JOB:
124 result << "All " << premise->Job << "s " << premise->Item->PluralDesc;
125 break;
126
127 case NONE_JOB:
128 result << "No " << premise->Job << " " << premise->Item->SingularDesc;
129 break;
130
131 case ALL_ITEM:
132 result << "All " << premise->Item->Noun << " are " << premise->Job << "s";
133 break;
134
135 case NONE_ITEM:
136 result << "No " << premise->Item->Noun << " are " << premise->Job << "s";
137 break;
138
139 case PERSON:
140 if (premise->Item == NULL) {
141 if (TheGame->StartsWithVowel(&premise->Job)) {
142 result << premise->Text << " is an " << premise->Job;
143 } else {
144 result << premise->Text << " is a " << premise->Job;
145 }
146 } else {
147 result << premise->Text << " " << premise->Item->SingularDesc;
148 }
149
150 break;
151 }
152
153 return result.str().c_str();
154 }
155
Tick()156 void BPMiniGame_SymbolicLogic::Tick() {
157 if (LastStateChange != -1 && LastStateChange + 500 < TheGame->TickCount) {
158 if (NumTries >= 10 && !MarathonMode) {
159 Success();
160 return;
161 } else {
162 LevelUp();
163 }
164 }
165 }
166
OnMouseDown()167 void BPMiniGame_SymbolicLogic::OnMouseDown() {
168
169 }
170
OnMouseMove()171 void BPMiniGame_SymbolicLogic::OnMouseMove() {
172
173 }
174
OnMouseUp()175 void BPMiniGame_SymbolicLogic::OnMouseUp() {
176 switch (GameState) {
177 case CORRECT:
178 case WRONG:
179 LevelUp();
180 break;
181
182 case WAITING:
183 // have we just answered the question?
184
185 if (TheGame->PointOverRect(TouchEvent.X, TouchEvent.Y, 11, 342, 143, 63)) {
186 // True clicked!
187 LastStateChange = TheGame->TickCount;
188
189 if (AnswerIsTrue) {
190 TheGame->PlaySound("correct");
191 GameState = CORRECT;
192 Score += 50;
193 } else {
194 TheGame->PlaySound("wrong");
195 GameState = WRONG;
196 Score -= 100;
197 }
198 } else if (TheGame->PointOverRect(TouchEvent.X, TouchEvent.Y, 166, 342, 143, 63)) {
199 // False clicked!
200 LastStateChange = TheGame->TickCount;
201
202 if (!AnswerIsTrue) {
203 TheGame->PlaySound("correct");
204 GameState = CORRECT;
205 Score += 50;
206 } else {
207 TheGame->PlaySound("wrong");
208 GameState = WRONG;
209 Score -= 50;
210 }
211 }
212
213 break;
214 }
215 }
216
LevelUp()217 void BPMiniGame_SymbolicLogic::LevelUp() {
218 if (NumTries >= 10 && !MarathonMode) {
219 return;
220 }
221
222 ++CurrentLevel;
223 ++NumTries;
224 LastStateChange = -1;
225 GameState = WAITING;
226
227 Premises.Clear();
228 LogicItems.Shuffle();
229
230 BPMiniGame_SymbolicLogic_Premise* FirstPremise;
231 BPMiniGame_SymbolicLogic_Premise* SecondPremise;
232
233 string Job;
234 string PersonName;
235 ostringstream NegativeConclusion;
236 ostringstream Conclusion;
237
238 bool is_negative = false;
239
240 if (TheGame->RandomRange(0, 1) == 1) {
241 NegativeConclusion << "not ";
242 is_negative = true;
243 }
244
245 Job = GetRandomJob();
246 PersonName = TheGame->GetName();
247
248 FirstPremise = new BPMiniGame_SymbolicLogic_Premise();
249 FirstPremise->Type = GetPremiseType();
250 FirstPremise->Job = Job;
251 FirstPremise->Item = LogicItems[0];
252 Premises.Add(FirstPremise);
253
254 SecondPremise = new BPMiniGame_SymbolicLogic_Premise();
255 SecondPremise->Type = PERSON;
256 SecondPremise->Text = PersonName;
257 switch (TheGame->RandomRange(0, 1)) {
258 case 0:
259 SecondPremise->Item = LogicItems[0];
260 Premises.Add(SecondPremise);
261
262 if (TheGame->StartsWithVowel(&Job)) {
263 Conclusion << "Therefore, " << PersonName << " is " << NegativeConclusion.str() << "an " << Job;
264 } else {
265 Conclusion << "Therefore, " << PersonName << " is " << NegativeConclusion.str() << "a " << Job;
266 }
267
268 break;
269
270 case 1:
271 SecondPremise->Job = Job;
272 Premises.Add(SecondPremise);
273
274 if (!is_negative) {
275 Conclusion << "Therefore, " << PersonName << " " << LogicItems[0]->SingularDesc;
276 } else {
277 Conclusion << "Therefore, " << PersonName << " " << LogicItems[0]->Negative;
278 }
279
280 break;
281 }
282
283 if (FirstPremise->Type == ALL_JOB) {
284 if (SecondPremise->Job.size() != 0) {
285 AnswerIsTrue = true;
286 if (is_negative) AnswerIsTrue = !AnswerIsTrue;
287 } else {
288 AnswerIsTrue = false;
289 }
290 } else if (FirstPremise->Type == ALL_ITEM) {
291 if (SecondPremise->Item != NULL) {
292 AnswerIsTrue = true;
293 if (is_negative) AnswerIsTrue = !AnswerIsTrue;
294 } else {
295 AnswerIsTrue = false;
296 }
297 } else if (FirstPremise->Type == NONE_JOB) {
298 if (SecondPremise->Job.size() != 0) {
299 AnswerIsTrue = false;
300 } else {
301 AnswerIsTrue = false;
302 }
303
304 if (is_negative) AnswerIsTrue = !AnswerIsTrue;
305 } else {
306 if (SecondPremise->Item != NULL) {
307 AnswerIsTrue = false;
308 } else {
309 AnswerIsTrue = false;
310 }
311
312 if (is_negative) AnswerIsTrue = !AnswerIsTrue;
313 }
314
315 string PrintMe = string();
316
317 for (int i = 0; i < Premises.Count; ++i) {
318 BPMiniGame_SymbolicLogic_Premise* premise = Premises[i];
319 string str = FlattenPremise(premise);
320 PrintMe.append(str);
321 PrintMe.append(". ");
322 }
323
324 PrintMe.append(Conclusion.str());
325 PrintMe.append(". ");
326
327 TheGame->AllocString(&sfcText, PrintMe.c_str(), LARGE, 282, 306, LEFT);
328 }
329
GetPremiseType()330 PremiseTypes BPMiniGame_SymbolicLogic::GetPremiseType() {
331 switch (TheGame->RandomRange(0, 3)) {
332 case 0:
333 return ALL_JOB;
334 case 1:
335 return NONE_JOB;
336 case 2:
337 return ALL_ITEM;
338 default:
339 return NONE_ITEM;
340 }
341 }
342
GetRandomJob()343 string BPMiniGame_SymbolicLogic::GetRandomJob() {
344 string meh = TheGame->TestBrainJobs[TheGame->RandomRange(0, 51)];
345 transform(meh.begin(), meh.end(), meh.begin(), (int(*)(int)) tolower);
346 return meh;
347 }
348
SetMarathon()349 void BPMiniGame_SymbolicLogic::SetMarathon() {
350 MarathonMode = true;
351 }
352