Compare commits
6 Commits
e620e6f5cb
...
db20e49f35
Author | SHA1 | Date | |
---|---|---|---|
db20e49f35 | |||
cd21c16da7 | |||
91624c62c1 | |||
30107cc6fa | |||
fadfab165a | |||
e1d216f06b |
45
BitBoard.cpp
45
BitBoard.cpp
@@ -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;
|
||||||
}
|
}
|
33
BitBoard.hpp
33
BitBoard.hpp
@@ -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
|
||||||
|
@@ -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
62
MoveGenerator.cpp
Normal 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
36
MoveGenerator.hpp
Normal 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
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user