Compare commits

...

6 Commits

7 changed files with 163 additions and 20 deletions

View File

@@ -25,13 +25,6 @@ std::ostream &operator<<(std::ostream &os, const BitBoard &board) {
return os; return os;
} }
BitBoard BitBoard::getRank(int r) {
return (genShift(1ULL, (r + 1) * 8) - 1) & genShift(~1ULL, r * 8 - 1);
}
BitBoard BitBoard::genShift(BitBoard x, const int s) {
return (s < 0) ? (x >> -s) : (s > 63) ? x : (x << s);
}
BitBoard BitBoard::northFill() const { BitBoard BitBoard::northFill() const {
BitBoard result(mBoard); BitBoard result(mBoard);
result |= (result << 8); result |= (result << 8);
@@ -52,11 +45,41 @@ BitBoard BitBoard::fileFill() const {
return northFill() | southFill(); return northFill() | southFill();
} }
BitBoard BitBoard::kingAttacks(const BitBoard bb) { BitBoard BitBoard::kingAttacks(const BitBoard kings) {
BitBoard result = bb.east() | bb.west() | bb; BitBoard result = kings.east() | kings.west() | kings;
result |= (result.north() | result.south()); result |= (result.north() | result.south());
result ^= bb; result ^= kings;
return result; return result;
}
BitBoard BitBoard::bishopAttacks(BitBoard bishops, BitBoard empty) {
BitBoard result = 0;
BitBoard diag1 = bishops;
BitBoard diag2 = bishops;
empty ^= bishops;
for (int i = 0; i < 7; i++) {
result |= (diag1 | diag2);
diag1 = (diag1.northWest() | diag1.southEast()) & empty;
diag2 = (diag2.northEast() | diag2.southWest()) & empty;
}
return (result | diag1.northWest() | diag1.southEast() | diag2.northEast() | diag2.southWest()) & ~bishops;
}
BitBoard BitBoard::pawnNorthAttacks(BitBoard pawns, BitBoard targets) {
return (pawns.northEast() | pawns.northWest()) & targets;
}
BitBoard BitBoard::pawnNorthMoves(BitBoard pawns, BitBoard empty) {
pawns = pawns.north() & empty;
return (pawns | (pawns.north() & Rank4)) & empty;
}
BitBoard BitBoard::pawnSouthAttacks(BitBoard pawns, BitBoard targets) {
return (pawns.southEast() | pawns.southWest()) & targets;
}
BitBoard BitBoard::pawnSouthMoves(BitBoard pawns, BitBoard empty) {
pawns = pawns.south() & empty;
return (pawns | (pawns.south() & Rank5)) & empty;
} }

View File

@@ -14,6 +14,14 @@ enum DefinedBoards : uint64_t {
FFile = AFile << 5, FFile = AFile << 5,
GFile = AFile << 6, GFile = AFile << 6,
HFile = AFile << 7, HFile = AFile << 7,
Rank1 = 0x00000000000000FF,
Rank2 = Rank1 << 8,
Rank3 = Rank1 << 16,
Rank4 = Rank1 << 24,
Rank5 = Rank1 << 32,
Rank6 = Rank1 << 40,
Rank7 = Rank1 << 48,
Rank8 = Rank1 << 56,
WhiteCastlingRank = (1ULL << A2) - 1, WhiteCastlingRank = (1ULL << A2) - 1,
BlackCastlingRank = (~1ULL << H7), BlackCastlingRank = (~1ULL << H7),
CastlingRanks = WhiteCastlingRank | BlackCastlingRank, CastlingRanks = WhiteCastlingRank | BlackCastlingRank,
@@ -98,20 +106,24 @@ public:
BitBoard southFill() const; BitBoard southFill() const;
BitBoard fileFill() const; BitBoard fileFill() const;
static BitBoard kingAttacks(BitBoard bb); static BitBoard bishopAttacks(BitBoard pos, BitBoard empty);
static BitBoard kingAttacks(BitBoard kings);
static BitBoard pawnNorthAttacks(BitBoard pawns, BitBoard targets);
static BitBoard pawnSouthAttacks(BitBoard pawns, BitBoard targets);
static BitBoard pawnNorthMoves(BitBoard pawns, BitBoard empty);
static BitBoard pawnSouthMoves(BitBoard pawns, BitBoard empty);
static BitBoard fromIndex(unsigned i); static BitBoard fromIndex(unsigned i);
static BitBoard getRank(int r);
// Returns the number of trailing 0-bits in b. // Returns the number of trailing 0-bits in b.
// WARN: Check for 0! // WARN: Check for 0!
int lsb() const; unsigned lsb() const;
unsigned pop();
private: private:
U64 mBoard = {}; U64 mBoard = {};
static BitBoard genShift(BitBoard x, int s);
}; };
// Relational operators // Relational operators
@@ -255,8 +267,15 @@ inline BitBoard BitBoard::southEast() const {
inline BitBoard BitBoard::southWest() const { inline BitBoard BitBoard::southWest() const {
return (mBoard >> 9) & ~HFile; return (mBoard >> 9) & ~HFile;
} }
inline int BitBoard::lsb() const {
inline unsigned BitBoard::lsb() const {
return __builtin_ctzll(mBoard); return __builtin_ctzll(mBoard);
} }
inline unsigned BitBoard::pop() {
unsigned i = lsb();
mBoard &= mBoard - 1;
return i;
}
#endif //CHESS_ENGINE_BITBOARD_HPP #endif //CHESS_ENGINE_BITBOARD_HPP

View File

@@ -36,6 +36,7 @@ add_library(cplchess_lib OBJECT
EngineFactory.cpp EngineFactory.cpp
Uci.cpp Uci.cpp
BitBoard.cpp BitBoard.cpp
MoveGenerator.cpp
) )
target_include_directories(cplchess_lib PUBLIC .) target_include_directories(cplchess_lib PUBLIC .)

