Modified Turn Response Protocol, added handling for SIGPIPE, changed placeholder...
authorSam Moore <matches@ucc.asn.au>
Wed, 30 Nov 2011 04:36:18 +0000 (12:36 +0800)
committerSam Moore <matches@ucc.asn.au>
Wed, 30 Nov 2011 04:36:18 +0000 (12:36 +0800)
The "outcome" of a move is now listed as:

TYPE [ATTACKER_RANK] [DEFENDER_RANK]

Where ATTACKER_RANK and DEFENDER_RANK will be present if TYPE is one of: KILLS, DIES, BOTHDIE, and indicate the ranks of the pieces involved.
This involved adding a class MovementResult, which stores the ranks of pieces in addition to an enum, replacing the enum Board::MovementResult

The sample agent "forfax" was causing broken pipes, which caused the manager program to exit.
I added a handler for SIGPIPE in manager/main.cpp to ensure that the manager program reports a DEFAULT victory to the other AI, and exits gracefully.
However, I still don't know WHY forfax causes broken pipes, but hopefully its a problem with forfax and not with the manager program.

I edited the images used by the graphical display to show the ordered ranks of the pieces, rather than some obscure characters.
Unfortunately I have just realised that the enum used for Piece::Type stores ranks in the wrong order.
In the actual game, LOWER numbers are better, in my enum, HIGHER numbers are better.
To make things more confusing, I made the printed ATTACKER_RANK and DEFENDER_RANK correspond to the traditional numbering, not the enum numbering...

24 files changed:
manager/controller.cpp
manager/controller.h
manager/forfax [new symlink]
manager/images/piece10.bmp
manager/images/piece11.bmp
manager/images/piece12.bmp
manager/images/piece13.bmp
manager/images/piece2.bmp
manager/images/piece3.bmp
manager/images/piece4.bmp
manager/images/piece5.bmp
manager/images/piece6.bmp
manager/images/piece7.bmp
manager/images/piece8.bmp
manager/images/piece9.bmp
manager/main.cpp
manager/movementresult.h [new file with mode: 0644]
manager/program.cpp
manager/program.h
manager/stratego.cpp
manager/stratego.h
samples/forfax/forfax.cpp
samples/forfax/main.cpp
web/index.html

index dad6e44..736663e 100644 (file)
@@ -8,9 +8,10 @@ using namespace std;
 
 /**
  * Queries the AI program to setup its pieces
+ * @param opponentName - string containing the name/id of the opponent AI program
  * @returns the result of the response
  */
-Board::MovementResult Controller::Setup(const char * opponentName)
+MovementResult Controller::Setup(const char * opponentName)
 {
        int y;
        switch (colour)
@@ -48,12 +49,12 @@ Board::MovementResult Controller::Setup(const char * opponentName)
                if (!GetMessage(line, 2.5))
                {
                        fprintf(stderr, "Timeout on setup\n");
-                       return Board::BAD_RESPONSE;
+                       return MovementResult::BAD_RESPONSE;
                }
                if ((int)(line.size()) != Board::theBoard.Width())
                {
                        fprintf(stderr, "Bad length of \"%s\" on setup\n", line.c_str());
-                       return Board::BAD_RESPONSE;
+                       return MovementResult::BAD_RESPONSE;
                }
        
                for (int x = 0; x < (int)(line.size()); ++x)
@@ -69,7 +70,7 @@ Board::MovementResult Controller::Setup(const char * opponentName)
                                if (usedUnits[type] > Piece::maxUnits[(int)type])
                                {
                                        fprintf(stderr, "Too many units of type %c\n", Piece::tokens[(int)(type)]);
-                                       return Board::BAD_RESPONSE;
+                                       return MovementResult::BAD_RESPONSE;
                                }
        
                                Board::theBoard.AddPiece(x, y+ii, type, colour);
@@ -79,10 +80,10 @@ Board::MovementResult Controller::Setup(const char * opponentName)
 
        if (usedUnits[(int)Piece::FLAG] <= 0)
        {
-               return Board::BAD_RESPONSE; //You need to include a flag!
+               return MovementResult::BAD_RESPONSE; //You need to include a flag!
        }
 
-       return Board::OK;
+       return MovementResult::OK;
 }
 
 
