#include <stdlib.h>
#include <stdio.h>
-#include "common.h"
-#include "controller.h"
-#include "stratego.h"
-using namespace std;
-#define theBoard Board::theBoard
+#include "game.h"
-#ifdef GRAPHICS
- bool CheckForQuitWhilstWaiting(int wait);
-#endif //GRAPHICS
+using namespace std;
-Controller * red;
-Controller * blue;
+Piece::Colour SetupGame(int argc, char ** argv);
+void DestroyGame();
+void PrintResults(const MovementResult & result, string & buffer);
-void cleanup();
int main(int argc, char ** argv)
{
- assert(argc == 3);
- for (int y = 5; y < 9; ++y)
- {
- for (int x = 3; x < 5; ++x)
- {
- theBoard.AddPiece(x,y,Piece::BOULDER, Piece::NONE);
- }
- for (int x = 9; x < 11; ++x)
- {
- theBoard.AddPiece(x,y,Piece::BOULDER, Piece::NONE);
- }
- }
- red = new Controller(Piece::RED, argv[1]);
- blue = new Controller(Piece::BLUE, argv[2]);
- atexit(cleanup);
- Board::MovementResult redSetup = red->Setup(argv[2]);
- Board::MovementResult blueSetup = blue->Setup(argv[1]);
- if (redSetup != Board::OK)
+ if (argc == 1)
{
- fprintf(stderr, "Blue wins by DEFAULT!\n");
- red->SendMessage("ILLEGAL");
- blue->SendMessage("DEFAULT");
+ fprintf(stderr, "Usage: stratego [options] red blue\n");
+ fprintf(stderr, " stratego --help\n");
exit(EXIT_SUCCESS);
+
}
- if (blueSetup != Board::OK)
+
+
+ Piece::Colour setupError = SetupGame(argc, argv);
+ MovementResult result = MovementResult::OK;
+ if (setupError == Piece::NONE)
{
- fprintf(stderr, "Red wins by DEFAULT!\n");
- red->SendMessage("DEFAULT");
- blue->SendMessage("ILLEGAL");
- exit(EXIT_SUCCESS);
+ result = Game::theGame->Play();
}
+ else
+ {
+ result = MovementResult::BAD_SETUP;
+ Game::theGame->ForceTurn(setupError);
+ }
+
+ Game::theGame->PrintEndMessage(result);
- Board::MovementResult result = Board::OK;
- system("clear");
- int count = 1;
+ string buffer = "";
+ PrintResults(result, buffer);
- #ifdef GRAPHICS
- if (!Graphics::Initialised())
- Graphics::Initialise("Stratego", theBoard.Width()*32, theBoard.Height()*32);
-
- #endif //GRAPHICS
+ //Message the AI's the quit message
+ Game::theGame->red->Message("QUIT " + buffer);
+ Game::theGame->blue->Message("QUIT " + buffer);
- string buffer;
+ //Log the message
+ if (Game::theGame->GetLogFile() != stdout)
+ Game::theGame->logMessage("%s\n", buffer.c_str());
- red->SendMessage("START");
- Colour turn = Piece::RED;
- while (Board::LegalResult(result))
- {
+ fprintf(stdout, "%s\n", buffer.c_str());
- fprintf(stderr, "This is move %d...\n", count);
- fprintf(stderr,"---RED's turn---\n");
- turn = Piece::RED;
- result = red->MakeMove(buffer);
- red->SendMessage(buffer);
- blue->SendMessage(buffer);
+ exit(EXIT_SUCCESS);
+ return 0;
+}
- if (!Board::LegalResult(result))
- break;
- #ifdef GRAPHICS
- Board::theBoard.Draw();
- if (CheckForQuitWhilstWaiting(0.2))
+Piece::Colour SetupGame(int argc, char ** argv)
+{
+ char * red = NULL; char * blue = NULL; double timeout = 0.00001; bool graphics = false; bool allowIllegal = false; FILE * log = NULL;
+ Piece::Colour reveal = Piece::BOTH; char * inputFile = NULL; int maxTurns = 5000; bool printBoard = false;
+ for (int ii=1; ii < argc; ++ii)
+ {
+ if (argv[ii][0] == '-')
+ {
+ switch (argv[ii][1])
{
- red->SendMessage("QUIT");
- blue->SendMessage("QUIT");
- exit(EXIT_SUCCESS);
- }
- #endif //GRAPHICS
- fprintf(stderr,"---BLUE's turn---\n");
- turn = Piece::BLUE;
- result = blue->MakeMove(buffer);
- blue->SendMessage(buffer);
- red->SendMessage(buffer);
-
- if (!Board::LegalResult(result))
- break;
-
-
+ case 't':
+ if (argc - ii <= 1)
+ {
+ fprintf(stderr, "ARGUMENT_ERROR - Expected timeout value after -t switch!\n");
+ exit(EXIT_FAILURE);
+ }
+ timeout = atof(argv[ii+1]);
+ ++ii;
+ break;
+ case 'g':
+ graphics = !graphics;
+ break;
+ case 'p':
+ printBoard = !printBoard;
+ break;
+ case 'i':
+ allowIllegal = !allowIllegal;
+ break;
- #ifdef GRAPHICS
- Board::theBoard.Draw();
- if (CheckForQuitWhilstWaiting(0.2))
+ case 'o':
+ if (argc - ii <= 1)
+ {
+ fprintf(stderr, "ARGUMENT_ERROR - Expected filename or \"stdout\" after -o switch!\n");
+ exit(EXIT_FAILURE);
+ }
+ if (log != NULL)
+ {
+ fprintf(stderr, "ARGUMENT_ERROR - Expected at most ONE -o switch!\n");
+ exit(EXIT_FAILURE);
+ }
+ if (strcmp(argv[ii+1], "stdout") == 0)
+ log = stdout;
+ else
+ log = fopen(argv[ii+1], "w");
+ setbuf(log, NULL);
+
+ ++ii;
+ break;
+
+ case 'r':
+ if (reveal == Piece::BOTH)
+ reveal = Piece::BLUE;
+ else
+ reveal = Piece::NONE;
+ break;
+ case 'b':
+ if (reveal == Piece::BOTH)
+ reveal = Piece::RED;
+ else
+ reveal = Piece::NONE;
+ break;
+ case 'm':
+ if (argc - ii <= 1)
+ {
+ fprintf(stderr, "ARGUMENT_ERROR - Expected max_turns value after -m switch!\n");
+ exit(EXIT_FAILURE);
+ }
+ if (strcmp(argv[ii+1], "inf") == 0)
+ maxTurns = -1;
+ else
+ maxTurns = atoi(argv[ii+1]);
+ ++ii;
+ break;
+ case 'f':
+ if (argc - ii <= 1)
+ {
+ fprintf(stderr, "ARGUMENT_ERROR - Expected filename after -f switch!\n");
+ exit(EXIT_FAILURE);
+ }
+ if (log != NULL)
+ {
+ fprintf(stderr, "ARGUMENT_ERROR - Expected at most ONE -f switch!\n");
+ exit(EXIT_FAILURE);
+ }
+ red = (char*)("file");
+ blue = (char*)("file");
+ inputFile = argv[ii+1];
+ ++ii;
+ break;
+ case 'h':
+ system("clear");
+ system("less manual.txt");
+ exit(EXIT_SUCCESS);
+ break;
+ case '-':
+ if (strcmp(argv[ii]+2, "help") == 0)
+ {
+ system("clear");
+ system("less manual.txt");
+ exit(EXIT_SUCCESS);
+ }
+ else
+ {
+ fprintf(stderr, "ARGUMENT_ERROR - Unrecognised switch \"%s\"...\n", argv[ii]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ }
+ else
+ {
+ if (red == NULL)
+ red = argv[ii];
+ else if (blue == NULL)
+ blue = argv[ii];
+ else
{
- red->SendMessage("QUIT");
- blue->SendMessage("QUIT");
- exit(EXIT_SUCCESS);
+ fprintf(stderr, "ARGUMENT_ERROR - Unexpected argument \"%s\"...\n", argv[ii]);
+ exit(EXIT_FAILURE);
}
- #else
- Board::theBoard.Print(stderr);
- sleep(1);
- system("clear");
- #endif //GRAPHICS
-
- ++count;
+ }
}
- printf("Final board state\n");
- #ifdef GRAPHICS
- Board::theBoard.Draw();
- if (CheckForQuitWhilstWaiting(4))
- {
- red->SendMessage("QUIT");
- blue->SendMessage("QUIT");
- exit(EXIT_SUCCESS);
- }
- #else
- Board::theBoard.Print(stderr);
- #endif //GRAPHICS
- sleep(2);
- if (turn == Piece::RED)
+ if (inputFile == NULL)
{
- fprintf(stderr,"Game ends on RED's turn - REASON: ");
+ if (red == NULL || blue == NULL) //Not enough arguments
+ {
+ fprintf(stderr, "ARGUMENT_ERROR - Did not recieve enough players (did you mean to use the -f switch?)\n");
+ exit(EXIT_FAILURE);
+ }
+ Game::theGame = new Game(red,blue, graphics, timeout, allowIllegal,log, reveal,maxTurns, printBoard);
}
- else if (turn == Piece::BLUE)
+ else
{
- fprintf(stderr,"Game ends on BLUE's turn - REASON: ");
+ Game::theGame = new Game(inputFile, graphics, timeout, allowIllegal,log, reveal,maxTurns, printBoard);
}
- else
+
+ if (Game::theGame == NULL)
{
- fprintf(stderr,"Game ends on ERROR's turn - REASON: ");
-
+ fprintf(stderr,"INTERNAL_ERROR - Error creating Game!\n");
+ exit(EXIT_FAILURE);
}
- switch (result)
+ atexit(DestroyGame);
+
+ return Game::theGame->Setup(red, blue);
+
+
+}
+
+void PrintResults(const MovementResult & result, string & buffer)
+{
+ stringstream s("");
+ switch (Game::theGame->Turn())
{
- case Board::NO_BOARD:
- fprintf(stderr,"Board does not exit?!\n");
- break;
- case Board::INVALID_POSITION:
- fprintf(stderr,"Coords outside board\n");
- break;
- case Board::NO_SELECTION:
- fprintf(stderr,"Move does not select a piece\n");
- break;
- case Board::NOT_YOUR_UNIT:
- fprintf(stderr,"Selected piece belongs to other player\n");
- break;
- case Board::IMMOBILE_UNIT:
- fprintf(stderr,"Selected piece is not mobile (FLAG or BOMB)\n");
- break;
- case Board::INVALID_DIRECTION:
- fprintf(stderr,"Selected unit cannot move that way\n");
- break;
- case Board::POSITION_FULL:
- fprintf(stderr,"Attempted move into square occupied by allied piece\n");
+ case Piece::RED:
+ s << Game::theGame->red->name << " RED ";
break;
- case Board::VICTORY:
- fprintf(stderr,"Captured the flag\n");
+ case Piece::BLUE:
+ s << Game::theGame->blue->name << " BLUE ";
break;
- case Board::BAD_RESPONSE:
- fprintf(stderr,"Unintelligable response\n");
+ case Piece::BOTH:
+ s << "neither BOTH ";
break;
- case Board::NO_MOVE:
- fprintf(stderr,"Did not make a move (may have exited)\n");
+ case Piece::NONE:
+ s << "neither NONE ";
break;
}
-
-
- exit(EXIT_SUCCESS);
-
- return 0;
-}
-
-#ifdef GRAPHICS
-
-bool CheckForQuitWhilstWaiting(int wait)
-{
-
-
- TimerThread timer(wait*1000000); //Wait in seconds
- timer.Start();
- while (!timer.Finished())
+ if (!Board::LegalResult(result) && result != MovementResult::BAD_SETUP)
+ s << "ILLEGAL ";
+ else if (!Board::HaltResult(result))
+ s << "INTERNAL_ERROR ";
+ else
{
- SDL_Event event;
- while (SDL_PollEvent(&event))
+ switch (result.type)
{
- switch (event.type)
- {
- case SDL_QUIT:
- timer.Stop();
- return true;
- break;
- }
+ case MovementResult::VICTORY:
+ 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 << "BOTH_ILLEGAL ";
+ break;
+ default:
+ s << "INTERNAL_ERROR ";
+ break;
}
}
- timer.Stop();
- return false;
+
+ s << Game::theGame->TurnCount() << " " << Game::theGame->theBoard.TotalPieceValue(Piece::RED) << " " << Game::theGame->theBoard.TotalPieceValue(Piece::BLUE);
+
+ buffer = s.str();
+
+
}
-void cleanup()
+void DestroyGame()
{
- delete red;
- delete blue;
+ delete Game::theGame;
+ Game::theGame = NULL;
}
-
-#endif //GRAPHICS