diff --git a/src/board/bitboard/attacks.hpp b/src/board/bitboard/attacks.hpp index 65bd3e8..02e357f 100644 --- a/src/board/bitboard/attacks.hpp +++ b/src/board/bitboard/attacks.hpp @@ -151,7 +151,7 @@ inline constexpr std::array black_pawn_attacks /// @brief Pre-calculated lookup table for pawn attacks inline constexpr utils::mdarray - pawn_attacks = {white_pawn_attacks, black_pawn_attacks}; + pawn_attacks = {{{{white_pawn_attacks}, {black_pawn_attacks}}}}; /// @brief Pre-calculated lookup table for knight attacks inline constexpr std::array knight_attacks = { diff --git a/src/main.cpp b/src/main.cpp index 5927f28..2513da9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,7 +9,7 @@ int main(const int argc, const char *argv[]) { board::bitboards::attacks::init(); if (argc > 1 && !strcmp(argv[1], "bench")) { - constexpr int bench_depth = 8; + constexpr int bench_depth = 11; search::searcher searcher; search::bench::run(searcher, bench_depth); diff --git a/src/search/bench.cpp b/src/search/bench.cpp index 92715a0..b832510 100644 --- a/src/search/bench.cpp +++ b/src/search/bench.cpp @@ -29,5 +29,8 @@ void search::bench::run(searcher& searcher, const u32 depth) { const auto seconds = elapsed / 1000; std::cout << std::format("\ninfo string {} seconds", seconds) << std::endl; - std::cout << std::format("{} nodes {} nps", total_nodes, total_nodes / seconds) << std::endl; + std::cout << std::format( + "{} nodes {} nps", total_nodes, + static_cast(static_cast(total_nodes) / static_cast(seconds))) + << std::endl; } diff --git a/src/search/search.cpp b/src/search/search.cpp index 2381741..7b78534 100644 --- a/src/search/search.cpp +++ b/src/search/search.cpp @@ -1,5 +1,6 @@ #include "search.hpp" +#include #include #include @@ -7,6 +8,7 @@ #include "../eval/eval.hpp" #include "../moves/movegen.hpp" +#include "../utils/mdarray.hpp" #include "../utils/time.hpp" namespace search { @@ -18,6 +20,25 @@ constexpr int rfp_margin = 70; constexpr int nmp_base_reduction = 3; +constexpr auto lmr_quiet_factor = 1.00; +constexpr auto lmr_quiet_divisor = 2.00; + +static const auto lmr_table = [] { + utils::mdarray lmr_table; + + for (int i = 1; i < constants::max_depth; ++i) { + for (int j = 1; j < constants::max_moves; ++j) { + lmr_table[i, j] = + static_cast(lmr_quiet_factor + std::log(i) * std::log(j) / lmr_quiet_divisor); + } + } + + return lmr_table; +}(); + +constexpr int lmr_min_depth = 2; +constexpr int lmr_move_threshold = 3; + } // namespace heuristics void searcher::reset() { @@ -264,16 +285,33 @@ score searcher::negamax(const board::position& pos, score current_score; + // Search the first move with a full window if (legal_moves == 1) - // Search the first move with a full window current_score = -negamax(copy, -beta, -alpha, depth - 1, ply + 1, child_pv); else { - // Do a null window search to see if we find a better move - current_score = -negamax(copy, -alpha - 1, -alpha, depth - 1, ply + 1, child_pv); - + // Apply LMR: Search moves that are late in move ordering with reduced depth + const auto reduction = depth > heuristics::lmr_min_depth + && legal_moves > heuristics::lmr_move_threshold + && current_move.is_quiet() + ? heuristics::lmr_table[depth, legal_moves] + : 0; + + // Ensure the reduced depth is not negative + const auto new_depth = depth - 1; + const auto reduced_depth = std::clamp(new_depth - reduction, 0, new_depth); + + // Perform a null window search at reduced depth + current_score = + -negamax(copy, -alpha - 1, -alpha, reduced_depth, ply + 1, child_pv); + + // Full depth search + if (current_score > alpha && reduced_depth < new_depth) + current_score = + -negamax(copy, -alpha - 1, -alpha, new_depth, ply + 1, child_pv); + + // If we found a better move, do a full window search if (current_score > alpha && pv_node) - // If we found a better move, do a full re-search - current_score = -negamax(copy, -beta, -alpha, depth - 1, ply + 1, child_pv); + current_score = -negamax(copy, -beta, -alpha, new_depth, ply + 1, child_pv); } if (current_score > best_score) { diff --git a/src/types.hpp b/src/types.hpp index 603b687..2830175 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -2,7 +2,6 @@ #include #include - using u8 = std::uint8_t; using u16 = std::uint16_t; using u32 = std::uint32_t;