@@ -90,11 +91,11 @@ Board::MovementResult Controller::Setup(const char * opponentName)
  * Queries the AI program to respond to a state of Board::theBoard
  * @returns The result of the response and/or move if made
  */
-Board::MovementResult Controller::MakeMove(string & buffer)
+MovementResult Controller::MakeMove(string & buffer)
 {
        
        if (!Running())
-               return Board::NO_MOVE; //AI has quit
+               return MovementResult::NO_MOVE; //AI has quit
        Board::theBoard.Print(output, colour);
 
        
@@ -103,7 +104,7 @@ Board::MovementResult Controller::MakeMove(string & buffer)
        buffer.clear();
        if (!GetMessage(buffer,2))
        {
-               return Board::NO_MOVE; //AI did not respond. It will lose by default.
+               return MovementResult::NO_MOVE; //AI did not respond. It will lose by default.
        }
 
        int x; int y; string direction="";
@@ -133,29 +134,39 @@ Board::MovementResult Controller::MakeMove(string & buffer)
        else
        {
                fprintf(stderr, "BAD_RESPONSE \"%s\"\n", buffer.c_str());
-               return Board::BAD_RESPONSE; //AI gave bogus direction - it will lose by default.        
+               return MovementResult::BAD_RESPONSE; //AI gave bogus direction - it will lose by default.       
        }
 
        int multiplier = 1;
        if (s.peek() != EOF)
                s >> multiplier;
-       Board::MovementResult moveResult = Board::theBoard.MovePiece(x, y, dir, multiplier, colour);
-       switch (moveResult)
+       MovementResult moveResult = Board::theBoard.MovePiece(x, y, dir, multiplier, colour);
+
+       s.clear();      s.str("");
+
+       //I stored the ranks in the wrong order; rank 1 is the marshal, 2 is the general etc...
+       //So I am reversing them in the output... great work
+       s << (Piece::BOMB - moveResult.attackerRank) << " " << (Piece::BOMB - moveResult.defenderRank) << "\n"; 
+       switch (moveResult.type)
        {
-               case Board::OK:
+               case MovementResult::OK:
                        buffer += " OK";
                        break;
-               case Board::VICTORY:
+               case MovementResult::VICTORY:
                        buffer += " FLAG";
                        break;
-               case Board::KILLS:
-                       buffer += " KILLS";
+               case MovementResult::KILLS:
+                       buffer += " KILLS ";
+                       buffer += s.str();
+
                        break;
-               case Board::DIES:
-                       buffer += " DIES";
+               case MovementResult::DIES:
+                       buffer += " DIES ";
+                       buffer += s.str();
                        break;
-               case Board::BOTH_DIE:
-                       buffer += " BOTHDIE";
+               case MovementResult::BOTH_DIE:
+                       buffer += " BOTHDIE ";
+                       buffer += s.str();
                        break;  
                default:
                        buffer += " ILLEGAL";
@@ -164,7 +175,7 @@ Board::MovementResult Controller::MakeMove(string & buffer)
        }
 
        if (!Board::LegalResult(moveResult))
-               return Board::OK; //HACK - Legal results returned!
+               return MovementResult::OK; //HACK - Legal results returned!
        else
                return moveResult;      
 
index 0e2e5cc..1fac88d 100644 (file)
@@ -15,9 +15,9 @@ class Controller : public Program
                Controller(const Piece::Colour & newColour, const char * executablePath) : Program(executablePath), colour(newColour) {}
                virtual ~Controller() {}
 
-               Board::MovementResult Setup(const char * opponentName); //Requests the AI program for the initial positioning of its pieces.
+               MovementResult Setup(const char * opponentName); //Requests the AI program for the initial positioning of its pieces.
 
-               Board::MovementResult MakeMove(std::string & buffer); //Queries the AI program for a response to the state of Board::theBoard
+               MovementResult MakeMove(std::string & buffer); //Queries the AI program for a response to the state of Board::theBoard
 
                const Piece::Colour colour; //Colour identifying the side of the AI program.
 
diff --git a/manager/forfax b/manager/forfax
new file mode 120000 (symlink)
index 0000000..a715b0f
--- /dev/null
@@ -0,0 +1 @@
+../samples/forfax/forfax
\ No newline at end of file
index cfeda8a..cf77ed4 100644 (file)
Binary files a/manager/images/piece10.bmp and b/manager/images/piece10.bmp differ
index f4ebeb2..b006d3d 100644 (file)
Binary files a/manager/images/piece11.bmp and b/manager/images/piece11.bmp differ
index 6c9544e..8c67a48 100644 (file)
Binary files a/manager/images/piece12.bmp and b/manager/images/piece12.bmp differ
index 0878912..f822c24 100644 (file)
Binary files a/manager/images/piece13.bmp and b/manager/images/piece13.bmp differ
index ef4927b..0a11b11 100644 (file)
Binary files a/manager/images/piece2.bmp and b/manager/images/piece2.bmp differ
index 4209648..40ca3f8 100644 (file)
Binary files a/manager/images/piece3.bmp and b/manager/images/piece3.bmp differ
index 63161fb..0a27a46 100644 (file)
Binary files a/manager/images/piece4.bmp and b/manager/images/piece4.bmp differ
index 9163c12..051bd43 100644 (file)
Binary files a/manager/images/piece5.bmp and b/manager/images/piece5.bmp differ
index 321bf55..5ca389b 100644 (file)
Binary files a/manager/images/piece6.bmp and b/manager/images/piece6.bmp differ
index e690190..aaf28a1 100644 (file)
Binary files a/manager/images/piece7.bmp and b/manager/images/piece7.bmp differ
index 8ada911..b2ea5b7 100644 (file)
Binary files a/manager/images/piece8.bmp and b/manager/images/piece8.bmp differ
index e22c4b6..e37e251 100644 (file)
Binary files a/manager/images/piece9.bmp and b/manager/images/piece9.bmp differ
index 96569eb..4f203d9 100644 (file)
@@ -18,8 +18,12 @@ using namespace std;
 
 Controller * red;
 Controller * blue;
+Colour turn;
 
 void cleanup();
+
+void BrokenPipe(int sig);
+
 int main(int argc, char ** argv)
 {
        assert(argc == 3);
@@ -39,17 +43,18 @@ int main(int argc, char ** argv)
        red = new Controller(Piece::RED, argv[1]);
        blue = new Controller(Piece::BLUE, argv[2]);
        atexit(cleanup);
+       signal(SIGPIPE, BrokenPipe);
 
-       Board::MovementResult redSetup = red->Setup(argv[2]);
-       Board::MovementResult blueSetup = blue->Setup(argv[1]);
-       if (redSetup != Board::OK)
+       MovementResult redSetup = red->Setup(argv[2]);
+       MovementResult blueSetup = blue->Setup(argv[1]);
+       if (redSetup != MovementResult::OK)
        {
                fprintf(stderr, "Blue wins by DEFAULT!\n");
                red->SendMessage("ILLEGAL");
                blue->SendMessage("DEFAULT");
                exit(EXIT_SUCCESS);
        }
-       if (blueSetup != Board::OK)
+       if (blueSetup != MovementResult::OK)
        {
                fprintf(stderr, "Red wins by DEFAULT!\n");
                red->SendMessage("DEFAULT");
@@ -57,7 +62,7 @@ int main(int argc, char ** argv)
                exit(EXIT_SUCCESS);
        }
 
-       Board::MovementResult result = Board::OK;
+       MovementResult result(MovementResult::OK);
        system("clear");
        int count = 1;
 
@@ -70,17 +75,17 @@ int main(int argc, char ** argv)
        string buffer;
 
        red->SendMessage("START");
-       Colour turn = Piece::RED;
+       turn = Piece::RED;
        while (Board::LegalResult(result))
        {
 
-               fprintf(stderr, "This is move %d...\n", count);
-               fprintf(stderr,"---RED's turn---\n");
+               
                turn = Piece::RED;
+               fprintf(stderr, "%d RED: ", count);
                result = red->MakeMove(buffer);
                red->SendMessage(buffer);
                blue->SendMessage(buffer);
-
+               fprintf(stderr, "%s\n", buffer.c_str());
                if (!Board::LegalResult(result))
                        break;
                #ifdef GRAPHICS
@@ -92,11 +97,13 @@ int main(int argc, char ** argv)
                                exit(EXIT_SUCCESS);
                        }
                #endif //GRAPHICS
-               fprintf(stderr,"---BLUE's turn---\n");
+               
                turn = Piece::BLUE;
+               fprintf(stderr, "%d BLU: ", count);
                result = blue->MakeMove(buffer);
                blue->SendMessage(buffer);
                red->SendMessage(buffer);
+               fprintf(stderr, "%s\n", buffer.c_str());
 
                if (!Board::LegalResult(result))
                        break;
@@ -148,36 +155,36 @@ int main(int argc, char ** argv)
                fprintf(stderr,"Game ends on ERROR's turn - REASON: ");
                        
        }
-       switch (result)
+       switch (result.type)
        {
-               case Board::NO_BOARD:
+               case MovementResult::NO_BOARD:
                        fprintf(stderr,"Board does not exit?!\n");
                        break;
-               case Board::INVALID_POSITION:
+               case MovementResult::INVALID_POSITION:
                        fprintf(stderr,"Coords outside board\n");
                        break;
-               case Board::NO_SELECTION:
+               case MovementResult::NO_SELECTION:
                        fprintf(stderr,"Move does not select a piece\n");
                        break;
-               case Board::NOT_YOUR_UNIT:
+               case MovementResult::NOT_YOUR_UNIT:
                        fprintf(stderr,"Selected piece belongs to other player\n");
                        break;
-               case Board::IMMOBILE_UNIT:
+               case MovementResult::IMMOBILE_UNIT:
                        fprintf(stderr,"Selected piece is not mobile (FLAG or BOMB)\n");
                        break;
-               case Board::INVALID_DIRECTION:
+               case MovementResult::INVALID_DIRECTION:
                        fprintf(stderr,"Selected unit cannot move that way\n");
                        break;
-               case Board::POSITION_FULL:
+               case MovementResult::POSITION_FULL:
                        fprintf(stderr,"Attempted move into square occupied by allied piece\n");
                        break;
-               case Board::VICTORY:
+               case MovementResult::VICTORY:
                        fprintf(stderr,"Captured the flag\n");
                        break;
-               case Board::BAD_RESPONSE:
+               case MovementResult::BAD_RESPONSE:
                        fprintf(stderr,"Unintelligable response\n");
                        break;
-               case Board::NO_MOVE:
+               case MovementResult::NO_MOVE:
                        fprintf(stderr,"Did not make a move (may have exited)\n");
                        break;
        }
@@ -221,4 +228,24 @@ void cleanup()
        delete blue;
 }
 
