stellarUCI Chess engine written in C++20 |
git clone git://git.dimitrijedobrota.com/stellar.git |
Log | Files | Refs | README | LICENSE | |
commit | 2f3a26c1d985412b453547ebd5c01190e378684e |
parent | fcde3f48c51361419b4d2f43652dd622e50660b7 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Wed, 13 Mar 2024 19:54:46 +0000 |
Beter enum handling, get rid of to_underlying()
Diffstat:M | CMakeLists.txt | | | +- |
M | src/arena/game.cpp | | | ++-- |
M | src/arena/logger.hpp | | | +- |
M | src/arena/match.cpp | | | +- |
M | src/attack/bishop.cpp | | | +++++++++++---------------- |
M | src/attack/king.hpp | | | +++++++------ |
M | src/attack/knight.hpp | | | +++++++------ |
M | src/attack/pawnb.hpp | | | +++++++------ |
M | src/attack/pawnw.hpp | | | +++++++------ |
M | src/attack/rook.cpp | | | +++++++++++---------------- |
M | src/attack/slider.hpp | | | +- |
M | src/board/board.cpp | | | ++++++++-------- |
M | src/board/board.hpp | | | +++++++++++++++++++------------------------ |
M | src/board/zobrist.hpp | | | +++--- |
M | src/engine/engine.cpp | | | +++--- |
M | src/engine/evaluate.cpp | | | +-- |
M | src/engine/score.hpp | | | ++++++----- |
M | src/move/move.cpp | | | ++--- |
M | src/move/move.hpp | | | +- |
M | src/move/movelist.cpp | | | +++++----- |
M | src/piece/piece.hpp | | | +++-- |
M | src/utils/bitboard.cpp | | | ++ |
M | src/utils/bitboard.hpp | | | + |
M | src/utils/square.hpp | | | +++++-------- |
M | src/utils/utils.hpp | | | +++-------------------------- |
25 files changed, 118 insertions(+), 152 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Stellar
VERSION 1.3.0
VERSION 1.3.1
DESCRIPTION "Chess engine written in C++"
HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git
LANGUAGES CXX
diff --git a/src/arena/game.cpp b/src/arena/game.cpp
@@ -84,7 +84,7 @@ std::ostream &operator<<(std::ostream &os, const Game &game) {
os << std::format("\n[White \"{}\"]", game.get_white());
os << std::format("\n[Black \"{}\"]", game.get_black());
os << std::format("\n[Result \"{}-{}\"]", (int)game.is_win_white(), (int)game.is_win_black());
os << std::format("\n[Termination \"{}\"]", name[to_underlying(game.get_terminate())]);
os << std::format("\n[Termination \"{}\"]", name[game.get_terminate()]);
if (game.fen != Game::startPosition) {
os << std::format("\n[SetUp \"1\"]");
os << std::format("\n[FEN \"{}\"]", game.fen);
@@ -97,7 +97,7 @@ std::ostream &operator<<(std::ostream &os, const Game &game) {
const color::Color side = board.get_side();
if (side == color::BLACK) os << std::format("1. ... ");
for (int i = 0; i < game.list.size(); i++) {
if (i % 2 == to_underlying(side)) os << std::format("{}. ", i / 2 + 1);
if (i % 2 == side) os << std::format("{}. ", i / 2 + 1);
os << std::format("{} ", Game::san ? Game::to_san(board, game.list[i]) : (std::string)game.list[i]);
game.list[i].make(board);
}
diff --git a/src/arena/logger.hpp b/src/arena/logger.hpp
@@ -22,7 +22,7 @@ inline void set_level(const Level lvl) { active = lvl; }
inline void log(const std::string &message, const Level lvl = Arena) {
static const std::string name[] = {"crit", "arena", "debug", "info"};
if (lvl > active) return;
std::cerr << std::format("[ {:>5} ] {}\n", name[to_underlying(lvl)], message);
std::cerr << std::format("[ {:>5} ] {}\n", name[lvl], message);
}
inline void error(const char *call) { log(std::format("{}, {}", call, std::strerror(errno)), Critical); }
diff --git a/src/arena/match.cpp b/src/arena/match.cpp
@@ -31,7 +31,7 @@ Game Match::play(Settings swhite, Settings sblack, const std::string fen = Game:
break;
}
Engine *engine = engines[to_underlying(turn)];
Engine *engine = engines[turn];
engine->send(std::format("{} moves {}", position, game.get_moves()));
engine->send(get_go(swhite, sblack, turn));
diff --git a/src/attack/bishop.cpp b/src/attack/bishop.cpp
@@ -45,49 +45,44 @@ inline constexpr const bitboard::direction_f dir[4] = {bitboard::noEaOne, bitboa
bitboard::soEaOne, bitboard::soWeOne};
inline constexpr U32 hash(const U64 key, const square::Square square) {
uint8_t square_i = to_underlying(square);
return (key * bishop_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]);
return (key * bishop_magic_numbers[square]) >> (64 - relevant_bits[square]);
}
inline constexpr U64 mask_fly(const square::Square square, U64 block) {
uint8_t square_i = to_underlying(square);
int tr = square_i / 8, tf = square_i % 8;
int tr = square / 8, tf = square % 8;
int len[4] = {std::min(7 - tf, 7 - tr), std::min(tf, 7 - tr), std::min(7 - tf, tr), std::min(tf, tr)};
return attack::slider::mask(square, block, dir, len);
}
std::array<U64, 64> masks = {{0}};
inline U64 mask(const square::Square square) { return masks[to_underlying(square)]; }
std::array<U64, 64> mask = {{0}};
std::array<std::array<U64, 4098>, 64> attacks = {{{0}}};
void init(void) {
for (uint8_t square = 0; square < 64; square++) {
for (square::Square square = square::a1; square <= square::h8; ++square) {
int tr = square / 8, tf = square % 8;
int len[4] = {std::min(7 - tf, 7 - tr) - 1, std::min(tf, 7 - tr) - 1, std::min(7 - tf, tr) - 1,
std::min(tf, tr) - 1};
masks[square] = attack::slider::mask(static_cast<square::Square>(square), C64(0), dir, len);
mask[square] = attack::slider::mask(square, C64(0), dir, len);
}
for (uint8_t square = 0; square < 64; square++) {
square::Square Square = static_cast<square::Square>(square);
U64 attack_mask = mask(Square);
for (square::Square square = square::a1; square <= square::h8; ++square) {
U64 attack_mask = mask[square];
uint8_t relevant_bits = bit::count(attack_mask);
U64 occupancy_indices = C64(1) << relevant_bits;
for (U64 idx = 0; idx < occupancy_indices; idx++) {
U64 occupancy = attack::slider::occupancy(idx, relevant_bits, attack_mask);
U32 magic_index = hash(occupancy, Square);
attacks[square][magic_index] = mask_fly(Square, occupancy);
U32 magic_index = hash(occupancy, square);
attacks[square][magic_index] = mask_fly(square, occupancy);
}
}
}
U64 attack(const square::Square square, U64 occupancy) {
occupancy &= mask(square);
occupancy &= mask[square];
occupancy = hash(occupancy, square);
return attacks[to_underlying(square)][occupancy];
return attacks[square][occupancy];
}
} // namespace bishop
diff --git a/src/attack/king.hpp b/src/attack/king.hpp
@@ -14,7 +14,7 @@ namespace king {
static constexpr U64 mask(const square::Square square) {
U64 bitboard = C64(0), attacks = C64(0);
bit::set(bitboard, to_underlying(square));
bit::set(bitboard, square);
attacks |= bitboard::westOne(bitboard) | bitboard::eastOne(bitboard);
attacks |= bitboard::soutOne(bitboard) | bitboard::nortOne(bitboard);
attacks |= bitboard::soutOne(bitboard) | bitboard::nortOne(bitboard);
@@ -27,14 +27,15 @@ static constexpr U64 mask(const square::Square square) {
typedef std::array<U64, 64> attack_array;
const attack_array attacks = []() -> attack_array {
std::array<U64, 64> attacks;
for (uint8_t square = 0; square < 64; square++)
attacks[square] = mask(static_cast<square::Square>(square));
for (square::Square square = square::a1; square <= square::h8; ++square) {
attacks[square] = mask(square);
}
return attacks;
}();
inline constexpr U64 attack(const square::Square square, U64 occupancy) {
return attacks[to_underlying(square)];
}
inline constexpr U64 attack(const square::Square square, U64 occupancy) { return attacks[square]; }
} // namespace king
} // namespace attack
diff --git a/src/attack/knight.hpp b/src/attack/knight.hpp
@@ -14,7 +14,7 @@ namespace knight {
static constexpr U64 mask(const square::Square square) {
U64 bitboard = C64(0), attacks = C64(0), tmp;
bit::set(bitboard, to_underlying(square));
bit::set(bitboard, square);
tmp = bitboard::nortOne(bitboard::nortOne(bitboard));
attacks |= bitboard::westOne(tmp) | bitboard::eastOne(tmp);
tmp = bitboard::soutOne(bitboard::soutOne(bitboard));
@@ -30,14 +30,15 @@ static constexpr U64 mask(const square::Square square) {
typedef std::array<U64, 64> attack_array;
const attack_array attacks = []() -> attack_array {
std::array<U64, 64> attacks;
for (uint8_t square = 0; square < 64; square++)
attacks[square] = mask(static_cast<square::Square>(square));
for (square::Square square = square::a1; square <= square::h8; ++square) {
attacks[square] = mask(square);
}
return attacks;
}();
inline constexpr U64 attack(const square::Square square, U64 occupancy) {
return attacks[to_underlying(square)];
}
inline constexpr U64 attack(const square::Square square, U64 occupancy) { return attacks[square]; }
} // namespace knight
} // namespace attack
diff --git a/src/attack/pawnb.hpp b/src/attack/pawnb.hpp
@@ -14,21 +14,22 @@ namespace pawnb {
static constexpr U64 mask(const square::Square square) {
U64 bitboard = C64(0);
bit::set(bitboard, to_underlying(square));
bit::set(bitboard, square);
return bitboard::soWeOne(bitboard) | bitboard::soEaOne(bitboard);
}
typedef std::array<U64, 64> attack_array;
const attack_array attacks = []() -> attack_array {
std::array<U64, 64> attacks;
for (uint8_t square = 0; square < 64; square++)
attacks[square] = mask(static_cast<square::Square>(square));
for (square::Square square = square::a1; square <= square::h8; ++square) {
attacks[square] = mask(square);
}
return attacks;
}();
inline constexpr U64 attack(const square::Square square, U64 occupancy) {
return attacks[to_underlying(square)];
}
inline constexpr U64 attack(const square::Square square, U64 occupancy) { return attacks[square]; }
} // namespace pawnb
}; // namespace attack
diff --git a/src/attack/pawnw.hpp b/src/attack/pawnw.hpp
@@ -14,21 +14,22 @@ namespace pawnw {
static constexpr U64 mask(const square::Square square) {
U64 bitboard = C64(0);
bit::set(bitboard, to_underlying(square));
bit::set(bitboard, square);
return bitboard::noWeOne(bitboard) | bitboard::noEaOne(bitboard);
}
typedef std::array<U64, 64> attack_array;
const attack_array attacks = []() -> attack_array {
std::array<U64, 64> attacks;
for (uint8_t square = 0; square < 64; square++)
attacks[square] = mask(static_cast<square::Square>(square));
for (square::Square square = square::a1; square <= square::h8; ++square) {
attacks[square] = mask(square);
}
return attacks;
}();
inline constexpr U64 attack(const square::Square square, U64 occupancy) {
return attacks[to_underlying(square)];
}
inline constexpr U64 attack(const square::Square square, U64 occupancy) { return attacks[square]; }
} // namespace pawnw
} // namespace attack
diff --git a/src/attack/rook.cpp b/src/attack/rook.cpp
@@ -44,49 +44,44 @@ inline constexpr const bitboard::direction_f dir[4] = {bitboard::westOne, bitboa
bitboard::eastOne, bitboard::nortOne};
inline constexpr U32 hash(const U64 key, const square::Square square) {
uint8_t square_i = to_underlying(square);
return (key * rook_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]);
return (key * rook_magic_numbers[square]) >> (64 - relevant_bits[square]);
}
inline constexpr U64 mask_fly(const square::Square square, U64 block) {
uint8_t square_i = to_underlying(square);
int tr = square_i / 8, tf = square_i % 8;
int tr = square / 8, tf = square % 8;
int len[4] = {tf, tr, 7 - tf, 7 - tr};
return attack::slider::mask(square, block, dir, len);
}
std::array<U64, 64> masks = {{0}};
U64 mask(const square::Square square) { return masks[to_underlying(square)]; }
std::array<U64, 64> mask = {{0}};
std::array<std::array<U64, 4096>, 64> attacks = {{{0}}};
void init(void) {
for (uint8_t square = 0; square < 64; square++) {
for (square::Square square = square::a1; square <= square::h8; ++square) {
const int tr = square / 8, tf = square % 8;
const int len[4] = {tf - 1, tr - 1, 6 - tf, 6 - tr};
masks[square] = attack::slider::mask(static_cast<square::Square>(square), C64(0), dir, len);
mask[square] = attack::slider::mask(square, C64(0), dir, len);
}
for (uint8_t square = 0; square < 64; square++) {
square::Square Square = static_cast<square::Square>(square);
U64 attack_mask = mask(Square);
for (square::Square square = square::a1; square <= square::h8; ++square) {
U64 attack_mask = mask[square];
uint8_t relevant_bits = bit::count(attack_mask);
U64 occupancy_indices = C64(1) << relevant_bits;
for (U64 idx = 0; idx < occupancy_indices; idx++) {
U64 occupancy = attack::slider::occupancy(idx, relevant_bits, attack_mask);
U32 magic_index = hash(occupancy, Square);
attacks[square][magic_index] = mask_fly(Square, occupancy);
U32 magic_index = hash(occupancy, square);
attacks[square][magic_index] = mask_fly(square, occupancy);
}
}
}
U64 attack(const square::Square square, U64 occupancy) {
occupancy &= mask(square);
occupancy &= mask[square];
occupancy = hash(occupancy, square);
return attacks[to_underlying(square)][occupancy];
return attacks[square][occupancy];
}
} // namespace rook
diff --git a/src/attack/slider.hpp b/src/attack/slider.hpp
@@ -25,7 +25,7 @@ inline constexpr U64 occupancy(U64 index, uint8_t bits_in_mask, U64 attack_mask)
inline constexpr U64 mask(const square::Square square, U64 block, const bitboard::direction_f dir[4],
const int len[4]) {
U64 bitboard = C64(0), attacks = C64(0);
bit::set(bitboard, to_underlying(square));
bit::set(bitboard, square);
for (int i = 0; i < 4; i++) {
U64 tmp = bitboard;
for (int j = 0; j < len[i]; j++) {
diff --git a/src/board/board.cpp b/src/board/board.cpp
@@ -39,13 +39,13 @@ Board::Board(const std::string &fen) {
: throw std::runtime_error("Invalid player char");
for (i += 2; fen[i] != ' '; i++) {
if (fen[i] == 'K') castle |= to_underlying(Castle::WK);
if (fen[i] == 'K') castle |= Castle::WK;
else if (fen[i] == 'Q')
castle |= to_underlying(Castle::WQ);
castle |= Castle::WQ;
else if (fen[i] == 'k')
castle |= to_underlying(Castle::BK);
castle |= Castle::BK;
else if (fen[i] == 'q')
castle |= to_underlying(Castle::BQ);
castle |= Castle::BQ;
else if (fen[i] == '-') {
i++;
break;
@@ -73,10 +73,10 @@ std::ostream &operator<<(std::ostream &os, const Board &board) {
os << ((board.side == color::WHITE) ? "white" : "black") << "\n";
os << "Enpassant: " << square::to_coordinates(board.enpassant) << "\n";
os << " Castle:";
os << ((board.castle & to_underlying(Board::Castle::WK)) ? 'K' : '-');
os << ((board.castle & to_underlying(Board::Castle::WQ)) ? 'Q' : '-');
os << ((board.castle & to_underlying(Board::Castle::BK)) ? 'k' : '-');
os << ((board.castle & to_underlying(Board::Castle::BQ)) ? 'q' : '-');
os << ((board.castle & Board::Castle::WK) ? 'K' : '-');
os << ((board.castle & Board::Castle::WQ) ? 'Q' : '-');
os << ((board.castle & Board::Castle::BK) ? 'k' : '-');
os << ((board.castle & Board::Castle::BQ) ? 'q' : '-');
os << "\n Hash:" << board.hash << "\n\n";
return os;
diff --git a/src/board/board.hpp b/src/board/board.hpp
@@ -15,7 +15,7 @@
class Board {
public:
enum class Castle : uint8_t {
enum Castle : uint8_t {
WK = 1,
WQ = 2,
BK = 4,
@@ -90,16 +90,12 @@ constexpr U64 Board::get_hash() const { return hash; }
constexpr uint8_t Board::get_castle() const { return castle; }
constexpr square::Square Board::get_enpassant() const { return enpassant; }
constexpr U64 Board::get_bitboard_color(color::Color side) const { return colors[to_underlying(side)]; }
constexpr U64 Board::get_bitboard_occupancy() const {
return colors[to_underlying(color::WHITE)] | colors[to_underlying(color::BLACK)];
}
constexpr U64 Board::get_bitboard_piece(piece::Type piece) const { return pieces[to_underlying(piece)]; }
constexpr U64 Board::get_bitboard_color(color::Color side) const { return colors[side]; }
constexpr U64 Board::get_bitboard_occupancy() const { return colors[color::WHITE] | colors[color::BLACK]; }
constexpr U64 Board::get_bitboard_piece(piece::Type piece) const { return pieces[piece]; }
constexpr U64 Board::get_bitboard_piece(piece::Type piece, color::Color color) const {
return pieces[to_underlying(piece)] & colors[to_underlying(color)];
return pieces[piece] & colors[color];
}
constexpr U64 Board::get_bitboard_piece_attacks(piece::Type type, color::Color color,
@@ -119,14 +115,14 @@ constexpr U64 Board::get_bitboard_square_land(square::Square land, piece::Type p
}
constexpr color::Color Board::get_square_piece_color(square::Square square) const {
if (bit::get(colors[to_underlying(color::WHITE)], to_underlying(square))) return color::WHITE;
if (bit::get(colors[to_underlying(color::BLACK)], to_underlying(square))) return color::BLACK;
if (bit::get(colors[color::WHITE], square)) return color::WHITE;
if (bit::get(colors[color::BLACK], square)) return color::BLACK;
throw std::exception();
}
constexpr piece::Type Board::get_square_piece_type(square::Square square) const {
for (piece::Type type : piece::TypeIter()) {
if (bit::get(pieces[to_underlying(type)], to_underlying(square))) return type;
for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) {
if (bit::get(pieces[type], square)) return type;
}
return piece::Type::NONE;
}
@@ -160,19 +156,19 @@ constexpr void Board::set_enpassant(square::Square target) {
}
constexpr void Board::pop_bitboard_color(color::Color color, square::Square square) {
bit::pop(colors[to_underlying(color)], to_underlying(square));
bit::pop(colors[color], square);
}
constexpr void Board::set_bitboard_color(color::Color color, square::Square square) {
bit::set(colors[to_underlying(color)], to_underlying(square));
bit::set(colors[color], square);
}
constexpr void Board::pop_bitboard_piece(piece::Type type, square::Square square) {
bit::pop(pieces[to_underlying(type)], to_underlying(square));
bit::pop(pieces[type], square);
}
constexpr void Board::set_bitboard_piece(piece::Type type, square::Square square) {
bit::set(pieces[to_underlying(type)], to_underlying(square));
bit::set(pieces[type], square);
}
constexpr void Board::pop_piece(piece::Type type, color::Color side, square::Square square) {
@@ -188,13 +184,13 @@ constexpr void Board::set_piece(piece::Type type, color::Color side, square::Squ
/* Queries */
constexpr bool Board::is_square_occupied(square::Square square) const {
return bit::get(get_bitboard_occupancy(), to_underlying(square));
return bit::get(get_bitboard_occupancy(), square);
}
constexpr bool Board::is_square_attacked(square::Square square, color::Color side) const {
const color::Color side_other = color::other(side);
for (piece::Type type : piece::TypeIter()) {
for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) {
if (get_bitboard_piece_attacks(type, side_other, square) & get_bitboard_piece(type, side)) {
return true;
}
@@ -205,11 +201,11 @@ constexpr bool Board::is_square_attacked(square::Square square, color::Color sid
constexpr bool Board::is_piece_attack_square(piece::Type type, color::Color color, square::Square source,
square::Square target) const {
return get_bitboard_piece_attacks(type, color, source) & (C64(1) << to_underlying(target));
return get_bitboard_piece_attacks(type, color, source) & (C64(1) << target);
}
constexpr bool Board::is_check() const {
U64 king = pieces[to_underlying(piece::Type::KING)] & colors[to_underlying(side)];
U64 king = pieces[piece::Type::KING] & colors[side];
color::Color side_other = (side == color::BLACK) ? color::WHITE : color::BLACK;
auto square = static_cast<square::Square>(bit::lsb_index(king));
return is_square_attacked(square, side_other);
@@ -219,7 +215,7 @@ U64 zobrist::hash(const Board &board) {
U64 key_final = C64(0);
uint8_t square = 0;
for (piece::Type type : piece::TypeIter()) {
for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) {
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]; }
@@ -232,8 +228,7 @@ U64 zobrist::hash(const Board &board) {
key_final ^= keys_castle[board.get_castle()];
if (board.get_side() == color::BLACK) key_final ^= keys_side;
if (board.get_enpassant() != square::Square::no_sq)
key_final ^= keys_enpassant[to_underlying(board.get_enpassant())];
if (board.get_enpassant() != square::Square::no_sq) key_final ^= keys_enpassant[board.get_enpassant()];
return key_final;
}
diff --git a/src/board/zobrist.hpp b/src/board/zobrist.hpp
@@ -19,7 +19,7 @@ const U64 keys_side = Random(C32(1699391443))();
inline void init() {
Random gen1(C64(1804289383));
for (piece::Type type : piece::TypeIter()) {
for (piece::Type type = piece::PAWN; type <= piece::KING; ++type) {
int piece_index_white = piece::get(type, color::Color::WHITE).index;
int piece_index_black = piece::get(type, color::Color::BLACK).index;
for (int square = 0; square < 64; square++) {
@@ -42,9 +42,9 @@ inline void init() {
inline U64 hash(const Board &board);
inline constexpr U64 key_side() { return keys_side; }
inline constexpr U64 key_castle(int exp) { return keys_castle[exp]; }
inline constexpr U64 key_enpassant(square::Square square) { return keys_enpassant[to_underlying(square)]; }
inline constexpr U64 key_enpassant(square::Square square) { return keys_enpassant[square]; }
inline constexpr U64 key_piece(piece::Type type, color::Color color, square::Square square) {
return keys_piece[piece::get_index(type, color)][to_underlying(square)];
return keys_piece[piece::get_index(type, color)][square];
}
}; // namespace zobrist
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
@@ -135,11 +135,11 @@ U32 inline move_score(const Move move) {
const piece::Type type = board.get_square_piece_type(move.source());
if (move.is_capture()) {
const piece::Type captured = board.get_square_piece_type(move.target());
return capture[to_underlying(type)][to_underlying(captured)] + 10000;
return capture[type][captured] + 10000;
}
if (killer[0][ply] == move) return 9000;
if (killer[1][ply] == move) return 8000;
return history[piece::get_index(type, board.get_side())][to_underlying(move.target())];
return history[piece::get_index(type, board.get_side())][move.target()];
}
void move_list_sort(MoveList &list, std::vector<int> &score, int crnt) {
@@ -368,7 +368,7 @@ int16_t negamax(int16_t alpha, int16_t beta, uint8_t depth, bool null) {
if (score > alpha) {
if (!move.is_capture()) {
const piece::Type piece = board.get_square_piece_type(move.source());
history[piece::get_index(piece, board.get_side())][to_underlying(move.target())] += depth;
history[piece::get_index(piece, board.get_side())][move.target()] += depth;
}
alpha = score;
diff --git a/src/engine/evaluate.cpp b/src/engine/evaluate.cpp
@@ -89,7 +89,6 @@ int16_t score_position_side(const Board &board, const color::Color side, const u
int16_t total = 0, opening = 0, endgame = 0;
int8_t square_i;
const uint8_t side_i = to_underlying(side);
const U64 pawns = board.get_bitboard_piece(PAWN);
const U64 pawnsS = board.get_bitboard_piece(PAWN, side);
const U64 pawnsO = pawns & ~pawnsS;
@@ -112,7 +111,7 @@ int16_t score_position_side(const Board &board, const color::Color side, const u
endgame -= score::pawn_double_endgame;
}
if (!(pawnsO & mask_passed[side_i][square_i])) total += score::pawn_passed[side_i][rank];
if (!(pawnsO & mask_passed[side][square_i])) total += score::pawn_passed[side][rank];
}
bitboard = board.get_bitboard_piece(KNIGHT, side);
diff --git a/src/engine/score.hpp b/src/engine/score.hpp
@@ -1,6 +1,7 @@
#ifndef STELLAR_SCORE_H
#define STELLAR_SCORE_H
#include "piece.hpp"
#include "utils.hpp"
#define MAX_PLY 64
@@ -146,13 +147,13 @@ enum Phase {
};
inline constexpr int16_t get(const piece::Type piece, const Phase phase = OPENING) {
return value[to_underlying(phase)][to_underlying(piece)];
return value[phase][piece];
}
inline constexpr int16_t get(const piece::Type piece, const color::Color color, const square::Square square,
const Phase phase = ENDGAME) {
uint8_t square_i = to_underlying(color == color::WHITE ? square : square::mirror(square));
return position[to_underlying(phase)][to_underlying(piece)][square_i];
inline constexpr int16_t get(piece::Type piece, color::Color color, square::Square square,
Phase phase = ENDGAME) {
if (color != color::WHITE) square = square::mirror(square);
return position[phase][piece][square];
}
inline constexpr const uint8_t pawn_double_opening = 5;
diff --git a/src/move/move.cpp b/src/move/move.cpp
@@ -41,7 +41,7 @@ bool Move::make(Board &board) const {
const square::Square source = this->source(), target = this->target();
const auto ntarget =
static_cast<square::Square>(to_underlying(this->target()) + (color == color::Color::WHITE ? -8 : +8));
static_cast<square::Square>(this->target() + (color == color::Color::WHITE ? -8 : +8));
const piece::Type piece = board.get_square_piece_type(source);
@@ -83,8 +83,7 @@ bool Move::make(Board &board) const {
}
}
board.and_castle(castling_rights[to_underlying(this->source())] &
castling_rights[to_underlying(this->target())]);
board.and_castle(castling_rights[this->source()] & castling_rights[this->target()]);
if (!board.is_check()) {
board.switch_side();
diff --git a/src/move/move.hpp b/src/move/move.hpp
@@ -29,7 +29,7 @@ struct Move {
Move() : source_i(0), target_i(0), flags_i(0) {}
Move(square::Square source, square::Square target, Flag flags)
: source_i(to_underlying(source)), target_i(to_underlying(target)), flags_i(flags) {}
: source_i(source), target_i(target), flags_i(flags) {}
friend bool operator==(const Move a, const Move b) {
return a.source_i == b.source_i && a.target_i == b.target_i && a.flags_i == b.flags_i;
diff --git a/src/move/movelist.cpp b/src/move/movelist.cpp
@@ -63,7 +63,7 @@ void MoveList::generate(const Board &board, bool attacks_only) {
}
// All piece move
for (const piece::Type type : ++piece::TypeIter()) {
for (piece::Type type = piece::KNIGHT; type <= piece::KING; ++type) {
U64 bitboard = board.get_bitboard_piece(type, color);
bitboard_for_each_bit(src_i, bitboard) {
const auto src = static_cast<square::Square>(src_i);
@@ -85,12 +85,12 @@ void MoveList::generate(const Board &board, bool attacks_only) {
// Castling
if (color == color::WHITE) {
if (!board.is_square_attacked(square::e1, color::BLACK)) {
if (board.get_castle() & to_underlying(Board::Castle::WK)) {
if (board.get_castle() & 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.emplace_back(square::e1, square::g1, Move::CASTLEK);
}
if (board.get_castle() & to_underlying(Board::Castle::WQ)) {
if (board.get_castle() & 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) &&
@@ -100,12 +100,12 @@ void MoveList::generate(const Board &board, bool attacks_only) {
}
} else {
if (!board.is_square_attacked(square::e8, color::WHITE)) {
if (board.get_castle() & to_underlying(Board::Castle::BK)) {
if (board.get_castle() & 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.emplace_back(square::Square::e8, square::Square::g8, Move::CASTLEK);
}
if (board.get_castle() & to_underlying(Board::Castle::BQ)) {
if (board.get_castle() & 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) &&
diff --git a/src/piece/piece.hpp b/src/piece/piece.hpp
@@ -18,7 +18,8 @@ enum Type {
KING,
NONE = 7,
};
typedef Iterator<Type, Type::PAWN, Type::KING> TypeIter;
ENABLE_INCR_OPERATORS_ON(Type)
struct Piece {
const uint8_t index;
@@ -68,7 +69,7 @@ inline constexpr const U64 get_index(const Type type, const color::Color color)
inline constexpr const Piece &get_from_code(const char code) {
color::Color color = isupper(code) ? color::WHITE : color::BLACK;
for (Type type : TypeIter()) {
for (Type type = PAWN; type <= KING; ++type) {
const Piece &piece = get(type, color);
if (piece.code == code) return piece;
}
diff --git a/src/utils/bitboard.cpp b/src/utils/bitboard.cpp
@@ -4,6 +4,7 @@
#include <iostream>
namespace bitboard {
void print(U64 bitboard) {
for (int rank = 0; rank < 8; rank++) {
for (int file = 0; file < 8; file++) {
@@ -17,4 +18,5 @@ void print(U64 bitboard) {
std::cout << "\n A B C D E F G H\n\n";
std::cout << " Bitboard: " << std::hex << bitboard << std::dec << std::endl;
}
} // namespace bitboard
diff --git a/src/utils/bitboard.hpp b/src/utils/bitboard.hpp
@@ -1,6 +1,7 @@
#ifndef STELLAR_BITBOARD_H
#define STELLAR_BITBOARD_H
#include "square.hpp"
#include "utils.hpp"
namespace bitboard {
diff --git a/src/utils/square.hpp b/src/utils/square.hpp
@@ -6,7 +6,7 @@
namespace square {
enum Square {
enum Square : int {
// clang-format off
a1, b1, c1, d1, e1, f1, g1, h1,
a2, b2, c2, d2, e2, f2, g2, h2,
@@ -19,7 +19,7 @@ enum Square {
// clang-format on
};
typedef Iterator<Square, Square::a1, Square::h8> Iter;
ENABLE_INCR_OPERATORS_ON(Square)
inline constexpr const Square mirror_array[]{
// clang-format off
@@ -47,13 +47,10 @@ inline constexpr const char *coordinates_array[] = {
// clang-format on
};
inline constexpr const uint8_t file(const Square square) { return to_underlying(square) & 0x07; }
inline constexpr const uint8_t rank(const Square square) { return to_underlying(square) >> 3; }
inline constexpr const uint8_t file(const Square square) { return square & 0x07; }
inline constexpr const uint8_t rank(const Square square) { return square >> 3; }
inline constexpr const Square mirror(const Square square) { return mirror_array[square]; }
inline constexpr const std::string to_coordinates(const Square square) {
return coordinates_array[to_underlying(square)];
}
inline constexpr const std::string to_coordinates(const Square square) { return coordinates_array[square]; }
inline const Square from_coordinates(const std::string &cord) {
return static_cast<Square>((cord[1] - '1') * 8 + (cord[0] - 'a'));
diff --git a/src/utils/utils.hpp b/src/utils/utils.hpp
@@ -9,31 +9,8 @@
typedef uint64_t U64;
typedef uint32_t U32;
#include <type_traits>
template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept {
return static_cast<typename std::underlying_type<E>::type>(e);
}
template <typename C, C beginVal, C endVal> class Iterator {
typedef typename std::underlying_type<C>::type val_t;
int val;
public:
constexpr Iterator(const C &f) : val(static_cast<val_t>(f)) {}
constexpr Iterator() : val(static_cast<val_t>(beginVal)) {}
constexpr Iterator operator++() {
++val;
return *this;
}
constexpr C operator*() { return static_cast<C>(val); }
constexpr Iterator begin() { return *this; }
constexpr Iterator end() {
// static const Iterator endIter = ++Iterator(endVal);
// return endIter;
return ++Iterator(endVal);
}
constexpr bool operator!=(const Iterator &i) { return val != i.val; }
};
#define ENABLE_INCR_OPERATORS_ON(T) \
inline T &operator++(T &d) { return d = T(int(d) + 1); } \
inline T &operator--(T &d) { return d = T(int(d) - 1); }
#endif