| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 | #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     setBit      (int row, int column)        { setBit(row * 8 + column); }    inline void     unsetBit    (int row, int column)        { unsetBit(row * 8 + column); }    static const    U64 aColumn             = 0x0101010101010101ULL;    static const    U64 hColumn             = 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 & ~aColumn) >> 1; }    inline Bitboard eastOne     (void)      { return (bits & ~aColumn) >> 1; }    inline void     moveWestOne (void)      { bits = (bits & ~hColumn) << 1; }    inline Bitboard westOne     (void)      { return (bits & ~hColumn) << 1; }    inline void     moveNWOne   (void)      { bits = (bits << 7) & ~hColumn; }    inline Bitboard nwOne       (void)      { return (bits << 7) & ~hColumn; }    inline void     moveNEOne   (void)      { bits = (bits << 9) & ~aColumn; }    inline Bitboard neOne       (void)      { return (bits << 9) & ~aColumn; }    inline void     moveSWOne   (void)      { bits = (bits >> 9) & ~hColumn; }    inline Bitboard swOne       (void)      { return (bits >> 9) & ~hColumn; }    inline void     moveSEOne   (void)      { bits = (bits >> 7) & ~aColumn; }    inline Bitboard seOne       (void)      { return (bits >> 7) & ~aColumn; }    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_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
 |