+void BrokenPipe(int sig)
+{
+       if (turn == Piece::RED)
+       {
+               fprintf(stderr,"Game ends on RED's turn - REASON: Broken pipe\n");
+               blue->SendMessage("DEFAULT");   
+       }
+       else if (turn == Piece::BLUE)
+       {
+               fprintf(stderr,"Game ends on BLUE's turn - REASON: Broken pipe\n");
+               red->SendMessage("DEFAULT");
+       }
+       else
+       {
+               fprintf(stderr,"Game ends on ERROR's turn - REASON: Broken pipe\n");
+                       
+       }
+       exit(EXIT_SUCCESS);
+}
+       
 #endif //GRAPHICS
diff --git a/manager/movementresult.h b/manager/movementresult.h
new file mode 100644 (file)
index 0000000..8df375c
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * Contains declaration for MovementResult class
+ */
+#ifndef MOVERESULT_H
+#define MOVERESULT_H
+
+class Board;
+class Piece;
+
+/**
+ * Class used to indicate the result of a move in stratego
+ */
+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} Type;
+
+               MovementResult(const Type & result = OK, const Piece::Type & newAttackerRank = Piece::NOTHING, const Piece::Type & newDefenderRank = Piece::NOTHING)
+                       : type(result), attackerRank(newAttackerRank), defenderRank(newDefenderRank) {}
+               MovementResult(const MovementResult & cpy) : type(cpy.type), attackerRank(cpy.attackerRank), defenderRank(cpy.defenderRank) {}
+               virtual ~MovementResult() {}
+               
+
+               bool operator==(const Type & equType) const {return type == equType;}
+               bool operator!=(const Type & equType) const {return type != equType;}
+
+               Type type;
+               Piece::Type attackerRank;
+               Piece::Type defenderRank;
+};
+
+#endif //MOVERESULT_H
+
+//EOF
index ea5304c..8b4e4af 100644 (file)
@@ -10,6 +10,7 @@
 
 using namespace std;
 
