mirror of
https://github.com/opelly27/Stockfish.git
synced 2026-05-20 08:37:44 +00:00
Move extract_pv_from_tt() and insert_pv_in_tt() under RootMove
Functional change only due to additional do/undo move but absolutly harmless. Also handle re-insertion in tt of PV lines also for multi PV case.
This commit is contained in:
+104
-92
@@ -127,33 +127,15 @@ namespace {
|
|||||||
: non_pv_score < m.non_pv_score;
|
: non_pv_score < m.non_pv_score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void extract_pv_from_tt(Position& pos);
|
||||||
|
void insert_pv_in_tt(Position& pos);
|
||||||
|
|
||||||
int64_t nodes;
|
int64_t nodes;
|
||||||
Value pv_score;
|
Value pv_score;
|
||||||
Value non_pv_score;
|
Value non_pv_score;
|
||||||
Move pv[PLY_MAX_PLUS_2];
|
Move pv[PLY_MAX_PLUS_2];
|
||||||
};
|
};
|
||||||
|
|
||||||
RootMove::RootMove() {
|
|
||||||
|
|
||||||
nodes = 0;
|
|
||||||
pv_score = non_pv_score = -VALUE_INFINITE;
|
|
||||||
pv[0] = MOVE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
RootMove& RootMove::operator=(const RootMove& rm) {
|
|
||||||
|
|
||||||
const Move* src = rm.pv;
|
|
||||||
Move* dst = pv;
|
|
||||||
|
|
||||||
// Avoid a costly full rm.pv[] copy
|
|
||||||
do *dst++ = *src; while (*src++ != MOVE_NONE);
|
|
||||||
|
|
||||||
nodes = rm.nodes;
|
|
||||||
pv_score = rm.pv_score;
|
|
||||||
non_pv_score = rm.non_pv_score;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// RootMoveList struct is essentially a std::vector<> of RootMove objects,
|
// RootMoveList struct is essentially a std::vector<> of RootMove objects,
|
||||||
// with an handful of methods above the standard ones.
|
// with an handful of methods above the standard ones.
|
||||||
@@ -293,7 +275,7 @@ namespace {
|
|||||||
/// Local functions
|
/// Local functions
|
||||||
|
|
||||||
Value id_loop(Position& pos, Move searchMoves[]);
|
Value id_loop(Position& pos, Move searchMoves[]);
|
||||||
Value root_search(Position& pos, SearchStack* ss, RootMoveList& rml, Value* alphaPtr, Value* betaPtr);
|
Value root_search(Position& pos, SearchStack* ss, Value* alphaPtr, Value* betaPtr, Depth depth, RootMoveList& rml);
|
||||||
|
|
||||||
template <NodeType PvNode, bool SpNode>
|
template <NodeType PvNode, bool SpNode>
|
||||||
Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply);
|
Value search(Position& pos, SearchStack* ss, Value alpha, Value beta, Depth depth, int ply);
|
||||||
@@ -331,8 +313,6 @@ namespace {
|
|||||||
void wait_for_stop_or_ponderhit();
|
void wait_for_stop_or_ponderhit();
|
||||||
void init_ss_array(SearchStack* ss, int size);
|
void init_ss_array(SearchStack* ss, int size);
|
||||||
void print_pv_info(const Position& pos, Move pv[], Value alpha, Value beta, Value value);
|
void print_pv_info(const Position& pos, Move pv[], Value alpha, Value beta, Value value);
|
||||||
void insert_pv_in_tt(const Position& pos, Move pv[]);
|
|
||||||
void extract_pv_from_tt(const Position& pos, Move bestMove, Move pv[]);
|
|
||||||
|
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
void* init_thread(void* threadID);
|
void* init_thread(void* threadID);
|
||||||
@@ -533,6 +513,7 @@ namespace {
|
|||||||
Value id_loop(Position& pos, Move searchMoves[]) {
|
Value id_loop(Position& pos, Move searchMoves[]) {
|
||||||
|
|
||||||
SearchStack ss[PLY_MAX_PLUS_2];
|
SearchStack ss[PLY_MAX_PLUS_2];
|
||||||
|
Depth depth;
|
||||||
Move EasyMove = MOVE_NONE;
|
Move EasyMove = MOVE_NONE;
|
||||||
Value value, alpha = -VALUE_INFINITE, beta = VALUE_INFINITE;
|
Value value, alpha = -VALUE_INFINITE, beta = VALUE_INFINITE;
|
||||||
|
|
||||||
@@ -593,8 +574,11 @@ namespace {
|
|||||||
beta = Min(ValueByIteration[Iteration - 1] + AspirationDelta, VALUE_INFINITE);
|
beta = Min(ValueByIteration[Iteration - 1] + AspirationDelta, VALUE_INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search to the current depth, rml is updated and sorted, alpha and beta could change
|
// Search to the current depth, rml is updated and sorted,
|
||||||
value = root_search(pos, ss, rml, &alpha, &beta);
|
// alpha and beta could change.
|
||||||
|
depth = (Iteration - 2) * ONE_PLY + InitialDepth;
|
||||||
|
|
||||||
|
value = root_search(pos, ss, &alpha, &beta, depth, rml);
|
||||||
|
|
||||||
if (AbortSearch)
|
if (AbortSearch)
|
||||||
break; // Value cannot be trusted. Break out immediately!
|
break; // Value cannot be trusted. Break out immediately!
|
||||||
@@ -700,13 +684,13 @@ namespace {
|
|||||||
// scheme, prints some information to the standard output and handles
|
// scheme, prints some information to the standard output and handles
|
||||||
// the fail low/high loops.
|
// the fail low/high loops.
|
||||||
|
|
||||||
Value root_search(Position& pos, SearchStack* ss, RootMoveList& rml, Value* alphaPtr, Value* betaPtr) {
|
Value root_search(Position& pos, SearchStack* ss, Value* alphaPtr,
|
||||||
|
Value* betaPtr, Depth depth, RootMoveList& rml) {
|
||||||
StateInfo st;
|
StateInfo st;
|
||||||
CheckInfo ci(pos);
|
CheckInfo ci(pos);
|
||||||
int64_t nodes;
|
int64_t nodes;
|
||||||
Move move;
|
Move move;
|
||||||
Depth depth, ext, newDepth;
|
Depth ext, newDepth;
|
||||||
Value value, alpha, beta;
|
Value value, alpha, beta;
|
||||||
bool isCheck, moveIsCheck, captureOrPromotion, dangerous;
|
bool isCheck, moveIsCheck, captureOrPromotion, dangerous;
|
||||||
int researchCountFH, researchCountFL;
|
int researchCountFH, researchCountFL;
|
||||||
@@ -715,7 +699,6 @@ namespace {
|
|||||||
alpha = *alphaPtr;
|
alpha = *alphaPtr;
|
||||||
beta = *betaPtr;
|
beta = *betaPtr;
|
||||||
isCheck = pos.is_check();
|
isCheck = pos.is_check();
|
||||||
depth = (Iteration - 2) * ONE_PLY + InitialDepth;
|
|
||||||
|
|
||||||
// Step 1. Initialize node (polling is omitted at root)
|
// Step 1. Initialize node (polling is omitted at root)
|
||||||
ss->currentMove = ss->bestMove = MOVE_NONE;
|
ss->currentMove = ss->bestMove = MOVE_NONE;
|
||||||
@@ -836,9 +819,9 @@ namespace {
|
|||||||
|
|
||||||
// We are failing high and going to do a research. It's important to update
|
// We are failing high and going to do a research. It's important to update
|
||||||
// the score before research in case we run out of time while researching.
|
// the score before research in case we run out of time while researching.
|
||||||
rml[i].pv_score = value;
|
|
||||||
ss->bestMove = move;
|
ss->bestMove = move;
|
||||||
extract_pv_from_tt(pos, move, rml[i].pv);
|
rml[i].pv_score = value;
|
||||||
|
rml[i].extract_pv_from_tt(pos);
|
||||||
|
|
||||||
// Print information to the standard output
|
// Print information to the standard output
|
||||||
print_pv_info(pos, rml[i].pv, alpha, beta, value);
|
print_pv_info(pos, rml[i].pv, alpha, beta, value);
|
||||||
@@ -871,9 +854,9 @@ namespace {
|
|||||||
// PV move or new best move!
|
// PV move or new best move!
|
||||||
|
|
||||||
// Update PV
|
// Update PV
|
||||||
rml[i].pv_score = value;
|
|
||||||
ss->bestMove = move;
|
ss->bestMove = move;
|
||||||
extract_pv_from_tt(pos, move, rml[i].pv);
|
rml[i].pv_score = value;
|
||||||
|
rml[i].extract_pv_from_tt(pos);
|
||||||
|
|
||||||
if (MultiPV == 1)
|
if (MultiPV == 1)
|
||||||
{
|
{
|
||||||
@@ -933,9 +916,10 @@ namespace {
|
|||||||
// Sort the moves before to return
|
// Sort the moves before to return
|
||||||
rml.sort();
|
rml.sort();
|
||||||
|
|
||||||
// Write PV to transposition table, in case the relevant entries have
|
// Write PV lines to transposition table, in case the relevant entries
|
||||||
// been overwritten during the search.
|
// have been overwritten during the search.
|
||||||
insert_pv_in_tt(pos, rml[0].pv);
|
for (int i = 0; i < MultiPV; i++)
|
||||||
|
rml[i].insert_pv_in_tt(pos);
|
||||||
|
|
||||||
return alpha;
|
return alpha;
|
||||||
}
|
}
|
||||||
@@ -2159,60 +2143,6 @@ split_point_start: // At split points actual search starts from here
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// insert_pv_in_tt() is called at the end of a search iteration, and inserts
|
|
||||||
// the PV back into the TT. This makes sure the old PV moves are searched
|
|
||||||
// first, even if the old TT entries have been overwritten.
|
|
||||||
|
|
||||||
void insert_pv_in_tt(const Position& pos, Move pv[]) {
|
|
||||||
|
|
||||||
StateInfo st;
|
|
||||||
TTEntry* tte;
|
|
||||||
Position p(pos, pos.thread());
|
|
||||||
Value v, m = VALUE_NONE;
|
|
||||||
|
|
||||||
for (int i = 0; pv[i] != MOVE_NONE; i++)
|
|
||||||
{
|
|
||||||
tte = TT.retrieve(p.get_key());
|
|
||||||
if (!tte || tte->move() != pv[i])
|
|
||||||
{
|
|
||||||
v = (p.is_check() ? VALUE_NONE : evaluate(p, m));
|
|
||||||
TT.store(p.get_key(), VALUE_NONE, VALUE_TYPE_NONE, DEPTH_NONE, pv[i], v, m);
|
|
||||||
}
|
|
||||||
p.do_move(pv[i], st);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// extract_pv_from_tt() builds a PV by adding moves from the transposition table.
|
|
||||||
// We consider also failing high nodes and not only VALUE_TYPE_EXACT nodes. This
|
|
||||||
// allow to always have a ponder move even when we fail high at root and also a
|
|
||||||
// long PV to print that is important for position analysis.
|
|
||||||
|
|
||||||
void extract_pv_from_tt(const Position& pos, Move bestMove, Move pv[]) {
|
|
||||||
|
|
||||||
StateInfo st;
|
|
||||||
TTEntry* tte;
|
|
||||||
Position p(pos, pos.thread());
|
|
||||||
int ply = 0;
|
|
||||||
|
|
||||||
assert(bestMove != MOVE_NONE);
|
|
||||||
|
|
||||||
pv[ply] = bestMove;
|
|
||||||
p.do_move(pv[ply++], st);
|
|
||||||
|
|
||||||
while ( (tte = TT.retrieve(p.get_key())) != NULL
|
|
||||||
&& tte->move() != MOVE_NONE
|
|
||||||
&& move_is_legal(p, tte->move())
|
|
||||||
&& ply < PLY_MAX
|
|
||||||
&& (!p.is_draw() || ply < 2))
|
|
||||||
{
|
|
||||||
pv[ply] = tte->move();
|
|
||||||
p.do_move(pv[ply++], st);
|
|
||||||
}
|
|
||||||
pv[ply] = MOVE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// init_thread() is the function which is called when a new thread is
|
// init_thread() is the function which is called when a new thread is
|
||||||
// launched. It simply calls the idle_loop() function with the supplied
|
// launched. It simply calls the idle_loop() function with the supplied
|
||||||
// threadID. There are two versions of this function; one for POSIX
|
// threadID. There are two versions of this function; one for POSIX
|
||||||
@@ -2640,7 +2570,89 @@ split_point_start: // At split points actual search starts from here
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// The RootMoveList class
|
/// RootMove and RootMoveList method's definitions
|
||||||
|
|
||||||
|
RootMove::RootMove() {
|
||||||
|
|
||||||
|
nodes = 0;
|
||||||
|
pv_score = non_pv_score = -VALUE_INFINITE;
|
||||||
|
pv[0] = MOVE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RootMove& RootMove::operator=(const RootMove& rm) {
|
||||||
|
|
||||||
|
const Move* src = rm.pv;
|
||||||
|
Move* dst = pv;
|
||||||
|
|
||||||
|
// Avoid a costly full rm.pv[] copy
|
||||||
|
do *dst++ = *src; while (*src++ != MOVE_NONE);
|
||||||
|
|
||||||
|
nodes = rm.nodes;
|
||||||
|
pv_score = rm.pv_score;
|
||||||
|
non_pv_score = rm.non_pv_score;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract_pv_from_tt() builds a PV by adding moves from the transposition table.
|
||||||
|
// We consider also failing high nodes and not only VALUE_TYPE_EXACT nodes. This
|
||||||
|
// allow to always have a ponder move even when we fail high at root and also a
|
||||||
|
// long PV to print that is important for position analysis.
|
||||||
|
|
||||||
|
void RootMove::extract_pv_from_tt(Position& pos) {
|
||||||
|
|
||||||
|
StateInfo state[PLY_MAX_PLUS_2], *st = state;
|
||||||
|
TTEntry* tte;
|
||||||
|
int ply = 1;
|
||||||
|
|
||||||
|
assert(pv[0] != MOVE_NONE && move_is_legal(pos, pv[0]));
|
||||||
|
|
||||||
|
pos.do_move(pv[0], *st++);
|
||||||
|
|
||||||
|
while ( (tte = TT.retrieve(pos.get_key())) != NULL
|
||||||
|
&& tte->move() != MOVE_NONE
|
||||||
|
&& move_is_legal(pos, tte->move())
|
||||||
|
&& ply < PLY_MAX
|
||||||
|
&& (!pos.is_draw() || ply < 2))
|
||||||
|
{
|
||||||
|
pv[ply] = tte->move();
|
||||||
|
pos.do_move(pv[ply++], *st++);
|
||||||
|
}
|
||||||
|
pv[ply] = MOVE_NONE;
|
||||||
|
|
||||||
|
do pos.undo_move(pv[--ply]); while (ply);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert_pv_in_tt() is called at the end of a search iteration, and inserts
|
||||||
|
// the PV back into the TT. This makes sure the old PV moves are searched
|
||||||
|
// first, even if the old TT entries have been overwritten.
|
||||||
|
|
||||||
|
void RootMove::insert_pv_in_tt(Position& pos) {
|
||||||
|
|
||||||
|
StateInfo state[PLY_MAX_PLUS_2], *st = state;
|
||||||
|
TTEntry* tte;
|
||||||
|
Key k;
|
||||||
|
Value v, m = VALUE_NONE;
|
||||||
|
int ply = 0;
|
||||||
|
|
||||||
|
assert(pv[0] != MOVE_NONE && move_is_legal(pos, pv[0]));
|
||||||
|
|
||||||
|
do {
|
||||||
|
k = pos.get_key();
|
||||||
|
tte = TT.retrieve(k);
|
||||||
|
|
||||||
|
// Don't overwrite exsisting correct entries
|
||||||
|
if (!tte || tte->move() != pv[ply])
|
||||||
|
{
|
||||||
|
v = (pos.is_check() ? VALUE_NONE : evaluate(pos, m));
|
||||||
|
TT.store(k, VALUE_NONE, VALUE_TYPE_NONE, DEPTH_NONE, pv[ply], v, m);
|
||||||
|
}
|
||||||
|
pos.do_move(pv[ply], *st++);
|
||||||
|
|
||||||
|
} while (pv[++ply] != MOVE_NONE);
|
||||||
|
|
||||||
|
do pos.undo_move(pv[--ply]); while (ply);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RootMoveList::RootMoveList(Position& pos, Move searchMoves[]) {
|
RootMoveList::RootMoveList(Position& pos, Move searchMoves[]) {
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@
|
|||||||
////
|
////
|
||||||
|
|
||||||
const int PLY_MAX = 100;
|
const int PLY_MAX = 100;
|
||||||
const int PLY_MAX_PLUS_2 = 102;
|
const int PLY_MAX_PLUS_2 = PLY_MAX + 2;
|
||||||
|
|
||||||
|
|
||||||
////
|
////
|
||||||
|
|||||||
Reference in New Issue
Block a user