[Board] Refactor and implement makeMove
This commit is contained in:
135
Board.cpp
135
Board.cpp
@@ -10,26 +10,28 @@ Board::Board() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Board::setPiece(const Square &square, const Piece::Optional &piece) {
|
void Board::setPiece(const Square &square, const Piece::Optional &piece) {
|
||||||
|
if (!piece.has_value())
|
||||||
|
return;
|
||||||
|
|
||||||
auto index = square.index();
|
auto index = square.index();
|
||||||
for (auto &item : mPieceBBs) {
|
for (auto &bb : mPieceBBs) {
|
||||||
clearIndex(item, index);
|
clearIndex(bb, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIndex(mPieceBBs[piece->typeVal() + piece->colorVal()], index);
|
setIndex(mPieceBBs[toIndex(piece->type())], index);
|
||||||
|
setIndex(mPieceBBs[toIndex(piece->color())], index);
|
||||||
|
setIndex(mOccupiedBB, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Piece::Optional Board::piece(const Square &square) const {
|
Piece::Optional Board::piece(const Square &square) const {
|
||||||
int i = 0;
|
|
||||||
BitBoard mask = indexToBitBoard(square.index());
|
BitBoard mask = indexToBitBoard(square.index());
|
||||||
for (const auto &kPieceBb : mPieceBBs) {
|
if (!(mOccupiedBB & mask)) {
|
||||||
if (kPieceBb & mask) {
|
return std::nullopt;
|
||||||
return Piece::fromValue(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
auto c = pieceColor(mask);
|
||||||
}
|
auto t = pieceType(mask);
|
||||||
return std::nullopt;
|
return Piece(c, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::setTurn(PieceColor turn) {
|
void Board::setTurn(PieceColor turn) {
|
||||||
@@ -41,11 +43,11 @@ PieceColor Board::turn() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Board::setCastlingRights(CastlingRights cr) {
|
void Board::setCastlingRights(CastlingRights cr) {
|
||||||
mCr = cr;
|
mCR = cr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CastlingRights Board::castlingRights() const {
|
CastlingRights Board::castlingRights() const {
|
||||||
return mCr;
|
return mCR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::setEnPassantSquare(const Square::Optional &square) {
|
void Board::setEnPassantSquare(const Square::Optional &square) {
|
||||||
@@ -57,7 +59,56 @@ Square::Optional Board::enPassantSquare() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Board::makeMove(const Move &move) {
|
void Board::makeMove(const Move &move) {
|
||||||
(void) move;
|
|
||||||
|
BitBoard fromBB = indexToBitBoard(move.from().index());
|
||||||
|
BitBoard toBB = indexToBitBoard(move.to().index());
|
||||||
|
BitBoard changeBB = fromBB ^ toBB;
|
||||||
|
|
||||||
|
// If Piece is captured
|
||||||
|
if (mOccupiedBB & toBB) {
|
||||||
|
auto capturedPiece = Piece(!mTurn, pieceType(toBB));
|
||||||
|
mPieceBBs[toIndex(capturedPiece.color())] ^= toBB;
|
||||||
|
mPieceBBs[toIndex(capturedPiece.type())] ^= toBB;
|
||||||
|
mOccupiedBB ^= fromBB;
|
||||||
|
|
||||||
|
if (toBB & CastlingRanks) { // Check castling rights
|
||||||
|
handleCastlingRights(capturedPiece, toBB);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mOccupiedBB ^= changeBB; // update occupied bitboard
|
||||||
|
}
|
||||||
|
|
||||||
|
auto movedPiece = Piece(mTurn, pieceType(fromBB));
|
||||||
|
mPieceBBs[toIndex(movedPiece.color())] ^= changeBB; // update color bitboard
|
||||||
|
|
||||||
|
// TODO verify if we should check if piece == Pawn
|
||||||
|
if (move.promotion().has_value()) {
|
||||||
|
mPieceBBs[toIndex(movedPiece.type())] ^= fromBB; // Remove old piece
|
||||||
|
mPieceBBs[toIndex(move.promotion().value())] ^= toBB; // Set new piece
|
||||||
|
} else {
|
||||||
|
mPieceBBs[toIndex(movedPiece.type())] ^= changeBB; // remove and set piece bitboard
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fromBB & CastlingRanks)) {
|
||||||
|
handleCastlingRights(movedPiece, fromBB);
|
||||||
|
|
||||||
|
if (isMoveCastling(fromBB, toBB, movedPiece)) {
|
||||||
|
BitBoard rookBB;
|
||||||
|
if (toBB & GFile) { // Kingside
|
||||||
|
rookBB = (fromBB << 3) | (fromBB << 1);
|
||||||
|
} else {
|
||||||
|
rookBB = (fromBB >> 4) | (fromBB >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mPieceBBs[toIndex(PieceType::Rook)] ^= rookBB;
|
||||||
|
mPieceBBs[toIndex(movedPiece.color())] ^= rookBB;
|
||||||
|
mOccupiedBB ^= rookBB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// change turn
|
||||||
|
mTurn = !mTurn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::pseudoLegalMoves(MoveVec &moves) const {
|
void Board::pseudoLegalMoves(MoveVec &moves) const {
|
||||||
@@ -69,12 +120,61 @@ void Board::pseudoLegalMovesFrom(const Square &from,
|
|||||||
(void) from;
|
(void) from;
|
||||||
(void) moves;
|
(void) moves;
|
||||||
}
|
}
|
||||||
|
void Board::handleCastlingRights(const Piece &piece, const BitBoard &bb) {
|
||||||
|
if (piece.type() != PieceType::King && piece.type() != PieceType::Rook) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto crColor = CastlingRights::White;
|
||||||
|
auto crKingside = CastlingRights::WhiteKingside;
|
||||||
|
auto crQueenside = CastlingRights::WhiteQueenside;
|
||||||
|
|
||||||
|
if (piece.color() == PieceColor::Black) {
|
||||||
|
crColor = CastlingRights::Black;
|
||||||
|
crKingside = CastlingRights::BlackKingside;
|
||||||
|
crQueenside = CastlingRights::BlackQueenside;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mCR & crColor) == CastlingRights::None) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (piece.type() == PieceType::King) {
|
||||||
|
mCR &= ~crColor;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (piece.type() == PieceType::Rook) {
|
||||||
|
if (bb & (HFile & CastlingRanks)) { // Kingside
|
||||||
|
mCR &= ~crKingside;
|
||||||
|
} else if (bb & (AFile & CastlingRanks)) { // Queenside
|
||||||
|
mCR &= ~crQueenside;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Board::isMoveCastling(const BitBoard &from, const BitBoard &to, const Piece &piece) {
|
||||||
|
if (piece.type() != PieceType::King)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!(to & CastlingSquares)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (piece.color() == PieceColor::White) {
|
||||||
|
return (from & indexToBitBoard(E1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (from & indexToBitBoard(E8));
|
||||||
|
}
|
||||||
|
|
||||||
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
|
||||||
for (int i = 63; i >= 0; i--) {
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
int rank = i * 8;
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
// Get the piece for this index. Assume it exists.
|
// Get the piece for this index. Assume it exists.
|
||||||
auto piece = board.piece(Square::fromIndex(i).value());
|
auto piece = board.piece(Square::fromIndex(rank + j).value());
|
||||||
|
|
||||||
// Print piece, otherwise '.';
|
// Print piece, otherwise '.';
|
||||||
if (piece.has_value()) {
|
if (piece.has_value()) {
|
||||||
@@ -83,12 +183,9 @@ std::ostream &operator<<(std::ostream &os, const Board &board) {
|
|||||||
os << '.';
|
os << '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a file is done, output newline
|
|
||||||
if (i % 8 == 0) {
|
|
||||||
os << '\n';
|
|
||||||
} else {
|
|
||||||
os << ' ';
|
os << ' ';
|
||||||
}
|
}
|
||||||
|
os << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
74
Board.hpp
74
Board.hpp
@@ -10,7 +10,11 @@
|
|||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#define BB_NUM 12 // 6 pieces, 2 colors
|
#define BB_NUM 8 // 6 pieces, 2 colors
|
||||||
|
|
||||||
|
enum class BoardIndex {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Board {
|
class Board {
|
||||||
public:
|
public:
|
||||||
@@ -39,21 +43,81 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
BitBoard mPieceBBs[BB_NUM] = {};
|
BitBoard mPieceBBs[BB_NUM] = {};
|
||||||
|
BitBoard mOccupiedBB = 0;
|
||||||
|
|
||||||
PieceColor mTurn = PieceColor::White;
|
PieceColor mTurn = PieceColor::White;
|
||||||
CastlingRights mCr;
|
CastlingRights mCR = CastlingRights::None;
|
||||||
unsigned mEPS = 64;
|
unsigned mEPS = 64;
|
||||||
|
|
||||||
static inline void clearIndex(BitBoard &b, unsigned i) {
|
enum DefinedBoards : BitBoard {
|
||||||
|
AFile = 0x0101010101010101,
|
||||||
|
BFile = AFile << 1,
|
||||||
|
CFile = AFile << 2,
|
||||||
|
DFile = AFile << 3,
|
||||||
|
EFile = AFile << 4,
|
||||||
|
FFile = AFile << 5,
|
||||||
|
GFile = AFile << 6,
|
||||||
|
HFile = AFile << 7,
|
||||||
|
WhiteCastlingRank = (1ULL << A2) - 1,
|
||||||
|
BlackCastlingRank = (~1ULL << H7),
|
||||||
|
CastlingRanks = WhiteCastlingRank | BlackCastlingRank,
|
||||||
|
CastlingSquares = (WhiteCastlingRank | BlackCastlingRank) & (CFile | GFile),
|
||||||
|
};
|
||||||
|
|
||||||
|
void handleCastlingRights(const Piece &piece, const BitBoard &bb);
|
||||||
|
// 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 inline void clearIndex(BitBoard &b, const unsigned i) {
|
||||||
b &= ~(1ULL << i);
|
b &= ~(1ULL << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setIndex(BitBoard &b, unsigned i) {
|
static inline void setIndex(BitBoard &b, const unsigned i) {
|
||||||
b |= 1ULL << i;
|
b |= 1ULL << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline BitBoard indexToBitBoard(unsigned i) {
|
static inline BitBoard indexToBitBoard(const unsigned i) {
|
||||||
return (1ULL << i);
|
return (1ULL << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
auto color = PieceColor::White;
|
||||||
|
if (!(mPieceBBs[static_cast<unsigned>(color)] & mask)) {
|
||||||
|
color = !color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PieceType pieceType(const BitBoard &mask) const {
|
||||||
|
for (int i = 2; i < BB_NUM; i++) {
|
||||||
|
if (mPieceBBs[i] & mask) {
|
||||||
|
return static_cast<PieceType>(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should not happen
|
||||||
|
return static_cast<PieceType>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void applyMask(const BitBoard &mask) {
|
||||||
|
for (auto &item : mPieceBBs) {
|
||||||
|
item ^= mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the number of trailing 0-bits in b.
|
||||||
|
// WARN: Check for 0!
|
||||||
|
static inline int getLSB(const BitBoard b) {
|
||||||
|
return __builtin_ctzll(b);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, const Board &board);
|
std::ostream &operator<<(std::ostream &os, const Board &board);
|
||||||
|
11
Piece.cpp
11
Piece.cpp
@@ -19,18 +19,10 @@ PieceColor Piece::color() const {
|
|||||||
return mColor;
|
return mColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Piece::colorVal() const {
|
|
||||||
return static_cast<int>(mColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
PieceType Piece::type() const {
|
PieceType Piece::type() const {
|
||||||
return mType;
|
return mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Piece::typeVal() const {
|
|
||||||
return static_cast<int>(mType);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<PieceType> Piece::pieceTypeFromSymbol(char symbol) {
|
std::optional<PieceType> Piece::pieceTypeFromSymbol(char symbol) {
|
||||||
switch (toupper(symbol)) {
|
switch (toupper(symbol)) {
|
||||||
case 'P': return PieceType::Pawn;
|
case 'P': return PieceType::Pawn;
|
||||||
@@ -42,9 +34,6 @@ std::optional<PieceType> Piece::pieceTypeFromSymbol(char symbol) {
|
|||||||
default: return std::nullopt;
|
default: return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Piece::Optional Piece::fromValue(unsigned int value) {
|
|
||||||
return Piece(valToColor(value), valToType(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Piece &lhs, const Piece &rhs) {
|
bool operator==(const Piece &lhs, const Piece &rhs) {
|
||||||
return lhs.color() == rhs.color() && lhs.type() == rhs.type();
|
return lhs.color() == rhs.color() && lhs.type() == rhs.type();
|
||||||
|
27
Piece.hpp
27
Piece.hpp
@@ -5,17 +5,17 @@
|
|||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
enum class PieceColor {
|
enum class PieceColor {
|
||||||
White = 0,
|
White = 0x0,
|
||||||
Black = 1,
|
Black = 0x1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PieceType {
|
enum class PieceType {
|
||||||
Pawn = 0b000,
|
Pawn = 2,
|
||||||
Knight = 0b010,
|
Knight,
|
||||||
Bishop = 0b100,
|
Bishop,
|
||||||
Rook = 0b110,
|
Rook,
|
||||||
Queen = 0b1000,
|
Queen,
|
||||||
King = 0b1010
|
King
|
||||||
};
|
};
|
||||||
|
|
||||||
class Piece {
|
class Piece {
|
||||||
@@ -27,26 +27,15 @@ public:
|
|||||||
Piece(PieceColor color, PieceType type);
|
Piece(PieceColor color, PieceType type);
|
||||||
|
|
||||||
static Optional fromSymbol(char symbol);
|
static Optional fromSymbol(char symbol);
|
||||||
static Optional fromValue(unsigned value);
|
|
||||||
|
|
||||||
static std::optional<PieceType> pieceTypeFromSymbol(char symbol);
|
static std::optional<PieceType> pieceTypeFromSymbol(char symbol);
|
||||||
|
|
||||||
PieceColor color() const;
|
PieceColor color() const;
|
||||||
PieceType type() const;
|
PieceType type() const;
|
||||||
int colorVal() const;
|
|
||||||
int typeVal() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PieceColor mColor;
|
const PieceColor mColor;
|
||||||
const PieceType mType;
|
const PieceType mType;
|
||||||
|
|
||||||
static inline PieceColor valToColor(unsigned v) {
|
|
||||||
return static_cast<PieceColor>(v % 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline PieceType valToType(unsigned v) {
|
|
||||||
return static_cast<PieceType>(v - (v % 2));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(const Piece &lhs, const Piece &rhs);
|
bool operator==(const Piece &lhs, const Piece &rhs);
|
||||||
|
11
Square.hpp
11
Square.hpp
@@ -5,6 +5,17 @@
|
|||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
enum SquareIndex : unsigned {
|
||||||
|
A1, B1, C1, D1, E1, F1, G1, H1,
|
||||||
|
A2, B2, C2, D2, E2, F2, G2, H2,
|
||||||
|
A3, B3, C3, D3, E3, F3, G3, H3,
|
||||||
|
A4, B4, C4, D4, E4, F4, G4, H4,
|
||||||
|
A5, B5, C5, D5, E5, F5, G5, H5,
|
||||||
|
A6, B6, C6, D6, E6, F6, G6, H6,
|
||||||
|
A7, B7, C7, D7, E7, F7, G7, H7,
|
||||||
|
A8, B8, C8, D8, E8, F8, G8, H8
|
||||||
|
};
|
||||||
|
|
||||||
class Square {
|
class Square {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user