Fixed segfault in manager program
[progcomp2012.git] / manager / stratego.cpp
index 871d382..f2df0ff 100644 (file)
@@ -1,4 +1,4 @@
-#include "common.h"
+
 
 #include "stratego.h"
 
@@ -7,19 +7,18 @@ using namespace std;
 /**
  * Static variables
  */
-Board Board::theBoard(14,14);
+
 //nothing, boulder, flag, spy, scout, miner, sergeant, lietenant, captain, major, colonel, general, marshal, bomb, error
-char  Piece::tokens[] = {'.','+','F','y','s','n','S','L','c','m','C','G','M','B','?'};
+char  Piece::tokens[] = {'.','*','F','s','9','8','7','6','5','4','3','2','1','B','?'};
 int Piece::maxUnits[] = {0,0,1,1,8,5,4,4,4,3,2,1,1,6,0};
 
 
 
-#ifdef GRAPHICS
-       Piece::TextureManager Piece::textures;
-#endif //GRAPHICS
+
+Piece::TextureManager Piece::textures;
+
 
 
-#ifdef GRAPHICS
 
 Piece::TextureManager::~TextureManager()
 {
@@ -42,7 +41,7 @@ Texture & Piece::TextureManager::operator[](const LUint & at)
        }
        return *(Array<Texture*>::operator[](at));
 }
-#endif //GRAPHICS
+
 
 /**
  * Gets the type of a piece, based off a character token
@@ -66,7 +65,7 @@ Piece::Type Piece::GetType(char fromToken)
  * @param newWidth - the width of the board
  * @param newHeight - the height of the board
  */
