X-Git-Url: https://git.ucc.asn.au/?p=progcomp2012.git;a=blobdiff_plain;f=progcomp%2Fjudge%2Fmanager%2Fgame.cpp;fp=progcomp%2Fjudge%2Fmanager%2Fgame.cpp;h=0000000000000000000000000000000000000000;hp=3d6dcc805ab091e57fac2121c64ee0bf2f1cf273;hb=1a03b2543b67f0551e62babec4cd119f1e0e4640;hpb=e8a611c553bd336550c50ed7491d5800a2ae7142 diff --git a/progcomp/judge/manager/game.cpp b/progcomp/judge/manager/game.cpp deleted file mode 100644 index 3d6dcc8..0000000 --- a/progcomp/judge/manager/game.cpp +++ /dev/null @@ -1,609 +0,0 @@ -#include "game.h" - -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) : 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) -{ - gameCreated = false; - if (gameCreated) - { - fprintf(stderr, "Game::Game - Error - Tried to create more than one Game!\n"); - exit(EXIT_FAILURE); - } - gameCreated = true; - Game::theGame = this; - signal(SIGPIPE, Game::HandleBrokenPipe); - - - if (graphicsEnabled && (!Graphics::Initialised())) - Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32); - - if (strcmp(redPath, "human") == 0) - red = new Human_Controller(Piece::RED, graphicsEnabled); - else - red = new AI_Controller(Piece::RED, redPath); - - - if (strcmp(bluePath, "human") == 0) - blue = new Human_Controller(Piece::BLUE, graphicsEnabled); - else - blue = new AI_Controller(Piece::BLUE, bluePath); - - -} - -Game::Game(const char * fromFile, const bool enableGraphics, double newStallTime, const bool allowIllegal, FILE * newLog, const Piece::Colour & newReveal, int newMaxTurns, bool newPrintBoard) : 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) -{ - gameCreated = false; - if (gameCreated) - { - fprintf(stderr, "Game::Game - Error - Tried to create more than one Game!\n"); - exit(EXIT_FAILURE); - } - gameCreated = true; - Game::theGame = this; - signal(SIGPIPE, Game::HandleBrokenPipe); - - - if (graphicsEnabled && (!Graphics::Initialised())) - Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32); - - input = fopen(fromFile, "r"); - - red = new FileController(Piece::RED, input); - blue = new FileController(Piece::BLUE, input); - - -} - -Game::~Game() -{ - - delete red; - delete blue; - - if (log != NULL && log != stdout && log != stderr) - fclose(log); - - if (input != NULL && input != stdin) - fclose(input); -} - -/** - * Attempts to setup the board and controllers - * @param redName the name of the red AI - * @param blueName the name of the blue AI - * @returns A colour, indicating if there were any errors - Piece::NONE indicates no errors - Piece::BOTH indicates errors with both AI - Piece::RED / Piece::BLUE indicates an error with only one of the two AI - */ -Piece::Colour Game::Setup(const char * redName, const char * blueName) -{ - - if (!red->Valid()) - { - logMessage("Controller for Player RED is invalid!\n"); - if (!red->HumanController()) - logMessage("Check that program \"%s\" exists and has executable permissions set.\n", redName); - } - if (!blue->Valid()) - { - logMessage("Controller for Player BLUE is invalid!\n"); - if (!blue->HumanController()) - logMessage("Check that program \"%s\" exists and has executable permissions set.\n", blueName); - } - if (!red->Valid()) - { - if (!blue->Valid()) - return Piece::BOTH; - return Piece::RED; - } - else if (!blue->Valid()) - { - return Piece::BLUE; - } - - for (int y = 4; y < 6; ++y) - { - for (int x = 2; x < 4; ++x) - { - theBoard.AddPiece(x,y,Piece::BOULDER, Piece::NONE); - } - for (int x = 6; x < 8; ++x) - { - theBoard.AddPiece(x,y,Piece::BOULDER, Piece::NONE); - } - } - - - MovementResult redSetup = red->Setup(blueName); - MovementResult blueSetup = blue->Setup(redName); - - - Piece::Colour result = Piece::NONE; - if (redSetup != MovementResult::OK) - { - if (blueSetup != MovementResult::OK) - { - logMessage("BOTH players give invalid setup!\n"); - result = Piece::BOTH; - } - else - { - //logMessage("Player RED gave an invalid setup!\n"); - result = Piece::RED; - } - - } - else if (blueSetup != MovementResult::OK) - { - //logMessage("Player BLUE gave an invalid setup!\n"); - result = Piece::BLUE; - } - - - logMessage("%s RED SETUP\n", red->name.c_str()); - if (redSetup == MovementResult::OK) - { - for (int y=0; y < 4; ++y) - { - for (int x=0; x < theBoard.Width(); ++x) - { - if (theBoard.GetPiece(x, y) != NULL) - logMessage("%c", Piece::tokens[(int)(theBoard.GetPiece(x, y)->type)]); - else - logMessage("."); - } - logMessage("\n"); - } - } - else - { - logMessage("INVALID!\n"); - } - - logMessage("%s BLUE SETUP\n", blue->name.c_str()); - if (blueSetup == MovementResult::OK) - { - for (int y=0; y < 4; ++y) - { - for (int x=0; x < theBoard.Width(); ++x) - { - if (theBoard.GetPiece(x, theBoard.Height()-4+y) != NULL) - logMessage("%c", Piece::tokens[(int)(theBoard.GetPiece(x, theBoard.Height()-4+y)->type)]); - else - logMessage("."); - } - logMessage("\n"); - } - } - else - { - logMessage("INVALID!\n"); - } - - - return result; - -} - -void Game::Wait(double wait) -{ - if (wait <= 0) - return; - - TimerThread timer(wait*1000000); //Wait in seconds - timer.Start(); - - if (!graphicsEnabled) - { - while (!timer.Finished()); - timer.Stop(); - return; - } - - - while (!timer.Finished()) - { - SDL_Event event; - while (SDL_PollEvent(&event)) - { - switch (event.type) - { - case SDL_QUIT: - timer.Stop(); - exit(EXIT_SUCCESS); - break; - } - } - } - timer.Stop(); - -} - -void Game::HandleBrokenPipe(int sig) -{ - if (theGame == NULL) - { - 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: "); - theGame->blue->Message("DEFAULT"); - } - else if (theGame->turn == Piece::BLUE) - { - - theGame->logMessage("Game ends on BLUE's turn - REASON: "); - theGame->red->Message("DEFAULT"); - } - else - { - theGame->logMessage("Game ends on ERROR's turn - REASON: "); - - } - - theGame->logMessage("SIGPIPE - Broken pipe (AI program may have segfaulted)\n"); - - if (Game::theGame->printBoard) - Game::theGame->theBoard.PrintPretty(stdout, Piece::BOTH); - - if (Game::theGame->graphicsEnabled && theGame->log == stdout) - { - theGame->logMessage("CLOSE WINDOW TO EXIT\n"); - Game::theGame->theBoard.Draw(Piece::BOTH); - while (true) - { - SDL_Event event; - while (SDL_PollEvent(&event)) - { - switch (event.type) - { - case SDL_QUIT: - exit(EXIT_SUCCESS); - break; - } - } - } - } - else - { - if (theGame->log == stdout) - { - theGame->logMessage( "PRESS ENTER TO EXIT\n"); - theGame->theBoard.Print(theGame->log); - while (fgetc(stdin) != '\n'); - } - } - - - exit(EXIT_SUCCESS); -} - -void Game::PrintEndMessage(const MovementResult & result) -{ - if (turnCount == 0) - { - logMessage("Game ends in the SETUP phase - REASON: "); - } - else - { - if (turn == Piece::RED) - { - logMessage("Game ends on RED's turn - REASON: "); - } - else if (turn == Piece::BLUE) - { - logMessage("Game ends on BLUE's turn - REASON: "); - } - else - { - logMessage("Game ends on ERROR's turn - REASON: "); - - } - } - switch (result.type) - { - case MovementResult::OK: - logMessage("Status returned OK, unsure why game halted...\n"); - break; - case MovementResult::DIES: - logMessage("Status returned DIES, unsure why game halted...\n"); - break; - case MovementResult::KILLS: - logMessage("Status returned KILLS, unsure why game halted...\n"); - break; - case MovementResult::BOTH_DIE: - logMessage("Status returned BOTH_DIE, unsure why game halted...\n"); - break; - case MovementResult::NO_BOARD: - logMessage("Board does not exit?!\n"); - break; - case MovementResult::INVALID_POSITION: - logMessage("Coords outside board\n"); - break; - case MovementResult::NO_SELECTION: - logMessage("Move does not select a piece\n"); - break; - case MovementResult::NOT_YOUR_UNIT: - logMessage("Selected piece belongs to other player\n"); - break; - case MovementResult::IMMOBILE_UNIT: - logMessage("Selected piece is not mobile (FLAG or BOMB)\n"); - break; - case MovementResult::INVALID_DIRECTION: - logMessage("Selected unit cannot move that way\n"); - break; - case MovementResult::POSITION_FULL: - logMessage("Attempted move into square occupied by neutral or allied piece\n"); - break; - case MovementResult::VICTORY: - logMessage("Captured the flag\n"); - break; - case MovementResult::BAD_RESPONSE: - logMessage("Unintelligable response\n"); - break; - case MovementResult::NO_MOVE: - logMessage("Did not make a move (may have exited)\n"); - break; - case MovementResult::COLOUR_ERROR: - logMessage("Internal controller error - COLOUR_ERROR\n"); - break; - case MovementResult::ERROR: - logMessage("Internal controller error - Unspecified ERROR\n"); - break; - case MovementResult::DRAW_DEFAULT: - logMessage("Game declared a draw after %d turns\n", turnCount); - break; - case MovementResult::DRAW: - logMessage("Game declared a draw because neither player has mobile pieces\n"); - break; - case MovementResult::SURRENDER: - logMessage("This player has surrendered!\n"); - break; - case MovementResult::BAD_SETUP: - switch (turn) - { - case Piece::RED: - logMessage("An illegal setup was made by RED\n"); - break; - case Piece::BLUE: - logMessage("An illegal setup was made by BLUE\n"); - break; - case Piece::BOTH: - logMessage("An illegal setup was made by BOTH players\n"); - break; - case Piece::NONE: - logMessage("Unknown internal error.\n"); - break; - } - break; - - } - - if (printBoard) - { - system("clear"); - fprintf(stdout, "%d Final State\n", turnCount); - theBoard.PrintPretty(stdout, Piece::BOTH); - fprintf(stdout, "\n"); - } - if (graphicsEnabled && log == stdout) - { - logMessage("CLOSE WINDOW TO EXIT\n"); - theBoard.Draw(Piece::BOTH); - while (true) - { - SDL_Event event; - while (SDL_PollEvent(&event)) - { - switch (event.type) - { - case SDL_QUIT: - exit(EXIT_SUCCESS); - break; - } - } - } - } - else - { - if (log == stdout) - { - logMessage("PRESS ENTER TO EXIT\n"); - while (fgetc(stdin) != '\n'); - } - } - -} - - - -MovementResult Game::Play() -{ - - MovementResult result = MovementResult::OK; - turnCount = 1; - string buffer; - - Piece::Colour toReveal = reveal; - - - - - - red->Message("START"); - - - - while (!Board::HaltResult(result) && (turnCount < maxTurns || maxTurns < 0)) - { - if (red->HumanController() && blue->HumanController()) - toReveal = Piece::RED; - if (printBoard) - { - system("clear"); - if (turnCount == 0) - fprintf(stdout, "START:\n"); - else - fprintf(stdout, "%d BLUE:\n", turnCount); - theBoard.PrintPretty(stdout, toReveal); - fprintf(stdout, "\n\n"); - } - - if (graphicsEnabled) - theBoard.Draw(toReveal); - - turn = Piece::RED; - logMessage( "%d RED: ", turnCount); - result = red->MakeMove(buffer); - red->Message(buffer); - blue->Message(buffer); - logMessage( "%s\n", buffer.c_str()); - if (Board::HaltResult(result)) - break; - - if (stallTime > 0) - Wait(stallTime); - else - ReadUserCommand(); - - if (blue->HumanController() && red->HumanController()) - toReveal = Piece::BLUE; - if (printBoard) - { - system("clear"); - fprintf(stdout, "%d RED:\n", turnCount); - theBoard.PrintPretty(stdout, toReveal); - fprintf(stdout, "\n\n"); - } - if (graphicsEnabled) - theBoard.Draw(toReveal); - - - - turn = Piece::BLUE; - logMessage( "%d BLU: ", turnCount); - result = blue->MakeMove(buffer); - blue->Message(buffer); - red->Message(buffer); - logMessage( "%s\n", buffer.c_str()); - - if (Board::HaltResult(result)) - break; - - - - - - if (stallTime > 0) - Wait(stallTime); - else - ReadUserCommand(); - - if (theBoard.MobilePieces(Piece::BOTH) == 0) - result = MovementResult::DRAW; - - ++turnCount; - } - - if ((maxTurns >= 0 && turnCount >= maxTurns) && result == MovementResult::OK) - { - result = MovementResult::DRAW_DEFAULT; - } - - - return result; - - - -} - -/** - * Logs a message to the game's log file if it exists - * @param format the format string - * @param additional parameters - printed using va_args - * @returns the result of vfprintf or a negative number if the log file does not exist - */ -int Game::logMessage(const char * format, ...) -{ - if (log == NULL) - return -666; - va_list ap; - va_start(ap, format); - - int result = vfprintf(log, format, ap); - va_end(ap); - - return result; -} - -/** - * Waits for a user command - * Currently ignores the command. - */ -void Game::ReadUserCommand() -{ - fprintf(stdout, "Waiting for user to press enter...\n"); - string command(""); - for (char c = fgetc(stdin); c != '\n' && (int)(c) != EOF; c = fgetc(stdin)) - { - command += c; - } -} - -MovementResult FileController::QuerySetup(const char * opponentName, std::string setup[]) -{ - - char c = fgetc(file); - name = ""; - while (c != ' ') - { - name += c; - c = fgetc(file); - } - - while (fgetc(file) != '\n'); - - for (int y = 0; y < 4; ++y) - { - setup[y] = ""; - for (int x = 0; x < Game::theGame->theBoard.Width(); ++x) - { - setup[y] += fgetc(file); - } - - if (fgetc(file) != '\n') - { - return MovementResult::BAD_RESPONSE; - } - } - return MovementResult::OK; - - -} - -MovementResult FileController::QueryMove(std::string & buffer) -{ - char buf[BUFSIZ]; - - fgets(buf, sizeof(buf), file); - char * s = (char*)(buf); - while (*s != ':' && *s != '\0') - ++s; - - s += 2; - - buffer = string(s); - return MovementResult::OK; -} - -