BitBoard.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #ifndef CHESSY_BITBOARD_H
  2. #define CHESSY_BITBOARD_H
  3. #include "BitOperations.h"
  4. #include <cinttypes>
  5. #include <type_traits>
  6. #include <string>
  7. namespace chessy
  8. {
  9. enum PieceType : char;
  10. struct Index;
  11. struct Move;
  12. struct Bitboard;
  13. using Side = int;
  14. const Side WHITE_SIDE = 0;
  15. const Side BLACK_SIDE = 1;
  16. inline constexpr Side otherSide(Side side)
  17. {
  18. return !side;
  19. }
  20. }
  21. enum chessy::PieceType : char
  22. {
  23. EMPTY = -1,
  24. PAWN = 0,
  25. KNIGHT = 1,
  26. BISHOP = 2,
  27. ROOK = 3,
  28. QUEEN = 4,
  29. KING = 5,
  30. };
  31. /*!
  32. * data structure to index one field on a chess board
  33. */
  34. struct chessy::Index
  35. {
  36. int8_t index;
  37. Index(void) = default;
  38. inline constexpr Index(int8_t ind) : index{ ind } {}
  39. inline Index(const std::string& name) :
  40. Index{ name[1] - '1', name[0] - 'a' } {}
  41. inline constexpr Index(int row, int column) :
  42. index{int8_t(((row & 0x7) << 3) + (column & 0x7))} {}
  43. inline operator int8_t (void) const { return index; }
  44. inline int getColumn (void) const { return index & 0x7; }
  45. inline int getRow (void) const { return (index >> 3) & 0x7; }
  46. inline std::string getName(void) const
  47. {
  48. return { char('a' + getColumn()), char(getRow() + '1') };
  49. }
  50. };
  51. /*!
  52. * data structure that holds a simple move
  53. */
  54. struct chessy::Move
  55. {
  56. Index origin;
  57. Index destination;
  58. //! If the move is a promotion move, this field stores
  59. //! the type of the resulting piece.
  60. //! If this field is equal to <code>PieceType::PAWN</code>,
  61. //! it is indicated, that no promotion happened.
  62. PieceType promotion;
  63. bool isCastling;
  64. Move (void) = default;
  65. Move (const Move&) = default;
  66. Move (Move&&) = default;
  67. ~Move (void) = default;
  68. Move& operator= (const Move&) = default;
  69. Move& operator= (Move&&) = default;
  70. inline Move(const std::string& move) :
  71. promotion{ PieceType::PAWN }, isCastling{ false }
  72. {
  73. if (move.length() < 4)
  74. return;
  75. origin = Index { move.substr(0, 2) };
  76. destination = Index { move.substr(2, 2) };
  77. if (move.length() > 4) {
  78. switch (move[4]) {
  79. case 'n': promotion = PieceType::KNIGHT; break;
  80. case 'b': promotion = PieceType::BISHOP; break;
  81. case 'r': promotion = PieceType::ROOK; break;
  82. case 'q': promotion = PieceType::QUEEN; break;
  83. }
  84. }
  85. }
  86. inline Move(Index origin, Index destination) :
  87. origin{ origin }, destination{ destination },
  88. promotion{ PieceType::PAWN }, isCastling{ false } {}
  89. inline Move(Index origin, Index destination, PieceType promotion) :
  90. origin{ origin }, destination{ destination }, promotion{ promotion },
  91. isCastling{ false } {}
  92. inline Move(Index origin, Index destination, bool isCastling) :
  93. origin{ origin }, destination{ destination },
  94. promotion{ PieceType::PAWN }, isCastling{ isCastling } {}
  95. inline std::string asString(void) const
  96. {
  97. return origin.getName() + destination.getName() +
  98. (promotion == PieceType::KNIGHT ? "n" : "") +
  99. (promotion == PieceType::BISHOP ? "b" : "") +
  100. (promotion == PieceType::ROOK ? "r" : "") +
  101. (promotion == PieceType::QUEEN ? "q" : "");
  102. }
  103. };
  104. struct chessy::Bitboard
  105. {
  106. U64 bits;
  107. Bitboard (void) = default;
  108. Bitboard (const Bitboard&) = default;
  109. Bitboard (Bitboard&&) = default;
  110. ~Bitboard (void) = default;
  111. Bitboard& operator= (const Bitboard&) = default;
  112. Bitboard& operator= (Bitboard&&) = default;
  113. inline constexpr Bitboard(U64 bits) : bits{ bits } {}
  114. inline static Bitboard fromIndex(Index i) { return U64(1) << i; }
  115. inline void setBit (Index i) { bits |= U64(1) << i.index; }
  116. inline void unsetBit (Index i) { bits |= ~(U64(1) << i.index); }
  117. inline void setBit (int row, int column)
  118. { setBit(row * 8 + column); }
  119. inline void unsetBit (int row, int column)
  120. { unsetBit(row * 8 + column); }
  121. static const U64 aColumn = 0x0101010101010101ULL;
  122. static const U64 hColumn = 0x8080808080808080ULL;
  123. inline void moveNorth (int dist) { bits <<= (8 * dist); }
  124. inline Bitboard north (int dist) { return bits << (8 * dist); }
  125. inline void moveSouth (int dist) { bits >>= (8 * dist); }
  126. inline Bitboard south (int dist) { return bits >> (8 * dist); }
  127. inline void moveNorthOne(void) { bits <<= 8; }
  128. inline Bitboard northOne (void) { return bits << 8; }
  129. inline void moveSouthOne(void) { bits >>= 8; }
  130. inline Bitboard southOne (void) { return bits >> 8; }
  131. inline void moveEastOne (void) { bits = (bits & ~aColumn) >> 1; }
  132. inline Bitboard eastOne (void) { return (bits & ~aColumn) >> 1; }
  133. inline void moveWestOne (void) { bits = (bits & ~hColumn) << 1; }
  134. inline Bitboard westOne (void) { return (bits & ~hColumn) << 1; }
  135. inline void moveNWOne (void) { bits = (bits << 7) & ~hColumn; }
  136. inline Bitboard nwOne (void) { return (bits << 7) & ~hColumn; }
  137. inline void moveNEOne (void) { bits = (bits << 9) & ~aColumn; }
  138. inline Bitboard neOne (void) { return (bits << 9) & ~aColumn; }
  139. inline void moveSWOne (void) { bits = (bits >> 9) & ~hColumn; }
  140. inline Bitboard swOne (void) { return (bits >> 9) & ~hColumn; }
  141. inline void moveSEOne (void) { bits = (bits >> 7) & ~aColumn; }
  142. inline Bitboard seOne (void) { return (bits >> 7) & ~aColumn; }
  143. template<Side side>
  144. inline void pushOne(void)
  145. {
  146. if (side == WHITE_SIDE)
  147. moveNorthOne();
  148. else
  149. moveSouthOne();
  150. }
  151. inline void operator &= (const Bitboard& b) { bits &= b.bits; }
  152. inline void operator |= (const Bitboard& b) { bits |= b.bits; }
  153. inline void operator ^= (const Bitboard& b) { bits ^= b.bits; }
  154. inline Bitboard operator & (const Bitboard& b) const { return bits & b.bits; }
  155. inline Bitboard operator | (const Bitboard& b) const { return bits | b.bits; }
  156. inline Bitboard operator ^ (const Bitboard& b) const { return bits ^ b.bits; }
  157. inline Bitboard operator ~ (void) const { return ~bits; }
  158. inline bool operator == (const Bitboard& b) const { return bits == b.bits; }
  159. inline bool operator != (const Bitboard& b) const { return bits != b.bits; }
  160. inline operator U64(void) const { return bits; }
  161. inline explicit operator bool(void) const { return bits != 0; }
  162. inline void applyMove(Move move)
  163. {
  164. bits &= ~fromIndex(move.origin);
  165. bits |= fromIndex(move.destination);
  166. }
  167. inline Bitboard mirror(void) const { return byteswap(bits); }
  168. inline Index getLeastSignificantBit (void) const { return trailingZeroes(bits); }
  169. inline int popcount (void) const { return chessy::popcount(bits); }
  170. };
  171. static_assert(std::is_pod<chessy::Bitboard>::value,
  172. "chessy::Bitboard should be a POD structure.");
  173. static_assert(std::is_pod<chessy::Index>::value,
  174. "chessy::Index should be a POD structure.");
  175. static_assert(sizeof(chessy::Bitboard) == sizeof(uint64_t),
  176. "chessy::Bitboard should be 64 bits in size.");
  177. #endif // CHESSY_BITBOARD_H