- // EasyMoveManager structure is used to detect an 'easy move'. When the PV is
- // stable across multiple search iterations, we can quickly return the best move.
- struct EasyMoveManager {
-
- void clear() {
- stableCnt = 0;
- expectedPosKey = 0;
- pv[0] = pv[1] = pv[2] = MOVE_NONE;
- }
-
- Move get(Key key) const {
- return expectedPosKey == key ? pv[2] : MOVE_NONE;
- }
-
- void update(Position& pos, const std::vector<Move>& newPv) {
-
- assert(newPv.size() >= 3);
-
- // Keep track of how many times in a row the 3rd ply remains stable
- stableCnt = (newPv[2] == pv[2]) ? stableCnt + 1 : 0;
-
- if (!std::equal(newPv.begin(), newPv.begin() + 3, pv))
- {
- std::copy(newPv.begin(), newPv.begin() + 3, pv);
-
- StateInfo st[2];
- pos.do_move(newPv[0], st[0]);
- pos.do_move(newPv[1], st[1]);
- expectedPosKey = pos.key();
- pos.undo_move(newPv[1]);
- pos.undo_move(newPv[0]);
- }
- }
-
- int stableCnt;
- Key expectedPosKey;
- Move pv[3];
- };
-
- // skip half of the plies in blocks depending on the helper thread idx.
- bool skip_ply(int idx, int ply) {
-
- idx = (idx - 1) % 20 + 1; // cycle after 20 threads.
-
- // number of successive plies to skip, depending on idx.
- int ones = 1;
- while (ones * (ones + 1) < idx)
- ones++;
-
- return ((ply + idx - 1) / ones - ones) % 2 == 0;
- }
-
- EasyMoveManager EasyMove;
- Value DrawValue[COLOR_NB];
-