+
 /**
  * Constructor
  * @param executablePath - path to the program that will be run
@@ -21,6 +22,8 @@ using namespace std;
  */
 Program::Program(const char * executablePath) : input(NULL), output(NULL), pid(0)
 {
+       
+
        int readPipe[2]; int writePipe[2];
        assert(pipe(readPipe) == 0);
        assert(pipe(writePipe) == 0);
@@ -88,6 +91,7 @@ Program::~Program()
  * Sends a message to the wrapped AI program
  * WARNING: Always prints a new line after the message (so don't include a new line)
  *     This is because everything is always line buffered.
+ * @returns true if the message was successfully sent; false if it was not (ie: the process was not running!)
  */
 bool Program::SendMessage(const char * print, ...)
 {
@@ -97,12 +101,15 @@ bool Program::SendMessage(const char * print, ...)
        va_list ap;
        va_start(ap, print);
 
-       vfprintf(output, print, ap);
-       fprintf(output, "\n");
-
+       if (vfprintf(output, print, ap) < 0 || fprintf(output, "\n") < 0)
+       {
+               va_end(ap);
+               return false;
+       }
+       va_end(ap);
        
 
-       va_end(ap);
+
 
        return true;
 }
@@ -161,3 +168,5 @@ bool Program::Running() const
 }
 
 
+
+
index 406d954..bddde0f 100644 (file)
@@ -24,6 +24,8 @@ class Program
 
                bool Running() const;
 
+               
+
        protected:
                FILE * input;   //Stream used for sending information TO the process
                FILE * output; //Stream used for retrieving information FROM the process
index 8ffad72..871d382 100644 (file)
@@ -232,32 +232,32 @@ Piece * Board::GetPiece(int x, int y)
  * @param colour - Colour which the piece must match for the move to be valid
  * @returns A MovementResult which indicates the result of the move - OK is good, VICTORY means that a flag was captured, anything else is an error
  */
-Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction, int multiplier,const Piece::Colour & colour)
+MovementResult Board::MovePiece(int x, int y, const Direction & direction, int multiplier,const Piece::Colour & colour)
 {
        if (board == NULL) 
        {
-               return NO_BOARD;
+               return MovementResult(MovementResult::NO_BOARD);
        }
        if (!(x >= 0 && x < width && y >= 0 && y < height)) 
        {
-               return INVALID_POSITION;
+               return MovementResult(MovementResult::INVALID_POSITION);
        }
        Piece * target = board[x][y];
        if (target == NULL) 
        {
-               return NO_SELECTION;
+               return MovementResult(MovementResult::NO_SELECTION);
        }
        if (!(colour == Piece::NONE || target->colour == colour)) 
        {
-               return NOT_YOUR_UNIT;
+               return MovementResult(MovementResult::NOT_YOUR_UNIT);
        }
        if (target->type == Piece::FLAG || target->type == Piece::BOMB || target->type == Piece::BOULDER) 
        {
-               return IMMOBILE_UNIT;
+               return MovementResult(MovementResult::IMMOBILE_UNIT);
        }
        if (multiplier > 1 && target->type != Piece::SCOUT)
        {
-               return INVALID_DIRECTION; //Can only move a scout multiple times.
+               return MovementResult(MovementResult::INVALID_DIRECTION); //Can only move a scout multiple times.
        }
        int x2 = x; int y2 = y;
 
@@ -280,11 +280,11 @@ Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction
                }
                if (!(x2 >= 0 && x2 < width && y2 >= 0 && y2 < height)) 
                {
-                       return INVALID_DIRECTION;
+                       return MovementResult(MovementResult::INVALID_DIRECTION);
                }
                if (ii < multiplier-1 && board[x2][y2] != NULL)
                {
-                       return POSITION_FULL;
+                       return MovementResult(MovementResult::POSITION_FULL);
                }
        }
        Piece * defender = board[x2][y2];
