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;
|
||||
}
|
||||
|
||||
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 result(mBoard);
|
||||
result |= (result << 8);
|
||||
@@ -52,11 +45,41 @@ BitBoard BitBoard::fileFill() const {
|
||||
return northFill() | southFill();
|
||||
}
|
||||
|
||||
BitBoard BitBoard::kingAttacks(const BitBoard bb) {
|
||||
BitBoard result = bb.east() | bb.west() | bb;
|
||||
BitBoard BitBoard::kingAttacks(const BitBoard kings) {
|
||||
BitBoard result = kings.east() | kings.west() | kings;
|
||||
result |= (result.north() | result.south());
|
||||
result ^= bb;
|
||||
result ^= kings;
|
||||
|
||||
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,
|
||||
GFile = AFile << 6,
|
||||
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,
|
||||
BlackCastlingRank = (~1ULL << H7),
|
||||
CastlingRanks = WhiteCastlingRank | BlackCastlingRank,
|
||||
@@ -98,20 +106,24 @@ public:
|
||||
BitBoard southFill() 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 getRank(int r);
|
||||
|
||||
// Returns the number of trailing 0-bits in b.
|
||||
// WARN: Check for 0!
|
||||
int lsb() const;
|
||||
unsigned lsb() const;
|
||||
unsigned pop();
|
||||
|
||||
private:
|
||||
U64 mBoard = {};
|
||||
|
||||
static BitBoard genShift(BitBoard x, int s);
|
||||
};
|
||||
|
||||
// Relational operators
|
||||
@@ -255,8 +267,15 @@ inline BitBoard BitBoard::southEast() const {
|
||||
inline BitBoard BitBoard::southWest() const {
|
||||
return (mBoard >> 9) & ~HFile;
|
||||
}
|
||||
inline int BitBoard::lsb() const {
|
||||
|
||||
inline unsigned BitBoard::lsb() const {
|
||||
return __builtin_ctzll(mBoard);
|
||||
}
|
||||
inline unsigned BitBoard::pop() {
|
||||
unsigned i = lsb();
|
||||
mBoard &= mBoard - 1;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
#endif //CHESS_ENGINE_BITBOARD_HPP
|
||||
|
@@ -36,6 +36,7 @@ add_library(cplchess_lib OBJECT
|
||||
EngineFactory.cpp
|
||||
Uci.cpp
|
||||
BitBoard.cpp
|
||||
MoveGenerator.cpp
|
||||
)
|
||||
|
||||
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:
|
||||
|
||||
constexpr static const PieceType PromotionTypes[4] = {PieceType::Knight, PieceType::Bishop, PieceType::Rook, PieceType::Queen};
|
||||
|
||||
using Optional = std::optional<Piece>;
|
||||
|
||||
Piece(PieceColor color, PieceType type);
|
||||
|
@@ -26,6 +26,9 @@ public:
|
||||
static Optional fromIndex(Index index);
|
||||
static Optional fromName(const std::string &name);
|
||||
|
||||
Square(Index index);
|
||||
|
||||
|
||||
Coordinate file() const;
|
||||
Coordinate rank() const;
|
||||
Index index() const;
|
||||
@@ -40,9 +43,6 @@ public:
|
||||
static const Square A8, B8, C8, D8, E8, F8, G8, H8;
|
||||
|
||||
private:
|
||||
|
||||
Square(Index index);
|
||||
|
||||
Index mIndex;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user