00001 // cwchessboard -- A C++ chessboard tool set 00002 // 00003 //! @file ChessPosition.h This file contains the declaration of class ChessPosition. 00004 // 00005 // Copyright (C) 2008, by 00006 // 00007 // Carlo Wood, Run on IRC <carlo@alinoe.com> 00008 // RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt 00009 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61 00010 // 00011 // This program is free software: you can redistribute it and/or modify 00012 // it under the terms of the GNU General Public License as published by 00013 // the Free Software Foundation, either version 2 of the License, or 00014 // (at your option) any later version. 00015 // 00016 // This program is distributed in the hope that it will be useful, 00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 // GNU General Public License for more details. 00020 // 00021 // You should have received a copy of the GNU General Public License 00022 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00023 00024 #ifndef CHESSPOSITION_H 00025 #define CHESSPOSITION_H 00026 00027 #ifndef USE_PCH 00028 #endif 00029 00030 #include "BitBoard.h" 00031 #include "Piece.h" 00032 #include "PieceIterator.h" 00033 #include "MoveIterator.h" 00034 #include "Array.h" 00035 #include "CastleFlags.h" 00036 #include "EnPassant.h" 00037 #include "CountBoard.h" 00038 00039 namespace cwchess { 00040 00041 /** @brief A chess position. 00042 * 00043 * This class represents a chess position. 00044 * It has all information regarding a single position, 00045 * including the full move count (because that is needed 00046 * for the FEN code), the half move clock (to determine 00047 * whether a derived position becomes a draw due to the 00048 * 50 moves rule), en passant and castling information. 00049 * / 00050 class ChessPosition { 00051 private: 00052 ArrayCode<BitBoard> M_bitboards; //!< Bitboards reflecting the current position. 00053 ArrayIndex<Piece> M_pieces; //!< A piece per square. The index of the array is an Index. 00054 ArrayColor<BitBoard> M_attackers; //!< Bitboards for squares of enemy pieces on the same line as the king and all squares in between. 00055 ArrayColor<BitBoard> M_pinning; //!< Squares between attacker and king for actually pinned pieces (including attacker). 00056 ArrayColor<CountBoard> M_defended; //!< The number times a square is defended. 00057 ArrayColor<uint8_t> M_king_battery_attack_count; //!< The number of times that a king is 'attacked' by pieces behind another attacker. 00058 uint16_t M_full_move_number; //!< The number of the full move. It starts at 1, and is incremented after Black's move. 00059 uint8_t M_half_move_clock; //!< Number of half moves since the last pawn advance or capture. 00060 CastleFlags M_castle_flags; //!< Whether black and white may castle long or short. 00061 Color M_to_move; //!< The active color. 00062 EnPassant M_en_passant; //!< A pawn that can be taken en passant, or zeroed if none such pawn exists. 00063 bool M_double_check; //!< Cached value of wether or not M_to_move is in double check. 00064 00065 public: 00066 00067 /** @name Constructor* / 00068 //@{ 00069 00070 //! @brief Construct an uninitialized position. 00071 // 00072 // Because ChessPosition::clear doesn't set M_to_move, the only 00073 // member variable initialized here is M_to_move because it needs 00074 // to be set to something before we can call ChessPosition::place, 00075 // or uninitialized memory would be used. 00076 ChessPosition(void) : M_to_move(white) { } 00077 00078 //@} 00079 00080 /** @name Position setup* / 00081 //@{ 00082 00083 /** @brief Clear the board. 00084 * 00085 * This does not change whose move it is. 00086 * The half move clock and full move number are reset (to zero and one respectively). 00087 * / 00088 void clear(void); 00089 00090 /** @brief Set up the initial position.* / 00091 void initial_position(void); 00092 00093 /** @brief Skip a move. 00094 * 00095 * This resets the right to capture en passant. 00096 * Skipping a move is counted as move. 00097 * 00098 * @returns TRUE if the result is a draw due to the 50 moves rule. 00099 * / 00100 bool skip_move(void); 00101 00102 /** @brief Explicitly set whose turn it is. 00103 * 00104 * This does not change the half move clock or full move number, nor does it change the en passant information. 00105 * The reason for that is that this call is probably done as part of a position setup and calls that explicitely 00106 * set en passant information and the move counters might already have been called. However, calling this 00107 * an odd number of times after en passant information was set therefore leaves the position is an erroneous state. 00108 * 00109 * If you just want to change who is to move from a given position, then use %skip_move. 00110 * 00111 * @param color : The color that has to move next from this position. 00112 * / 00113 void to_move(Color const& color); 00114 00115 /** @brief Explicitly set the number of half moves since the last pawn move or capture. 00116 * 00117 * This does not change the full move number, en passant information or whose turn it is. 00118 * / 00119 void set_half_move_clock(int count) { M_half_move_clock = count; } 00120 00121 /** @brief Explicitly set the move number. 00122 * 00123 * This does not change the half move clock, en passant information or whose turn it is. 00124 * / 00125 void set_full_move_number(int move) { M_full_move_number = move; } 00126 00127 /** @brief Explicity set the en passant information. 00128 * 00129 * This also sets whose turn it is. No error checking is done on whether there is 00130 * actually a pawn that could have just moved two squares. 00131 * 00132 * @param index : The square that a pawn just passed by advancing two square. 00133 * 00134 * @returns TRUE if there are indeed one or two pawns that can take en passant. 00135 * / 00136 bool set_en_passant(Index const& index); 00137 00138 /** @brief Swap colors. 00139 * 00140 * This changes the color of each piece, 00141 * toggles whose turn it is and mirrors the position vertically. 00142 * The resulting position is technically identical to the original position, 00143 * but with different colors for each piece. 00144 * 00145 * In order to make the position technically equivalent, the half 00146 * move clock is unchanged; however, the full move number is reset 00147 * (to one) because it would impossible to really have the same 00148 * history: it is not possible that black started the game. 00149 * / 00150 void swap_colors(void); 00151 00152 /** @brief Place a piece on the board. 00153 * 00154 * Place a \a piece on the board. 00155 * If there is already a piece there, it is replaced. 00156 * It is also possible to place 'nothing', in which case any piece that was there is removed. 00157 * 00158 * If the king or a rook is placed, then the castling flags are updated to 00159 * allow castling by default. If this is not what you want, then call %moved 00160 * to signal that castling is not allowed <em>after</em> placing both, the king 00161 * and the rook(s). 00162 * 00163 * If a pawn is marked as En Passant then that is persistent: it will stay 00164 * that way (placing a piece is not the same as making a move). However, if 00165 * the pawn that can be taken en passant is moved, replaced (by again a pawn) 00166 * or when a piece is put behind it, so that it's impossible that it was 00167 * the last move (no logic will check other reasons, like being in check), 00168 * then its En Passant status is reset. For example, if there is a white 00169 * pawn on f4 that can be taken en passant by a black pawn on g4, and the 00170 * pawn on g4 is removed or replaced then that doesn't change the status 00171 * of the pawn on f4. If (later) a black pawn in placed on g4, then that 00172 * pawn will be able to take the white pawn on f4, provided that nothing 00173 * has been placed, even temporarily, on f3 or f2, and the pawn on f4 was 00174 * never replaced. 00175 * 00176 * At the moment the only placement that is refused is placing pawns on rank 1 or 8. 00177 * 00178 * @param code : The piece to be placed on the board. 00179 * @param index : Where to place the piece. 00180 * 00181 * @returns TRUE if the piece was placed, FALSE if it was refused. 00182 * / 00183 bool place(Code const& code, Index const& index); 00184 00185 /** @brief Specifically specify that a king or rook has already moved. 00186 * 00187 * Calling this function is only necessary if king and rook are both 00188 * on the initial squares. Placing the rook or king after calling 00189 * this function will reset the castling flags (to allow castling); 00190 * therefore first place the pieces and then, if necessary, call 00191 * this function. 00192 * 00193 * @param index : The (initial position of the) rook or king. 00194 * / 00195 void set_has_moved(Index const& index) { M_castle_flags.piece_moved_from(piece_at(index), index); } 00196 00197 /** @brief Specifically specify that a king or rook didn't move yet. 00198 * 00199 * This function only has effect if the king or rook is on its initial square. 00200 * 00201 * @param index : The (initial position of the) rook or king. 00202 * / 00203 void clear_has_moved(Index const& index) { M_castle_flags.update_placed(piece_at(index).code(), index); } 00204 00205 /** @brief Read a FEN code. 00206 * 00207 * @param FEN : A Forsyth-Edwards Notation. 00208 * 00209 * If the FEN code is non-parsable, the function return FALSE and 00210 * the position is in an undefined state. Therefore you might 00211 * want to use the function as follows: 00212 * 00213 * <pre> 00214 * ChessPosition tmp(current_chess_position); 00215 * if (tmp.load_FEN(fen)) 00216 * current_chess_position = tmp; 00217 * else 00218 * { 00219 * // report error 00220 * } 00221 * </pre> 00222 * 00223 * @returns TRUE if loading was successful. 00224 * / 00225 bool load_FEN(std::string const& FEN); 00226 00227 //@} 00228 00229 #ifndef DOXYGEN 00230 // Needs access to M_pieces. 00231 friend class PieceIterator; 00232 #endif 00233 00234 /** @name Accessors* / 00235 //@{ 00236 00237 /** @brief Return the Piece on the square \a index.* / 00238 Piece piece_at(Index const& index) const { return M_pieces[index]; } 00239 00240 /** @brief Return the Piece on the square \a col, \a row.* / 00241 Piece piece_at(int col, int row) const { return M_pieces[Index(col, row)]; } 00242 00243 /** @brief Return whose turn it is.* / 00244 Color to_move(void) const { return M_to_move; } 00245 00246 /** @brief Return the half move clock.* / 00247 unsigned int half_move_clock(void) const { return M_half_move_clock; } 00248 00249 /** @brief Return the full move number.* / 00250 unsigned int full_move_number(void) const { return M_full_move_number; } 00251 00252 /** @brief Return the castle flag object.* / 00253 CastleFlags const& castle_flags(void) const { return M_castle_flags; } 00254 00255 /** @brief Return the en passant object.* / 00256 EnPassant const& en_passant(void) const { return M_en_passant; } 00257 00258 /** @brief Return a BitBoard with bits set for all \a code, where \a code may not be 'nothing'.* / 00259 BitBoard const& all(Code const& code) const { return M_bitboards[code]; } 00260 00261 /** @brief Return a BitBoard with bits set for all pieces of color \a color.* / 00262 BitBoard const& all(Color const& color) const { return M_bitboards[color]; } 00263 00264 //@} 00265 00266 public_notdocumented: 00267 // Added for debugging purposes. 00268 ArrayColor<CountBoard> const& get_defended(void) const { return M_defended; } 00269 BitBoard attackers(Color const& color) const { return M_attackers[color]; } 00270 BitBoard pinned(Color const& color) const { return M_pinning[color]; } 00271 00272 public: 00273 /** @name Visitors* / 00274 //@{ 00275 00276 /** @brief Return the FEN code for this position.* / 00277 std::string FEN(void) const; 00278 00279 /** @brief Return the offset into the candidates_table for type \a type. 00280 * 00281 * The type may not be a pawn (there is no candidates_table entry for a pawn). 00282 * / 00283 int candidates_table_offset(Type const& type) const 00284 { 00285 int n = type(); 00286 n -= (n > 4) ? 3 : 2; 00287 n <<= 6; 00288 return n; 00289 } 00290 00291 /** @brief Return a BitBoard with bits set for all squares that are candidates to move to. 00292 * 00293 * In the case of the pawn, the returned BitBoard is exact. 00294 * In the case of the king, the castling squares are not included. 00295 * In all other cases the returned squares assume an empty board. 00296 * 00297 * This function may not be called for an empty square. 00298 * / 00299 BitBoard candidates(Index const& index) const 00300 { 00301 Piece const& piece(M_pieces[index]); 00302 if (piece == black_pawn) 00303 { 00304 BitBoardData data; 00305 mask_t flags = piece.flags()(); 00306 data.M_bitmask = (flags << 50) | (flags << 40); 00307 data.M_bitmask& = CW_MASK_T_CONST(0xe0400000000000); 00308 data.M_bitmask >>= 62 - index(); 00309 return BitBoard(data); 00310 } 00311 else if (piece == white_pawn) 00312 { 00313 BitBoardData data; 00314 mask_t flags = piece.flags()(); 00315 data.M_bitmask = flags | (flags << 6); 00316 data.M_bitmask& = 0x1038; 00317 data.M_bitmask <<= index() + 4; 00318 return BitBoard(data); 00319 } 00320 return BitBoard(candidates_table[candidates_table_offset(piece.type()) + index()]); 00321 } 00322 00323 /** @brief Return a BitBoard with bits set for each square that a piece can reach in one move. 00324 * 00325 * The parameter \a attacked_squares only influences pawns and the king. 00326 * If set, the squares returned for a pawn are always the two attacked 00327 * squares (independent of other pieces); and the king does not return 00328 * any castling squares. The definition would be: squares that the 00329 * opponent may not move to with his king. 00330 * 00331 * @param index : The position of the piece under investigation. 00332 * @param attacked_squares : If true, rather return if squares are attacked than whether the piece can move there. 00333 * / 00334 BitBoard reachables(Index const& index, bool attacked_squares = false) const; 00335 00336 /** @brief Return a BitBoard with bits set for each square that a piece defends, or would defend if an exchange was going on there. 00337 * 00338 * This function returns the squares that the enemy king is not allowed to go to 00339 * as a result of this piece. However, the attacks are considered to go through 00340 * slider pieces of the same type. For example, if you ask about the defendables 00341 * of a white rook on e1, and there is already a white rook (or queen) on e2, 00342 * then the square e3 (and beyond) is returned nevertheless. 00343 * 00344 * It is not necessary for the piece to actually stand on the board yet. 00345 * 00346 * @param code : The piece. 00347 * @param index : The place that the piece is considered to be standing on. 00348 * @param battery : Internal output variable (ignore it). 00349 * / 00350 BitBoard defendables(Code const& code, Index const& index, bool& battery) const; 00351 00352 /** @brief Return the index of the king with color \a color.* / 00353 Index index_of_king(Color const& color) const { CodeData data = { king_bits | color() }; return mask2index(M_bitboards[data]()); } 00354 00355 /** @brief Return true if the king is in check.* / 00356 bool check(void) const { return M_bitboards[Code(M_to_move, king)].test(M_defended[M_to_move.opposite()].any()); } 00357 00358 /** @brief Return true if the king of color \a color is in check.* / 00359 bool check(Color const& color) const { return M_bitboards[Code(color, king)].test(M_defended[color.opposite()].any()); } 00360 00361 /** @brief Return true if the king of color \a color is in double check.* / 00362 bool double_check(Color const& color) const 00363 { Color opposite_color(color.opposite()); 00364 CodeData data = { king_bits | color() }; 00365 return M_defended[opposite_color].count(M_bitboards[data]) - M_king_battery_attack_count[opposite_color] > 1; } 00366 00367 /** @brief Return true if the king or rook on \a index has moved or not. 00368 * 00369 * Calling this function for another piece than a king or rook returns false. 00370 * / 00371 bool has_moved(Index const& index) { return M_castle_flags.has_moved(M_pieces[index].code(), index); } 00372 00373 /** @brief Return a BitBoard with bits set for each square the piece at index can legally go to. 00374 * 00375 * @param index : The square that the piece stands on that is to be considered. 00376 * / 00377 BitBoard moves(Index const& index) const; 00378 00379 /** @brief Return true if the move is a legal move.* / 00380 bool legal(Move const& move) const; 00381 00382 //@} 00383 00384 /** @name Iterators* / 00385 //@{ 00386 00387 /** @brief Return an iterator to the first piece of color \a color. 00388 * 00389 * The iterator will iterate over all pieces with color \a color. 00390 * / 00391 PieceIterator piece_begin(Color const& color) const { return PieceIterator(this, M_bitboards[color]); } 00392 00393 /** @brief Return an iterator one beyond the last piece.* / 00394 PieceIterator piece_end(void) const { return PieceIterator(); } 00395 00396 /** @brief Return an iterator to the first piece with code \a code. 00397 * 00398 * The iterator will iterate over all pieces with code \a code; \a code may not be empty. 00399 * / 00400 PieceIterator piece_begin(Code const& code) const { return PieceIterator(this, M_bitboards[code]); } 00401 00402 /** @brief Return an iterator to the first move of the piece at index \a index.* / 00403 MoveIterator move_begin(Index const& index) const { return MoveIterator(this, index); } 00404 00405 /** @brief Return an iterator one beyond the last move.* / 00406 MoveIterator move_end(void) const { return MoveIterator(); } 00407 00408 //@} 00409 00410 /** @name Game play* / 00411 //@{ 00412 00413 /** @brief Execute move \a move.* / 00414 bool execute(Move const& move); 00415 00416 //@} 00417 00418 protected: 00419 void reset_en_passant(void) { if (M_en_passant.exists()) clear_en_passant(); } 00420 00421 private: 00422 // Reset the right to take en passant. 00423 void clear_en_passant(void); 00424 00425 // Increment M_half_move_clock (or reset if \a pawn_advance_or_capture is true) and M_full_move_number if appropriate. 00426 bool increment_counters(bool pawn_advance_or_capture); 00427 00428 // Update the fl_pawn_can_take_* pawn flags for a piece of color \a color that was removed from (col, row). 00429 void update_removed(uint8_t col, uint8_t row, Color const& color); 00430 00431 // Update the fl_pawn_can_take_* pawn flags for a piece of color \a color that was placed at (col, row). 00432 void update_placed(uint8_t col, uint8_t row, Color const& color); 00433 00434 // Update pinning flags. 00435 void update_pinning(Code const& code, Index const& index, mask_t mask, Direction const& direction, BitBoard const& line); 00436 00437 // Calculate a bitboard with all pieces minus all bishop movers and first hit pawn, plus blocking bits after those first pawns. 00438 BitBoard all_pieces_minus_bishop_movers(Color const& color, Index const& index) const; 00439 00440 // Calculate the squares that would be blocked by a piece with code \a code at \a index and than add or subtract them from M_defended. 00441 // Also update M_king_battery_attack_count. 00442 void update_blocked_defendables(Code const& code, Index const& index, bool add); 00443 00444 private: 00445 static BitBoardData candidates_table[5 * 64]; 00446 }; 00447 00448 } // namespace cwchess 00449 00450 #ifndef DOXYGEN // Hide this from doxygen in order to make some graph less wide. 00451 #include "PieceIterator.inl" 00452 #include "MoveIterator.inl" 00453 #endif 00454 00455 #endif // CHESSPOSITION_H