-Board::Board(int newWidth, int newHeight) : winner(Piece::NONE), width(newWidth), height(newHeight), board(NULL)
+Board::Board(int newWidth, int newHeight) : winner(Piece::NONE), width(newWidth), height(newHeight), board(NULL), pieces()
 {
        board = new Piece**[width];
        for (int x=0; x < width; ++x)
@@ -93,7 +92,7 @@ Board::~Board()
 /**
  * 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)
 {
@@ -108,26 +107,89 @@ 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");
        }
@@ -135,16 +197,18 @@ void Board::Print(FILE * stream, const Piece::Colour & reveal)
 }
 
 
-#ifdef GRAPHICS
+
 /**
  * Draw the board state to graphics
  * @param reveal - Pieces matching this colour will be revealed. All others will be shown as blank coloured squares.
  */
-void Board::Draw(const Piece::Colour & reveal)
+void Board::Draw(const Piece::Colour & reveal, bool showRevealed)
 {
        if (!Graphics::Initialised())
        {
-               Graphics::Initialise("Stratego", width*32, height*32);
+               fprintf(stderr, "ERROR - Board::Draw called whilst graphics disabled!!!\n");
+               exit(EXIT_FAILURE);
+               
        }
 
        Graphics::ClearScreen();
@@ -159,7 +223,8 @@ void Board::Draw(const Piece::Colour & reveal)
                                //Don't display anything
 
                        }
-                       else if (piece->colour != Piece::NONE && (piece->colour == reveal || reveal == Piece::BOTH))
+                       else if ((piece->colour != Piece::NONE && (piece->colour == reveal || reveal == Piece::BOTH))
+                                       || (piece->beenRevealed && showRevealed))
                        {
                                //Display the piece
                                Piece::textures[(int)(piece->type)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
@@ -170,10 +235,10 @@ void Board::Draw(const Piece::Colour & reveal)
                                switch (piece->colour)
                                {
                                        case Piece::RED:
-                                               Piece::textures[(int)(Piece::BOULDER)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
+                                               Piece::textures[(int)(Piece::NOTHING)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
                                                break;
                                        case Piece::BLUE:
-                                               Piece::textures[(int)(Piece::BOULDER)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
+                                               Piece::textures[(int)(Piece::NOTHING)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
                                                break;
                                        case Piece::NONE:
                                                Piece::textures[(int)(Piece::BOULDER)].DrawColour(x*32,y*32,0,1, Piece::GetGraphicsColour(piece->colour));
@@ -189,7 +254,6 @@ void Board::Draw(const Piece::Colour & reveal)
        Graphics::UpdateScreen();
        
 }
-#endif //GRAPHICS
 
 /**
  * Adds a piece to the board
@@ -206,6 +270,8 @@ bool Board::AddPiece(int x, int y, const Piece::Type & newType, const Piece::Col
 
        Piece * piece = new Piece(newType, newColour);
        board[x][y] = piece;
+
+       pieces.push_back(piece);
        return true;
 }
 
@@ -295,6 +361,9 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
        }
        else if (defender->colour != target->colour)
        {
+               defender->beenRevealed = true;
+               target->beenRevealed = true;
+
                Piece::Type defenderType = defender->type;
                Piece::Type attackerType = target->type;
 
@@ -311,7 +380,7 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
                {
                        if (target->type == Piece::MINER)
                        {
-
+                               RemovePiece(defender);
                                delete defender;
                                board[x][y] = NULL;
                                board[x2][y2] = target;
@@ -319,6 +388,8 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
                        }
                        else
                        {
+                               RemovePiece(defender);
+                               RemovePiece(target);
                                delete defender;
                                delete target;
                                board[x][y] = NULL;
@@ -328,6 +399,7 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
                }
                else if (defender->type == Piece::MARSHAL && target->type == Piece::SPY)
                {
+                       RemovePiece(defender);
                        delete defender;
                        board[x][y] = NULL;
                        board[x2][y2] = target;
@@ -335,6 +407,7 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
                }
                else if (target->operator > (*defender))
                {
+                       RemovePiece(defender);
                        delete defender;
                        board[x][y] = NULL;
                        board[x2][y2] = target;
@@ -342,6 +415,7 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
                }
                else if (target->operator==(*defender) && rand() % 2 == 0)
                {
+                       RemovePiece(defender);
                        delete defender;
                        board[x][y] = NULL;
                        board[x2][y2] = target; 
@@ -349,6 +423,7 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
                }
                else
                {
+                       RemovePiece(target);
                        delete target;
                        board[x][y] = NULL;
                        return MovementResult(MovementResult::DIES, attackerType, defenderType);
@@ -361,5 +436,77 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
        return MovementResult(MovementResult::OK);
 }      
 
+/**
+ * Removes a piece from the board
+ * @param piece The piece to remove
+ * @returns true iff the piece actually existed
+ */
+bool Board::RemovePiece(Piece * piece)
+{
+       bool result = false;
+       for (int x = 0; x < width; ++x)
+       {
+               for (int y = 0; y < height; ++y)        
+               {
+                       if (board[x][y] == piece)
+                       {
+                               result = true;
+                               board[x][y] = NULL;
+                       }
+               }
+       }
+
+       vector<Piece*>::iterator i = pieces.begin();
+       while (i != pieces.end())
+       {
+               if ((*i) == piece)
+               {
+                       i = pieces.erase(i);
+                       result = true;
+                       continue;
+               }
+               ++i;
+       }
+       return result;
+}
+
+/**
+ * Returns the total value of pieces belonging to colour
+ * @param colour the colour
+ * @returns the total value of pieces belonging to colour.
+ *     (Redundant repetition <3)
+ */
+int Board::TotalPieceValue(const Piece::Colour & colour) const
+{
+       int result = 0;
+       for (vector<Piece*>::const_iterator i = pieces.begin(); i != pieces.end(); ++i)
+       {
+               if ((*i)->colour == colour || colour == Piece::BOTH)
+               {
+                       result += (*i)->PieceValue();
+               }
+       }
+       return result;
+}
+
+/**
+ * Returns the total number of mobile pieces belonging to colour
+ * @param colour the colour
+ * @returns the total value of mobile pieces belonging to colour.
+ *     (Redundant repetition <3)
+ */
+int Board::MobilePieces(const Piece::Colour & colour) const
+{
+       int result = 0;
+       for (vector<Piece*>::const_iterator i = pieces.begin(); i != pieces.end(); ++i)
+       {
+               if ((*i)->colour == colour || colour == Piece::BOTH)
+               {
+                       if ((*i)->type <= Piece::MARSHAL && (*i)->type >= Piece::SPY)
+                               result++;
+               }
+       }
+       return result;
+}
 
 

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