123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- #ifndef CHESSY_BITBOARD_H
- #define CHESSY_BITBOARD_H
- #include "BitOperations.h"
- #include <cinttypes>
- #include <type_traits>
- #include <string>
- namespace chessy
- {
- enum PieceType : char;
- struct Index;
- struct Move;
- struct Bitboard;
- using Side = int;
- const Side WHITE_SIDE = 0;
- const Side BLACK_SIDE = 1;
- inline constexpr Side otherSide(Side side)
- {
- return !side;
- }
- }
- enum chessy::PieceType : char
- {
- EMPTY = -1,
- PAWN = 0,
- KNIGHT = 1,
- BISHOP = 2,
- ROOK = 3,
- QUEEN = 4,
- KING = 5,
- };
- /*!
- * data structure to index one field on a chess board
- */
- struct chessy::Index
- {
- int8_t index;
- Index(void) = default;
- inline constexpr Index(int8_t ind) : index{ ind } {}
- inline Index(const std::string& name) :
- Index{ name[1] - '1', name[0] - 'a' } {}
- inline constexpr Index(int row, int column) :
- index{int8_t(((row & 0x7) << 3) + (column & 0x7))} {}
- inline operator int8_t (void) const { return index; }
- inline int getColumn (void) const { return index & 0x7; }
- inline int getRow (void) const { return (index >> 3) & 0x7; }
- inline std::string getName(void) const
- {
- return { char('a' + getColumn()), char(getRow() + '1') };
- }
- };
- /*!
- * data structure that holds a simple move
- */
- struct chessy::Move
- {
- Index origin;
- Index destination;
- //! If the move is a promotion move, this field stores
- //! the type of the resulting piece.
- //! If this field is equal to <code>PieceType::PAWN</code>,
- //! it is indicated, that no promotion happened.
- PieceType promotion;
- bool isCastling;
- Move (void) = default;
- Move (const Move&) = default;
- Move (Move&&) = default;
- ~Move (void) = default;
- Move& operator= (const Move&) = default;
- Move& operator= (Move&&) = default;
- inline Move(const std::string& move) :
- promotion{ PieceType::PAWN }, isCastling{ false }
- {
- if (move.length() < 4)
- return;
- origin = Index { move.substr(0, 2) };
- destination = Index { move.substr(2, 2) };
- if (move.length() > 4) {
- switch (move[4]) {
- case 'n': promotion = PieceType::KNIGHT; break;
- case 'b': promotion = PieceType::BISHOP; break;
- case 'r': promotion = PieceType::ROOK; break;
- case 'q': promotion = PieceType::QUEEN; break;
- }
- }
- }
- inline Move(Index origin, Index destination) :
- origin{ origin }, destination{ destination },
- promotion{ PieceType::PAWN }, isCastling{ false } {}
- inline Move(Index origin, Index destination, PieceType promotion) :
- origin{ origin }, destination{ destination }, promotion{ promotion },
- isCastling{ false } {}
- inline Move(Index origin, Index destination, bool isCastling) :
- origin{ origin }, destination{ destination },
- promotion{ PieceType::PAWN }, isCastling{ isCastling } {}
- inline std::string asString(void) const
- {
- return origin.getName() + destination.getName() +
- (promotion == PieceType::KNIGHT ? "n" : "") +
- (promotion == PieceType::BISHOP ? "b" : "") +
- (promotion == PieceType::ROOK ? "r" : "") +
- (promotion == PieceType::QUEEN ? "q" : "");
- }
- };
- struct chessy::Bitboard
- {
- U64 bits;
- Bitboard (void) = default;
- Bitboard (const Bitboard&) = default;
- Bitboard (Bitboard&&) = default;
- ~Bitboard (void) = default;
- Bitboard& operator= (const Bitboard&) = default;
- Bitboard& operator= (Bitboard&&) = default;
- inline constexpr Bitboard(U64 bits) : bits{ bits } {}
- inline static Bitboard fromIndex(Index i) { return U64(1) << i; }
- inline void setBit (Index i) { bits |= U64(1) << i.index; }
- inline void unsetBit (Index i) { bits |= ~(U64(1) << i.index); }
- inline void toggleBit (Index i) { bits ^= U64(1) << i.index; }
- inline void setBit (int row, int column)
- { setBit(row * 8 + column); }
- inline void unsetBit (int row, int column)
- { unsetBit(row * 8 + column); }
- static const U64 hColumn = 0x0101010101010101ULL;
- static const U64 aColumn = 0x8080808080808080ULL;
- inline void moveNorth (int dist) { bits <<= (8 * dist); }
- inline Bitboard north (int dist) { return bits << (8 * dist); }
- inline void moveSouth (int dist) { bits >>= (8 * dist); }
- inline Bitboard south (int dist) { return bits >> (8 * dist); }
- inline void moveNorthOne(void) { bits <<= 8; }
- inline Bitboard northOne (void) { return bits << 8; }
- inline void moveSouthOne(void) { bits >>= 8; }
- inline Bitboard southOne (void) { return bits >> 8; }
- inline void moveEastOne (void) { bits = (bits & ~hColumn) >> 1; }
- inline Bitboard eastOne (void) { return (bits & ~hColumn) >> 1; }
- inline void moveWestOne (void) { bits = (bits & ~aColumn) << 1; }
- inline Bitboard westOne (void) { return (bits & ~aColumn) << 1; }
- inline void moveNWOne (void) { bits = (bits << 7) & ~aColumn; }
- inline Bitboard nwOne (void) { return (bits << 7) & ~aColumn; }
- inline void moveNEOne (void) { bits = (bits << 9) & ~hColumn; }
- inline Bitboard neOne (void) { return (bits << 9) & ~hColumn; }
- inline void moveSWOne (void) { bits = (bits >> 9) & ~aColumn; }
- inline Bitboard swOne (void) { return (bits >> 9) & ~aColumn; }
- inline void moveSEOne (void) { bits = (bits >> 7) & ~hColumn; }
- inline Bitboard seOne (void) { return (bits >> 7) & ~hColumn; }
- inline static Bitboard getColumn(int index)
- {
- return hColumn << index;
- }
-
- inline static Bitboard getRow(int index)
- {
- return 0xFFULL << (index * 8);
- }
- template<Side side>
- inline void pushOne(void)
- {
- if (side == WHITE_SIDE)
- moveNorthOne();
- else
- moveSouthOne();
- }
- inline void operator &= (const Bitboard& b) { bits &= b.bits; }
- inline void operator |= (const Bitboard& b) { bits |= b.bits; }
- inline void operator ^= (const Bitboard& b) { bits ^= b.bits; }
- inline Bitboard operator & (const Bitboard& b) const { return bits & b.bits; }
- inline Bitboard operator | (const Bitboard& b) const { return bits | b.bits; }
- inline Bitboard operator ^ (const Bitboard& b) const { return bits ^ b.bits; }
- inline Bitboard operator ~ (void) const { return ~bits; }
- inline bool operator == (const Bitboard& b) const { return bits == b.bits; }
- inline bool operator != (const Bitboard& b) const { return bits != b.bits; }
- inline operator U64(void) const { return bits; }
- inline explicit operator bool(void) const { return bits != 0; }
- inline void applyMove(Move move)
- {
- bits &= ~fromIndex(move.origin);
- bits |= fromIndex(move.destination);
- }
- inline Bitboard mirror(void) const { return byteswap(bits); }
- inline Index getLeastSignificantBit (void) const { return trailingZeroes(bits); }
- inline int popcount (void) const { return chessy::popcount(bits); }
- static const uint64_t aFile = 0x8080808080808080ULL;
- static const uint64_t hFile = 0x0101010101010101ULL;
- };
- static_assert(std::is_pod<chessy::Bitboard>::value,
- "chessy::Bitboard should be a POD structure.");
- static_assert(std::is_pod<chessy::Index>::value,
- "chessy::Index should be a POD structure.");
- static_assert(sizeof(chessy::Bitboard) == sizeof(uint64_t),
- "chessy::Bitboard should be 64 bits in size.");
- #endif // CHESSY_BITBOARD_H
|