class AI_Controller : public Controller, private Program
{
public:
- AI_Controller(const Piece::Colour & newColour, const char * executablePath, const double newTimeout = 2.0) : Controller(newColour), Program(executablePath), timeout(newTimeout) {}
+ AI_Controller(const Piece::Colour & newColour, const char * executablePath, const double newTimeout = 2.0) : Controller(newColour, executablePath), Program(executablePath), timeout(newTimeout) {}
virtual ~AI_Controller() {}
virtual void Message(const char * message) {Program::SendMessage(message);}
+ virtual bool Valid() const {return Program::Running();}
+
private:
const double timeout; //Timeout in seconds for messages from the AI Program
usedUnits[(int)(type)]++;
if (usedUnits[type] > Piece::maxUnits[(int)type])
{
- fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
+ //fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
return MovementResult::BAD_RESPONSE;
}
Game::theGame->theBoard.AddPiece(x, yStart+y, type, colour);
}
else
{
- fprintf(stderr, "BAD_RESPONSE \"%s\"\n", buffer.c_str());
+ //fprintf(stderr, "BAD_RESPONSE \"%s\"\n", buffer.c_str());
return MovementResult::BAD_RESPONSE; //Player gave bogus direction - it will lose by default.
}
class Controller
{
public:
- Controller(const Piece::Colour & newColour) : colour(newColour) {}
+ Controller(const Piece::Colour & newColour, const char * newName = "no-name") : colour(newColour), name(newName) {}
virtual ~Controller() {}
MovementResult Setup(const char * opponentName);
virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]) = 0;
virtual MovementResult QueryMove(std::string & buffer) = 0;
+ virtual bool Valid() const {return true;}
const Piece::Colour colour;
+ std::string name;
+
};
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) : red(NULL), blue(NULL), turn(Piece::RED), theBoard(10,10), graphicsEnabled(enableGraphics), stallTime(newStallTime), allowIllegalMoves(allowIllegal), log(newLog), reveal(newReveal), turnCount(0)
+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)
{
- static bool gameCreated = false;
+ gameCreated = false;
if (gameCreated)
{
- if (log != NULL)
- fprintf(log, "ERROR - Game has already been created!\n");
+ fprintf(stderr, "Game::Game - Error - Tried to create more than one Game!\n");
exit(EXIT_FAILURE);
}
gameCreated = true;
if (strcmp(bluePath, "human") == 0)
blue = new Human_Controller(Piece::BLUE, graphicsEnabled);
else
- blue = new AI_Controller(Piece::BLUE, redPath);
+ 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()
{
- fprintf(stderr, "Killing AI\n");
+
delete red;
delete blue;
if (log != NULL && log != stdout && log != stderr)
fclose(log);
+
+ if (input != NULL && input != stdin)
+ fclose(input);
}
bool Game::Setup(const char * redName, const char * blueName)
{
+ if (!red->Valid())
+ {
+ logMessage("Controller for Player RED is invalid!\n");
+ }
+ if (!blue->Valid())
+ {
+ logMessage("Controller for Player BLUE is invalid!\n");
+ }
+ if (!red->Valid() || !blue->Valid())
+ return false;
+
for (int y = 4; y < 6; ++y)
{
for (int x = 2; x < 4; ++x)
{
if (blueSetup != MovementResult::OK)
{
- if (log != NULL)
- fprintf(log, "BOTH players give invalid setup!\n");
+ logMessage("BOTH players give invalid setup!\n");
red->Message("ILLEGAL");
blue->Message("ILLEGAL");
}
else
{
- if (log != NULL)
- fprintf(log, "Player RED gave an invalid setup!\n");
+ logMessage("Player RED gave an invalid setup!\n");
red->Message("ILLEGAL");
blue->Message("DEFAULT");
}
}
else if (blueSetup != MovementResult::OK)
{
- if (log != NULL)
- fprintf(log, "Player BLUE gave an invalid setup!\n");
+ logMessage("Player BLUE gave an invalid setup!\n");
red->Message("DEFAULT");
blue->Message("ILLEGAL");
return false;
}
+
+ logMessage("%s RED SETUP\n", red->name.c_str());
+ for (int y=0; y < 4; ++y)
+ {
+ for (int x=0; x < theBoard.Width(); ++x)
+ logMessage("%c", Piece::tokens[(int)(theBoard.GetPiece(x, y)->type)]);
+ logMessage("\n");
+ }
+
+ logMessage("%s BLUE SETUP\n", blue->name.c_str());
+ for (int y=0; y < 4; ++y)
+ {
+ for (int x=0; x < theBoard.Width(); ++x)
+ logMessage("%c", Piece::tokens[(int)(theBoard.GetPiece(x, theBoard.Height()-4 + y)->type)]);
+ logMessage("\n");
+ }
+
+
return true;
}
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)
{
case MovementResult::ERROR:
logMessage("Internal controller error - Unspecified ERROR\n");
break;
+ case MovementResult::DRAW:
+ logMessage("Game declared a draw after %d turns\n", turnCount);
+ 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");
red->Message("START");
- logMessage("START");
- while (Board::LegalResult(result))
+ //logMessage("START\n");
+ while (Board::LegalResult(result) && (turnCount < maxTurns || maxTurns < 0))
{
break;
if (graphicsEnabled)
theBoard.Draw(reveal);
+ if (printBoard)
+ {
+ system("clear");
+ fprintf(stdout, "%d RED:\n", turnCount);
+ theBoard.PrintPretty(stdout, reveal);
+ fprintf(stdout, "\n\n");
+ }
Wait(stallTime);
turn = Piece::BLUE;
if (graphicsEnabled)
theBoard.Draw(reveal);
+ if (printBoard)
+ {
+ system("clear");
+ fprintf(stdout, "%d BLUE:\n", turnCount);
+ theBoard.PrintPretty(stdout, reveal);
+ fprintf(stdout, "\n\n");
+ }
+
Wait(stallTime);
++turnCount;
}
+ if ((maxTurns >= 0 && turnCount >= maxTurns) && result == MovementResult::OK)
+ {
+ result = MovementResult::DRAW;
+ turn = Piece::BOTH;
+ }
+
return result;
return result;
}
+
+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;
+}
class Game
{
public:
- Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH);
+ Game(const char * redPath, const char * bluePath, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH, int maxTurns = 5000, const bool printBoard = false);
+ Game(const char * fromFile, const bool enableGraphics, double newStallTime = 1.0, const bool allowIllegal=false, FILE * newLog = NULL, const Piece::Colour & newRevealed = Piece::BOTH, int maxTurns = 5000, const bool printBoard = false);
virtual ~Game();
int TurnCount() const {return turnCount;}
static Game * theGame;
- private:
+ public:
int logMessage(const char * format, ...);
+ FILE * GetLogFile() const {return log;}
Controller * red;
Controller * blue;
+ private:
Piece::Colour turn;
public:
private:
FILE * log;
+
Piece::Colour reveal;
int turnCount;
+
+ static bool gameCreated;
+
+ FILE * input;
+
+ int maxTurns;
+ const bool printBoard;
};
+class FileController : public Controller
+{
+ public:
+ 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 MovementResult QuerySetup(const char * opponentName, std::string setup[]);
+ virtual MovementResult QueryMove(std::string & buffer);
+ virtual bool Valid() const {return file != NULL;}
+
+ private:
+ FILE * file;
+
+
+};
+
+
#endif //MAIN_H
class Human_Controller : public Controller
{
public:
- Human_Controller(const Piece::Colour & newColour, const bool enableGraphics) : Controller(newColour), graphicsEnabled(enableGraphics) {}
+ Human_Controller(const Piece::Colour & newColour, const bool enableGraphics) : Controller(newColour, "human"), graphicsEnabled(enableGraphics) {}
virtual ~Human_Controller() {}
virtual MovementResult QuerySetup(const char * opponentName, std::string setup[]);
using namespace std;
+void CreateGame(int argc, char ** argv);
+void DestroyGame();
+void PrintResults(const MovementResult & result);
+
int main(int argc, char ** argv)
{
+
+
+
+ if (argc == 1)
+ {
+ fprintf(stderr, "Usage: stratego [options] red blue\n");
+ fprintf(stderr, " stratego --help\n");
+ exit(EXIT_SUCCESS);
+
+ }
+ CreateGame(argc, argv);
+ if (Game::theGame == NULL)
+ {
+ fprintf(stderr, "ERROR: Couldn't create a game!\n");
+ exit(EXIT_FAILURE);
+ }
+
+ MovementResult result = Game::theGame->Play();
+ Game::theGame->PrintEndMessage(result);
+ PrintResults(result);
+
+ exit(EXIT_SUCCESS);
+ return 0;
+}
+void CreateGame(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;
+ 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] == '-')
++ii;
break;
case 'g':
- graphics = true;
+ graphics = !graphics;
+ break;
+ case 'p':
+ printBoard = !printBoard;
break;
case 'i':
- allowIllegal = true;
+ allowIllegal = !allowIllegal;
break;
case 'o':
else
reveal = Piece::NONE;
break;
+ case 'm':
+ if (argc - ii <= 1)
+ {
+ fprintf(stderr, "Expected max_turns value after -m switch!\n");
+ exit(EXIT_FAILURE);
+ }
+ if (strcmp(argv[ii+1], "inf"))
+ maxTurns = -1;
+ else
+ maxTurns = atoi(argv[ii+1]);
+ ++ii;
+ break;
+ case 'f':
+ if (argc - ii <= 1)
+ {
+ fprintf(stderr, "Expected filename after -f switch!\n");
+ exit(EXIT_FAILURE);
+ }
+ if (log != NULL)
+ {
+ fprintf(stderr, "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");
}
}
}
- if (argc == 1)
+
+ if (inputFile == NULL)
{
- fprintf(stderr, "Usage: stratego [options] red blue\n");
- fprintf(stderr, " stratego --help\n");
- exit(EXIT_SUCCESS);
-
+ Game::theGame = new Game(red,blue, graphics, timeout, allowIllegal,log, reveal,maxTurns, printBoard);
}
-
- Game game(red, blue, graphics, timeout, allowIllegal, log, reveal);
-
-
- if (!game.Setup(red, blue))
+ else
+ {
+ Game::theGame = new Game(inputFile, graphics, timeout, allowIllegal,log, reveal,maxTurns, printBoard);
+ }
+ if (!Game::theGame->Setup(red, blue))
{
- fprintf(stdout, "NONE %d\n",game.TurnCount());
+ fprintf(stdout, "NONE %d\n",Game::theGame->TurnCount());
exit(EXIT_SUCCESS);
}
+
+ atexit(DestroyGame);
- MovementResult result = game.Play();
- game.PrintEndMessage(result);
+}
- Piece::Colour winner = game.Turn();
+void PrintResults(const MovementResult & result)
+{
+ Piece::Colour winner = Game::theGame->Turn();
if (Board::LegalResult(result))
{
if (winner == Piece::BOTH)
switch (winner)
{
case Piece::RED:
- fprintf(stdout, "%s RED %d\n", red,game.TurnCount());
+ fprintf(stdout, "%s RED %d\n", Game::theGame->red->name.c_str(),Game::theGame->TurnCount());
+ Game::theGame->logMessage("%s RED %d\n", Game::theGame->red->name.c_str(),Game::theGame->TurnCount());
break;
case Piece::BLUE:
- fprintf(stdout, "%s BLUE %d\n", blue,game.TurnCount());
+ fprintf(stdout, "%s BLUE %d\n", Game::theGame->blue->name.c_str(),Game::theGame->TurnCount());
+ Game::theGame->logMessage("%s BLUE %d\n", Game::theGame->blue->name.c_str(),Game::theGame->TurnCount());
break;
case Piece::BOTH:
- fprintf(stdout, "DRAW %d\n",game.TurnCount());
+ fprintf(stdout, "DRAW %d\n",Game::theGame->TurnCount());
+ Game::theGame->logMessage("DRAW %d\n",Game::theGame->TurnCount());
break;
case Piece::NONE:
- fprintf(stdout, "NONE %d\n",game.TurnCount());
+ fprintf(stdout, "NONE %d\n",Game::theGame->TurnCount());
+ Game::theGame->logMessage("NONE %d\n",Game::theGame->TurnCount());
break;
}
-
-
-
-
-
-
- exit(EXIT_SUCCESS);
-
- return 0;
}
-
+void DestroyGame()
+{
+ delete Game::theGame;
+ Game::theGame = NULL;
+}
This program is still a work in progress. Consider it a Beta version.
SYNOPSIS
- stratego {[-girb] [-o= output_file ] [-t= stall_time] red_player blue_player | {-h | --help}}
+ stratego {[-gpirb] [-o output_file ] [-t stall_time] [-m max_turns] {red_player blue_player | -f input_file} | {-h | --help} }
DESCRIPTION
stratego manages a game of Stratego. It stores the state of the board, and uses a simple protocol to interface with AI programs.
By itself, stratego does not "play" the game. An external AI program must be used. stratego is intended to be used for the testing of
various AI strategies, written in any programming language. It will be used for the UCC Programming Competition 2012.
- Unless -h, or --help is given, both red_player and blue_player must be supplied.
+ Unless the -h (--help) or -f switch is given, both red_player and blue_player must be supplied.
red_player
Should be either a path to an executable file which will control the Red player, or "human".
OPTIONS
-g
By default, graphics are disabled. If the -g switch is present, stratego will draw the game as it is played using OpenGL
+ -p
+ By default, even if graphics are disabled, the board state is not printed. If -p is present, the board will be printed to stdout.
+ If the system supports colour, the characters will be in colour.
+ If -p and -g are both present you will see both behaviours (overkill)!
-i
By default, stratego will exit if a move which is deemed "illegal" is made. If the -i switch is present, illegal moves will be ignored.
That is, the move will not be made (effectively the player making the illegal move loses a turn).
-t
By default, stratego executes moves as fast as they are recieved. If the -t switch is present, a delay of stall_time will be introduced
between each move.
+
+ -m
+ By default, the game is declared a Draw after 5000 turns have ellapsed.
+ Use this option to change the maximum number of turns.
+ To play for an infinite number of turns, supply "inf" as max_number.
+
+ -f
+ By default, stratego requires red_player and blue_player to enact a game.
+ If this option is supplied, a file previously produced by using the -o switch is read, and the game reenacted.
+ All switches function as normal with -f.
+ NOTE: It is recommended that -g is used with -f.
+
-h, --help
- If the -h switch is present, this page will be printed and stratego will exit.
+ If the -h switch is used, this page will be printed and stratego will exit.
+
+
GAME RULES
Each player sets up 40 pieces on the Board. The pieces consist of the following:
class MovementResult
{
public:
- typedef enum {OK, DIES, KILLS, BOTH_DIE, NO_BOARD, INVALID_POSITION, NO_SELECTION, NOT_YOUR_UNIT, IMMOBILE_UNIT, INVALID_DIRECTION, POSITION_FULL, VICTORY, BAD_RESPONSE, NO_MOVE, COLOUR_ERROR, ERROR} Type;
+ typedef enum {OK, DIES, KILLS, BOTH_DIE, NO_BOARD, INVALID_POSITION, NO_SELECTION, NOT_YOUR_UNIT, IMMOBILE_UNIT, INVALID_DIRECTION, POSITION_FULL, VICTORY, BAD_RESPONSE, NO_MOVE, COLOUR_ERROR, ERROR, DRAW} Type;
MovementResult(const Type & result = OK, const Piece::Type & newAttackerRank = Piece::NOTHING, const Piece::Type & newDefenderRank = Piece::NOTHING)
: type(result), attackerRank(newAttackerRank), defenderRank(newDefenderRank) {}
if (kill(pid, 0) == 0) //Check if the process created is still running...
{
fputc(EOF, output); //If it was, tell it to stop with EOF
- sleep(1); //Give it 1 second to respond...
+ usleep(500000); //Give it 1/2 a second to respond...
if (kill(pid, 0) == 0) //Check if its still running
{
kill(pid, 9); //Slay the infidel mercilessly!
/**
* Print textual representation of the board to a stream
* @param stream - the stream to print information to
- * @param reveal - Pieces matching this colour will have their identify revealed, other pieces will be shown as '#' or '*' for RED or BLUE respectively.
+ * @param reveal - Pieces matching this colour will have their identify revealed, other pieces will be shown as '#'
*/
void Board::Print(FILE * stream, const Piece::Colour & reveal)
{
}
else if (piece->colour != Piece::NONE && (piece->colour == reveal || reveal == Piece::BOTH))
{
+
fprintf(stream, "%c", Piece::tokens[piece->type]);
+
+
}
else
{
switch (piece->colour)
{
case Piece::RED:
+ case Piece::BLUE:
fprintf(stream, "#");
+ break;
+ case Piece::NONE:
+ fprintf(stream, "+");
+ break;
+ case Piece::BOTH:
+ fprintf(stream, "$");
+ break;
+ }
+ }
+ }
+ fprintf(stream, "\n");
+ }
+
+}
+
+/**
+ * Print textual representation of the board to a stream
+ * @param stream - the stream to print information to
+ * @param reveal - Pieces matching this colour will have their identify revealed, other pieces will be shown as '#'
+ */
+void Board::PrintPretty(FILE * stream, const Piece::Colour & reveal)
+{
+ for (int y=0; y < height; ++y)
+ {
+ for (int x=0; x < width; ++x)
+ {
+ Piece * piece = board[x][y];
+ if (piece == NULL)
+ {
+ fprintf(stream, ".");
+ }
+ else if (piece->colour != Piece::NONE && (piece->colour == reveal || reveal == Piece::BOTH))
+ {
+ switch (piece->colour)
+ {
+ case Piece::RED:
+ fprintf(stream, "%c[%d;%d;%dm",0x1B,1,31,40);
+ break;
+ case Piece::BLUE:
+ fprintf(stream, "%c[%d;%d;%dm",0x1B,1,34,40);
+ break;
+ default:
+ break;
+ }
+ fprintf(stream, "%c", Piece::tokens[piece->type]);
+
+ }
+ else
+ {
+ switch (piece->colour)
+ {
+ case Piece::RED:
+ fprintf(stream, "%c[%d;%d;%dm",0x1B,1,31,41);
+
break;
case Piece::BLUE:
- fprintf(stream, "*");
+ fprintf(stream, "%c[%d;%d;%dm",0x1B,1,34,44);
break;
case Piece::NONE:
- fprintf(stream, "+");
+ fprintf(stream, "%c[%d;%d;%dm",0x1B,1,37,47);
break;
case Piece::BOTH:
- fprintf(stream, "$"); //Should never see these!
+ //Should never see this
+ fprintf(stream, "%c[%d;%d;%dm",0x1B,1,33,43);
break;
- }
+
+ }
+ fprintf(stream, "#");
+
}
+ fprintf(stream, "%c[%d;%d;%dm",0x1B,0,7,0);
}
fprintf(stream, "\n");
}
virtual ~Board(); //Destructor
void Print(FILE * stream, const Piece::Colour & reveal=Piece::BOTH); //Print board
+ void PrintPretty(FILE * stream, const Piece::Colour & reveal=Piece::BOTH); //Print board using colour
void Draw(const Piece::Colour & reveal=Piece::BOTH); //Draw board
static bool LegalResult(const MovementResult & result)
{
- return (result == MovementResult::OK || result == MovementResult::DIES || result == MovementResult::KILLS || result == MovementResult::BOTH_DIE);
+ return (result == MovementResult::OK || result == MovementResult::DIES || result == MovementResult::KILLS || result == MovementResult::BOTH_DIE || result == MovementResult::VICTORY || result == MovementResult::DRAW);
}
MovementResult MovePiece(int x, int y, const Direction & direction, int multiplier=1,const Piece::Colour & colour=Piece::NONE); //Move piece from position in direction
--- /dev/null
+forfax RED SETUP
+FB8sB479B8
+BB31555583
+6724898974
+967B669999
+dummy BLUE SETUP
+967B669999
+6724898974
+BB31555583
+FB8sB479B8
+1 RED: 9 3 DOWN OK
+1 BLU: 1 6 UP OK
+2 RED: 9 4 DOWN OK
+2 BLU: 8 6 UP OK
+3 RED: 9 5 DOWN DIES 9 9
+3 BLU: 2 6 LEFT OK
+4 RED: 8 3 DOWN OK
+4 BLU: 0 6 UP OK
+5 RED: 8 2 DOWN OK
+5 BLU: 0 7 UP OK
+6 RED: 9 2 LEFT OK
+6 BLU: 1 5 UP OK
+7 RED: 8 4 DOWN KILLS 9 9
+7 BLU: 4 6 UP OK
+8 RED: 4 3 DOWN OK
+8 BLU: 7 6 RIGHT OK
+9 RED: 5 3 LEFT OK
+9 BLU: 0 6 DOWN OK
+10 RED: 5 2 DOWN OK
+10 BLU: 1 4 UP DIES 6 6
+11 RED: 8 5 DOWN DIES 9 9
+11 BLU: 6 6 RIGHT OK
+12 RED: 4 4 DOWN DIES 6 6
+12 BLU: 9 6 UP OK
+13 RED: 9 1 DOWN OK
+13 BLU: 1 6 LEFT OK
+14 RED: 8 1 RIGHT OK
+14 BLU: 6 7 UP OK
+15 RED: 8 3 RIGHT OK
+15 BLU: 1 7 UP OK
+16 RED: 8 2 DOWN OK
+16 BLU: 0 5 RIGHT OK
+17 RED: 9 3 DOWN OK
+17 BLU: 1 5 UP OK
+18 RED: 9 2 DOWN OK
+18 BLU: 6 8 UP OK
+19 RED: 9 4 DOWN KILLS 7 9
+19 BLU: 0 6 UP OK
+20 RED: 5 1 DOWN OK
+20 BLU: 9 7 UP OK
+21 RED: 4 3 DOWN OK
+21 BLU: 6 9 UP OK
+22 RED: 9 5 DOWN DIES 7 4
+22 BLU: 9 8 UP OK
+23 RED: 1 3 DOWN KILLS 6 9
+23 BLU: 6 8 DOWN OK
+24 RED: 0 3 RIGHT OK
+24 BLU: 6 7 DOWN OK
+25 RED: 4 4 DOWN DIES 6 6
+25 BLU: 9 9 UP OK
+26 RED: 6 1 LEFT OK
+26 BLU: 5 6 UP OK
+27 RED: 8 3 DOWN OK
+27 BLU: 8 6 UP OK
+28 RED: 9 1 DOWN OK
+28 BLU: 0 5 RIGHT OK
+29 RED: 8 4 DOWN KILLS 4 9
+29 BLU: 1 5 UP DIES 7 6
+30 RED: 9 3 DOWN OK
+30 BLU: 4 5 UP OK
+31 RED: 7 1 LEFT OK
+31 BLU: 5 5 UP OK
+32 RED: 5 3 DOWN DIES 9 6
+32 BLU: 4 7 UP OK
+33 RED: 5 2 DOWN OK
+33 BLU: 5 4 UP DIES 6 5
+34 RED: 8 5 DOWN OK
+34 BLU: 7 6 RIGHT DIES 9 4
+35 RED: 5 3 LEFT OK
+35 BLU: 8 7 UP DIES 7 4
+36 RED: 9 4 DOWN OK
+36 BLU: 6 6 DOWN OK
+37 RED: 4 3 DOWN KILLS 5 6
+37 BLU: 8 8 UP OK
+38 RED: 9 5 DOWN KILLS 3 4
+38 BLU: 7 8 RIGHT OK
+39 RED: 8 6 LEFT OK
+39 BLU: 7 9 UP OK
+40 RED: 9 6 DOWN KILLS 3 3
+40 BLU: 7 7 UP DIES 9 4
+41 RED: 6 3 LEFT OK
+41 BLU: 9 8 UP DIES 8 3
+42 RED: 9 7 LEFT KILLS 3 8
+42 BLU: 6 9 RIGHT OK
+43 RED: 7 6 DOWN OK
+43 BLU: 5 7 UP OK
+44 RED: 8 7 DOWN KILLS 3 5
+44 BLU: 3 7 RIGHT OK
+45 RED: 7 7 LEFT KILLS 4 8
+45 BLU: 4 6 UP OK
+46 RED: 4 4 DOWN KILLS 5 8
+46 BLU: 6 8 UP DIES 5 4
+47 RED: 5 3 DOWN OK
+47 BLU: 3 8 UP OK
+48 RED: 8 8 LEFT KILLS 3 9
+48 BLU: 3 9 UP OK
+49 RED: 6 7 DOWN OK
+49 BLU: 0 7 RIGHT OK
+50 RED: 6 8 LEFT KILLS 4 5
+50 BLU: 3 8 DOWN OK
+51 RED: 7 8 DOWN KILLS 3 7
+51 BLU: 1 6 LEFT OK
+52 RED: 5 8 LEFT KILLS 4 5
+52 BLU: 2 8 RIGHT OK
+53 RED: 5 4 LEFT OK
+53 BLU: 3 8 LEFT OK
+54 RED: 7 9 RIGHT BOTHDIE 3 B
+54 BLU: 1 7 LEFT OK
+55 RED: 4 8 DOWN BOTHDIE 4 B
+55 BLU: 2 8 RIGHT OK
+56 RED: 4 2 DOWN OK
+56 BLU: 2 9 UP OK
+57 RED: 7 3 LEFT OK
+57 BLU: 2 8 DOWN OK
+58 RED: 6 2 LEFT OK
+58 BLU: 2 9 UP OK
+59 RED: 1 4 DOWN OK
+59 BLU: 2 8 DOWN OK
+60 RED: 7 2 LEFT OK
+60 BLU: 2 7 UP OK
+61 RED: 1 3 DOWN OK
+61 BLU: 2 9 UP OK
+62 RED: 4 5 RIGHT OK
+62 BLU: 2 8 UP OK
+63 RED: 4 4 DOWN OK
+63 BLU: 3 9 LEFT OK
+64 RED: 2 3 LEFT OK
+64 BLU: 3 8 DOWN OK
+65 RED: 2 2 DOWN OK
+65 BLU: 3 7 DOWN OK
+66 RED: 1 5 DOWN OK
+66 BLU: 2 6 LEFT KILLS 2 6
+67 RED: 4 3 DOWN OK
+67 BLU: 3 8 LEFT OK
+68 RED: 6 3 LEFT OK
+68 BLU: 3 9 RIGHT OK
+69 RED: 4 5 DOWN OK
+69 BLU: 2 9 RIGHT OK
+70 RED: 4 6 LEFT BOTHDIE 9 B
+70 BLU: 4 9 UP OK
+71 RED: 1 4 DOWN OK
+71 BLU: 2 8 DOWN OK
+72 RED: 6 2 DOWN OK
+72 BLU: 2 9 UP OK
+73 RED: 5 3 DOWN OK
+73 BLU: 3 9 LEFT OK
+74 RED: 5 2 DOWN OK
+74 BLU: 0 6 UP OK
+75 RED: 1 2 RIGHT OK
+75 BLU: 0 7 RIGHT OK
+76 RED: 4 4 DOWN OK
+76 BLU: 5 9 LEFT OK
+77 RED: 7 0 DOWN OK
+77 BLU: 1 7 LEFT OK
+78 RED: 1 3 DOWN OK
+78 BLU: 2 8 RIGHT OK
+79 RED: 5 5 DOWN KILLS 5 9
+79 BLU: 4 8 RIGHT OK
+80 RED: 5 4 DOWN OK
+80 BLU: 2 9 RIGHT OK
+81 RED: 4 5 DOWN OK
+81 BLU: 3 9 LEFT OK
+82 RED: 0 2 RIGHT OK
+82 BLU: 0 5 RIGHT KILLS 7 9
+83 RED: 2 3 LEFT OK
+83 BLU: 2 9 RIGHT OK
+84 RED: 3 2 RIGHT OK
+84 BLU: 3 9 LEFT OK
+85 RED: 4 6 DOWN DIES 8 4
+85 BLU: 1 5 LEFT OK
+86 RED: 5 6 RIGHT OK
+86 BLU: 0 5 RIGHT OK
+87 RED: 3 1 DOWN OK
+87 BLU: 0 7 RIGHT OK
+88 RED: 4 1 LEFT OK
+88 BLU: 3 8 UP OK
+89 RED: 5 5 LEFT OK
+89 BLU: 1 7 LEFT OK
+90 RED: 6 6 DOWN OK
+90 BLU: 2 7 UP OK
+91 RED: 5 3 DOWN OK
+91 BLU: 2 6 RIGHT OK
+92 RED: 6 3 LEFT OK
+92 BLU: 1 6 DOWN OK
+93 RED: 4 5 DOWN OK
+93 BLU: 2 9 RIGHT OK
+94 RED: 6 7 DOWN OK
+94 BLU: 3 6 LEFT OK
+95 RED: 6 8 LEFT DIES 5 3
+95 BLU: 4 9 RIGHT OK
+96 RED: 9 0 DOWN OK
+96 BLU: 5 8 LEFT OK
+97 RED: 4 6 LEFT OK
+97 BLU: 4 8 DOWN OK
+98 RED: 1 4 DOWN KILLS 7 7
+98 BLU: 3 9 LEFT OK
+99 RED: 2 2 DOWN OK
+99 BLU: 0 7 UP OK
+100 RED: 3 6 DOWN DIES 9 1
+100 BLU: 4 7 RIGHT OK
+101 RED: 2 1 DOWN OK
+101 BLU: 2 9 RIGHT OK
+102 RED: 2 0 DOWN OK
+102 BLU: 3 9 LEFT OK
+103 RED: 5 4 LEFT OK
+103 BLU: 2 9 RIGHT OK
+104 RED: 1 5 DOWN OK
+104 BLU: 1 7 LEFT OK
+105 RED: 5 3 LEFT OK
+105 BLU: 3 9 UP OK
+106 RED: 1 6 RIGHT KILLS 7 8
+106 BLU: 0 7 RIGHT OK
+107 RED: 1 3 DOWN OK
+107 BLU: 3 7 LEFT OK
+108 RED: 1 2 DOWN OK
+108 BLU: 1 7 LEFT OK
+109 RED: 2 2 LEFT OK
+109 BLU: 4 9 LEFT OK
+110 RED: 2 1 DOWN OK
+110 BLU: 3 9 LEFT OK
+111 RED: 1 4 DOWN OK
+111 BLU: 2 9 RIGHT OK
+112 RED: 1 5 DOWN OK
+112 BLU: 3 9 LEFT OK
+113 RED: 1 3 DOWN OK
+113 BLU: 2 9 UP OK
+114 RED: 1 4 DOWN OK
+114 BLU: 2 8 DOWN OK
+115 RED: 2 3 LEFT OK
+115 BLU: 5 9 LEFT OK
+116 RED: 1 3 DOWN OK
+116 BLU: 0 7 RIGHT OK
+117 RED: 2 2 DOWN OK
+117 BLU: 2 7 RIGHT OK
+118 RED: 2 3 LEFT OK
+118 BLU: 3 8 DOWN OK
+119 RED: 1 6 DOWN DIES 2 2
+119 BLU: 4 9 RIGHT OK
+120 RED: 2 6 LEFT OK
+120 BLU: 2 9 UP OK
+121 RED: 3 2 LEFT OK
+121 BLU: 5 9 LEFT OK
+122 RED: 2 2 DOWN OK
+122 BLU: 1 7 LEFT OK
+123 RED: 3 1 LEFT OK
+123 BLU: 0 6 RIGHT KILLS 6 7
+124 RED: 1 5 DOWN DIES 6 6
+124 BLU: 4 9 RIGHT OK
+125 RED: 2 1 DOWN OK
+125 BLU: 3 9 LEFT OK
+126 RED: 2 2 RIGHT OK
+126 BLU: 2 8 RIGHT OK
+127 RED: 3 2 UP OK
+127 BLU: 5 9 LEFT OK
+128 RED: 4 2 RIGHT OK
+128 BLU: 0 7 RIGHT OK
+129 RED: 3 1 LEFT OK
+129 BLU: 1 7 LEFT OK
+130 RED: 2 1 DOWN OK
+130 BLU: 0 7 RIGHT OK
+131 RED: 2 2 RIGHT OK
+131 BLU: 1 7 LEFT OK
+132 RED: 3 2 RIGHT OK
+132 BLU: 2 9 RIGHT OK
+133 RED: 5 1 LEFT OK
+133 BLU: 3 9 LEFT OK
+134 RED: 4 1 LEFT OK
+134 BLU: 0 7 RIGHT OK
+135 RED: 3 1 LEFT OK
+135 BLU: 1 7 LEFT OK
+136 RED: 2 1 DOWN OK
+136 BLU: 2 9 RIGHT OK
+137 RED: 2 2 RIGHT OK
+137 BLU: 3 9 LEFT OK
+138 RED: 4 2 UP OK
+138 BLU: 2 9 RIGHT OK
+139 RED: 3 2 RIGHT OK
+139 BLU: 3 9 LEFT OK
+140 RED: 4 1 LEFT OK
+140 BLU: 2 9 RIGHT OK
+141 RED: 3 1 LEFT OK
+141 BLU: 0 7 RIGHT OK
+142 RED: 2 1 DOWN OK
+142 BLU: 3 9 LEFT OK
+143 RED: 4 2 UP OK
+143 BLU: 3 8 DOWN OK
+144 RED: 2 2 RIGHT OK
+144 BLU: 2 9 UP OK
+145 RED: 4 1 LEFT OK
+145 BLU: 4 9 RIGHT OK
+146 RED: 3 1 LEFT OK
+146 BLU: 5 9 LEFT OK
+147 RED: 2 1 DOWN OK
+147 BLU: 3 9 LEFT OK
+148 RED: 3 2 RIGHT OK
+148 BLU: 1 6 LEFT OK
+149 RED: 2 2 RIGHT OK
+149 BLU: 1 7 LEFT OK
+150 RED: 3 2 UP OK
+150 BLU: 2 8 RIGHT OK
+151 RED: 3 1 LEFT OK
+151 BLU: 2 9 RIGHT OK
+152 RED: 2 1 DOWN OK
+152 BLU: 3 9 LEFT OK
+153 RED: 2 2 RIGHT OK
+153 BLU: 2 9 RIGHT OK
+154 RED: 4 4 DOWN OK
+154 BLU: 3 9 LEFT OK
+155 RED: 3 2 UP OK
+155 BLU: 2 9 RIGHT OK
+156 RED: 3 1 LEFT OK
+156 BLU: 0 7 RIGHT OK
+157 RED: 2 1 DOWN OK
+157 BLU: 3 9 LEFT OK
+158 RED: 2 2 RIGHT OK
+158 BLU: 2 9 RIGHT OK
+159 RED: 4 5 DOWN OK
+159 BLU: 3 9 LEFT OK
+160 RED: 4 6 LEFT OK
+160 BLU: 4 9 LEFT OK
+161 RED: 3 2 UP OK
+161 BLU: 2 9 UP OK
+162 RED: 3 6 LEFT OK
+162 BLU: 3 8 RIGHT OK
+163 RED: 3 1 LEFT OK
+163 BLU: 3 9 LEFT OK
+164 RED: 2 1 DOWN OK
+164 BLU: 2 9 RIGHT OK
+165 RED: 2 2 RIGHT OK
+165 BLU: 1 9 UP ILLEGAL
+Game ends on BLUE's turn - REASON: Selected piece is not mobile (FLAG or BOMB)
+forfax RED 165
//Print chosen move to stdout
cout << choice.piece->x << " " << choice.piece->y << " " << direction << "\n";
- cerr << "\nForfax move " << choice.piece->x << " " << choice.piece->y << " " << direction << " [score = " << choice.score << "]\n";
+ //cerr << "\nForfax move " << choice.piece->x << " " << choice.piece->y << " " << direction << " [score = " << choice.score << "]\n";
move = forfax.MakeMove();
}
+ /*
switch (move)
{
case Forfax::OK:
cerr << argv[0] << " Error - An error occurred with the board!\n";
break;
}
+ */
+ //cerr << "Final board state:\n";
+ //forfax.PrintBoard(cerr);
- cerr << "Final board state:\n";
- forfax.PrintBoard(cerr);
-
- cerr << "Forfax is now exiting!\n";
+ //cerr << "Forfax is now exiting!\n";
exit(EXIT_SUCCESS);