00001 // cwchessboard -- A C++ chessboard tool set 00002 // 00003 //! @file EnPassant.h This file contains the declaration of class EnPassant. 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 ENPASSANT_H 00025 #define ENPASSANT_H 00026 00027 #ifndef USE_PCH 00028 #endif 00029 00030 #define DEBUG_ENPASSANT_EXISTS 0 00031 00032 #if DEBUG_ENPASSANT_EXISTS 00033 #include <cassert> 00034 #endif 00035 00036 namespace cwchess { 00037 00038 /** @brief An object representing en passant information. 00039 * 00040 * This is an internal class, you should not normally need. 00041 * 00042 * If EnPassant::exists() returns true, then a pawn exists that can be taken en passant, 00043 * or could be taken en passant if an enemy pawn was standing next to it. 00044 * This means that in 'position setup mode', placing a pawn next to the en passant 00045 * pawn (on index EnPassant::pawn_index()) will be able to take the en passant pawn. 00046 * 00047 * @sa ChessPosition::en_passant 00048 * / 00049 class EnPassant { 00050 private: 00051 //! @brief En passant information. 00052 // 00053 // PEIIIIII, where 'IIIIII' is the index of the square that a pawn just passed by moving two squares forward, 00054 // and bit 'P' is a flag indicating that a pawn is not allowed to take en passant because it is pinned. 00055 // If 'E' is set then all I must be 0 and the index is 'index_end'. 00056 // 00057 // If there exists no en passant pawn then 'P' must be 0. 00058 uint8_t M_bits; 00059 00060 public: 00061 #ifndef DOXYGEN 00062 //! @brief Construct an uninitialized EnPassant object. 00063 EnPassant(void) { } 00064 00065 //! @brief Construct EnPassant object with index \a index. 00066 EnPassant(Index const& index) : M_bits(index()) { } 00067 00068 //! @brief Assignment operator. 00069 EnPassant& operator=(EnPassant const& en_passant) { M_bits = en_passant.M_bits; return* this; } 00070 00071 //! @brief Clear the EnPassant object. 00072 void clear(void) { M_bits = index_end.M_bits; } 00073 00074 //! @brief Return the FEN field with en passant information. 00075 std::string FEN4(void) const; 00076 #endif 00077 00078 //! @brief Return TRUE if the last move was a pawn advancing two squares. 00079 bool exists(void) const { return M_bits != index_end.M_bits; } 00080 00081 /** @name Accessors* / 00082 //@{ 00083 00084 //! @brief Return the index of the square that was passed. 00085 Index index(void) const 00086 { 00087 #if DEBUG_ENPASSANT_EXISTS 00088 assert(exists()); 00089 #endif 00090 IndexData result = { M_bits & 0x7f }; 00091 return result; 00092 } 00093 00094 //! @brief Return the index of the pawn that just advanced two squares. 00095 Index pawn_index(void) const 00096 { 00097 #if DEBUG_ENPASSANT_EXISTS 00098 assert(exists()); 00099 #endif 00100 IndexData result = { (M_bits & 0x7f) ^ 8 }; 00101 return result; 00102 } 00103 00104 //! @brief Return the index of the square that pawn came from. 00105 Index from_index(void) const 00106 { 00107 #if DEBUG_ENPASSANT_EXISTS 00108 assert(exists()); 00109 #endif 00110 IndexData result = { (M_bits & 0x7f) ^ 24 }; 00111 return result; 00112 } 00113 00114 //! @brief Return TRUE if taking en passant is not allowed due to <em>horizontal</em> pinning. 00115 bool pinned(void) const 00116 { 00117 #if DEBUG_ENPASSANT_EXISTS 00118 assert(exists()); 00119 #endif 00120 return (M_bits & 0x80); 00121 } 00122 00123 //@} 00124 00125 #ifndef DOXYGEN 00126 //! @brief Taking en passant is not allowed because it is pinned. 00127 void pinned_set(void) 00128 { 00129 #if DEBUG_ENPASSANT_EXISTS 00130 assert(exists()); 00131 #endif 00132 M_bits |= 0x80; 00133 } 00134 00135 //! @brief Taking en passant is allowed again, because it is unpinned. 00136 void pinned_reset(void) { M_bits& = 0x7f; } 00137 #endif 00138 00139 }; 00140 00141 } // namespace cwchess 00142 00143 #endif // ENPASSANT_H