X-Git-Url: https://git.ucc.asn.au/?p=progcomp2012.git;a=blobdiff_plain;f=judge%2Fmanager%2Fgame.cpp;h=3f5b46b5e08b439e4691599b5270f224559c6ba5;hp=f25c9f381cfcc62f25eaa951b3928bd34e44468d;hb=add28d0a7f265f5fcfdd67a4c1e590b19f76272e;hpb=341297b4dce9528d54fe9dceeff0d6dc33f70abe diff --git a/judge/manager/game.cpp b/judge/manager/game.cpp index f25c9f3..3f5b46b 100644 --- a/judge/manager/game.cpp +++ b/judge/manager/game.cpp @@ -1,5 +1,7 @@ #include "game.h" #include +#include + using namespace std; @@ -7,7 +9,7 @@ using namespace std; Game* Game::theGame = NULL; bool Game::gameCreated = false; -Game::Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime) +Game::Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime, const char * newImageOutput) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime), imageOutput(newImageOutput) { gameCreated = false; if (gameCreated) @@ -22,7 +24,13 @@ Game::Game(const char * redPath, const char * bluePath, const bool enableGraphic #ifdef BUILD_GRAPHICS if (graphicsEnabled && (!Graphics::Initialised())) - Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32); + { + string s = "Stratego: "; + s += string(redPath); + s += " "; + s += string(bluePath); + Graphics::Initialise(s.c_str(), theBoard.Width()*GRID_SIZE, theBoard.Height()*GRID_SIZE); + } #endif //BUILD_GRAPHICS @@ -43,10 +51,10 @@ Game::Game(const char * redPath, const char * bluePath, const bool enableGraphic fprintf(stderr, "BLUE! (blue: \"%s\")\n", bluePath); exit(EXIT_FAILURE); } - logMessage("Game initialised.\n"); +// logMessage("Game initialised.\n"); } -Game::Game(const char * fromFile, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime) +Game::Game(const char * fromFile, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard, double newTimeoutTime,const char * newImageOutput) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0), input(NULL), maxTurns(newMaxTurns), printBoard(newPrintBoard), timeoutTime(newTimeoutTime), imageOutput(newImageOutput) { gameCreated = false; if (gameCreated) @@ -60,7 +68,11 @@ Game::Game(const char * fromFile, const bool enableGraphics, double newStallTime #ifdef BUILD_GRAPHICS if (graphicsEnabled && (!Graphics::Initialised())) - Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32); + { + string s = "Stratego: (file) "; + s += string(fromFile); + Graphics::Initialise(s.c_str(), theBoard.Width()*GRID_SIZE, theBoard.Height()*GRID_SIZE); + } #endif //BUILD_GRAPHICS input = fopen(fromFile, "r"); @@ -208,21 +220,23 @@ void Game::Wait(double wait) if (wait <= 0) return; - TimerThread timer(wait*1000000); //Wait in seconds - timer.Start(); + + #ifdef BUILD_GRAPHICS + + if (!graphicsEnabled) { - while (!timer.Finished()); - timer.Stop(); + usleep(1000000*wait); //Wait in seconds return; } - #endif //BUILD_GRAPHICS + TimerThread timer(wait*1000000); //Wait in seconds + timer.Start(); while (!timer.Finished()) { - #ifdef BUILD_GRAPHICS + SDL_Event event; while (SDL_PollEvent(&event)) { @@ -234,9 +248,12 @@ void Game::Wait(double wait) break; } } - #endif //BUILD_GRAPHICS } timer.Stop(); + + #else + usleep(wait*1000000); //Wait in seconds + #endif //BUILD_GRAPHICS } @@ -247,62 +264,61 @@ void Game::HandleBrokenPipe(int sig) fprintf(stderr, "ERROR - Recieved SIGPIPE during game exit!\n"); exit(EXIT_FAILURE); } - if (theGame->turn == Piece::RED) - { - theGame->logMessage("Game ends on RED's turn - REASON: "); - if (theGame->blue->Valid()) //Should probably check this - theGame->blue->Message("DEFAULT"); - } - else if (theGame->turn == Piece::BLUE) - { - - theGame->logMessage("Game ends on BLUE's turn - REASON: "); - if (theGame->red->Valid()) //Should probably check this - theGame->red->Message("DEFAULT"); - } - else - { - theGame->logMessage("Game ends on ERROR's turn - REASON: "); - - } theGame->logMessage("SIGPIPE - Broken pipe (AI program no longer running)\n"); - if (Game::theGame->printBoard) - Game::theGame->theBoard.PrintPretty(stdout, Piece::BOTH); + MovementResult result = MovementResult::BAD_RESPONSE; - - #ifdef BUILD_GRAPHICS - if (Game::theGame->graphicsEnabled && theGame->log == stdout) + if (theGame->turn == Piece::RED) { - theGame->logMessage("CLOSE WINDOW TO EXIT\n"); - Game::theGame->theBoard.Draw(Piece::BOTH); - while (true) + if (theGame->red->Valid()) { - SDL_Event event; - while (SDL_PollEvent(&event)) + theGame->logMessage(" Strange; RED still appears valid.\n"); + if (theGame->blue->Valid()) { - switch (event.type) - { - case SDL_QUIT: - exit(EXIT_SUCCESS); - break; - } - } + theGame->logMessage(" BLUE also appears valid. Exiting with ERROR.\n"); + result = MovementResult::ERROR; + } + else + { + theGame->logMessage("BLUE is invalid. Wait for BLUE's turn to exit.\n"); + return; + } } } - else - #endif //BUILD_GRAPHICS + if (theGame->turn == Piece::BLUE) { - if (theGame->log == stdout || theGame->log == stderr) + if (theGame->blue->Valid()) { - theGame->logMessage( "PRESS ENTER TO EXIT\n"); - theGame->theBoard.Print(theGame->log); - while (fgetc(stdin) != '\n'); + theGame->logMessage(" Strange; BLUE still appears valid.\n"); + if (theGame->red->Valid()) + { + theGame->logMessage(" RED also appears valid. Exiting with ERROR.\n"); + result = MovementResult::ERROR; + } + else + { + theGame->logMessage("RED is invalid. Wait for RED's turn to exit.\n"); + return; + } } } - + + Game::theGame->PrintEndMessage(result); + + string buffer = ""; + PrintResults(result, buffer); + + //Message the AI's the quit message + Game::theGame->red->Message("QUIT " + buffer); + Game::theGame->blue->Message("QUIT " + buffer); + + //Log the message + if (Game::theGame->GetLogFile() != stdout) + Game::theGame->logMessage("%s\n", buffer.c_str()); + + fprintf(stdout, "%s\n", buffer.c_str()); exit(EXIT_SUCCESS); } @@ -408,6 +424,7 @@ void Game::PrintEndMessage(const MovementResult & result) } break; + } if (printBoard) @@ -479,10 +496,10 @@ MovementResult Game::Play() - logMessage("Messaging red with \"START\"\n"); +// logMessage("Messaging red with \"START\"\n"); red->Message("START"); - + int moveCount = 0; while (!Board::HaltResult(result) && (turnCount < maxTurns || maxTurns < 0)) { @@ -501,7 +518,15 @@ MovementResult Game::Play() #ifdef BUILD_GRAPHICS if (graphicsEnabled) + { theBoard.Draw(toReveal); + if (imageOutput != "") + { + string imageFile = "" + imageOutput + "/"+ itostr(moveCount) + ".bmp"; + Graphics::ScreenShot(imageFile.c_str()); + } + + } #endif //BUILD_GRAPHICS turn = Piece::RED; @@ -516,8 +541,6 @@ MovementResult Game::Play() logMessage( "%d RED: ", turnCount); result = red->MakeMove(buffer); - red->Message(buffer); - blue->Message(buffer); logMessage( "%s\n", buffer.c_str()); if (!Board::HaltResult(result)) @@ -527,6 +550,12 @@ MovementResult Game::Play() if (Board::HaltResult(result)) break; + red->Message(buffer); + blue->Message(buffer); + + + + if (stallTime >= 0) Wait(stallTime); else @@ -541,10 +570,19 @@ MovementResult Game::Play() theBoard.PrintPretty(stdout, toReveal); fprintf(stdout, "\n\n"); } + + ++moveCount; #ifdef BUILD_GRAPHICS if (graphicsEnabled) + { theBoard.Draw(toReveal); + if (imageOutput != "") + { + string imageFile = "" + imageOutput + "/" + itostr(moveCount) + ".bmp"; + Graphics::ScreenShot(imageFile.c_str()); + } + } #endif //BUILD_GRAPHICS @@ -561,8 +599,6 @@ MovementResult Game::Play() logMessage( "%d BLU: ", turnCount); result = blue->MakeMove(buffer); - blue->Message(buffer); - red->Message(buffer); logMessage( "%s\n", buffer.c_str()); if (!Board::HaltResult(result)) @@ -572,6 +608,10 @@ MovementResult Game::Play() if (Board::HaltResult(result)) break; + red->Message(buffer); + blue->Message(buffer); + + if (theBoard.MobilePieces(Piece::RED) == 0) result = MovementResult::DRAW; @@ -589,7 +629,7 @@ MovementResult Game::Play() else ReadUserCommand(); - + ++moveCount; ++turnCount; } @@ -771,6 +811,9 @@ void Game::MakeControllers(const char * redPath, const char * bluePath) { Network * redNetwork = NULL; Network * blueNetwork = NULL; + //To allow for running two network controllers (I don't know why you would, but beside the point...) use two ports + static const int port1 = 4560; + static const int port2 = 4561; if (redPath[0] == '@') { @@ -789,7 +832,7 @@ void Game::MakeControllers(const char * redPath, const char * bluePath) if (network == NULL) { logMessage("Creating server for red AI... "); - redNetwork = new Server(); + redNetwork = new Server(port1); logMessage("Successful!\n"); } @@ -797,7 +840,7 @@ void Game::MakeControllers(const char * redPath, const char * bluePath) { network = (const char*)(network+1); logMessage("Creating client for red AI... "); - redNetwork = new Client(network); + redNetwork = new Client(network, port2); logMessage("Connected to address %s\n", network); } @@ -825,7 +868,7 @@ void Game::MakeControllers(const char * redPath, const char * bluePath) if (network == NULL) { logMessage("Creating server for blue AI... "); - blueNetwork = new Server(); + blueNetwork = new Server(port2); logMessage("Successful!\n"); } @@ -833,7 +876,7 @@ void Game::MakeControllers(const char * redPath, const char * bluePath) { network = (const char*)(network+1); logMessage("Creating client for blue AI... "); - blueNetwork = new Client(network); + blueNetwork = new Client(network, port1); logMessage("Connected to address %s\n", network); } logMessage(" (Blue's responses will be received over the connection)\n"); @@ -855,6 +898,72 @@ void Game::MakeControllers(const char * redPath, const char * bluePath) red = new NetworkSender(Piece::RED, red, blueNetwork); logMessage(" (Red's responses will be copied over the connection)\n"); } + + red->FixName(); blue->FixName(); + +} + +string itostr(int i) +{ + stringstream s; + s << i; + return s.str(); +} + + +void Game::PrintResults(const MovementResult & result, string & buffer) +{ + stringstream s(""); + switch (Game::theGame->Turn()) + { + case Piece::RED: + s << Game::theGame->red->name << " RED "; + break; + case Piece::BLUE: + s << Game::theGame->blue->name << " BLUE "; + break; + case Piece::BOTH: + s << "neither BOTH "; + break; + case Piece::NONE: + s << "neither NONE "; + break; + } + + if (!Board::LegalResult(result) && result != MovementResult::BAD_SETUP) + s << "ILLEGAL "; + else if (!Board::HaltResult(result)) + s << "INTERNAL_ERROR "; + else + { + switch (result.type) + { + case MovementResult::VICTORY_FLAG: + case MovementResult::VICTORY_ATTRITION: //It does not matter how you win, it just matters that you won! + s << "VICTORY "; + break; + case MovementResult::SURRENDER: + s << "SURRENDER "; + break; + case MovementResult::DRAW: + s << "DRAW "; + break; + case MovementResult::DRAW_DEFAULT: + s << "DRAW_DEFAULT "; + break; + case MovementResult::BAD_SETUP: + s << "BAD_SETUP "; + break; + default: + s << "INTERNAL_ERROR "; + break; + } + } + s << Game::theGame->TurnCount() << " " << Game::theGame->theBoard.TotalPieceValue(Piece::RED) << " " << Game::theGame->theBoard.TotalPieceValue(Piece::BLUE); + + buffer = s.str(); + + }