2 * agent++ : A Sample agent for UCC::Progcomp2013
4 * @purpose Definitions for game related classes; Piece, Square, Board
15 * @param new_x, new_y - Position of piece
16 * @param new_colour - Colour of piece
17 * @param type1, type2 - Types of piece
18 * @param new_type_index - Index for initial type of piece
19 * @param new_piece_index - Index for piece in a vector
21 Piece::Piece(int new_x, int new_y, const Piece::Colour & new_colour, const Piece::Type & type1, const Piece::Type & type2,
22 int new_type_index, int new_piece_index)
23 : x(new_x), y(new_y), colour(new_colour), type_index(new_type_index), types(), current_type(), piece_index(new_piece_index)
25 types[0] = type1; types[1] = type2;
26 if (type_index < 0 || type_index >= 2)
28 current_type = Piece::UNKNOWN;
32 current_type = types[type_index];
38 * @param cpy - Piece to copy construct from
40 Piece::Piece(const Piece & cpy) : x(cpy.x), y(cpy.y), colour(cpy.colour), type_index(cpy.type_index), piece_index(cpy.piece_index)
42 types[0] = cpy.types[0];
43 types[1] = cpy.types[1];
48 * @param choose_types - Indicates whether Board should setup the 2nd types of pieces; default false
50 Board::Board(bool choose_types)
51 : white(), black(), white_unknown(), black_unknown(), white_nUnknown(0), black_nUnknown(0),
52 white_king(NULL), black_king(NULL), parent(NULL)
55 // initialise all the Squares
56 for (int x = 0; x < BOARD_WIDTH; ++x)
58 for (int y = 0; y < BOARD_HEIGHT; ++y)
65 // const arrays simplify below code
66 Piece::Colour colours[] = {Piece::BLACK, Piece::WHITE};
67 Piece::Type types[] = {Piece::PAWN, Piece::BISHOP, Piece::KNIGHT, Piece::ROOK, Piece::QUEEN};
69 // frequency of each type of piece
70 map<Piece::Type, int> freq;
71 freq[Piece::ROOK] = 2;
72 freq[Piece::BISHOP] = 2;
73 freq[Piece::KNIGHT] = 2;
74 freq[Piece::QUEEN] = 1;
75 freq[Piece::PAWN] = 8;
85 // for white and black...
86 for (int i = 0; i < 2; ++i)
88 vector<Piece*> & v = pieces(colours[i]); // get vector of pieces
93 int y = (i == 0) ? 1 : BOARD_HEIGHT-2;
94 for (int x = 0; x < BOARD_WIDTH; ++x)
96 Piece::AddPiece(v, x, y, colours[i], Piece::PAWN, Piece::UNKNOWN);
100 y = (i == 0) ? 0 : BOARD_HEIGHT-1;
101 Piece::AddPiece(v, 0, y, colours[i], Piece::ROOK, Piece::UNKNOWN);
102 Piece::AddPiece(v, BOARD_WIDTH-1, y, colours[i], Piece::ROOK, Piece::UNKNOWN);
103 Piece::AddPiece(v, 1, y, colours[i], Piece::KNIGHT, Piece::UNKNOWN);
104 Piece::AddPiece(v, BOARD_WIDTH-2, y, colours[i], Piece::KNIGHT, Piece::UNKNOWN);
105 Piece::AddPiece(v, 2, y, colours[i], Piece::BISHOP, Piece::UNKNOWN);
106 Piece::AddPiece(v, BOARD_WIDTH-3, y, colours[i], Piece::BISHOP, Piece::UNKNOWN);
107 Piece::AddPiece(v, 3, y, colours[i], Piece::QUEEN, Piece::UNKNOWN);
109 Piece * k = Piece::AddPiece(v, 4, y, colours[i], Piece::KING, Piece::KING, 1);
116 // add to board and choose second types if required
117 map<Piece::Type, int> f(freq);
119 for (unsigned j = 0; j < v.size(); ++j)
122 grid[p->x][p->y].piece = p;
125 if (p->types[1] != Piece::UNKNOWN)
131 } while (f[types[type2]] <= 0);
132 f[types[type2]] -= 1;
134 p->types[1] = types[type2];
148 * @param cpy - Board to clone
150 Board::Board(Board & cpy)
151 : white(cpy.white), black(cpy.black), white_unknown(cpy.white_unknown), black_unknown(cpy.black_unknown),
152 white_nUnknown(cpy.white_nUnknown), black_nUnknown(cpy.black_nUnknown),
153 white_king(cpy.white_king), black_king(cpy.black_king), parent(&cpy)
155 for (int x = 0; x < BOARD_WIDTH; ++x)
157 for (int y = 0; y < BOARD_HEIGHT; ++y)
161 grid[x][y].piece = cpy.grid[x][y].piece;
173 for (int x = 0; x < BOARD_WIDTH; ++x)
175 for (int y = 0; y < BOARD_HEIGHT; ++y)
177 delete grid[x][y].piece;
184 * @funct Update_select
185 * @purpose Update Piece that has been selected
186 * @param x, y - Position of Piece to update
187 * @param index - 0 or 1 - State the Piece "collapsed" into
188 * @param type - Type of the Piece as a string
190 void Board::Update_select(int x, int y, int index, const string & type)
192 Board::Update_select(x, y, index, Piece::str2type(type));
196 * @funct Update_select
197 * @purpose Update Piece that has been selected
198 * @param x, y - Position of Piece to update
199 * @param index - 0 or 1 - State the Piece "collapsed" into
200 * @param t - Type of the Piece
202 void Board::Update_select(int x, int y, int index, const Piece::Type & t)
204 cerr << "Updating " << x << "," << y << " " << grid[x][y].piece << " " << index << " " << t << "\n";
205 Square & s = grid[x][y];
209 assert(s.piece != NULL);
210 assert(index >= 0 && index < 2);
211 s.piece->type_index = index;
213 if (s.piece->types[index] == Piece::UNKNOWN)
215 map<Piece::Type, int> & m = unknown_types(s.piece->colour);
218 throw Exception("Board::Update_select", "Too many pieces of type %s found", Piece::type2str(t));
220 nUnknown(s.piece->colour)--;
223 s.piece->types[index] = t;
224 s.piece->current_type = t;
229 * @purpose Move a Piece from one square to another
230 * @param x1, y1 - Coords of Square containing moving Piece
231 * @param x2, y2 - Coords of Square to move into
232 * NOTE: Any Piece in the destination Square will be destroyed ("taken")
233 * and the Board's other members updated accordingly
235 void Board::Update_move(int x1, int y1, int x2, int y2)
237 Square & s1 = grid[x1][y1];
238 Square & s2 = grid[x2][y2];
245 if (s2.piece != NULL)
247 vector<Piece*> & p = pieces(s2.piece->colour);
248 vector<Piece*>::iterator i = p.begin();
260 (*i)->piece_index -= 1;
263 Piece * k = king(s2.piece->colour);
266 if (k->colour == Piece::WHITE)
271 if ((IsClone() && s2.piece == parent->grid[x2][y2].piece) == false)
286 * @purpose Get all moves for a Piece and store them
288 * @param v - vector to store Squares in. Will *not* be cleared.
290 void Board::Get_moves(Piece * p, vector<Square*> & v)
292 assert(p->current_type != Piece::UNKNOWN);
293 int x = p->x; int y = p->y;
294 if (p->current_type == Piece::KING)
300 Move(p, x+1, y+1, v);
301 Move(p, x+1, y-1, v);
302 Move(p, x-1, y+1, v);
303 Move(p, x-1, y-1, v);
305 else if (p->current_type == Piece::KNIGHT)
307 Move(p, x+2, y+1, v);
308 Move(p, x+2, y-1, v);
309 Move(p, x-2, y+1, v);
310 Move(p, x-2, y-1, v);
311 Move(p, x+1, y+2, v);
312 Move(p, x-1, y+2, v);
313 Move(p, x+1, y-2, v);
314 Move(p, x-1, y-2, v);
316 else if (p->current_type == Piece::PAWN)
318 int y1 = (p->colour == Piece::WHITE) ? BOARD_HEIGHT-2 : 1;
319 int y2 = (p->colour == Piece::WHITE) ? y1 - 2 : y1 + 2;
320 if (p->types[0] == Piece::PAWN && p->y == y1)
325 y2 = (p->colour == Piece::WHITE) ? y - 1 : y + 1;
328 if (Valid_position(x-1, y2) && grid[x-1][y2].piece != NULL)
330 if (Valid_position(x+1, y2) && grid[x+1][y2].piece != NULL)
333 else if (p->current_type == Piece::BISHOP)
340 else if (p->current_type == Piece::ROOK)
347 else if (p->current_type == Piece::QUEEN)
363 * @purpose Add a move to the vector, if it is valid
364 * @param p - Piece that would move
365 * @param x, y - Destination Square coords
366 * @param v - vector to put the destination Square in, if the move is valid
368 void Board::Move(Piece * p, int x, int y, vector<Square*> & v)
370 if (Valid_position(x, y) && (grid[x][y].piece == NULL || grid[x][y].piece->colour != p->colour))
372 v.push_back(&(grid[x][y]));
375 // cerr << "Square " << x << "," << y << " invalid; " << grid[x][y].piece << "\n";
380 * @purpose Add moves in a specified direction to the vector, until we get to an invalid move
381 * @param p - Piece to start scanning from
382 * @param vx, vy - "velocity" - change in coords each move
383 * @param v - vector to store valid Squares in
385 void Board::Scan(Piece * p, int vx, int vy, vector<Square*> & v)
389 while (Valid_position(x, y) && (grid[x][y].piece == NULL || grid[x][y].piece->colour != p->colour))
391 v.push_back(&(grid[x][y]));
392 if (grid[x][y].piece != NULL)
401 * @purpose Convert string to Piece::Type
402 * @param str - The string
403 * @returns A Piece::Type
405 Piece::Type Piece::str2type(const string & str)
409 else if (str == "queen")
411 else if (str == "rook")
413 else if (str == "bishop")
414 return Piece::BISHOP;
415 else if (str == "knight")
416 return Piece::KNIGHT;
417 else if (str == "pawn")
419 else if (str == "unknown")
420 return Piece::UNKNOWN;
422 throw Exception("Piece::str2type", "String \"%s\" doesn't represent a type", str.c_str());
423 return Piece::UNKNOWN;
428 * @purpose Convert Piece::Type to string
429 * @param t - The Types
430 * @returns a const char*
432 const char * Piece::type2str(const Piece::Type & t)
451 throw Exception("Piece::type2str", "Unknown type %d", (int)t);
458 * @purpose Convert string to Piece::Colour
459 * @param str - The string
460 * @returns A Piece::Colour
462 Piece::Colour Piece::str2colour(const string & str)
466 else if (str == "black")
469 throw Exception("Piece::str2colour", "string \"%s\" is not white|black", str.c_str());
470 return Piece::BLACK; // should never get here
475 * @purpose Creates a new Piece and adds it to a vector
476 * @param v - The vector
477 * @params - All remaining parameters passed to Piece::Piece
478 * @returns Pointer to the new Piece
480 Piece * Piece::AddPiece(vector<Piece*> & v, int x, int y, const Piece::Colour & colour, const Piece::Type & t1, const Piece::Type & t2,
483 Piece * p = new Piece(x,y,colour,t1, t2,type_index, v.size());
490 * @purpose If necessary, copy the piece in the square
491 * @param s - The square
493 void Board::Clone_copy(Square & s)
495 if (s.piece == NULL || !IsClone()) return;
496 if (parent->grid[s.x][s.y].piece == s.piece)
498 s.piece = new Piece(*(s.piece));
499 vector<Piece*> & v = pieces(s.piece->colour);
500 v[s.piece->piece_index] = s.piece;