Compare commits

..

3 Commits

Author SHA1 Message Date
4f96d189fa [Board] Initial pseudoLegalMovesFrom 2022-12-22 18:38:16 +01:00
b64530cb3d [Board] Implement MoveGenerator 2022-12-22 18:37:52 +01:00
e18146e00c [BitBoard] Add castlingMoves 2022-12-22 18:36:36 +01:00
4 changed files with 79 additions and 20 deletions

View File

@@ -53,6 +53,17 @@ BitBoard BitBoard::kingAttacks(const BitBoard kings) {
return result; return result;
} }
BitBoard BitBoard::castlingMoves(BitBoard kings, BitBoard rooks, BitBoard empty) {
kings |= (kings.east() | kings.west()) & empty;
kings |= (kings.east() | kings.west()) & empty;
kings |= kings.west() & empty;
rooks |= (rooks.east() | rooks.west()) & empty;
rooks |= (rooks.east() | rooks.west()) & empty;
rooks |= (rooks.east()) & empty;
return kings & rooks & CastlingSquares;
}
BitBoard BitBoard::bishopAttacks(BitBoard bishops, BitBoard empty) { BitBoard BitBoard::bishopAttacks(BitBoard bishops, BitBoard empty) {
BitBoard result = 0; BitBoard result = 0;
BitBoard diag1 = bishops; BitBoard diag1 = bishops;

View File

@@ -108,6 +108,7 @@ public:
static BitBoard bishopAttacks(BitBoard pos, BitBoard empty); static BitBoard bishopAttacks(BitBoard pos, BitBoard empty);
static BitBoard kingAttacks(BitBoard kings); static BitBoard kingAttacks(BitBoard kings);
static BitBoard castlingMoves(BitBoard kings, BitBoard rooks, BitBoard empty);
static BitBoard pawnNorthAttacks(BitBoard pawns, BitBoard targets); static BitBoard pawnNorthAttacks(BitBoard pawns, BitBoard targets);
static BitBoard pawnSouthAttacks(BitBoard pawns, BitBoard targets); static BitBoard pawnSouthAttacks(BitBoard pawns, BitBoard targets);

View File

@@ -15,18 +15,18 @@ void Board::setPiece(const Square &square, const Piece::Optional &piece) {
return; return;
auto index = square.index(); auto index = square.index();
for (auto &bb : mPieceBBs) { for (int i = 0; i < BB_NUM; i++) {
bb.clear(index); mPieceBBs[i].clear(index);
} }
mPieceBBs[toIndex(piece->type())].set(index); mPieceBBs[toIndex(piece->type())].set(index);
mPieceBBs[toIndex(piece->color())].set(index); mPieceBBs[toIndex(piece->color())].set(index);
mOccupiedBB.set(index); (*mOccupiedBB).set(index);
} }
Piece::Optional Board::piece(const Square &square) const { Piece::Optional Board::piece(const Square &square) const {
BitBoard mask = BitBoard::fromIndex(square.index()); BitBoard mask = BitBoard::fromIndex(square.index());
if (!(mOccupiedBB & mask)) { if (!(*mOccupiedBB & mask)) {
return std::nullopt; return std::nullopt;
} }
@@ -68,17 +68,17 @@ void Board::makeMove(const Move &move) {
BitBoard changeBB = fromBB ^ toBB; BitBoard changeBB = fromBB ^ toBB;
// If Piece is captured // If Piece is captured
if (mOccupiedBB & toBB) { if (*mOccupiedBB & toBB) {
auto capturedPiece = Piece(!mTurn, pieceType(toBB)); auto capturedPiece = Piece(!mTurn, pieceType(toBB));
mPieceBBs[toIndex(capturedPiece.color())] ^= toBB; mPieceBBs[toIndex(capturedPiece.color())] ^= toBB;
mPieceBBs[toIndex(capturedPiece.type())] ^= toBB; mPieceBBs[toIndex(capturedPiece.type())] ^= toBB;
mOccupiedBB ^= fromBB; *mOccupiedBB ^= fromBB;
if (toBB & CastlingRanks) { // Check castling rights if (toBB & CastlingRanks) { // Check castling rights
handleCastlingRights(capturedPiece, toBB); handleCastlingRights(capturedPiece, toBB);
} }
} else { } else {
mOccupiedBB ^= changeBB; // update occupied bitboard *mOccupiedBB ^= changeBB; // update occupied bitboard
} }
auto movedPiece = Piece(mTurn, pieceType(fromBB)); auto movedPiece = Piece(mTurn, pieceType(fromBB));
@@ -105,7 +105,7 @@ void Board::makeMove(const Move &move) {
mPieceBBs[toIndex(PieceType::Rook)] ^= rookBB; mPieceBBs[toIndex(PieceType::Rook)] ^= rookBB;
mPieceBBs[toIndex(movedPiece.color())] ^= rookBB; mPieceBBs[toIndex(movedPiece.color())] ^= rookBB;
mOccupiedBB ^= rookBB; *mOccupiedBB ^= rookBB;
} }
} }
@@ -124,7 +124,7 @@ void Board::handleEnPassant(const Move &move, const Piece &movedPiece) {
mPieceBBs[toIndex(capturedPiece.color())] ^= epBB; mPieceBBs[toIndex(capturedPiece.color())] ^= epBB;
mPieceBBs[toIndex(capturedPiece.type())] ^= epBB; mPieceBBs[toIndex(capturedPiece.type())] ^= epBB;
mOccupiedBB ^= epBB; *mOccupiedBB ^= epBB;
} }
} }
@@ -150,8 +150,41 @@ void Board::pseudoLegalMoves(MoveVec &moves) const {
} }
void Board::pseudoLegalMovesFrom(const Square &from, Board::MoveVec &moves) const { void Board::pseudoLegalMovesFrom(const Square &from, Board::MoveVec &moves) const {
(void) from; auto fromBB = BitBoard::fromIndex(from.index());
(void) moves;
if (!(fromBB & mPieceBBs[toIndex(mTurn)])) {
return;
}
auto p = Piece(mTurn, pieceType(fromBB));
BitBoard movesBB;
switch (p.type()) {
case PieceType::Pawn:mMoveGenerator->generatePawnMoves(from, mEPS, mTurn, moves);
return;
case PieceType::Knight: break;
case PieceType::Bishop:movesBB = BitBoard::bishopAttacks(fromBB, ~*mOccupiedBB) & ~mPieceBBs[toIndex(mTurn)];
break;
case PieceType::Rook: break;
case PieceType::Queen: break;
case PieceType::King:movesBB = BitBoard::kingAttacks(fromBB) & ~mPieceBBs[toIndex(mTurn)];
if (hasCastlingRights()) {
if (mTurn == PieceColor::White) {
movesBB |= BitBoard::castlingMoves(fromBB, ~mPieceBBs[toIndex(PieceType::Rook)], ~*mOccupiedBB)
& WhiteCastlingRank;
} else {
movesBB |= BitBoard::castlingMoves(fromBB, ~mPieceBBs[toIndex(PieceType::Rook)], ~*mOccupiedBB)
& BlackCastlingRank;
}
}
break;
}
while (movesBB) {
auto to = Square(movesBB.pop());
moves.emplace_back(from, to, std::nullopt);
}
} }
void Board::handleCastlingRights(const Piece &piece, const BitBoard &bb) { void Board::handleCastlingRights(const Piece &piece, const BitBoard &bb) {
if (piece.type() != PieceType::King && piece.type() != PieceType::Rook) { if (piece.type() != PieceType::King && piece.type() != PieceType::Rook) {
@@ -200,6 +233,14 @@ bool Board::isMoveCastling(const BitBoard &from, const BitBoard &to, const Piece
return from & BitBoard::fromIndex(E8); return from & BitBoard::fromIndex(E8);
} }
constexpr bool Board::hasCastlingRights() const {
switch (mTurn) {
case PieceColor::White:return (mCR & CastlingRights::White) != CastlingRights::None;
case PieceColor::Black:return (mCR & CastlingRights::Black) != CastlingRights::None;
}
return false;
}
std::ostream &operator<<(std::ostream &os, const Board &board) { std::ostream &operator<<(std::ostream &os, const Board &board) {
// For debugging only, performance isn't important // For debugging only, performance isn't important

View File

@@ -6,10 +6,12 @@
#include "Move.hpp" #include "Move.hpp"
#include "CastlingRights.hpp" #include "CastlingRights.hpp"
#include "BitBoard.hpp" #include "BitBoard.hpp"
#include "MoveGenerator.hpp"
#include <optional> #include <optional>
#include <iosfwd> #include <iosfwd>
#include <vector> #include <vector>
#include <memory>
#define BB_NUM 8 // 6 pieces, 2 colors #define BB_NUM 8 // 6 pieces, 2 colors
@@ -35,26 +37,30 @@ public:
void pseudoLegalMoves(MoveVec &moves) const; void pseudoLegalMoves(MoveVec &moves) const;
void pseudoLegalMovesFrom(const Square &from, MoveVec &moves) const; void pseudoLegalMovesFrom(const Square &from, MoveVec &moves) const;
static constexpr int toIndex(PieceType t) {
return static_cast<int>(t);
}
static constexpr int toIndex(PieceColor c) {
return static_cast<int>(c);
}
private: private:
BitBoard mPieceBBs[BB_NUM] = {}; std::shared_ptr<BitBoard[BB_NUM]> mPieceBBs = std::shared_ptr<BitBoard[BB_NUM]>(new BitBoard[BB_NUM]);
BitBoard mOccupiedBB = 0; // BitBoard mPieceBBs[BB_NUM] = {};
std::shared_ptr<BitBoard> mOccupiedBB = std::make_shared<BitBoard>(0);
std::shared_ptr<MoveGenerator> mMoveGenerator = std::make_shared<MoveGenerator>(mPieceBBs, mOccupiedBB);
PieceColor mTurn = PieceColor::White; PieceColor mTurn = PieceColor::White;
CastlingRights mCR = CastlingRights::None; CastlingRights mCR = CastlingRights::None;
std::optional<Square> mEPS; std::optional<Square> mEPS;
void handleCastlingRights(const Piece &piece, const BitBoard &bb); void handleCastlingRights(const Piece &piece, const BitBoard &bb);
constexpr bool hasCastlingRights() const;
// Check if the move is castling without checking the rights or validity. // Check if the move is castling without checking the rights or validity.
static bool isMoveCastling(const BitBoard &from, const BitBoard &to, const Piece &piece); static bool isMoveCastling(const BitBoard &from, const BitBoard &to, const Piece &piece);
static inline int toIndex(PieceType t) {
return static_cast<int>(t);
}
static inline int toIndex(PieceColor c) {
return static_cast<int>(c);
}
inline PieceColor pieceColor(const BitBoard &mask) const { inline PieceColor pieceColor(const BitBoard &mask) const {
auto color = PieceColor::White; auto color = PieceColor::White;
if (!(mPieceBBs[static_cast<unsigned>(color)] & mask)) { if (!(mPieceBBs[static_cast<unsigned>(color)] & mask)) {