stellar

Stellar - UCI Chess engine written in C++20
git clone git://git.dimitrijedobrota.com/stellar.git
Log | Files | Refs | README | LICENSE

commit 67c3102f90a864a87055d35c03d2b17f41fa99fd
parent b3231023f2f855d0f1b27d7e834bba800bb6da5a
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Mon, 14 Aug 2023 16:58:21 +0200

Fix performance issue, slight problem with engine...

Diffstat:
Msrc/board/board.cpp | 53+++++++++++++++++++++--------------------------------
Msrc/engine/engine.cpp | 14++++++++------
Msrc/include/board.hpp | 17+++++++----------
Msrc/include/move.hpp | 35++++++++++++++++-------------------
Msrc/include/piece.hpp | 8+++++++-
Msrc/include/zobrist.hpp | 16++++++----------
Msrc/move/move.cpp | 58+++++++++++++++++++++++++++++-----------------------------
Msrc/move/movelist.cpp | 69+++++++++++++++++++++++++++++++++------------------------------------
Msrc/perft/perft.cpp | 23++++++++++++++++-------
9 files changed, 143 insertions(+), 150 deletions(-)

diff --git a/src/board/board.cpp b/src/board/board.cpp @@ -23,28 +23,16 @@ U64 Board::get_bitboard_occupancy(void) const { U64 Board::get_bitboard_piece(piece::Type piece) const { return pieces[to_underlying(piece)]; } -U64 Board::get_bitboard_piece(const piece::Piece &piece) const { - return get_bitboard_piece(piece.type, piece.color); -} - U64 Board::get_bitboard_piece(piece::Type piece, Color color) const { return pieces[to_underlying(piece)] & colors[to_underlying(color)]; } -U64 Board::get_bitboard_piece_attacks(piece::Type piece, Color color, Square square) const { - return get_bitboard_piece_attacks(piece::get(piece, color), square); -} - -U64 Board::get_bitboard_piece_attacks(const piece::Piece &piece, Square square) const { - return piece(square, get_bitboard_occupancy()); +U64 Board::get_bitboard_piece_attacks(piece::Type type, Color color, Square from) const { + return piece::get_attack(type, color, from, get_bitboard_occupancy()); } -U64 Board::get_bitboard_piece_moves(piece::Type piece, Color color, Square square) const { - return get_bitboard_piece_moves(piece::get(piece, color), square); -} - -U64 Board::get_bitboard_piece_moves(const piece::Piece &piece, Square square) const { - return get_bitboard_piece_attacks(piece, square) & ~get_bitboard_color(piece.color); +U64 Board::get_bitboard_piece_moves(piece::Type type, Color color, Square square) const { + return get_bitboard_piece_attacks(type, color, square) & ~get_bitboard_color(color); } Color Board::get_square_piece_color(Square square) const { @@ -57,7 +45,7 @@ piece::Type Board::get_square_piece_type(Square square) const { for (piece::Type type : piece::TypeIter()) { if (bit_get(pieces[to_underlying(type)], to_underlying(square))) return type; } - throw std::exception(); + return piece::Type::NONE; } const piece::Piece *Board::get_square_piece(Square square) const { @@ -93,22 +81,22 @@ void Board::set_bitboard_color(Color color, Square square) { bit_set(colors[to_underlying(color)], to_underlying(square)); } -void Board::pop_bitboard_piece(const piece::Piece &piece, Square square) { - bit_pop(pieces[to_underlying(piece.type)], to_underlying(square)); +void Board::pop_bitboard_piece(piece::Type type, Square square) { + bit_pop(pieces[to_underlying(type)], to_underlying(square)); } -void Board::set_bitboard_piece(const piece::Piece &piece, Square square) { - bit_set(pieces[to_underlying(piece.type)], to_underlying(square)); +void Board::set_bitboard_piece(piece::Type type, Square square) { + bit_set(pieces[to_underlying(type)], to_underlying(square)); } -void Board::pop_piece(const piece::Piece &piece, Square square) { - pop_bitboard_color(piece.color, square); - pop_bitboard_piece(piece, square); +void Board::pop_piece(piece::Type type, Color side, Square square) { + pop_bitboard_color(side, square); + pop_bitboard_piece(type, square); } -void Board::set_piece(const piece::Piece &piece, Square square) { - set_bitboard_color(piece.color, square); - set_bitboard_piece(piece, square); +void Board::set_piece(piece::Type type, Color side, Square square) { + set_bitboard_color(side, square); + set_bitboard_piece(type, square); } /* Queries */ @@ -121,16 +109,16 @@ bool Board::is_square_attacked(Square square, Color side) const { Color side_other = (side == Color::BLACK) ? Color::WHITE : Color::BLACK; for (piece::Type type : piece::TypeIter()) { - if (get_bitboard_piece_attacks(piece::get(type, side_other), square) & - get_bitboard_piece(piece::get(type, side))) + if (get_bitboard_piece_attacks(type, side_other, square) & get_bitboard_piece(type, side)) { return 1; + } } return 0; } -bool Board::is_piece_attack_square(const piece::Piece &piece, Square source, Square target) const { - return get_bitboard_piece_attacks(piece, source) & (C64(1) << to_underlying(target)); +bool Board::is_piece_attack_square(piece::Type type, Color color, Square source, Square target) const { + return get_bitboard_piece_attacks(type, color, source) & (C64(1) << to_underlying(target)); } bool Board::is_check(void) const { @@ -144,7 +132,8 @@ Board::Board(const std::string &fen) { int file = 0, rank = 7, i; for (i = 0; fen[i] != ' '; i++) { if (isalpha(fen[i])) { - set_piece(piece::get_from_code(fen[i]), static_cast<Square>(rank * 8 + file)); + const piece::Piece &piece = piece::get_from_code(fen[i]); + set_piece(piece.type, piece.color, static_cast<Square>(rank * 8 + file)); file++; } else if (isdigit(fen[i])) { file += fen[i] - '0'; diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp @@ -23,7 +23,7 @@ Board board; TTable ttable(C64(0x400000)); Move pv_table[MAX_PLY][MAX_PLY]; Move killer[2][MAX_PLY]; -U32 history[16][64]; +U32 history[12][64]; int pv_length[MAX_PLY]; bool follow_pv; U64 nodes; @@ -31,8 +31,8 @@ U32 ply; Move move_list_best_move; U32 inline move_list_score(Move move) { - const piece::Type type = move.piece().type; - if (move.is_capture()) return piece::score(type, move.piece_capture().type) + 10000; + const piece::Type type = move.piece(); + if (move.is_capture()) return piece::score(type, move.captured()) + 10000; if (killer[0][ply] == move) return 9000; if (killer[1][ply] == move) return 8000; return history[to_underlying(type)][to_underlying(move.target())]; @@ -268,7 +268,8 @@ int negamax(int alpha, int beta, int depth, bool null) { if (score > alpha) { if (!move.is_capture()) { - history[move.piece().index][to_underlying(move.target())] += depth; + int index = piece::get(move.piece(), board.get_side()).index; + history[index][to_underlying(move.target())] += depth; } alpha = score; @@ -302,7 +303,7 @@ int negamax(int alpha, int beta, int depth, bool null) { void move_print_UCI(Move move) { std::cout << square_to_coordinates(move.source()) << square_to_coordinates(move.target()); - if (move.is_promote()) std::cout << move.piece_promote().code; + // if (move.is_promote()) std::cout << move.piece_promote().code; } void search_position(int depth) { @@ -413,7 +414,8 @@ Move parse_move(char *move_string) { const Move move = list[i]; if (move.source() == source && move.target() == target) { if (move_string[4]) { - if (tolower(move.piece_promote().code) != move_string[4]) continue; + char code = piece::get(move.promoted(), board.get_side()).code; + if (tolower(code) != move_string[4]) continue; } return move; } diff --git a/src/include/board.hpp b/src/include/board.hpp @@ -33,12 +33,9 @@ class Board { U64 get_bitboard_piece(piece::Type piece) const; U64 get_bitboard_piece(piece::Type piece, Color color) const; - U64 get_bitboard_piece(const piece::Piece &piece) const; - U64 get_bitboard_piece_attacks(piece::Type piece, Color color, Square square) const; - U64 get_bitboard_piece_attacks(const piece::Piece &piece, Square square) const; - U64 get_bitboard_piece_moves(piece::Type piece, Color color, Square square) const; - U64 get_bitboard_piece_moves(const piece::Piece &piece, Square square) const; + U64 get_bitboard_piece_attacks(piece::Type piece, Color color, Square from) const; + U64 get_bitboard_piece_moves(piece::Type piece, Color color, Square from) const; Color get_square_piece_color(Square square) const; piece::Type get_square_piece_type(Square square) const; @@ -54,17 +51,17 @@ class Board { void pop_bitboard_color(Color color, Square square); void set_bitboard_color(Color color, Square square); - void pop_bitboard_piece(const piece::Piece &piece, Square square); - void set_bitboard_piece(const piece::Piece &piece, Square square); + void pop_bitboard_piece(piece::Type type, Square square); + void set_bitboard_piece(piece::Type type, Square square); - void pop_piece(const piece::Piece &piece, Square square); - void set_piece(const piece::Piece &piece, Square square); + void pop_piece(piece::Type type, Color side, Square square); + void set_piece(piece::Type type, Color side, Square square); /* Queries */ bool is_square_attacked(Square Square, Color side) const; bool is_square_occupied(Square Square) const; - bool is_piece_attack_square(const piece::Piece &piece, Square source, Square target) const; + bool is_piece_attack_square(piece::Type type, Color color, Square source, Square target) const; bool is_check(void) const; private: diff --git a/src/include/move.hpp b/src/include/move.hpp @@ -11,12 +11,11 @@ struct Move { Move() = default; - Move(Square source, Square target, const piece::Piece *piece, const piece::Piece *capture, - const piece::Piece *promote, bool dbl, bool enpassant, bool castle) - : source_i(to_underlying(source)), target_i(to_underlying(target)), piece_i(piece->index), - piece_capture_i(capture ? capture->index : 0), piece_promote_i(promote ? promote->index : 0), - dbl(dbl), enpassant(enpassant), castle(castle), capture(capture != NULL), promote(promote != NULL) { - } + Move(Square source, Square target, piece::Type piece, piece::Type capture, piece::Type promote, bool dbl, + bool enpassant, bool castle) + : source_i(to_underlying(source)), target_i(to_underlying(target)), piece_i(to_underlying(piece)), + capture_i(to_underlying(capture)), promote_i(to_underlying(promote)), dbl(dbl), + enpassant(enpassant), castle(castle) {} bool operator==(const Move &m) const = default; @@ -26,32 +25,30 @@ struct Move { bool is_double(void) const { return dbl; } bool is_enpassant(void) const { return enpassant; } bool is_castle(void) const { return castle; } - bool is_capture(void) const { return capture; } - bool is_promote(void) const { return promote; } + bool is_capture(void) const { return capture_i != to_underlying(piece::Type::NONE); } + bool is_promote(void) const { return promote_i != to_underlying(piece::Type::NONE); } - const piece::Piece &piece(void) const { return piece::get_from_index(piece_i); } - const piece::Piece &piece_capture(void) const { return piece::get_from_index(piece_capture_i); } - const piece::Piece &piece_promote(void) const { return piece::get_from_index(piece_promote_i); } + const piece::Type piece(void) const { return static_cast<piece::Type>(piece_i); } + const piece::Type captured(void) const { return static_cast<piece::Type>(capture_i); } + const piece::Type promoted(void) const { return static_cast<piece::Type>(promote_i); } bool make(Board &board, bool attack_only) const; friend std::ostream &operator<<(std::ostream &os, Move move); private: - inline void piece_remove(Board &board, const piece::Piece &piece, Square square) const; - inline void piece_set(Board &board, const piece::Piece &piece, Square square) const; - inline void piece_move(Board &board, const piece::Piece &piece, Square source, Square target) const; + inline void piece_remove(Board &board, piece::Type type, Color color, Square square) const; + inline void piece_set(Board &board, piece::Type type, Color color, Square square) const; + inline void piece_move(Board &board, piece::Type type, Color color, Square source, Square target) const; unsigned source_i : 6; unsigned target_i : 6; - unsigned piece_i : 5; - unsigned piece_capture_i : 5; - unsigned piece_promote_i : 5; + unsigned piece_i : 3; + unsigned capture_i : 3; + unsigned promote_i : 3; bool dbl : 1; bool enpassant : 1; bool castle : 1; - bool capture : 1; - bool promote : 1; }; #endif diff --git a/src/include/piece.hpp b/src/include/piece.hpp @@ -15,7 +15,7 @@ enum class Type { ROOK, QUEEN, KING, - TypeSIZE + NONE = 7, }; typedef Iterator<Type, Type::PAWN, Type::KING> TypeIter; @@ -96,6 +96,12 @@ constexpr const Piece &get(Type type, Color color) { return table[static_cast<int>(color)][static_cast<int>(type)]; } +constexpr const U64 get_attack(Type type, Color color, Square from, U64 occupancy) { + return get(type, color)(from, occupancy); +} + +constexpr const char get_code(Type type, Color color = Color::WHITE) { return get(type, color).code; } +constexpr const U64 get_index(Type type, Color color) { return get(type, color).index; } constexpr const Piece &get_from_code(char code) { Color color = isupper(code) ? Color::WHITE : Color::BLACK; diff --git a/src/include/zobrist.hpp b/src/include/zobrist.hpp @@ -16,8 +16,8 @@ class Zobrist { static inline constexpr U64 key_side(void) { return keys_side; } static inline constexpr U64 key_castle(int exp) { return keys_castle[exp]; } static inline constexpr U64 key_enpassant(Square square) { return keys_enpassant[to_underlying(square)]; } - static inline constexpr U64 key_piece(const piece::Piece &piece, Square square) { - return keys_piece[piece.index][to_underlying(square)]; + static inline constexpr U64 key_piece(piece::Type type, Color color, Square square) { + return keys_piece[piece::get_index(type, color)][to_underlying(square)]; } static inline U64 hash(const Board &board) { @@ -25,18 +25,14 @@ class Zobrist { uint8_t square; for (piece::Type type : piece::TypeIter()) { - const piece::Piece &piece_white = piece::get(type, Color::WHITE); - int piece_white_index = piece_white.index; - U64 bitboard_white = board.get_bitboard_piece(piece_white); - + int piece_white_index = piece::get_index(type, Color::WHITE); + U64 bitboard_white = board.get_bitboard_piece(type, Color::WHITE); bitboard_for_each_bit(square, bitboard_white) { key_final ^= keys_piece[piece_white_index][square]; } - const piece::Piece &piece_black = piece::get(type, Color::BLACK); - int piece_black_index = piece_black.index; - U64 bitboard_black = board.get_bitboard_piece(piece_black); - + int piece_black_index = piece::get_index(type, Color::BLACK); + U64 bitboard_black = board.get_bitboard_piece(type, Color::BLACK); bitboard_for_each_bit(square, bitboard_black) { key_final ^= keys_piece[piece_black_index][square]; } diff --git a/src/move/move.cpp b/src/move/move.cpp @@ -5,21 +5,23 @@ #include <algorithm> #include <iomanip> -void Move::piece_remove(Board &board, const piece::Piece &piece, Square square) const { - board.pop_piece(piece, square); - board.xor_hash(Zobrist::key_piece(piece, square)); +void Move::piece_remove(Board &board, piece::Type type, Color color, Square square) const { + board.pop_piece(type, color, square); + board.xor_hash(Zobrist::key_piece(type, color, square)); } -void Move::piece_set(Board &board, const piece::Piece &piece, Square square) const { - board.set_piece(piece, square); - board.xor_hash(Zobrist::key_piece(piece, square)); +void Move::piece_set(Board &board, piece::Type type, Color color, Square square) const { + board.set_piece(type, color, square); + board.xor_hash(Zobrist::key_piece(type, color, square)); } -void Move::piece_move(Board &board, const piece::Piece &piece, Square source, Square target) const { - piece_remove(board, piece, source); - piece_set(board, piece, target); +void Move::piece_move(Board &board, piece::Type type, Color color, Square source, Square target) const { + piece_remove(board, type, color, source); + piece_set(board, type, color, target); } +using piece::Type::ROOK; + bool Move::make(Board &board, bool attack_only) const { static constexpr const int castling_rights[64] = { // clang-format off @@ -38,8 +40,8 @@ bool Move::make(Board &board, bool attack_only) const { if (is_capture()) return make(board, false); return 0; } else { - const piece::Piece &piece = this->piece(); const Color color = board.get_side(); + Color colorOther = color == Color::BLACK ? Color::WHITE : Color::BLACK; const Square source = this->source(); const Square target = this->target(); @@ -48,34 +50,32 @@ bool Move::make(Board &board, bool attack_only) const { if (!is_capture()) { if (is_promote()) { - piece_remove(board, piece, source); - piece_set(board, piece_promote(), target); + piece_remove(board, piece(), color, source); + piece_set(board, promoted(), color, target); } else { - piece_move(board, piece, source, target); + piece_move(board, piece(), color, source, target); } } else { if (is_enpassant()) { - piece_move(board, piece, source, target); - piece_remove(board, piece_capture(), ntarget); + piece_move(board, piece(), color, source, target); + piece_remove(board, captured(), colorOther, ntarget); } else if (is_promote()) { - piece_remove(board, piece, source); - piece_remove(board, piece_capture(), target); - piece_set(board, piece_promote(), target); + piece_remove(board, piece(), color, source); + piece_remove(board, captured(), colorOther, target); + piece_set(board, promoted(), color, target); } else { - piece_remove(board, piece_capture(), target); - piece_move(board, piece, source, target); + piece_remove(board, captured(), colorOther, target); + piece_move(board, piece(), color, source, target); } } board.set_enpassant(is_double() ? ntarget : Square::no_sq); if (is_castle()) { - static constexpr const piece::Piece &rook_white = piece::get(piece::Type::ROOK, Color::WHITE); - static constexpr const piece::Piece &rook_black = piece::get(piece::Type::ROOK, Color::BLACK); - if (target == Square::g1) piece_move(board, rook_white, Square::h1, Square::f1); - if (target == Square::c1) piece_move(board, rook_white, Square::a1, Square::d1); - if (target == Square::g8) piece_move(board, rook_black, Square::h8, Square::f8); - if (target == Square::c8) piece_move(board, rook_black, Square::a8, Square::d8); + if (target == Square::g1) piece_move(board, ROOK, Color::WHITE, Square::h1, Square::f1); + if (target == Square::c1) piece_move(board, ROOK, Color::WHITE, Square::a1, Square::d1); + if (target == Square::g8) piece_move(board, ROOK, Color::BLACK, Square::h8, Square::f8); + if (target == Square::c8) piece_move(board, ROOK, Color::BLACK, Square::a8, Square::d8); } board.xor_hash(Zobrist::key_castle(board.get_castle())); @@ -94,9 +94,9 @@ bool Move::make(Board &board, bool attack_only) const { std::ostream &operator<<(std::ostream &os, Move move) { os << square_to_coordinates(move.source()) << " "; os << square_to_coordinates(move.target()) << " "; - os << move.piece().code << " "; - os << (move.is_capture() ? move.piece_capture().code : '.') << " "; - os << (move.is_promote() ? move.piece_promote().code : '.') << " "; + os << piece::get_code(move.piece()) << " "; + os << (move.is_capture() ? piece::get_code(move.captured()) : '.') << " "; + os << (move.is_promote() ? piece::get_code(move.promoted()) : '.') << " "; os << move.is_double() << " "; os << move.is_enpassant() << " "; os << move.is_castle(); diff --git a/src/move/movelist.cpp b/src/move/movelist.cpp @@ -1,4 +1,5 @@ #include "movelist.hpp" +#include "piece.hpp" #include <iomanip> #define pawn_canPromote(color, source) \ @@ -9,6 +10,14 @@ ((color == Color::BLACK && source >= Square::a7 && source <= Square::h7) || \ (color == Color::WHITE && source >= Square::a2 && source <= Square::h2)) +using piece::Type::BISHOP; +using piece::Type::KING; +using piece::Type::KNIGHT; +using piece::Type::NONE; +using piece::Type::PAWN; +using piece::Type::QUEEN; +using piece::Type::ROOK; + void MoveList::generate(const Board &board) { this->clear(); @@ -18,104 +27,92 @@ void MoveList::generate(const Board &board) { Color colorOther = color == Color::BLACK ? Color::WHITE : Color::BLACK; // pawn moves - const piece::Piece &pawn = piece::get(piece::Type::PAWN, color); const int add = (color == Color::WHITE) ? +8 : -8; - U64 bitboard = board.get_bitboard_piece(pawn); + U64 bitboard = board.get_bitboard_piece(PAWN, color); bitboard_for_each_bit(src_i, bitboard) { const Square src = static_cast<Square>(src_i); const Square tgt = static_cast<Square>(tgt_i = src_i + add); if (!board.is_square_occupied(tgt)) { if (pawn_canPromote(color, src)) { - list.push_back( - Move(src, tgt, &pawn, nullptr, &piece::get(piece::Type::KNIGHT, color), 0, 0, 0)); - list.push_back( - Move(src, tgt, &pawn, nullptr, &piece::get(piece::Type::BISHOP, color), 0, 0, 0)); - list.push_back( - Move(src, tgt, &pawn, nullptr, &piece::get(piece::Type::ROOK, color), 0, 0, 0)); - list.push_back( - Move(src, tgt, &pawn, nullptr, &piece::get(piece::Type::QUEEN, color), 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, NONE, KNIGHT, 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, NONE, BISHOP, 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, NONE, ROOK, 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, NONE, QUEEN, 0, 0, 0)); } else { - list.push_back(Move(src, tgt, &pawn, 0, 0, 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, NONE, NONE, 0, 0, 0)); // two ahead const Square tgt = static_cast<Square>(tgt_i + add); if (pawn_onStart(color, src) && !board.is_square_occupied(tgt)) - list.push_back(Move(src, tgt, &pawn, 0, 0, 1, 0, 0)); + list.push_back(Move(src, tgt, PAWN, NONE, NONE, 1, 0, 0)); } } // capture - U64 attack = board.get_bitboard_piece_attacks(pawn, src) & board.get_bitboard_color(colorOther); + U64 attack = + board.get_bitboard_piece_attacks(PAWN, color, src) & board.get_bitboard_color(colorOther); bitboard_for_each_bit(tgt_i, attack) { const Square tgt = static_cast<Square>(tgt_i); - const piece::Piece *capture = board.get_square_piece(tgt); + const piece::Type capture = board.get_square_piece_type(tgt); if (pawn_canPromote(color, src)) { - list.push_back( - Move(src, tgt, &pawn, capture, &piece::get(piece::Type::KNIGHT, color), 0, 0, 0)); - list.push_back( - Move(src, tgt, &pawn, capture, &piece::get(piece::Type::BISHOP, color), 0, 0, 0)); - list.push_back( - Move(src, tgt, &pawn, capture, &piece::get(piece::Type::ROOK, color), 0, 0, 0)); - list.push_back( - Move(src, tgt, &pawn, capture, &piece::get(piece::Type::QUEEN, color), 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, capture, KNIGHT, 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, capture, BISHOP, 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, capture, ROOK, 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, capture, QUEEN, 0, 0, 0)); } else { - list.push_back(Move(src, tgt, &pawn, capture, 0, 0, 0, 0)); + list.push_back(Move(src, tgt, PAWN, capture, NONE, 0, 0, 0)); } } // en passant const Square enpassant = board.get_enpassant(); - if (enpassant != Square::no_sq && board.is_piece_attack_square(pawn, src, enpassant)) - list.push_back( - Move(src, enpassant, &pawn, &piece::get(piece::Type::PAWN, colorOther), 0, 0, 1, 0)); + if (enpassant != Square::no_sq && board.is_piece_attack_square(PAWN, color, src, enpassant)) + list.push_back(Move(src, enpassant, PAWN, PAWN, NONE, 0, 1, 0)); } // All piece move for (const piece::Type type : ++piece::TypeIter()) { - const piece::Piece &piece = piece::get(type, color); - U64 bitboard = board.get_bitboard_piece(piece); + U64 bitboard = board.get_bitboard_piece(type, color); bitboard_for_each_bit(src_i, bitboard) { const Square src = static_cast<Square>(src_i); - U64 attack = board.get_bitboard_piece_moves(piece, src); + U64 attack = board.get_bitboard_piece_moves(type, color, src); bitboard_for_each_bit(tgt_i, attack) { const Square tgt = static_cast<Square>(tgt_i); - list.push_back(Move(src, tgt, &piece, board.get_square_piece(tgt), 0, 0, 0, 0)); + list.push_back(Move(src, tgt, type, board.get_square_piece_type(tgt), NONE, 0, 0, 0)); } } } // Castling if (color == Color::WHITE) { - static const piece::Piece &piece = piece::get(piece::Type::KING, Color::WHITE); if (!board.is_square_attacked(Square::e1, Color::BLACK)) { if (board.get_castle() & to_underlying(Board::Castle::WK)) { if (!board.is_square_occupied(Square::f1) && !board.is_square_occupied(Square::g1) && !board.is_square_attacked(Square::f1, Color::BLACK)) - list.push_back(Move(Square::e1, Square::g1, &piece, 0, 0, 0, 0, 1)); + list.push_back(Move(Square::e1, Square::g1, KING, NONE, NONE, 0, 0, 1)); } if (board.get_castle() & to_underlying(Board::Castle::WQ)) { if (!board.is_square_occupied(Square::d1) && !board.is_square_occupied(Square::c1) && !board.is_square_occupied(Square::b1) && !board.is_square_attacked(Square::d1, Color::BLACK) && !board.is_square_attacked(Square::c1, Color::BLACK)) - list.push_back(Move(Square::e1, Square::c1, &piece, 0, 0, 0, 0, 1)); + list.push_back(Move(Square::e1, Square::c1, KING, NONE, NONE, 0, 0, 1)); } } } else { - static const piece::Piece &piece = piece::get(piece::Type::KING, Color::BLACK); if (!board.is_square_attacked(Square::e8, Color::WHITE)) { if (board.get_castle() & to_underlying(Board::Castle::BK)) { if (!board.is_square_occupied(Square::f8) && !board.is_square_occupied(Square::g8) && !board.is_square_attacked(Square::f8, Color::WHITE)) - list.push_back(Move(Square::e8, Square::g8, &piece, 0, 0, 0, 0, 1)); + list.push_back(Move(Square::e8, Square::g8, KING, NONE, NONE, 0, 0, 1)); } if (board.get_castle() & to_underlying(Board::Castle::BQ)) { if (!board.is_square_occupied(Square::d8) && !board.is_square_occupied(Square::c8) && !board.is_square_occupied(Square::b8) && !board.is_square_attacked(Square::d8, Color::WHITE) && !board.is_square_attacked(Square::c8, Color::WHITE)) - list.push_back(Move(Square::e8, Square::c8, &piece, 0, 0, 0, 0, 1)); + list.push_back(Move(Square::e8, Square::c8, KING, NONE, NONE, 0, 0, 1)); } } } diff --git a/src/perft/perft.cpp b/src/perft/perft.cpp @@ -17,14 +17,16 @@ class Perft { typedef std::counting_semaphore<THREAD_MAX> semaphore_t; Perft(semaphore_t &sem) : sem(sem) {} void operator()(const Board &board_start, Move move, int depth) { - sem.acquire(); Board board = board_start; - if (move.make(board, 0)) { - if (depth > 1) - test(board, depth - 1); - else - score(board, move); + if (!move.make(board, 0)) return; + sem.acquire(); + + if (depth > 1) { + test(board, depth - 1); + } else { + score(board, move); } + mutex.acquire(); result += local; mutex.release(); @@ -67,6 +69,13 @@ class Perft { score(copy, list[i]); } } + + void debug(const Board &before, Move move, const Board &after) { + std::cout << std::setw(16) << std::hex << before.get_hash() << " "; + std::cout << move << " "; + std::cout << std::setw(16) << std::hex << after.get_hash() << "\n"; + } + void score(const Board &board, Move move) { local.node++; #ifdef USE_FULL_COUNT @@ -77,7 +86,6 @@ class Perft { if (move.is_promote()) local.promote++; #endif } - result_t local; semaphore_t &sem; static std::binary_semaphore mutex; @@ -100,6 +108,7 @@ void perft_test(const char *fen, int depth, int thread_num) { for (auto &thread : threads) thread.join(); + std::cout << std::dec; std::cout << " Nodes: " << Perft::result.node << "\n"; #ifdef USE_FULL_COUNT std::cout << " Captures: " << Perft::result.capture << "\n";