mirror of
https://github.com/sockspls/badfish
synced 2025-04-29 16:23:09 +00:00
Remove global TB variables from search.cpp
Follow up cleanup of #4968, removes the global variables from search and instead uses a dedicated tb config struct. closes https://github.com/official-stockfish/Stockfish/pull/4982 No functional change
This commit is contained in:
parent
32e46fc47f
commit
a5675f19d8
6 changed files with 89 additions and 75 deletions
|
@ -44,15 +44,13 @@ Bitboard BishopTable[0x1480]; // To store bishop attacks
|
||||||
|
|
||||||
void init_magics(PieceType pt, Bitboard table[], Magic magics[]);
|
void init_magics(PieceType pt, Bitboard table[], Magic magics[]);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the bitboard of target square for the given step
|
// Returns the bitboard of target square for the given step
|
||||||
// from the given square. If the step is off the board, returns empty bitboard.
|
// from the given square. If the step is off the board, returns empty bitboard.
|
||||||
inline Bitboard safe_destination(Square s, int step) {
|
Bitboard safe_destination(Square s, int step) {
|
||||||
Square to = Square(s + step);
|
Square to = Square(s + step);
|
||||||
return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
|
return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns an ASCII representation of a bitboard suitable
|
// Returns an ASCII representation of a bitboard suitable
|
||||||
// to be printed to standard output. Useful for debugging.
|
// to be printed to standard output. Useful for debugging.
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "bitboard.h"
|
|
||||||
#include "evaluate.h"
|
#include "evaluate.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "movegen.h"
|
#include "movegen.h"
|
||||||
|
@ -46,14 +45,6 @@
|
||||||
|
|
||||||
namespace Stockfish {
|
namespace Stockfish {
|
||||||
|
|
||||||
namespace Tablebases {
|
|
||||||
|
|
||||||
int Cardinality;
|
|
||||||
bool RootInTB;
|
|
||||||
bool UseRule50;
|
|
||||||
Depth ProbeDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace TB = Tablebases;
|
namespace TB = Tablebases;
|
||||||
|
|
||||||
using Eval::evaluate;
|
using Eval::evaluate;
|
||||||
|
@ -237,7 +228,7 @@ void Search::Worker::start_searching() {
|
||||||
if (bestThread != this)
|
if (bestThread != this)
|
||||||
sync_cout << UCI::pv(*bestThread, main_manager()->tm.elapsed(threads.nodes_searched()),
|
sync_cout << UCI::pv(*bestThread, main_manager()->tm.elapsed(threads.nodes_searched()),
|
||||||
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
|
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
|
||||||
TB::RootInTB)
|
tbConfig.rootInTB)
|
||||||
<< sync_endl;
|
<< sync_endl;
|
||||||
|
|
||||||
sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0], rootPos.is_chess960());
|
sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0], rootPos.is_chess960());
|
||||||
|
@ -379,7 +370,7 @@ void Search::Worker::iterative_deepening() {
|
||||||
&& mainThread->tm.elapsed(threads.nodes_searched()) > 3000)
|
&& mainThread->tm.elapsed(threads.nodes_searched()) > 3000)
|
||||||
sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()),
|
sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()),
|
||||||
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
|
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
|
||||||
TB::RootInTB)
|
tbConfig.rootInTB)
|
||||||
<< sync_endl;
|
<< sync_endl;
|
||||||
|
|
||||||
// In case of failing low/high increase aspiration window and
|
// In case of failing low/high increase aspiration window and
|
||||||
|
@ -414,7 +405,7 @@ void Search::Worker::iterative_deepening() {
|
||||||
|| mainThread->tm.elapsed(threads.nodes_searched()) > 3000))
|
|| mainThread->tm.elapsed(threads.nodes_searched()) > 3000))
|
||||||
sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()),
|
sync_cout << UCI::pv(*this, mainThread->tm.elapsed(threads.nodes_searched()),
|
||||||
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
|
threads.nodes_searched(), threads.tb_hits(), tt.hashfull(),
|
||||||
TB::RootInTB)
|
tbConfig.rootInTB)
|
||||||
<< sync_endl;
|
<< sync_endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,13 +650,13 @@ Value Search::Worker::search(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 5. Tablebases probe
|
// Step 5. Tablebases probe
|
||||||
if (!rootNode && !excludedMove && TB::Cardinality)
|
if (!rootNode && !excludedMove && tbConfig.cardinality)
|
||||||
{
|
{
|
||||||
int piecesCount = pos.count<ALL_PIECES>();
|
int piecesCount = pos.count<ALL_PIECES>();
|
||||||
|
|
||||||
if (piecesCount <= TB::Cardinality
|
if (piecesCount <= tbConfig.cardinality
|
||||||
&& (piecesCount < TB::Cardinality || depth >= TB::ProbeDepth) && pos.rule50_count() == 0
|
&& (piecesCount < tbConfig.cardinality || depth >= tbConfig.probeDepth)
|
||||||
&& !pos.can_castle(ANY_CASTLING))
|
&& pos.rule50_count() == 0 && !pos.can_castle(ANY_CASTLING))
|
||||||
{
|
{
|
||||||
TB::ProbeState err;
|
TB::ProbeState err;
|
||||||
TB::WDLScore wdl = Tablebases::probe_wdl(pos, &err);
|
TB::WDLScore wdl = Tablebases::probe_wdl(pos, &err);
|
||||||
|
@ -678,7 +669,7 @@ Value Search::Worker::search(
|
||||||
{
|
{
|
||||||
thisThread->tbHits.fetch_add(1, std::memory_order_relaxed);
|
thisThread->tbHits.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
|
||||||
int drawScore = TB::UseRule50 ? 1 : 0;
|
int drawScore = tbConfig.useRule50 ? 1 : 0;
|
||||||
|
|
||||||
Value tbValue = VALUE_TB - ss->ply;
|
Value tbValue = VALUE_TB - ss->ply;
|
||||||
|
|
||||||
|
@ -1962,53 +1953,5 @@ bool RootMove::extract_ponder_from_tt(const TranspositionTable& tt, Position& po
|
||||||
return pv.size() > 1;
|
return pv.size() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tablebases::rank_root_moves(const OptionsMap& options,
|
|
||||||
Position& pos,
|
|
||||||
Search::RootMoves& rootMoves) {
|
|
||||||
|
|
||||||
RootInTB = false;
|
|
||||||
UseRule50 = bool(options["Syzygy50MoveRule"]);
|
|
||||||
ProbeDepth = int(options["SyzygyProbeDepth"]);
|
|
||||||
Cardinality = int(options["SyzygyProbeLimit"]);
|
|
||||||
bool dtz_available = true;
|
|
||||||
|
|
||||||
// Tables with fewer pieces than SyzygyProbeLimit are searched with
|
|
||||||
// ProbeDepth == DEPTH_ZERO
|
|
||||||
if (Cardinality > MaxCardinality)
|
|
||||||
{
|
|
||||||
Cardinality = MaxCardinality;
|
|
||||||
ProbeDepth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Cardinality >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING))
|
|
||||||
{
|
|
||||||
// Rank moves using DTZ tables
|
|
||||||
RootInTB = root_probe(pos, rootMoves, options["Syzygy50MoveRule"]);
|
|
||||||
|
|
||||||
if (!RootInTB)
|
|
||||||
{
|
|
||||||
// DTZ tables are missing; try to rank moves using WDL tables
|
|
||||||
dtz_available = false;
|
|
||||||
RootInTB = root_probe_wdl(pos, rootMoves, options["Syzygy50MoveRule"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RootInTB)
|
|
||||||
{
|
|
||||||
// Sort moves according to TB rank
|
|
||||||
std::stable_sort(rootMoves.begin(), rootMoves.end(),
|
|
||||||
[](const RootMove& a, const RootMove& b) { return a.tbRank > b.tbRank; });
|
|
||||||
|
|
||||||
// Probe during search only if DTZ is not available and we are winning
|
|
||||||
if (dtz_available || rootMoves[0].tbScore <= VALUE_DRAW)
|
|
||||||
Cardinality = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Clean up if root_probe() and root_probe_wdl() have failed
|
|
||||||
for (auto& m : rootMoves)
|
|
||||||
m.tbRank = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Stockfish
|
} // namespace Stockfish
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "movepick.h"
|
#include "movepick.h"
|
||||||
#include "position.h"
|
#include "position.h"
|
||||||
|
#include "syzygy/tbprobe.h"
|
||||||
#include "timeman.h"
|
#include "timeman.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
|
@ -48,7 +49,6 @@ class UCI;
|
||||||
|
|
||||||
namespace Search {
|
namespace Search {
|
||||||
|
|
||||||
|
|
||||||
// Stack struct keeps track of the information we need to remember from nodes
|
// Stack struct keeps track of the information we need to remember from nodes
|
||||||
// shallower and deeper in the tree during the search. Each search thread has
|
// shallower and deeper in the tree during the search. Each search thread has
|
||||||
// its own array of Stack objects, indexed by the current ply.
|
// its own array of Stack objects, indexed by the current ply.
|
||||||
|
@ -238,6 +238,8 @@ class Worker {
|
||||||
// The main thread has a SearchManager, the others have a NullSearchManager
|
// The main thread has a SearchManager, the others have a NullSearchManager
|
||||||
std::unique_ptr<ISearchManager> manager;
|
std::unique_ptr<ISearchManager> manager;
|
||||||
|
|
||||||
|
Tablebases::Config tbConfig;
|
||||||
|
|
||||||
const OptionsMap& options;
|
const OptionsMap& options;
|
||||||
ThreadPool& threads;
|
ThreadPool& threads;
|
||||||
TranspositionTable& tt;
|
TranspositionTable& tt;
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
#include "tbprobe.h"
|
#include "tbprobe.h"
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -32,6 +31,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -42,6 +42,7 @@
|
||||||
#include "../position.h"
|
#include "../position.h"
|
||||||
#include "../search.h"
|
#include "../search.h"
|
||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
|
#include "../ucioption.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -1680,4 +1681,60 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, boo
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Config Tablebases::rank_root_moves(const OptionsMap& options,
|
||||||
|
Position& pos,
|
||||||
|
Search::RootMoves& rootMoves) {
|
||||||
|
Config config;
|
||||||
|
|
||||||
|
if (rootMoves.empty())
|
||||||
|
return config;
|
||||||
|
|
||||||
|
config.rootInTB = false;
|
||||||
|
config.useRule50 = bool(options["Syzygy50MoveRule"]);
|
||||||
|
config.probeDepth = int(options["SyzygyProbeDepth"]);
|
||||||
|
config.cardinality = int(options["SyzygyProbeLimit"]);
|
||||||
|
|
||||||
|
bool dtz_available = true;
|
||||||
|
|
||||||
|
// Tables with fewer pieces than SyzygyProbeLimit are searched with
|
||||||
|
// probeDepth == DEPTH_ZERO
|
||||||
|
if (config.cardinality > MaxCardinality)
|
||||||
|
{
|
||||||
|
config.cardinality = MaxCardinality;
|
||||||
|
config.probeDepth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.cardinality >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING))
|
||||||
|
{
|
||||||
|
// Rank moves using DTZ tables
|
||||||
|
config.rootInTB = root_probe(pos, rootMoves, options["Syzygy50MoveRule"]);
|
||||||
|
|
||||||
|
if (!config.rootInTB)
|
||||||
|
{
|
||||||
|
// DTZ tables are missing; try to rank moves using WDL tables
|
||||||
|
dtz_available = false;
|
||||||
|
config.rootInTB = root_probe_wdl(pos, rootMoves, options["Syzygy50MoveRule"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.rootInTB)
|
||||||
|
{
|
||||||
|
// Sort moves according to TB rank
|
||||||
|
std::stable_sort(
|
||||||
|
rootMoves.begin(), rootMoves.end(),
|
||||||
|
[](const Search::RootMove& a, const Search::RootMove& b) { return a.tbRank > b.tbRank; });
|
||||||
|
|
||||||
|
// Probe during search only if DTZ is not available and we are winning
|
||||||
|
if (dtz_available || rootMoves[0].tbScore <= VALUE_DRAW)
|
||||||
|
config.cardinality = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clean up if root_probe() and root_probe_wdl() have failed
|
||||||
|
for (auto& m : rootMoves)
|
||||||
|
m.tbRank = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
} // namespace Stockfish
|
} // namespace Stockfish
|
||||||
|
|
|
@ -20,16 +20,30 @@
|
||||||
#define TBPROBE_H
|
#define TBPROBE_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "../search.h"
|
|
||||||
|
|
||||||
namespace Stockfish {
|
namespace Stockfish {
|
||||||
class Position;
|
class Position;
|
||||||
class OptionsMap;
|
class OptionsMap;
|
||||||
|
|
||||||
|
using Depth = int;
|
||||||
|
|
||||||
|
namespace Search {
|
||||||
|
struct RootMove;
|
||||||
|
using RootMoves = std::vector<RootMove>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Stockfish::Tablebases {
|
namespace Stockfish::Tablebases {
|
||||||
|
|
||||||
|
struct Config {
|
||||||
|
int cardinality = 0;
|
||||||
|
bool rootInTB = false;
|
||||||
|
bool useRule50 = false;
|
||||||
|
Depth probeDepth = 0;
|
||||||
|
};
|
||||||
|
|
||||||
enum WDLScore {
|
enum WDLScore {
|
||||||
WDLLoss = -2, // Loss
|
WDLLoss = -2, // Loss
|
||||||
WDLBlessedLoss = -1, // Loss, but draw under 50-move rule
|
WDLBlessedLoss = -1, // Loss, but draw under 50-move rule
|
||||||
|
@ -54,7 +68,7 @@ WDLScore probe_wdl(Position& pos, ProbeState* result);
|
||||||
int probe_dtz(Position& pos, ProbeState* result);
|
int probe_dtz(Position& pos, ProbeState* result);
|
||||||
bool root_probe(Position& pos, Search::RootMoves& rootMoves, bool rule50);
|
bool root_probe(Position& pos, Search::RootMoves& rootMoves, bool rule50);
|
||||||
bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, bool rule50);
|
bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, bool rule50);
|
||||||
void rank_root_moves(const OptionsMap& options, Position& pos, Search::RootMoves& rootMoves);
|
Config rank_root_moves(const OptionsMap& options, Position& pos, Search::RootMoves& rootMoves);
|
||||||
|
|
||||||
} // namespace Stockfish::Tablebases
|
} // namespace Stockfish::Tablebases
|
||||||
|
|
||||||
|
|
|
@ -181,8 +181,7 @@ void ThreadPool::start_thinking(const OptionsMap& options,
|
||||||
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
|
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
|
||||||
rootMoves.emplace_back(m);
|
rootMoves.emplace_back(m);
|
||||||
|
|
||||||
if (!rootMoves.empty())
|
Tablebases::Config tbConfig = Tablebases::rank_root_moves(options, pos, rootMoves);
|
||||||
Tablebases::rank_root_moves(options, pos, rootMoves);
|
|
||||||
|
|
||||||
// After ownership transfer 'states' becomes empty, so if we stop the search
|
// After ownership transfer 'states' becomes empty, so if we stop the search
|
||||||
// and call 'go' again without setting a new position states.get() == nullptr.
|
// and call 'go' again without setting a new position states.get() == nullptr.
|
||||||
|
@ -205,6 +204,7 @@ void ThreadPool::start_thinking(const OptionsMap& options,
|
||||||
th->worker->rootMoves = rootMoves;
|
th->worker->rootMoves = rootMoves;
|
||||||
th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState);
|
th->worker->rootPos.set(pos.fen(), pos.is_chess960(), &th->worker->rootState);
|
||||||
th->worker->rootState = setupStates->back();
|
th->worker->rootState = setupStates->back();
|
||||||
|
th->worker->tbConfig = tbConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
main_thread()->start_searching();
|
main_thread()->start_searching();
|
||||||
|
|
Loading…
Add table
Reference in a new issue