+ // EasyMoveManager struct is used to detect a so called 'easy move'; when PV is
+ // stable across multiple search iterations we can fast 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 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.gives_check(newPv[0], CheckInfo(pos)));
+ pos.do_move(newPv[1], st[1], pos.gives_check(newPv[1], CheckInfo(pos)));
+ expectedPosKey = pos.key();
+ pos.undo_move(newPv[1]);
+ pos.undo_move(newPv[0]);
+ }
+ }
+
+ int stableCnt;
+ Key expectedPosKey;
+ Move pv[3];
+ };
+