using namespace std;
+
/**
* @constructor
* @param new_x, new_y - Position of piece
* @param new_colour - Colour of piece
* @param type1, type2 - Types of piece
- * @param index - Index for initial type of piece
+ * @param new_type_index - Index for initial type of piece
+ * @param new_piece_index - Index for piece in a vector
*/
-Piece::Piece(int new_x, int new_y, const Piece::Colour & new_colour, const Piece::Type & type1, const Piece::Type & type2, int index)
- : x(new_x), y(new_y), colour(new_colour), type_index(index), types(), current_type()
+Piece::Piece(int new_x, int new_y, const Piece::Colour & new_colour, const Piece::Type & type1, const Piece::Type & type2,
+ int new_type_index, int new_piece_index)
+ : x(new_x), y(new_y), colour(new_colour), type_index(new_type_index), types(), current_type(), piece_index(new_piece_index)
{
types[0] = type1; types[1] = type2;
- if (index < 0 || index >= 2)
+ if (type_index < 0 || type_index >= 2)
{
current_type = Piece::UNKNOWN;
}
else
{
- current_type = types[index];
+ current_type = types[type_index];
}
}
* @constructor
* @param cpy - Piece to copy construct from
*/
-Piece::Piece(const Piece & cpy) : x(cpy.x), y(cpy.y), colour(cpy.colour), type_index(cpy.type_index)
+Piece::Piece(const Piece & cpy) : x(cpy.x), y(cpy.y), colour(cpy.colour), type_index(cpy.type_index), piece_index(cpy.piece_index)
{
types[0] = cpy.types[0];
types[1] = cpy.types[1];
* @constructor
* @param choose_types - Indicates whether Board should setup the 2nd types of pieces; default false
*/
-Board::Board(bool choose_types)
+Board::Board(bool choose_types)
+ : white(), black(), white_unknown(), black_unknown(), white_nUnknown(0), black_nUnknown(0),
+ white_king(NULL), black_king(NULL), parent(NULL)
{
// initialise all the Squares
freq[Piece::QUEEN] = 1;
freq[Piece::PAWN] = 8;
+ if (!choose_types)
+ {
+ white_unknown = freq;
+ black_unknown = freq;
+ white_nUnknown = 15;
+ black_nUnknown = 15;
+ }
+
// for white and black...
for (int i = 0; i < 2; ++i)
{
int y = (i == 0) ? 1 : BOARD_HEIGHT-2;
for (int x = 0; x < BOARD_WIDTH; ++x)
{
- Piece * p = new Piece(x, y, colours[i], Piece::PAWN, Piece::UNKNOWN);
- v.push_back(p);
+ Piece::AddPiece(v, x, y, colours[i], Piece::PAWN, Piece::UNKNOWN);
}
// add other pieces
y = (i == 0) ? 0 : BOARD_HEIGHT-1;
- v.push_back(new Piece(0, y, colours[i], Piece::ROOK, Piece::UNKNOWN));
- v.push_back(new Piece(BOARD_WIDTH-1, y, colours[i], Piece::ROOK, Piece::UNKNOWN));
- v.push_back(new Piece(1, y, colours[i], Piece::KNIGHT, Piece::UNKNOWN));
- v.push_back(new Piece(BOARD_WIDTH-2, y, colours[i], Piece::KNIGHT, Piece::UNKNOWN));
- v.push_back(new Piece(2, y, colours[i], Piece::BISHOP, Piece::UNKNOWN));
- v.push_back(new Piece(BOARD_WIDTH-3, y, colours[i], Piece::BISHOP, Piece::UNKNOWN));
- v.push_back(new Piece(3, y, colours[i], Piece::QUEEN, Piece::UNKNOWN));
-
- Piece * k = new Piece(4, y, colours[i], Piece::KING, Piece::KING, 1);
+ Piece::AddPiece(v, 0, y, colours[i], Piece::ROOK, Piece::UNKNOWN);
+ Piece::AddPiece(v, BOARD_WIDTH-1, y, colours[i], Piece::ROOK, Piece::UNKNOWN);
+ Piece::AddPiece(v, 1, y, colours[i], Piece::KNIGHT, Piece::UNKNOWN);
+ Piece::AddPiece(v, BOARD_WIDTH-2, y, colours[i], Piece::KNIGHT, Piece::UNKNOWN);
+ Piece::AddPiece(v, 2, y, colours[i], Piece::BISHOP, Piece::UNKNOWN);
+ Piece::AddPiece(v, BOARD_WIDTH-3, y, colours[i], Piece::BISHOP, Piece::UNKNOWN);
+ Piece::AddPiece(v, 3, y, colours[i], Piece::QUEEN, Piece::UNKNOWN);
+
+ Piece * k = Piece::AddPiece(v, 4, y, colours[i], Piece::KING, Piece::KING, 1);
if (i == 0)
white_king = k;
else
black_king = k;
- v.push_back(k);
+
// add to board and choose second types if required
map<Piece::Type, int> f(freq);
/**
* @constructor
- * @param cpy - Board to copy construct from; each Piece in the copy will be *copied*
- * The Piece's in the copied Board may be altered without affecting the original
+ * @param cpy - Board to clone
*/
-Board::Board(const Board & cpy)
+Board::Board(Board & cpy)
+: white(cpy.white), black(cpy.black), white_unknown(cpy.white_unknown), black_unknown(cpy.black_unknown),
+ white_nUnknown(cpy.white_nUnknown), black_nUnknown(cpy.black_nUnknown),
+ white_king(cpy.white_king), black_king(cpy.black_king), parent(&cpy)
{
for (int x = 0; x < BOARD_WIDTH; ++x)
{
{
grid[x][y].x = x;
grid[x][y].y = y;
-
- if (cpy.grid[x][y].piece != NULL)
- {
- grid[x][y].piece = new Piece(*(cpy.grid[x][y].piece));
- pieces(grid[x][y].piece->colour).push_back(grid[x][y].piece);
- }
+ grid[x][y].piece = cpy.grid[x][y].piece;
}
}
}
* @purpose Update Piece that has been selected
* @param x, y - Position of Piece to update
* @param index - 0 or 1 - State the Piece "collapsed" into
- * @param type - Type of the Piece
+ * @param type - Type of the Piece as a string
*/
void Board::Update_select(int x, int y, int index, const string & type)
{
- cerr << "Updating " << x << "," << y << " " << grid[x][y].piece << " " << index << " " << type << "\n";
+ Board::Update_select(x, y, index, Piece::str2type(type));
+}
+
+/**
+ * @funct Update_select
+ * @purpose Update Piece that has been selected
+ * @param x, y - Position of Piece to update
+ * @param index - 0 or 1 - State the Piece "collapsed" into
+ * @param t - Type of the Piece
+ */
+void Board::Update_select(int x, int y, int index, const Piece::Type & t)
+{
+ cerr << "Updating " << x << "," << y << " " << grid[x][y].piece << " " << index << " " << t << "\n";
Square & s = grid[x][y];
+
+ Clone_copy(s);
+
assert(s.piece != NULL);
assert(index >= 0 && index < 2);
s.piece->type_index = index;
- s.piece->types[index] = Piece::str2type(type);
- s.piece->current_type = s.piece->types[index];
+
+ if (s.piece->types[index] == Piece::UNKNOWN)
+ {
+ map<Piece::Type, int> & m = unknown_types(s.piece->colour);
+ int n = (m[t]--);
+ if (n < 0)
+ throw Exception("Board::Update_select", "Too many pieces of type %s found", Piece::type2str(t));
+
+ nUnknown(s.piece->colour)--;
+
+ }
+ s.piece->types[index] = t;
+ s.piece->current_type = t;
}
/**
{
Square & s1 = grid[x1][y1];
Square & s2 = grid[x2][y2];
+
+ Clone_copy(s1);
+
+
+
+
if (s2.piece != NULL)
{
vector<Piece*> & p = pieces(s2.piece->colour);
}
++i;
}
+ while (i != p.end())
+ {
+ (*i)->piece_index -= 1;
+ ++i;
+ }
Piece * k = king(s2.piece->colour);
if (k == s2.piece)
{
else
black_king = NULL;
}
-
- delete s2.piece;
+ if ((IsClone() && s2.piece == parent->grid[x2][y2].piece) == false)
+ {
+ delete s2.piece;
+ }
}
s1.piece->x = s2.x;
return Piece::UNKNOWN;
}
+/**
+ * @funct type2str
+ * @purpose Convert Piece::Type to string
+ * @param t - The Types
+ * @returns a const char*
+ */
+const char * Piece::type2str(const Piece::Type & t)
+{
+ switch (t)
+ {
+ case PAWN:
+ return "pawn";
+ case BISHOP:
+ return "bishop";
+ case KNIGHT:
+ return "knight";
+ case ROOK:
+ return "rook";
+ case QUEEN:
+ return "queen";
+ case UNKNOWN:
+ return "unknown";
+ case KING:
+ return "king";
+ default:
+ throw Exception("Piece::type2str", "Unknown type %d", (int)t);
+ return "";
+ }
+}
+
/**
* @funct str2colour
* @purpose Convert string to Piece::Colour
return Piece::BLACK; // should never get here
}
+/**
+ * @funct AddPiece
+ * @purpose Creates a new Piece and adds it to a vector
+ * @param v - The vector
+ * @params - All remaining parameters passed to Piece::Piece
+ * @returns Pointer to the new Piece
+ */
+Piece * Piece::AddPiece(vector<Piece*> & v, int x, int y, const Piece::Colour & colour, const Piece::Type & t1, const Piece::Type & t2,
+ int type_index)
+{
+ Piece * p = new Piece(x,y,colour,t1, t2,type_index, v.size());
+ v.push_back(p);
+ return p;
+}
+/**
+ * @funct Clone_copy
+ * @purpose If necessary, copy the piece in the square
+ * @param s - The square
+ */
+void Board::Clone_copy(Square & s)
+{
+ if (s.piece == NULL || !IsClone()) return;
+ if (parent->grid[s.x][s.y].piece == s.piece)
+ {
+ s.piece = new Piece(*(s.piece));
+ vector<Piece*> & v = pieces(s.piece->colour);
+ v[s.piece->piece_index] = s.piece;
+ }
+
+}
\ No newline at end of file
typedef enum {PAWN, BISHOP, KNIGHT, ROOK, QUEEN, KING, UNKNOWN} Type;
typedef enum {WHITE=0, BLACK=1} Colour;
- Piece(int x, int y, const Colour & colour, const Type & type1, const Type & type2=UNKNOWN, int type_index = -1); // constructor
- Piece(const Piece & cpy); // copy constructor
virtual ~Piece() {} // destructor
int x; int y; // position of the piece
static Type str2type(const std::string & str);
static Colour str2colour(const std::string & str);
+ static const char * type2str(const Type & t);
+
+ static Piece * AddPiece(std::vector<Piece*> & v, int x, int y, const Colour & colour, const Type & type1, const Type & type2, int type_index=-1);
+
+ private:
+ friend class Board;
+ Piece(int x, int y, const Colour & colour, const Type & type1, const Type & type2
+ , int type_index, int new_piece_index); // constructor
+ Piece(const Piece & cpy); // copy constructor
+
+ int piece_index; // index of the piece in Board's pieces vector
+
};
{
public:
Board(bool choose_types = false); // constructor
- Board(const Board & cpy); // copy constructor
+ Board(Board & parent); // clones a board, copy on write
virtual ~Board(); // destructor
// helper; return vector of pieces given player colour
std::vector<Piece*> & pieces(const Piece::Colour & colour) {return ((colour == Piece::WHITE) ? white : black);}
+ // helper; return map of unidentified 2nd types for given colour
+ std::map<Piece::Type, int> & unknown_types(const Piece::Colour & colour)
+ {
+ return ((colour == Piece::WHITE) ? white_unknown : black_unknown);
+ }
+
+ int & nUnknown(const Piece::Colour & colour)
+ {
+ return ((colour == Piece::WHITE) ? white_nUnknown : black_nUnknown);
+ }
+
// helper; return king given player colour
Piece * king(const Piece::Colour & colour) {return ((colour == Piece::WHITE) ? white_king : black_king);}
void Update_move(int x, int y, int x2, int y2); // move a piece
void Update_select(int x, int y, int index, const std::string & type); // update a selected piece
+ void Update_select(int x, int y, int index, const Piece::Type & t);
Square & square(int x, int y) {return grid[x][y];} // get square on board
- void Get_moves(Piece * p, std::vector<Square*> & v); // get allowed moves for piece
+ void Get_moves(Piece * p, std::vector<Square*> & v); // get allowed moves for piece of known type
// determine if position is on the board
bool Valid_position(int x, int y) {return (x >= 0 && x <= BOARD_WIDTH-1 && y >= 0 && y <= BOARD_HEIGHT-1);}
+
+ bool IsClone() const {return parent != NULL;}
+ void Clone_copy(Square & s);
private:
Square grid[BOARD_WIDTH][BOARD_HEIGHT];
-
+ // All pieces for each player
std::vector<Piece*> white;
std::vector<Piece*> black;
+ // The number of pieces with each 2nd type that are still unidentified
+ std::map<Piece::Type, int> white_unknown;
+ std::map<Piece::Type, int> black_unknown;
+ int white_nUnknown;
+ int black_nUnknown;
Piece * white_king;
Piece * black_king;
+
+ Board * parent;
// Add a move to the vector if it is valid
void Move(Piece * p, int x, int y, std::vector<Square*> & v);