Skip to content

Commit

Permalink
Enforce better type safety on Piece and PieceType
Browse files Browse the repository at this point in the history
  • Loading branch information
ruicoelhopedro committed Feb 28, 2022
1 parent 269b2aa commit 0a131bd
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 67 deletions.
2 changes: 1 addition & 1 deletion src/Bitboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ namespace Bitboards

extern Bitboard between_squares[NUM_SQUARES][NUM_SQUARES];

template <Piece PIECE_TYPE>
template <PieceType PIECE_TYPE>
Bitboard get_attacks(Square square, Bitboard occupancy)
{
return pseudo_attacks[PIECE_TYPE][square];
Expand Down
12 changes: 6 additions & 6 deletions src/Move.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class Move
constexpr bool is_double_pawn_push() const { return move_type() == DOUBLE_PAWN_PUSH; }
constexpr bool is_promotion() const { return move_type() & KNIGHT_PROMO; }
constexpr bool is_castle() const { return (move_type() == KING_CASTLE) || (move_type() == QUEEN_CASTLE); }
constexpr Piece promo_piece() const { return (move_type() & 0b0011) + 1; }
constexpr PieceType promo_piece() const { return static_cast<PieceType>((move_type() & 0b0011) + 1); }
constexpr MoveType move_type() const { return static_cast<MoveType>(m_move >> 12); }
constexpr Hash hash() const { return (m_move & 0b111111111111) | ((m_move & 0b11000000000000000) >> 3); }
constexpr Hash to_int() const { return m_move; }
Expand All @@ -51,14 +51,14 @@ class Move
{
// Promotion
std::string promo_code;
Piece piece = promo_piece();
if (piece == 1)
PieceType piece = promo_piece();
if (piece == KNIGHT)
promo_code = "n";
else if (piece == 2)
else if (piece == BISHOP)
promo_code = "b";
else if (piece == 3)
else if (piece == ROOK)
promo_code = "r";
else if (piece == 4)
else if (piece == QUEEN)
promo_code = "q";
return get_square(from()) + get_square(to()) + promo_code;
}
Expand Down
6 changes: 3 additions & 3 deletions src/MoveOrder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ int MoveOrder::capture_score(Move move) const
{
// MVV-LVA
constexpr int piece_score[] = { 10, 30, 31, 50, 90, 1000 };
Piece from = m_position.board().get_piece_at(move.from());
Piece to = (move.is_ep_capture()) ? PAWN : m_position.board().get_piece_at(move.to());
PieceType from = m_position.board().get_piece_at(move.from());
PieceType to = move.is_ep_capture() ? PAWN : m_position.board().get_piece_at(move.to());
return piece_score[to] - piece_score[from];
}

Expand All @@ -142,7 +142,7 @@ int MoveOrder::quiet_score(Move move) const
// 1. Butterfly histories
// 2. Piece type-destination histories
// 3. Low ply histories (based on node counts)
auto piece = static_cast<PieceType>(m_position.board().get_piece_at(move.from()));
PieceType piece = m_position.board().get_piece_at(move.from());
return m_histories.butterfly_score(move, m_position.get_turn())
+ m_histories.piece_type_score(move, piece)
+ m_histories.low_ply_score(move, piece, m_ply);
Expand Down
2 changes: 1 addition & 1 deletion src/PieceSquareTables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ constexpr S psq_table_pawns[6][8] =
};


constexpr MixedScore piece_square(Piece piece, Square square, Turn turn)
constexpr MixedScore piece_square(PieceType piece, Square square, Turn turn)
{
// Correct piece position for table lookup
int sq_rank = (turn == WHITE) ? rank(square) : (7 - rank(square));
Expand Down
48 changes: 23 additions & 25 deletions src/Position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,29 +293,27 @@ Hash Board::generate_hash() const
Hash hash = 0;

// Position hash
for (int turn = 0; turn < 2; turn++)
for (int piece = 0; piece < 6; piece++)
for (Turn turn : { WHITE, BLACK })
for (PieceType piece : { PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING })
{
Bitboard piece_bb = m_pieces[piece][turn];
while (piece_bb)
hash ^= Zobrist::get_piece_turn_square(static_cast<PieceType>(piece),
static_cast<Turn>(turn),
piece_bb.bitscan_forward_reset());
hash ^= Zobrist::get_piece_turn_square(piece, turn, piece_bb.bitscan_forward_reset());
}

// Turn to move
if (m_turn == Turn::BLACK)
if (m_turn == BLACK)
hash ^= Zobrist::get_black_move();

// En-passsant square
if (m_enpassant_square != SQUARE_NULL)
hash ^= Zobrist::get_ep_file(file(m_enpassant_square));

// Castling rights
for (int side = 0; side < 2; side++)
for (int turn = 0; turn < 2; turn++)
for (CastleSide side : { KINGSIDE, QUEENSIDE })
for (Turn turn : { WHITE, BLACK })
if (m_castling_rights[side][turn])
hash ^= Zobrist::get_castle_side_turn(static_cast<CastleSide>(side), static_cast<Turn>(turn));
hash ^= Zobrist::get_castle_side_turn(side, turn);

return hash;
}
Expand All @@ -326,12 +324,12 @@ void Board::init()
// Pieces
for (Square square = 0; square < NUM_SQUARES; square++)
m_board_pieces[square] = NO_PIECE;
for (Piece piece = PAWN; piece < NUM_PIECE_TYPES; piece++)
for (PieceType piece : { PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING })
for (Turn turn : { WHITE, BLACK })
{
Bitboard bb = get_pieces(turn, piece);
while (bb)
m_board_pieces[bb.bitscan_forward_reset()] = get_board_piece(piece, turn);
m_board_pieces[bb.bitscan_forward_reset()] = get_piece(piece, turn);
}