@@ -295,23 +295,27 @@ Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction
        }
        else if (defender->colour != target->colour)
        {
+               Piece::Type defenderType = defender->type;
+               Piece::Type attackerType = target->type;
+
                if (defender->colour == Piece::NONE) 
                {
-                       return POSITION_FULL;
+                       return MovementResult(MovementResult::POSITION_FULL);
                }
                if (defender->type == Piece::FLAG)
                {
                        winner = target->colour;
-                       return VICTORY;
+                       return MovementResult(MovementResult::VICTORY);
                }
                else if (defender->type == Piece::BOMB)
                {
                        if (target->type == Piece::MINER)
                        {
+
                                delete defender;
                                board[x][y] = NULL;
                                board[x2][y2] = target;
-                               return KILLS;
+                               return MovementResult(MovementResult::KILLS, attackerType, defenderType);
                        }
                        else
                        {
@@ -319,7 +323,7 @@ Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction
                                delete target;
                                board[x][y] = NULL;
                                board[x2][y2] = NULL;
-                               return BOTH_DIE;
+                               return MovementResult(MovementResult::BOTH_DIE, attackerType, defenderType);
                        }
                }
                else if (defender->type == Piece::MARSHAL && target->type == Piece::SPY)
@@ -327,34 +331,34 @@ Board::MovementResult Board::MovePiece(int x, int y, const Direction & direction
                        delete defender;
                        board[x][y] = NULL;
                        board[x2][y2] = target;
-                       return KILLS;
+                       return MovementResult(MovementResult::KILLS, attackerType, defenderType);
                }
                else if (target->operator > (*defender))
                {
                        delete defender;
                        board[x][y] = NULL;
                        board[x2][y2] = target;
-                       return KILLS;
+                       return MovementResult(MovementResult::KILLS, attackerType, defenderType);
                }
                else if (target->operator==(*defender) && rand() % 2 == 0)
                {
                        delete defender;
                        board[x][y] = NULL;
                        board[x2][y2] = target; 
-                       return KILLS;
+                       return MovementResult(MovementResult::KILLS, attackerType, defenderType);
                }
                else
                {
                        delete target;
                        board[x][y] = NULL;
-                       return DIES;
+                       return MovementResult(MovementResult::DIES, attackerType, defenderType);
                }
        }
        else
        {
-               return POSITION_FULL;
+               return MovementResult(MovementResult::POSITION_FULL);
        }
