Skip to content

Commit

Permalink
Explicitly pass RootMoves to TB probes
Browse files Browse the repository at this point in the history
Currently Search::RootMoves is accessed and even
modified by TB probing functions in a hidden
and sneaky way.

This is bad practice and makes the code tricky.
Instead explicily pass the vector as function
argument so to clarify that the vector is modified
inside the functions.

No functional change.
  • Loading branch information
mcostalba authored and zamar committed Dec 6, 2014
1 parent eeb6d92 commit ba14647
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 44 deletions.
10 changes: 5 additions & 5 deletions src/search.cpp
Expand Up @@ -39,7 +39,7 @@ namespace Search {

volatile SignalsType Signals;
LimitsType Limits;
std::vector<RootMove> RootMoves;
RootMoveVector RootMoves;
Position RootPos;
Time::point SearchTime;
StateStackPtr SetupStates;
Expand Down Expand Up @@ -206,9 +206,9 @@ void Search::think() {
TB::Cardinality = Options["SyzygyProbeLimit"];

// Skip TB probing when no TB found: !TBLargest -> !TB::Cardinality
if (TB::Cardinality > TB::TBLargest)
if (TB::Cardinality > TB::MaxCardinality)
{
TB::Cardinality = TB::TBLargest;
TB::Cardinality = TB::MaxCardinality;
TB::ProbeDepth = DEPTH_ZERO;
}

Expand All @@ -226,15 +226,15 @@ void Search::think() {
{
// If the current root position is in the tablebases then RootMoves
// contains only moves that preserve the draw or win.
TB::RootInTB = Tablebases::root_probe(RootPos, TB::Score);
TB::RootInTB = Tablebases::root_probe(RootPos, RootMoves, TB::Score);

if (TB::RootInTB)
TB::Cardinality = 0; // Do not probe tablebases during the search

else // If DTZ tables are missing, use WDL tables as a fallback
{
// Filter out moves that do not preserve a draw or win
TB::RootInTB = Tablebases::root_probe_wdl(RootPos, TB::Score);
TB::RootInTB = Tablebases::root_probe_wdl(RootPos, RootMoves, TB::Score);

// Only probe during search if winning
if (TB::Score <= VALUE_DRAW)
Expand Down
3 changes: 2 additions & 1 deletion src/search.h
Expand Up @@ -68,6 +68,7 @@ struct RootMove {
std::vector<Move> pv;
};

typedef std::vector<RootMove> RootMoveVector;

/// The LimitsType struct stores information sent by GUI about available time
/// to search the current move, maximum depth/time, if we are in analysis mode
Expand Down Expand Up @@ -98,7 +99,7 @@ typedef std::auto_ptr<std::stack<StateInfo> > StateStackPtr;

extern volatile SignalsType Signals;
extern LimitsType Limits;
extern std::vector<RootMove> RootMoves;
extern RootMoveVector RootMoves;
extern Position RootPos;
extern Time::point SearchTime;
extern StateStackPtr SetupStates;
Expand Down
6 changes: 3 additions & 3 deletions src/syzygy/tbcore.cpp
Expand Up @@ -223,8 +223,8 @@ static void init_tb(char *str)
entry->num += pcs[i];
entry->symmetric = (key == key2);
entry->has_pawns = (pcs[TB_WPAWN] + pcs[TB_BPAWN] > 0);
if (entry->num > Tablebases::TBLargest)
Tablebases::TBLargest = entry->num;
if (entry->num > Tablebases::MaxCardinality)
Tablebases::MaxCardinality = entry->num;

if (entry->has_pawns) {
struct TBEntry_pawn *ptr = (struct TBEntry_pawn *)entry;
Expand Down Expand Up @@ -301,7 +301,7 @@ void Tablebases::init(const std::string& path)
LOCK_INIT(TB_mutex);

TBnum_piece = TBnum_pawn = 0;
TBLargest = 0;
MaxCardinality = 0;

for (i = 0; i < (1 << TBHASHBITS); i++)
for (j = 0; j < HSHMAX; j++) {
Expand Down
64 changes: 32 additions & 32 deletions src/syzygy/tbprobe.cpp
Expand Up @@ -22,7 +22,7 @@ namespace Zobrist {
extern Key psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
}

int Tablebases::TBLargest = 0;
int Tablebases::MaxCardinality = 0;

// Given a position with 6 or fewer pieces, produce a text string
// of the form KQPvKRP, where "KQP" represents the white pieces if
Expand All @@ -32,7 +32,7 @@ static void prt_str(Position& pos, char *str, int mirror)
Color color;
PieceType pt;
int i;

color = !mirror ? WHITE : BLACK;
for (pt = KING; pt >= PAWN; --pt)
for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
Expand Down Expand Up @@ -681,7 +681,7 @@ static Value wdl_to_Value[5] = {
//
// A return value false indicates that not all probes were successful and that
// no moves were filtered out.
bool Tablebases::root_probe(Position& pos, Value& TBScore)
bool Tablebases::root_probe(Position& pos, Search::RootMoveVector& rootMoves, Value& score)
{
int success;

Expand All @@ -692,8 +692,8 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
CheckInfo ci(pos);

// Probe each move.
for (size_t i = 0; i < Search::RootMoves.size(); i++) {
Move move = Search::RootMoves[i].pv[0];
for (size_t i = 0; i < rootMoves.size(); i++) {
Move move = rootMoves[i].pv[0];
pos.do_move(move, st, ci, pos.gives_check(move, ci));
int v = 0;
if (pos.checkers() && dtz > 0) {
Expand All @@ -713,7 +713,7 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
}
pos.undo_move(move);
if (!success) return false;
Search::RootMoves[i].score = (Value)v;
rootMoves[i].score = (Value)v;
}

// Obtain 50-move counter for the root position.
Expand All @@ -729,21 +729,21 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
wdl = (-dtz + cnt50 <= 100) ? -2 : -1;

// Determine the score to report to the user.
TBScore = wdl_to_Value[wdl + 2];
score = wdl_to_Value[wdl + 2];
// If the position is winning or losing, but too few moves left, adjust the
// score to show how close it is to winning or losing.
// NOTE: int(PawnValueEg) is used as scaling factor in score_to_uci().
if (wdl == 1 && dtz <= 100)
TBScore = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
score = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
else if (wdl == -1 && dtz >= -100)
TBScore = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);
score = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);

// Now be a bit smart about filtering out moves.
size_t j = 0;
if (dtz > 0) { // winning (or 50-move rule draw)
int best = 0xffff;
for (size_t i = 0; i < Search::RootMoves.size(); i++) {
int v = Search::RootMoves[i].score;
for (size_t i = 0; i < rootMoves.size(); i++) {
int v = rootMoves[i].score;
if (v > 0 && v < best)
best = v;
}
Expand All @@ -752,33 +752,33 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
// that stay safely within the 50-move budget, if there are any.
if (!has_repeated(st.previous) && best + cnt50 <= 99)
max = 99 - cnt50;
for (size_t i = 0; i < Search::RootMoves.size(); i++) {
int v = Search::RootMoves[i].score;
for (size_t i = 0; i < rootMoves.size(); i++) {
int v = rootMoves[i].score;
if (v > 0 && v <= max)
Search::RootMoves[j++] = Search::RootMoves[i];
rootMoves[j++] = rootMoves[i];
}
} else if (dtz < 0) { // losing (or 50-move rule draw)
int best = 0;
for (size_t i = 0; i < Search::RootMoves.size(); i++) {
int v = Search::RootMoves[i].score;
for (size_t i = 0; i < rootMoves.size(); i++) {
int v = rootMoves[i].score;
if (v < best)
best = v;
}
// Try all moves, unless we approach or have a 50-move rule draw.
if (-best * 2 + cnt50 < 100)
return true;
for (size_t i = 0; i < Search::RootMoves.size(); i++) {
if (Search::RootMoves[i].score == best)
Search::RootMoves[j++] = Search::RootMoves[i];
for (size_t i = 0; i < rootMoves.size(); i++) {
if (rootMoves[i].score == best)
rootMoves[j++] = rootMoves[i];
}
} else { // drawing
// Try all moves that preserve the draw.
for (size_t i = 0; i < Search::RootMoves.size(); i++) {
if (Search::RootMoves[i].score == 0)
Search::RootMoves[j++] = Search::RootMoves[i];
for (size_t i = 0; i < rootMoves.size(); i++) {
if (rootMoves[i].score == 0)
rootMoves[j++] = rootMoves[i];
}
}
Search::RootMoves.resize(j, Search::RootMove(MOVE_NONE));
rootMoves.resize(j, Search::RootMove(MOVE_NONE));

return true;
}
Expand All @@ -788,37 +788,37 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
//
// A return value false indicates that not all probes were successful and that
// no moves were filtered out.
bool Tablebases::root_probe_wdl(Position& pos, Value& TBScore)
bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoveVector& rootMoves, Value& score)
{
int success;

int wdl = Tablebases::probe_wdl(pos, &success);
if (!success) return false;
TBScore = wdl_to_Value[wdl + 2];
score = wdl_to_Value[wdl + 2];

StateInfo st;
CheckInfo ci(pos);

int best = -2;

// Probe each move.
for (size_t i = 0; i < Search::RootMoves.size(); i++) {
Move move = Search::RootMoves[i].pv[0];
for (size_t i = 0; i < rootMoves.size(); i++) {
Move move = rootMoves[i].pv[0];
pos.do_move(move, st, ci, pos.gives_check(move, ci));
int v = -Tablebases::probe_wdl(pos, &success);
pos.undo_move(move);
if (!success) return false;
Search::RootMoves[i].score = (Value)v;
rootMoves[i].score = (Value)v;
if (v > best)
best = v;
}

size_t j = 0;
for (size_t i = 0; i < Search::RootMoves.size(); i++) {
if (Search::RootMoves[i].score == best)
Search::RootMoves[j++] = Search::RootMoves[i];
for (size_t i = 0; i < rootMoves.size(); i++) {
if (rootMoves[i].score == best)
rootMoves[j++] = rootMoves[i];
}
Search::RootMoves.resize(j, Search::RootMove(MOVE_NONE));
rootMoves.resize(j, Search::RootMove(MOVE_NONE));

return true;
}
Expand Down
8 changes: 5 additions & 3 deletions src/syzygy/tbprobe.h
@@ -1,15 +1,17 @@
#ifndef TBPROBE_H
#define TBPROBE_H

#include "../search.h"

namespace Tablebases {

extern int TBLargest;
extern int MaxCardinality;

void init(const std::string& path);
int probe_wdl(Position& pos, int *success);
int probe_dtz(Position& pos, int *success);
bool root_probe(Position& pos, Value& TBScore);
bool root_probe_wdl(Position& pos, Value& TBScore);
bool root_probe(Position& pos, Search::RootMoveVector& rootMoves, Value& score);
bool root_probe_wdl(Position& pos, Search::RootMoveVector& rootMoves, Value& score);

}

Expand Down

0 comments on commit ba14647

Please sign in to comment.