62
MoveGenerator.cpp Normal file
View File

@@ -0,0 +1,62 @@
#include <iostream>
#include "MoveGenerator.hpp"
#include "Board.hpp"
MoveGenerator::MoveGenerator(const std::shared_ptr<BitBoard[]> &pieceBB,
const std::shared_ptr<BitBoard> &occupiedBB)
: mPieceBBs(pieceBB), mOccupiedBB(occupiedBB) {
}
void MoveGenerator::generatePawnMoves(const Square &from, const std::optional<Square> &eps,
PieceColor color, MoveVec &moves) const {
BitBoard targets = 0;
if (eps.has_value()) {
targets |= BitBoard::fromIndex(eps.value().index());
}
generatePawnMoves(from, targets, color, moves);
}
void MoveGenerator::generatePawnMoves(const Square &from, PieceColor color, MoveVec &moves) {
generatePawnMoves(from, BitBoard(0), color, moves);
}
void MoveGenerator::generatePawnMoves(const Square &from, BitBoard targets, PieceColor color, MoveVec &moves) const {
auto fromBB = BitBoard::fromIndex(from.index());
targets |= mPieceBBs[Board::toIndex(!color)];
BitBoard movesBB;
if (color == PieceColor::White) {
movesBB = BitBoard::pawnNorthAttacks(fromBB, targets) & ~mPieceBBs[Board::toIndex(color)];
movesBB |= BitBoard::pawnNorthMoves(fromBB, ~*mOccupiedBB);
} else {
movesBB = BitBoard::pawnSouthAttacks(fromBB, targets) & ~mPieceBBs[Board::toIndex(color)];
movesBB |= BitBoard::pawnSouthMoves(fromBB, ~*mOccupiedBB);
}
bool isPromotion = movesBB & (Rank1 | Rank8);
if (isPromotion) {
generateMovesWithPromotion(from, movesBB, moves);
} else {
generateMoves(from, movesBB, moves);
}
}
void MoveGenerator::generateMoves(const Square &from, BitBoard movesBB, MoveGenerator::MoveVec &moves) {
while (movesBB) {
auto to = Square(movesBB.pop());
moves.emplace_back(from, to, std::nullopt);
}
}
void MoveGenerator::generateMovesWithPromotion(const Square &from, BitBoard movesBB, MoveGenerator::MoveVec &moves) {
while (movesBB) {
auto to = Square(movesBB.pop());
for (const auto &kItem : Piece::PromotionTypes) {
moves.emplace_back(from, to, static_cast<PieceType>(kItem));
}
}
}

36
MoveGenerator.hpp Normal file
View File

@@ -0,0 +1,36 @@
#ifndef CHESS_ENGINE_MOVEGENERATOR_HPP
#define CHESS_ENGINE_MOVEGENERATOR_HPP
#include "Piece.hpp"
#include "Square.hpp"
#include "Move.hpp"
#include "CastlingRights.hpp"
#include "BitBoard.hpp"
#include <optional>
#include <iosfwd>
#include <vector>
#include <memory>
class MoveGenerator {
public:
using MoveVec = std::vector<Move>;
MoveGenerator(const std::shared_ptr<BitBoard[]>& pieceBB, const std::shared_ptr<BitBoard>& occupiedBB);
MoveGenerator(MoveGenerator &) = delete;
MoveGenerator &operator=(MoveGenerator const &) = delete;
void generatePawnMoves(const Square &from, const std::optional<Square> &eps, PieceColor color, MoveVec &moves) const;
void generatePawnMoves(const Square &from, PieceColor color, MoveVec &moves);
private:
const std::shared_ptr<const BitBoard[]> mPieceBBs;
const std::shared_ptr<const BitBoard> mOccupiedBB;
void generatePawnMoves(const Square &from, BitBoard targets, PieceColor color, MoveVec &moves) const;
static void generateMoves(const Square &from, BitBoard movesBB, MoveVec &moves);
static void generateMovesWithPromotion(const Square &from, BitBoard movesBB, MoveVec &moves);
};
#endif //CHESS_ENGINE_MOVEGENERATOR_HPP

View File

@@ -24,6 +24,8 @@ class Piece {
public: public:
constexpr static const PieceType PromotionTypes[4] = {PieceType::Knight, PieceType::Bishop, PieceType::Rook, PieceType::Queen};
using Optional = std::optional<Piece>; using Optional = std::optional<Piece>;
Piece(PieceColor color, PieceType type); Piece(PieceColor color, PieceType type);

View File

@@ -26,6 +26,9 @@ public:
static Optional fromIndex(Index index); static Optional fromIndex(Index index);
static Optional fromName(const std::string &name); static Optional fromName(const std::string &name);
Square(Index index);
Coordinate file() const; Coordinate file() const;
Coordinate rank() const; Coordinate rank() const;
Index index() const; Index index() const;
@@ -40,9 +43,6 @@ public:
static const Square A8, B8, C8, D8, E8, F8, G8, H8; static const Square A8, B8, C8, D8, E8, F8, G8, H8;
private: private:
Square(Index index);
Index mIndex; Index mIndex;
}; };