-       return OK;
+       return MovementResult(MovementResult::OK);
 }      
 
 
index 877af2d..25aa5cc 100644 (file)
@@ -89,6 +89,8 @@ class Piece
                
 };
 
+#include "movementresult.h"
+
 /**
  * A Stratego board
  */
@@ -112,12 +114,11 @@ class Board
 
                typedef enum {UP, DOWN, LEFT, RIGHT} Direction;
 
-               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} MovementResult; //The possible results from a move
-               //WARNING: Some of the MovementResults are returned by the Controller class in "controller.h", in Controller::MakeMove
+               
                
                static bool LegalResult(const MovementResult & result)
                {
-                       return (result == OK || result == DIES || result == KILLS || result == BOTH_DIE);
+                       return (result == MovementResult::OK || result == MovementResult::DIES || result == MovementResult::KILLS || result == MovementResult::BOTH_DIE);
                }       
 
                MovementResult MovePiece(int x, int y, const Direction & direction, int multiplier=1,const Piece::Colour & colour=Piece::NONE); //Move piece from position in direction
index e27af9f..6fa0ba3 100644 (file)
@@ -525,7 +525,7 @@ bool Forfax::MakeMove()
 
 bool Forfax::InterpretMove()
 {
-       int x; int y; string direction; string result; int multiplier = 1; 
+       int x; int y; string direction; string result; int multiplier = 1; int attackerVal = (int)(Piece::BOMB); int defenderVal = (int)(Piece::BOMB);
 
        cerr << "Forfax " << strColour << " waiting for movement information...\n";
        cin >> x; cin >> y; cin >> direction; cin >> result;
@@ -536,6 +536,20 @@ bool Forfax::InterpretMove()
                s >> multiplier;
                result.clear();
                cin >> result;
+
+               if (cin.peek() != '\n')
+               {
+                       cerr << "Forfax " << strColour << " reading ranks of pieces\n";
+                       s.clear(); s.str(result);
+                       s >> attackerVal;
+                       result.clear();
+                       cin >> result;  
+                       s.clear(); s.str(result);
+                       s >> defenderVal;
+                       result.clear();
+
+                       cin >> result;
+               }
        }
        if (cin.get() != '\n')
        {
@@ -544,6 +558,9 @@ bool Forfax::InterpretMove()
                return false;
        }
 