// Generate hash
Expand All @@ -342,7 +340,7 @@ void Board::init()

// Material and phase evaluation
m_phase = Phases::Total;
for (Piece piece = PAWN; piece < NUM_PIECE_TYPES; piece++)
for (PieceType piece : { PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING })
for (Turn turn : { WHITE, BLACK })
{
Bitboard bb = get_pieces(turn, piece);
Expand Down Expand Up @@ -375,12 +373,12 @@ void Board::generate_moves(MoveList& list, MoveGenType type) const
Board Board::make_move(Move move) const
{
Board result = *this;
PieceType piece = static_cast<PieceType>(get_piece_at(move.from()));
Color color = turn_to_color(m_turn);
PieceType piece = get_piece_at(move.from());

// Increment clocks
result.m_full_move_clock += m_turn;
if (piece == 0 || move.is_capture())
if (piece == PAWN || move.is_capture())
result.m_half_move_clock = 0;
else
result.m_half_move_clock++;
Expand Down Expand Up @@ -428,13 +426,13 @@ Board Board::make_move(Move move) const
// Set moving piece
result.m_pieces[piece][m_turn].set(move.to());
result.m_hash ^= Zobrist::get_piece_turn_square(piece, m_turn, move.to());
result.m_board_pieces[move.to()] = get_board_piece(piece, m_turn);
result.m_board_pieces[move.to()] = get_piece(piece, m_turn);
result.m_eval1 += piece_square(piece, move.to(), m_turn) * color;

// Per move type action
if (move.is_capture())
{
PieceType target_piece = static_cast<PieceType>(get_piece_at(move.to()));
PieceType target_piece = get_piece_at(move.to());

// En passant capture
int target = move.to();
Expand Down Expand Up @@ -493,19 +491,19 @@ Board Board::make_move(Move move) const
result.m_hash ^= Zobrist::get_piece_turn_square(ROOK, m_turn, iS);
result.m_hash ^= Zobrist::get_piece_turn_square(ROOK, m_turn, iE);
result.m_board_pieces[iS] = NO_PIECE;
result.m_board_pieces[iE] = get_board_piece(ROOK, m_turn);
result.m_board_pieces[iE] = get_piece(ROOK, m_turn);
result.m_eval1 -= piece_square(ROOK, iS, m_turn) * color;
result.m_eval1 += piece_square(ROOK, iE, m_turn) * color;
}

if (move.is_promotion())
{
PieceType promo_piece = static_cast<PieceType>(move.promo_piece());
PieceType promo_piece = move.promo_piece();
result.m_pieces[piece][m_turn].reset(move.to());
result.m_pieces[promo_piece][m_turn].set(move.to());
result.m_hash ^= Zobrist::get_piece_turn_square(piece, m_turn, move.to());
result.m_hash ^= Zobrist::get_piece_turn_square(promo_piece, m_turn, move.to());
result.m_board_pieces[move.to()] = get_board_piece(promo_piece, m_turn);
result.m_board_pieces[move.to()] = get_piece(promo_piece, m_turn);
result.m_eval1 -= piece_square(piece, move.to(), m_turn) * color;
result.m_eval1 += piece_square(promo_piece, move.to(), m_turn) * color;
result.m_eval1 -= piece_value[piece] * color;
Expand Down Expand Up @@ -616,7 +614,7 @@ Bitboard Board::get_pieces() const
}


Bitboard Board::get_pieces(Turn turn, Piece piece) const
Bitboard Board::get_pieces(Turn turn, PieceType piece) const
{
return m_pieces[piece][turn];
}
Expand Down Expand Up @@ -688,13 +686,13 @@ Square Board::least_valuable(Bitboard bb) const
Score Board::see(Move move, int threshold) const
{
// Static-Exchange evaluation with prunning
constexpr Score piece_score[] = { 0, 10, 30, 30, 50, 90, 1000 };
constexpr Score piece_score[] = { 10, 30, 30, 50, 90, 1000, 0, 0 };

Square target = move.to();

// Make the initial capture
Piece last_attacker = get_piece_at(move.from());
Score gain = piece_score[1 + (move.is_ep_capture() ? PAWN : get_piece_at(target))] - threshold / 10;
PieceType last_attacker = get_piece_at(move.from());
Score gain = piece_score[move.is_ep_capture() ? PAWN : get_piece_at(target)] - threshold / 10;
Bitboard from_bb = Bitboard::from_square(move.from());
Bitboard occupancy = get_pieces() ^ from_bb;
Turn side_to_move = ~m_turn;
Expand All @@ -714,7 +712,7 @@ Score Board::see(Move move, int threshold) const
Bitboard attacker_bb = Bitboard::from_square(attacker);

// Make the capture
gain += color * piece_score[1 + last_attacker];
gain += color * piece_score[last_attacker];
last_attacker = get_piece_at(attacker);
occupancy ^= attacker_bb;
side_to_move = ~side_to_move;
Expand Down Expand Up @@ -800,7 +798,7 @@ bool Board::legal(Move move) const
return false;

// Capture and destination square not occupied by the opponent (including ep)?
Piece piece = get_piece_at(move.from());
PieceType piece = get_piece_at(move.from());
Bitboard enemy_pieces = get_pieces() & ~our_pieces;
if (move.is_ep_capture() && piece == PAWN && m_enpassant_square != SQUARE_NULL)
enemy_pieces.set(m_enpassant_square);
Expand Down
20 changes: 10 additions & 10 deletions src/Position.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ class Board
Bitboard m_checkers;
MixedScore m_eval1;
uint8_t m_phase;
BoardPieces m_board_pieces[NUM_SQUARES];
Piece m_board_pieces[NUM_SQUARES];

protected:

template<Turn TURN, Piece PIECE_TYPE>
template<Turn TURN, PieceType PIECE_TYPE>
void generate_moves(MoveList& list, Bitboard filter, Bitboard occupancy) const
{
static_assert(PIECE_TYPE != PAWN && PIECE_TYPE != KING, "Pawn and king not supported!");
Expand Down Expand Up @@ -264,7 +264,7 @@ class Board
}


template<Turn TURN, Piece PIECE_TYPE>
template<Turn TURN, PieceType PIECE_TYPE>
bool legal(Move move, Bitboard occupancy) const
{
Bitboard filter = ~get_pieces<TURN>();
Expand Down Expand Up @@ -400,7 +400,7 @@ class Board
}


template<Piece PIECE_TYPE>
template<PieceType PIECE_TYPE>
bool legal(Move move, Bitboard occupancy) const
{
if (m_turn == WHITE)
Expand Down Expand Up @@ -434,16 +434,16 @@ class Board
void generate_moves(MoveList& list, MoveGenType type) const;


inline Piece get_piece_at(Square square) const
inline PieceType get_piece_at(Square square) const
{
return static_cast<Piece>(m_board_pieces[square] / 2);
return get_piece_type(m_board_pieces[square]);
}


bool is_valid() const;


template<Turn TURN, Piece PIECE_TYPE>
template<Turn TURN, PieceType PIECE_TYPE>
Bitboard get_pieces() const { return m_pieces[PIECE_TYPE][TURN]; }


Expand All @@ -462,7 +462,7 @@ class Board
Bitboard get_pieces() const;


Bitboard get_pieces(Turn turn, Piece piece) const;
Bitboard get_pieces(Turn turn, PieceType piece) const;


Bitboard checkers() const;
Expand All @@ -486,12 +486,12 @@ class Board
Bitboard attackers_battery(Square square, Bitboard occupancy) const
{
Bitboard bishops = get_pieces<TURN, BISHOP>() | get_pieces<TURN, QUEEN>();
Bitboard rooks = get_pieces<TURN, ROOK>() | get_pieces<TURN, QUEEN>();
Bitboard rooks = get_pieces<TURN, ROOK>() | get_pieces<TURN, QUEEN>();
return (Bitboards::get_attacks_pawns<~TURN>(square) & get_pieces<TURN, PAWN >()) |
(Bitboards::get_attacks<KNIGHT>(square, occupancy) & get_pieces<TURN, KNIGHT>()) |
(Bitboards::get_attacks<BISHOP>(square, occupancy ^ bishops) & bishops) |
(Bitboards::get_attacks<ROOK >(square, occupancy ^ rooks) & rooks) |
(Bitboards::get_attacks<KING >(square, occupancy) & get_pieces<TURN, KING>());
(Bitboards::get_attacks<KING >(square, occupancy) & get_pieces<TURN, KING>());
}


Expand Down
6 changes: 3 additions & 3 deletions src/Search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ namespace Search
// Update histories for quiet TT moves
if (tt_move != MOVE_NULL && !tt_move.is_capture() && !tt_move.is_promotion())
{
PieceType piece = static_cast<PieceType>(position.board().get_piece_at(tt_move.from()));
PieceType piece = position.board().get_piece_at(tt_move.from());
if (tt_score >= beta)
data.histories().fail_high(tt_move, data.last_move(), Turn, depth, Ply, piece);
else
Expand Down Expand Up @@ -800,7 +800,7 @@ namespace Search
// Make the move
Score score;
bool captureOrPromotion = move.is_capture() || move.is_promotion();
PieceType piece = static_cast<PieceType>(position.board().get_piece_at(move.from()));
PieceType piece = position.board().get_piece_at(move.from());
position.make_move(move);
nodes_searched++;
data.nodes_searched()++;
Expand Down Expand Up @@ -905,7 +905,7 @@ namespace Search
if (best_score >= alpha)
for (auto move : quiets_searched)
if (move != best_move)
data.histories().add_bonus(move, Turn, static_cast<PieceType>(position.board().get_piece_at(move.from())), -depth * depth / 4);
data.histories().add_bonus(move, Turn, position.board().get_piece_at(move.from()), -depth * depth / 4);

// Check for game end
if (n_moves == 0)
Expand Down
37 changes: 19 additions & 18 deletions src/Types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Square = int8_t;
using Value = int8_t;
using Hash = uint64_t;
using Piece = int8_t;
using Direction = int8_t;
using Score = int16_t;
using Depth = uint8_t;
Expand Down Expand Up @@ -40,31 +39,31 @@ enum Color : int8_t

enum PieceType : int8_t
{
PIECE_NONE = -1,
PAWN = 0,
KNIGHT = 1,
BISHOP = 2,
ROOK = 3,
QUEEN = 4,
KING = 5
KING = 5,
PIECE_NONE = 7
};


enum BoardPieces : int8_t
enum Piece : int8_t
{
NO_PIECE = 2 * PIECE_NONE,
W_PAWN = 2 * PAWN,
W_KNIGHT = 2 * KNIGHT,
W_BISHOP = 2 * BISHOP,
W_ROOK = 2 * ROOK,
W_QUEEN = 2 * QUEEN,
W_KING = 2 * KING,
B_PAWN = W_PAWN + 1,
B_KNIGHT = W_KNIGHT + 1,
B_BISHOP = W_BISHOP + 1,
B_ROOK = W_ROOK + 1,
B_QUEEN = W_QUEEN + 1,
B_KING = W_KING + 1
W_PAWN = PAWN,
W_KNIGHT = KNIGHT,
W_BISHOP = BISHOP,
W_ROOK = ROOK,
W_QUEEN = QUEEN,
W_KING = KING,
B_PAWN = W_PAWN | 0x8,
B_KNIGHT = W_KNIGHT | 0x8,
B_BISHOP = W_BISHOP | 0x8,
B_ROOK = W_ROOK | 0x8,
B_QUEEN = W_QUEEN | 0x8,
B_KING = W_KING | 0x8,
NO_PIECE = PIECE_NONE
};


Expand Down Expand Up @@ -206,7 +205,9 @@ constexpr Turn operator~(const Turn& other) { return (other == WHITE) ? BLACK :
constexpr Color operator-(const Color& other) { return static_cast<Color>(-static_cast<int>(other)); }


constexpr BoardPieces get_board_piece(Piece piece, Turn turn) { return static_cast<BoardPieces>(2 * piece + turn); }
constexpr Piece get_piece(PieceType pt, Turn turn) { return static_cast<Piece>(pt + (turn << 3)); }
constexpr PieceType get_piece_type(Piece pc) { return static_cast<PieceType>(pc & 0b111); }
constexpr Turn get_turn(Piece pc) { return static_cast<Turn>((pc & 0b1000) >> 3); }


constexpr bool is_mate(const Score& score)
Expand Down

0 comments on commit 0a131bd

Please sign in to comment.