if (!Running())
return MovementResult::NO_MOVE; //AI has quit
Game::theGame->theBoard.Print(output, colour);
-
+ //Game::theGame->logMessage("DEBUG: About to get message from %d\n", colour);
if (!GetMessage(buffer,timeout))
{
return MovementResult::NO_MOVE; //AI did not respond (within the timeout). It will lose by default.
}
+ //Game::theGame->logMessage("DEBUG: Got message \"%s\" from %d\n", buffer.c_str(), colour);
return MovementResult::OK; //Got the message
}
virtual MovementResult QuerySetup(const char * opponentName,std::string setup[]);
virtual MovementResult QueryMove(std::string & buffer);
- virtual void Message(const char * message)
+ virtual bool Message(const char * message)
{
//fprintf(stderr, "Sending message \"%s\" to AI program...\n", message);
- Program::SendMessage(message);
+ return Program::SendMessage(message);
}
virtual void Pause() {Program::Pause();} //Hack wrapper
virtual void Continue() {Program::Continue();} //Hack wrapper
}
-
+
int x; int y; string direction="";
stringstream s(buffer);
s >> x;
s >> direction;
+
+
+
Board::Direction dir;
if (direction == "UP")
{
}
else
{
+
if (Game::theGame->allowIllegalMoves)
return MovementResult::OK;
else
virtual bool HumanController() const {return false;} //Hacky... overrides in human_controller... avoids having to use run time type info
- void Message(const std::string & buffer) {Message(buffer.c_str());}
- virtual void Message(const char * string) = 0;
+ bool Message(const std::string & buffer) {return Message(buffer.c_str());}
+ virtual bool Message(const char * string) = 0;
virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]) = 0;
virtual MovementResult QueryMove(std::string & buffer) = 0;
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);
}
}
break;
+
}
if (printBoard)
logMessage( "%d RED: ", turnCount);
result = red->MakeMove(buffer);
- red->Message(buffer);
- blue->Message(buffer);
logMessage( "%s\n", buffer.c_str());
if (!Board::HaltResult(result))
if (Board::HaltResult(result))
break;
+ red->Message(buffer);
+ blue->Message(buffer);
+
+
+
+
if (stallTime >= 0)
Wait(stallTime);
else
logMessage( "%d BLU: ", turnCount);
result = blue->MakeMove(buffer);
- blue->Message(buffer);
- red->Message(buffer);
logMessage( "%s\n", buffer.c_str());
if (!Board::HaltResult(result))
if (Board::HaltResult(result))
break;
+ red->Message(buffer);
+ blue->Message(buffer);
+
+
if (theBoard.MobilePieces(Piece::RED) == 0)
result = MovementResult::DRAW;
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();
+
+
+}
+
void MakeControllers(const char * redPath, const char * bluePath); //Create a controller based off a path
public:
int logMessage(const char * format, ...);
+ static void PrintResults(const MovementResult & result, std::string & buffer);
FILE * GetLogFile() const {return log;}
Controller * red;
Controller * blue;
FileController(const Piece::Colour & newColour, FILE * newFile) : Controller(newColour, "file"), file(newFile) {}
virtual ~FileController() {}
- virtual void Message(const char * string) {} //Don't send messages
+ virtual bool Message(const char * string) {return true;} //Don't send messages
virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]);
virtual MovementResult QueryMove(std::string & buffer);
virtual bool Valid() const {return file != NULL;}
virtual bool HumanController() const {return true;}
virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]);
virtual MovementResult QueryMove(std::string & buffer);
- virtual void Message(const char * message) {fprintf(stderr, "%s\n", message);}
+ virtual bool Message(const char * message) {return (strlen(message) <= 0 || fprintf(stderr, "%s\n", message) > 0);}
private:
const bool graphicsEnabled;
Piece::Colour SetupGame(int argc, char ** argv);
void DestroyGame();
-void PrintResults(const MovementResult & result, string & buffer);
+
char * video = NULL;
Game::theGame->PrintEndMessage(result);
string buffer = "";
- PrintResults(result, buffer);
+ Game::PrintResults(result, buffer);
//Message the AI's the quit message
Game::theGame->red->Message("QUIT " + buffer);
}
-void 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();
-
-
-}
void DestroyGame()
{
virtual bool Valid() const {return NetworkController::Valid() && controller->Valid();}
- virtual void Message(const char * message)
+ virtual bool Message(const char * message)
{
//fprintf(stderr,"NetworkSender sending message %s to underlying controller\n", message);
- controller->Message(message);
+ return (controller->Message(message));
}
virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]);
NetworkReceiver(const Piece::Colour & colour, Network * newNetwork) : NetworkController(colour, newNetwork) {}
virtual ~NetworkReceiver() {}
- virtual void Message(const char * message) {} //Do nothing (Counter intuitive much)
+ virtual bool Message(const char * message) {return true;} //Do nothing (Counter intuitive much)
virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]);
virtual MovementResult QueryMove(std::string & buffer);
buffer += c;
}
//fprintf(stderr, "%s\n", buffer.c_str());
+ //fprintf(stderr,"DONE\n");
return true;
/* Old way, using threads, which apparently is terrible