+       Piece::Type attackerRank = Piece::Type(Piece::BOMB - attackerVal);
+       Piece::Type defenderRank = Piece::Type(Piece::BOMB - defenderVal);
+
        cerr << "Forfax " << strColour << " interpreting movement result of " << x << " " << y <<  " " << direction << " " << result << " ...\n";
 
 
index d0cea95..2b31fee 100644 (file)
@@ -6,13 +6,15 @@
 using namespace std;
 
 #include <stdio.h>
-
+void quit();
 Forfax forfax;
 int main(int argc, char ** argv)
 {
        setbuf(stdin, NULL);
        setbuf(stdout, NULL);
 
+       atexit(&quit);
+
        if (!forfax.Setup())
                exit(EXIT_SUCCESS);
 
@@ -25,3 +27,8 @@ int main(int argc, char ** argv)
 
        
 }
+
+void quit()
+{
+       cerr << " Forfax quit\n";
+}
index 25c2dae..7736907 100644 (file)
        <tr> <th> OUTCOME </th> <th> Description </th>  </tr>
        <tr> <td> OK </td> <td> The piece was successfully moved, nothing eventful happened </td> </tr>
        <tr> <td> FLAG </td> <td> The piece moved onto the opposing Flag; the game will end shortly </td> </tr>
-       <tr> <td> KILLS </td> <td> The piece landed on a square occupied by an enemy, and destroyed it, moving into the square </td> </tr>
-       <tr> <td> DIES </td> <td> The piece landed on a square occupied by an enemy, and was destroyed. The piece is removed from the board. </td> </tr>
-       <tr> <td> BOTHDIE </td> <td> The piece landed on a square occupied by an enemy, and <i>both</i> pieces were destroyed. </td> </tr>
+       <tr> <td> KILLS RANK1 RANK2 </td> <td> The piece landed on a square occupied by an enemy, and destroyed it, moving into the square </td> </tr>
+       <tr> <td> DIES RANK1 RANK2</td> <td> The piece landed on a square occupied by an enemy, and was destroyed. The piece is removed from the board. </td> </tr>
+       <tr> <td> BOTHDIE RANK1 RANK2</td> <td> The piece landed on a square occupied by an enemy, and <i>both</i> pieces were destroyed. </td> </tr>
        <tr> <td> ILLEGAL </td> <td> The moving player attempted to make an illegal move, and has hence lost the game. The game will end shortly. </td> </tr>
 </table>
+<p> If printed, RANK1 and RANK2 indicate the ranks of the moved piece and the defending piece (the piece who occupied the destination square) respectively. </p>
                
 
 <h4> Additional Turns </h4>

UCC git Repository :: git.ucc.asn.au