Skip to content

Commit 5488961

Browse files
committed
Reformat FastMove
Align to SF coding style. Verified no regression: LLR: 2.95 (-2.94,2.94) [-3.00,1.00] Total: 55938 W: 10893 L: 10835 D: 34210 No functional change.
1 parent 9a6cfee commit 5488961

File tree

1 file changed

+48
-45
lines changed

1 file changed

+48
-45
lines changed

src/search.cpp

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -90,47 +90,48 @@ namespace {
9090
Move best = MOVE_NONE;
9191
};
9292

93-
struct FastMove {
94-
FastMove() { clear(); }
93+
// EasyMoveManager struct is used to detect a so called 'easy move'; when PV is
94+
// stable across multiple search iterations we can fast return the best move.
95+
struct EasyMoveManager {
9596

96-
inline void clear() {
97-
expectedPosKey = 0;
98-
pv3[0] = pv3[1] = pv3[2] = MOVE_NONE;
97+
void clear() {
9998
stableCnt = 0;
99+
expectedPosKey = 0;
100+
pv[0] = pv[1] = pv[2] = MOVE_NONE;
100101
}
101102

102-
void update(Position& pos) {
103-
// Keep track how many times in a row the PV stays stable 3 ply deep.
104-
const std::vector<Move>& RMpv = RootMoves[0].pv;
105-
if (RMpv.size() >= 3)
106-
{
107-
if (pv3[2] == RMpv[2])
108-
stableCnt++;
109-
else
110-
stableCnt = 0, pv3[2] = RMpv[2];
103+
Move get(Key key) const {
104+
return expectedPosKey == key ? pv[2] : MOVE_NONE;
105+
}
111106

112-
if (!expectedPosKey || pv3[0] != RMpv[0] || pv3[1] != RMpv[1])
113-
{
114-
pv3[0] = RMpv[0], pv3[1] = RMpv[1];
115-
StateInfo st[2];
116-
pos.do_move(RMpv[0], st[0], pos.gives_check(RMpv[0], CheckInfo(pos)));
117-
pos.do_move(RMpv[1], st[1], pos.gives_check(RMpv[1], CheckInfo(pos)));
118-
expectedPosKey = pos.key();
119-
pos.undo_move(RMpv[1]);
120-
pos.undo_move(RMpv[0]);
121-
}
107+
void update(Position& pos, const std::vector<Move>& newPv) {
108+
109+
assert(newPv.size() >= 3);
110+
111+
// Keep track of how many times in a row 3rd ply remains stable
112+
stableCnt = (newPv[2] == pv[2]) ? stableCnt + 1 : 0;
113+
114+
if (!std::equal(newPv.begin(), newPv.begin() + 3, pv))
115+
{
116+
std::copy(newPv.begin(), newPv.begin() + 3, pv);
117+
118+
StateInfo st[2];
119+
pos.do_move(newPv[0], st[0], pos.gives_check(newPv[0], CheckInfo(pos)));
120+
pos.do_move(newPv[1], st[1], pos.gives_check(newPv[1], CheckInfo(pos)));
121+
expectedPosKey = pos.key();
122+
pos.undo_move(newPv[1]);
123+
pos.undo_move(newPv[0]);
122124
}
123-
else
124-
clear();
125125
}
126126

127-
Key expectedPosKey;
128-
Move pv3[3];
129127
int stableCnt;
130-
} FM;
128+
Key expectedPosKey;
129+
Move pv[3];
130+
};
131131

132132
size_t PVIdx;
133133
TimeManager TimeMgr;
134+
EasyMoveManager EasyMove;
134135
double BestMoveChanges;
135136
Value DrawValue[COLOR_NB];
136137
HistoryStats History;
@@ -323,9 +324,8 @@ namespace {
323324
Depth depth;
324325
Value bestValue, alpha, beta, delta;
325326

326-
// Init fastMove if the previous search generated a candidate and we now got the predicted position.
327-
const Move fastMove = (FM.expectedPosKey == pos.key()) ? FM.pv3[2] : MOVE_NONE;
328-
FM.clear();
327+
Move easyMove = EasyMove.get(pos.key());
328+
EasyMove.clear();
329329

330330
std::memset(ss-2, 0, 5 * sizeof(Stack));
331331

@@ -460,13 +460,13 @@ namespace {
460460
TimeMgr.pv_instability(BestMoveChanges);
461461

462462
// Stop the search if only one legal move is available or all
463-
// of the available time has been used or we matched a fastMove
463+
// of the available time has been used or we matched an easyMove
464464
// from the previous search and just did a fast verification.
465465
if ( RootMoves.size() == 1
466466
|| now() - SearchTime > TimeMgr.available_time()
467-
|| ( fastMove == RootMoves[0].pv[0]
467+
|| ( RootMoves[0].pv[0] == easyMove
468468
&& BestMoveChanges < 0.03
469-
&& 10 * (now() - SearchTime) > TimeMgr.available_time()))
469+
&& now() - SearchTime > TimeMgr.available_time() / 10))
470470
{
471471
// If we are allowed to ponder do not stop the search now but
472472
// keep pondering until the GUI sends "ponderhit" or "stop".
@@ -477,16 +477,17 @@ namespace {
477477
}
478478
}
479479

480-
// Update fast move stats.
481-
FM.update(pos);
480+
if (RootMoves[0].pv.size() >= 3)
481+
EasyMove.update(pos, RootMoves[0].pv);
482+
else
483+
EasyMove.clear();
482484
}
483485
}
484486

485-
// Clear any candidate fast move that wasn't completely stable for at least
486-
// the 6 final search iterations. (Independent of actual depth and thus TC.)
487-
// Time condition prevents consecutive fast moves.
488-
if (FM.stableCnt < 6 || now() - SearchTime < TimeMgr.available_time())
489-
FM.clear();
487+
// Clear any candidate easy move that wasn't stable for the last search
488+
// iterations; the second condition prevents consecutive fast moves.
489+
if (EasyMove.stableCnt < 6 || now() - SearchTime < TimeMgr.available_time())
490+
EasyMove.clear();
490491

491492
// If skill level is enabled, swap best PV line with the sub-optimal one
492493
if (skill.enabled())
@@ -1074,9 +1075,11 @@ namespace {
10741075

10751076
if (value > alpha)
10761077
{
1077-
// Clear fast move if unstable.
1078-
if (PvNode && pos.key() == FM.expectedPosKey && (move != FM.pv3[2] || moveCount > 1))
1079-
FM.clear();
1078+
// If there is an easy move for this position, clear it if unstable
1079+
if ( PvNode
1080+
&& EasyMove.get(pos.key())
1081+
&& (move != EasyMove.get(pos.key()) || moveCount > 1))
1082+
EasyMove.clear();
10801083

10811084
bestMove = SpNode ? splitPoint->bestMove = move : move;
10821085

0 commit comments

Comments
 (0)