7 Game* Game::theGame = NULL;
9 Game::Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const Piece::Colour & newReveal) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0)
11 static bool gameCreated = false;
15 fprintf(log, "ERROR - Game has already been created!\n");
20 signal(SIGPIPE, Game::HandleBrokenPipe);
23 if (graphicsEnabled && (!Graphics::Initialised()))
24 Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32);
26 if (strcmp(redPath, "human") == 0)
27 red = new Human_Controller(Piece::RED, graphicsEnabled);
29 red = new AI_Controller(Piece::RED, redPath);
32 if (strcmp(bluePath, "human") == 0)
33 blue = new Human_Controller(Piece::BLUE, graphicsEnabled);
35 blue = new AI_Controller(Piece::BLUE, redPath);
42 fprintf(stderr, "Killing AI\n");
46 if (log != NULL && log != stdout && log != stderr)
50 bool Game::Setup(const char * redName, const char * blueName)
53 for (int y = 4; y < 6; ++y)
55 for (int x = 2; x < 4; ++x)
57 theBoard.AddPiece(x,y,Piece::BOULDER, Piece::NONE);
59 for (int x = 6; x < 8; ++x)
61 theBoard.AddPiece(x,y,Piece::BOULDER, Piece::NONE);
66 MovementResult redSetup = red->Setup(blueName);
67 MovementResult blueSetup = blue->Setup(redName);
69 if (redSetup != MovementResult::OK)
71 if (blueSetup != MovementResult::OK)
74 fprintf(log, "BOTH players give invalid setup!\n");
75 red->Message("ILLEGAL");
76 blue->Message("ILLEGAL");
81 fprintf(log, "Player RED gave an invalid setup!\n");
82 red->Message("ILLEGAL");
83 blue->Message("DEFAULT");
87 else if (blueSetup != MovementResult::OK)
90 fprintf(log, "Player BLUE gave an invalid setup!\n");
91 red->Message("DEFAULT");
92 blue->Message("ILLEGAL");
99 void Game::Wait(double wait)
104 TimerThread timer(wait*1000000); //Wait in seconds
107 if (!graphicsEnabled)
109 while (!timer.Finished());
115 while (!timer.Finished())
118 while (SDL_PollEvent(&event))
133 void Game::HandleBrokenPipe(int sig)
135 if (theGame->turn == Piece::RED)
137 theGame->logMessage("Game ends on RED's turn - REASON: ");
138 theGame->blue->Message("DEFAULT");
140 else if (theGame->turn == Piece::BLUE)
143 theGame->logMessage("Game ends on BLUE's turn - REASON: ");
144 theGame->red->Message("DEFAULT");
148 theGame->logMessage("Game ends on ERROR's turn - REASON: ");
152 theGame->logMessage("SIGPIPE - Broken pipe (AI program may have segfaulted)\n");
156 if (Game::theGame->graphicsEnabled && theGame->log == stdout)
158 theGame->logMessage("CLOSE WINDOW TO EXIT\n");
159 Game::theGame->theBoard.Draw(Piece::BOTH);
163 while (SDL_PollEvent(&event))
176 if (theGame->log == stdout)
178 theGame->logMessage( "PRESS ENTER TO EXIT\n");
179 theGame->theBoard.Print(theGame->log);
180 while (fgetc(stdin) != '\n');
188 void Game::PrintEndMessage(const MovementResult & result)
190 if (turn == Piece::RED)
192 logMessage("Game ends on RED's turn - REASON: ");
194 else if (turn == Piece::BLUE)
196 logMessage("Game ends on BLUE's turn - REASON: ");
200 logMessage("Game ends on ERROR's turn - REASON: ");
205 case MovementResult::OK:
206 logMessage("Status returned OK, unsure why game halted...\n");
208 case MovementResult::DIES:
209 logMessage("Status returned DIES, unsure why game halted...\n");
211 case MovementResult::KILLS:
212 logMessage("Status returned KILLS, unsure why game halted...\n");
214 case MovementResult::BOTH_DIE:
215 logMessage("Status returned BOTH_DIE, unsure why game halted...\n");
217 case MovementResult::NO_BOARD:
218 logMessage("Board does not exit?!\n");
220 case MovementResult::INVALID_POSITION:
221 logMessage("Coords outside board\n");
223 case MovementResult::NO_SELECTION:
224 logMessage("Move does not select a piece\n");
226 case MovementResult::NOT_YOUR_UNIT:
227 logMessage("Selected piece belongs to other player\n");
229 case MovementResult::IMMOBILE_UNIT:
230 logMessage("Selected piece is not mobile (FLAG or BOMB)\n");
232 case MovementResult::INVALID_DIRECTION:
233 logMessage("Selected unit cannot move that way\n");
235 case MovementResult::POSITION_FULL:
236 logMessage("Attempted move into square occupied by allied piece\n");
238 case MovementResult::VICTORY:
239 logMessage("Captured the flag\n");
241 case MovementResult::BAD_RESPONSE:
242 logMessage("Unintelligable response\n");
244 case MovementResult::NO_MOVE:
245 logMessage("Did not make a move (may have exited)\n");
247 case MovementResult::COLOUR_ERROR:
248 logMessage("Internal controller error - COLOUR_ERROR\n");
250 case MovementResult::ERROR:
251 logMessage("Internal controller error - Unspecified ERROR\n");
256 if (graphicsEnabled && log == stdout)
258 logMessage("CLOSE WINDOW TO EXIT\n");
259 theBoard.Draw(Piece::BOTH);
263 while (SDL_PollEvent(&event))
278 logMessage("PRESS ENTER TO EXIT\n");
279 while (fgetc(stdin) != '\n');
287 MovementResult Game::Play()
290 MovementResult result = MovementResult::OK;
296 red->Message("START");
298 while (Board::LegalResult(result))
303 logMessage( "%d RED: ", turnCount);
304 result = red->MakeMove(buffer);
305 red->Message(buffer);
306 blue->Message(buffer);
307 logMessage( "%s\n", buffer.c_str());
308 if (!Board::LegalResult(result))
311 theBoard.Draw(reveal);
315 logMessage( "%d BLU: ", turnCount);
316 result = blue->MakeMove(buffer);
317 blue->Message(buffer);
318 red->Message(buffer);
319 logMessage( "%s\n", buffer.c_str());
321 if (!Board::LegalResult(result))
327 theBoard.Draw(reveal);
341 * Logs a message to the game's log file if it exists
342 * @param format the format string
343 * @param additional parameters - printed using va_args
344 * @returns the result of vfprintf or a negative number if the log file does not exist
346 int Game::logMessage(const char * format, ...)
351 va_start(ap, format);
353 int result = vfprintf(log, format, ap);