Commit 2120cc40 authored by Sam Moore's avatar Sam Moore
Browse files

Modified manager output/protocol, added "basic" AI, made Asmodeus better

Thats all
parent fe470c01
...@@ -80,6 +80,16 @@ MovementResult Controller::MakeMove(string & buffer) ...@@ -80,6 +80,16 @@ MovementResult Controller::MakeMove(string & buffer)
if (query != MovementResult::OK) if (query != MovementResult::OK)
return query; return query;
if (buffer == "NO_MOVE")
{
buffer += " OK";
return MovementResult::OK;
}
if (buffer == "SURRENDER")
{
buffer += " OK";
return MovementResult::SURRENDER;
}
int x; int y; string direction=""; int x; int y; string direction="";
stringstream s(buffer); stringstream s(buffer);
...@@ -149,7 +159,7 @@ MovementResult Controller::MakeMove(string & buffer) ...@@ -149,7 +159,7 @@ MovementResult Controller::MakeMove(string & buffer)
} }
if (Game::theGame->allowIllegalMoves && !Board::LegalResult(moveResult)) if (Game::theGame->allowIllegalMoves && !Board::LegalResult(moveResult))
return MovementResult::OK; //HACK - Legal results returned! return MovementResult::OK; //HACK - Illegal results returned as legal!
else else
return moveResult; return moveResult;
......
...@@ -21,7 +21,7 @@ class Controller ...@@ -21,7 +21,7 @@ class Controller
void Message(std::string & buffer) {Message(buffer.c_str());} void Message(const std::string & buffer) {Message(buffer.c_str());}
virtual void Message(const char * string) = 0; virtual void Message(const char * string) = 0;
virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]) = 0; virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]) = 0;
......
...@@ -74,7 +74,16 @@ Game::~Game() ...@@ -74,7 +74,16 @@ Game::~Game()
fclose(input); fclose(input);
} }
bool Game::Setup(const char * redName, const char * blueName) /**
* 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()) if (!red->Valid())
...@@ -85,8 +94,16 @@ bool Game::Setup(const char * redName, const char * blueName) ...@@ -85,8 +94,16 @@ bool Game::Setup(const char * redName, const char * blueName)
{ {
logMessage("Controller for Player BLUE is invalid!\n"); logMessage("Controller for Player BLUE is invalid!\n");
} }
if (!red->Valid() || !blue->Valid()) if (!red->Valid())
return false; {
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 y = 4; y < 6; ++y)
{ {
...@@ -104,35 +121,38 @@ bool Game::Setup(const char * redName, const char * blueName) ...@@ -104,35 +121,38 @@ bool Game::Setup(const char * redName, const char * blueName)
MovementResult redSetup = red->Setup(blueName); MovementResult redSetup = red->Setup(blueName);
MovementResult blueSetup = blue->Setup(redName); MovementResult blueSetup = blue->Setup(redName);
Piece::Colour result = Piece::NONE;
if (redSetup != MovementResult::OK) if (redSetup != MovementResult::OK)
{ {
if (blueSetup != MovementResult::OK) if (blueSetup != MovementResult::OK)
{ {
logMessage("BOTH players give invalid setup!\n"); logMessage("BOTH players give invalid setup!\n");
red->Message("ILLEGAL"); result = Piece::BOTH;
blue->Message("ILLEGAL");
} }
else else
{ {
logMessage("Player RED gave an invalid setup!\n"); logMessage("Player RED gave an invalid setup!\n");
red->Message("ILLEGAL"); result = Piece::RED;
blue->Message("DEFAULT");
} }
return false;
} }
else if (blueSetup != MovementResult::OK) else if (blueSetup != MovementResult::OK)
{ {
logMessage("Player BLUE gave an invalid setup!\n"); logMessage("Player BLUE gave an invalid setup!\n");
red->Message("DEFAULT"); result = Piece::BLUE;
blue->Message("ILLEGAL");
return false;
} }
logMessage("%s RED SETUP\n", red->name.c_str()); logMessage("%s RED SETUP\n", red->name.c_str());
for (int y=0; y < 4; ++y) for (int y=0; y < 4; ++y)
{ {
for (int x=0; x < theBoard.Width(); ++x) for (int x=0; x < theBoard.Width(); ++x)
{
if (theBoard.GetPiece(x, y) != NULL)
logMessage("%c", Piece::tokens[(int)(theBoard.GetPiece(x, y)->type)]); logMessage("%c", Piece::tokens[(int)(theBoard.GetPiece(x, y)->type)]);
else
logMessage(".");
}
logMessage("\n"); logMessage("\n");
} }
...@@ -145,7 +165,7 @@ bool Game::Setup(const char * redName, const char * blueName) ...@@ -145,7 +165,7 @@ bool Game::Setup(const char * redName, const char * blueName)
} }
return true; return result;
} }
...@@ -241,6 +261,12 @@ void Game::HandleBrokenPipe(int sig) ...@@ -241,6 +261,12 @@ void Game::HandleBrokenPipe(int sig)
void Game::PrintEndMessage(const MovementResult & result) void Game::PrintEndMessage(const MovementResult & result)
{ {
if (turnCount == 0)
{
logMessage("Game ends in the SETUP phase - REASON: ");
}
else
{
if (turn == Piece::RED) if (turn == Piece::RED)
{ {
logMessage("Game ends on RED's turn - REASON: "); logMessage("Game ends on RED's turn - REASON: ");
...@@ -254,6 +280,7 @@ void Game::PrintEndMessage(const MovementResult & result) ...@@ -254,6 +280,7 @@ void Game::PrintEndMessage(const MovementResult & result)
logMessage("Game ends on ERROR's turn - REASON: "); logMessage("Game ends on ERROR's turn - REASON: ");
} }
}
switch (result.type) switch (result.type)
{ {
case MovementResult::OK: case MovementResult::OK:
...@@ -287,7 +314,7 @@ void Game::PrintEndMessage(const MovementResult & result) ...@@ -287,7 +314,7 @@ void Game::PrintEndMessage(const MovementResult & result)
logMessage("Selected unit cannot move that way\n"); logMessage("Selected unit cannot move that way\n");
break; break;
case MovementResult::POSITION_FULL: case MovementResult::POSITION_FULL:
logMessage("Attempted move into square occupied by allied piece\n"); logMessage("Attempted move into square occupied by neutral or allied piece\n");
break; break;
case MovementResult::VICTORY: case MovementResult::VICTORY:
logMessage("Captured the flag\n"); logMessage("Captured the flag\n");
...@@ -304,9 +331,32 @@ void Game::PrintEndMessage(const MovementResult & result) ...@@ -304,9 +331,32 @@ void Game::PrintEndMessage(const MovementResult & result)
case MovementResult::ERROR: case MovementResult::ERROR:
logMessage("Internal controller error - Unspecified ERROR\n"); logMessage("Internal controller error - Unspecified ERROR\n");
break; break;
case MovementResult::DRAW: case MovementResult::DRAW_DEFAULT:
logMessage("Game declared a draw after %d turns\n", turnCount); logMessage("Game declared a draw after %d turns\n", turnCount);
break; 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;
} }
...@@ -359,7 +409,7 @@ MovementResult Game::Play() ...@@ -359,7 +409,7 @@ MovementResult Game::Play()
red->Message("START"); red->Message("START");
//logMessage("START\n"); //logMessage("START\n");
while (Board::LegalResult(result) && (turnCount < maxTurns || maxTurns < 0)) while (!Board::HaltResult(result) && (turnCount < maxTurns || maxTurns < 0))
{ {
...@@ -369,7 +419,7 @@ MovementResult Game::Play() ...@@ -369,7 +419,7 @@ MovementResult Game::Play()
red->Message(buffer); red->Message(buffer);
blue->Message(buffer); blue->Message(buffer);
logMessage( "%s\n", buffer.c_str()); logMessage( "%s\n", buffer.c_str());
if (!Board::LegalResult(result)) if (Board::HaltResult(result))
break; break;
if (graphicsEnabled) if (graphicsEnabled)
theBoard.Draw(reveal); theBoard.Draw(reveal);
...@@ -389,7 +439,7 @@ MovementResult Game::Play() ...@@ -389,7 +439,7 @@ MovementResult Game::Play()
red->Message(buffer); red->Message(buffer);
logMessage( "%s\n", buffer.c_str()); logMessage( "%s\n", buffer.c_str());
if (!Board::LegalResult(result)) if (Board::HaltResult(result))
break; break;
...@@ -406,13 +456,15 @@ MovementResult Game::Play() ...@@ -406,13 +456,15 @@ MovementResult Game::Play()
Wait(stallTime); Wait(stallTime);
if (theBoard.MobilePieces(Piece::BOTH) == 0)
result = MovementResult::DRAW;
++turnCount; ++turnCount;
} }
if ((maxTurns >= 0 && turnCount >= maxTurns) && result == MovementResult::OK) if ((maxTurns >= 0 && turnCount >= maxTurns) && result == MovementResult::OK)
{ {
result = MovementResult::DRAW; result = MovementResult::DRAW_DEFAULT;
turn = Piece::BOTH;
} }
......
...@@ -21,7 +21,7 @@ class Game ...@@ -21,7 +21,7 @@ class Game
void Wait(double wait); void Wait(double wait);
bool Setup(const char * redName, const char * blueName); Piece::Colour Setup(const char * redName, const char * blueName);
MovementResult Play(); MovementResult Play();
void PrintEndMessage(const MovementResult & result); void PrintEndMessage(const MovementResult & result);
...@@ -30,6 +30,7 @@ class Game ...@@ -30,6 +30,7 @@ class Game
const Piece::Colour Turn() const {return turn;} const Piece::Colour Turn() const {return turn;}
void ForceTurn(const Piece::Colour & newTurn) {turn = newTurn;}
int TurnCount() const {return turnCount;} int TurnCount() const {return turnCount;}
static Game * theGame; static Game * theGame;
......
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
using namespace std; using namespace std;
void CreateGame(int argc, char ** argv); Piece::Colour SetupGame(int argc, char ** argv);
void DestroyGame(); void DestroyGame();
void PrintResults(const MovementResult & result); void PrintResults(const MovementResult & result, string & buffer);
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
...@@ -26,22 +26,40 @@ int main(int argc, char ** argv) ...@@ -26,22 +26,40 @@ int main(int argc, char ** argv)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
CreateGame(argc, argv);
if (Game::theGame == NULL)
Piece::Colour setupError = SetupGame(argc, argv);
MovementResult result = MovementResult::OK;
if (setupError == Piece::NONE)
{ {
fprintf(stderr, "ERROR: Couldn't create a game!\n"); result = Game::theGame->Play();
exit(EXIT_FAILURE); }
else
{
result = MovementResult::BAD_SETUP;
Game::theGame->ForceTurn(setupError);
} }
MovementResult result = Game::theGame->Play();
Game::theGame->PrintEndMessage(result); Game::theGame->PrintEndMessage(result);
PrintResults(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); exit(EXIT_SUCCESS);
return 0; return 0;
} }
void CreateGame(int argc, char ** argv) 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; 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; Piece::Colour reveal = Piece::BOTH; char * inputFile = NULL; int maxTurns = 5000; bool printBoard = false;
...@@ -54,7 +72,7 @@ void CreateGame(int argc, char ** argv) ...@@ -54,7 +72,7 @@ void CreateGame(int argc, char ** argv)
case 't': case 't':
if (argc - ii <= 1) if (argc - ii <= 1)
{ {
fprintf(stderr, "Expected timeout value after -t switch!\n"); fprintf(stderr, "ARGUMENT_ERROR - Expected timeout value after -t switch!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
timeout = atof(argv[ii+1]); timeout = atof(argv[ii+1]);
...@@ -73,12 +91,12 @@ void CreateGame(int argc, char ** argv) ...@@ -73,12 +91,12 @@ void CreateGame(int argc, char ** argv)
case 'o': case 'o':
if (argc - ii <= 1) if (argc - ii <= 1)
{ {
fprintf(stderr, "Expected filename or \"stdout\" after -o switch!\n"); fprintf(stderr, "ARGUMENT_ERROR - Expected filename or \"stdout\" after -o switch!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (log != NULL) if (log != NULL)
{ {
fprintf(stderr, "Expected at most ONE -o switch!\n"); fprintf(stderr, "ARGUMENT_ERROR - Expected at most ONE -o switch!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (strcmp(argv[ii+1], "stdout") == 0) if (strcmp(argv[ii+1], "stdout") == 0)
...@@ -105,10 +123,10 @@ void CreateGame(int argc, char ** argv) ...@@ -105,10 +123,10 @@ void CreateGame(int argc, char ** argv)
case 'm': case 'm':
if (argc - ii <= 1) if (argc - ii <= 1)
{ {
fprintf(stderr, "Expected max_turns value after -m switch!\n"); fprintf(stderr, "ARGUMENT_ERROR - Expected max_turns value after -m switch!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (strcmp(argv[ii+1], "inf")) if (strcmp(argv[ii+1], "inf") == 0)
maxTurns = -1; maxTurns = -1;
else else
maxTurns = atoi(argv[ii+1]); maxTurns = atoi(argv[ii+1]);
...@@ -117,12 +135,12 @@ void CreateGame(int argc, char ** argv) ...@@ -117,12 +135,12 @@ void CreateGame(int argc, char ** argv)
case 'f': case 'f':
if (argc - ii <= 1) if (argc - ii <= 1)
{ {
fprintf(stderr, "Expected filename after -f switch!\n"); fprintf(stderr, "ARGUMENT_ERROR - Expected filename after -f switch!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (log != NULL) if (log != NULL)
{ {
fprintf(stderr, "Expected at most ONE -f switch!\n"); fprintf(stderr, "ARGUMENT_ERROR - Expected at most ONE -f switch!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
red = (char*)("file"); red = (char*)("file");
...@@ -144,7 +162,7 @@ void CreateGame(int argc, char ** argv) ...@@ -144,7 +162,7 @@ void CreateGame(int argc, char ** argv)
} }
else else
{ {
fprintf(stderr, "Unrecognised switch \"%s\"...\n", argv[ii]); fprintf(stderr, "ARGUMENT_ERROR - Unrecognised switch \"%s\"...\n", argv[ii]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -158,67 +176,93 @@ void CreateGame(int argc, char ** argv) ...@@ -158,67 +176,93 @@ void CreateGame(int argc, char ** argv)
blue = argv[ii]; blue = argv[ii];
else else
{ {
fprintf(stderr, "Unexpected argument \"%s\"...\n", argv[ii]); fprintf(stderr, "ARGUMENT_ERROR - Unexpected argument \"%s\"...\n", argv[ii]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
} }
if (inputFile == NULL) if (inputFile == NULL)
{ {
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); Game::theGame = new Game(red,blue, graphics, timeout, allowIllegal,log, reveal,maxTurns, printBoard);
} }
else else
{ {
Game::theGame = new Game(inputFile, graphics, timeout, allowIllegal,log, reveal,maxTurns, printBoard); Game::theGame = new Game(inputFile, graphics, timeout, allowIllegal,log, reveal,maxTurns, printBoard);
} }
if (!Game::theGame->Setup(red, blue))
if (Game::theGame == NULL)
{ {
fprintf(stdout, "NONE %d\n",Game::theGame->TurnCount()); fprintf(stderr,"INTERNAL_ERROR - Error creating Game!\n");
exit(EXIT_SUCCESS); exit(EXIT_FAILURE);
} }
atexit(DestroyGame); atexit(DestroyGame);
} return Game::theGame->Setup(red, blue);
void PrintResults(const MovementResult & result)
{
Piece::Colour winner = Game::theGame->Turn();
if (Board::LegalResult(result))
{
if (winner == Piece::BOTH)
winner = Piece::NONE;
else
{
if (winner == Piece::RED)
winner = Piece::BLUE;
else
winner = Piece::RED;
}
}
}
switch (winner) void PrintResults(const MovementResult & result, string & buffer)
{
stringstream s("");
switch (Game::theGame->Turn())
{ {
case Piece::RED: case Piece::RED:
fprintf(stdout, "%s RED %d\n", Game::theGame->red->name.c_str(),Game::theGame->TurnCount()); s << Game::theGame->red->name << " RED ";
Game::theGame->logMessage("%s RED %d\n", Game::theGame->red->name.c_str(),Game::theGame->TurnCount());
break; break;
case Piece::BLUE: case Piece::BLUE:
fprintf(stdout, "%s BLUE %d\n", Game::theGame->blue->name.c_str(),Game::theGame->TurnCount()); s << Game::theGame->blue->name << " BLUE ";
Game::theGame->logMessage("%s BLUE %d\n", Game::theGame->blue->name.c_str(),Game::theGame->TurnCount());
break; break;
case Piece::BOTH: case Piece::BOTH:
fprintf(stdout, "DRAW %d\n",Game::theGame->TurnCount()); s << "neither BOTH ";
Game::theGame->logMessage("DRAW %d\n",Game::theGame->TurnCount());
break; break;
case Piece::NONE: case Piece::NONE:
fprintf(stdout, "NONE %d\n",Game::theGame->TurnCount()); s << "neither NONE ";