mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 01:03:09 +00:00
Replace easyMove with simple scheme
Reduces time for a stable bestMove, giving some of the won time for the next move. the version before the pvDraw passed both STC and LTC passed STC: http://tests.stockfishchess.org/tests/view/59e98d5a0ebc590ccbb896ec LLR: 2.95 (-2.94,2.94) [-3.00,1.00] Total: 78561 W: 13945 L: 13921 D: 50695 elo = 0.106 +- 1.445 LOS: 55.716% passed LTC: http://tests.stockfishchess.org/tests/view/59eb9df90ebc590ccbb897ae LLR: 2.95 (-2.94,2.94) [-3.00,1.00] Total: 29056 W: 3640 L: 3530 D: 21886 elo = 1.315 +- 1.982 LOS: 90.314% This version, rebased on pvDrawPR with the obvious change, was verified again on STC: http://tests.stockfishchess.org/tests/view/59ee104e0ebc590ccbb89899 LLR: 2.96 (-2.94,2.94) [-3.00,1.00] Total: 19890 W: 3648 L: 3525 D: 12717 elo = 2.149 +- 2.895 LOS: 92.692% and LTC: http://tests.stockfishchess.org/tests/view/59f9673a0ebc590ccbb89ea0 Total : 17966 Win : 2273 ( 12.652%) Loss : 2149 ( 11.961%) Draw : 13544 ( 75.387%) Score : 50.345% Sensitivity : 0.014% 2*(W-L)/(W+L) : 5.608% LLR [-3.0, 1.0] : 2.95 BayesElo range : [ -1.161, 4.876, 10.830] (DrawElo: 341.132) LogisticElo range : [ -0.501, 2.105, 4.677] LOS : 94.369 % LTC again: LLR: 2.95 (-2.94,2.94) [-3.00,1.00] Total: 17966 W: 2273 L: 2149 D: 13544 LogisticElo range : [ -0.501, 2.105, 4.677] LOS : 94.369 % unchanged bench: 5234652
This commit is contained in:
parent
e0d2fdc843
commit
486c8175c4
2 changed files with 24 additions and 65 deletions
|
@ -96,46 +96,6 @@ namespace {
|
|||
Move best = MOVE_NONE;
|
||||
};
|
||||
|
||||
// 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]);
|
||||
}
|
||||
}
|
||||
|
||||
Key expectedPosKey;
|
||||
int stableCnt;
|
||||
Move pv[3];
|
||||
};
|
||||
|
||||
EasyMoveManager EasyMove;
|
||||
Value DrawValue[COLOR_NB];
|
||||
|
||||
template <NodeType NT>
|
||||
|
@ -220,6 +180,7 @@ void Search::clear() {
|
|||
|
||||
Threads.main()->callsCnt = 0;
|
||||
Threads.main()->previousScore = VALUE_INFINITE;
|
||||
Threads.main()->previousTimeReduction = 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -285,8 +246,7 @@ void MainThread::search() {
|
|||
|
||||
// Check if there are threads with a better score than main thread
|
||||
Thread* bestThread = this;
|
||||
if ( !this->easyMovePlayed
|
||||
&& Options["MultiPV"] == 1
|
||||
if ( Options["MultiPV"] == 1
|
||||
&& !Limits.depth
|
||||
&& !Skill(Options["Skill Level"]).enabled()
|
||||
&& rootMoves[0].pv[0] != MOVE_NONE)
|
||||
|
@ -326,8 +286,10 @@ void Thread::search() {
|
|||
|
||||
Stack stack[MAX_PLY+7], *ss = stack+4; // To reference from (ss-4) to (ss+2)
|
||||
Value bestValue, alpha, beta, delta;
|
||||
Move easyMove = MOVE_NONE;
|
||||
Move lastBestMove = MOVE_NONE;
|
||||
Depth lastBestMoveDepth = DEPTH_ZERO;
|
||||
MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
|
||||
double timeReduction = 1.0;
|
||||
|
||||
std::memset(ss-4, 0, 7 * sizeof(Stack));
|
||||
for (int i = 4; i > 0; i--)
|
||||
|
@ -338,9 +300,7 @@ void Thread::search() {
|
|||
|
||||
if (mainThread)
|
||||
{
|
||||
easyMove = EasyMove.get(rootPos.key());
|
||||
EasyMove.clear();
|
||||
mainThread->easyMovePlayed = mainThread->failedLow = false;
|
||||
mainThread->failedLow = false;
|
||||
mainThread->bestMoveChanges = 0;
|
||||
}
|
||||
|
||||
|
@ -453,6 +413,11 @@ void Thread::search() {
|
|||
if (!Threads.stop)
|
||||
completedDepth = rootDepth;
|
||||
|
||||
if (rootMoves[0].pv[0] != lastBestMove) {
|
||||
lastBestMove = rootMoves[0].pv[0];
|
||||
lastBestMoveDepth = rootDepth;
|
||||
}
|
||||
|
||||
// Have we found a "mate in x"?
|
||||
if ( Limits.mate
|
||||
&& bestValue >= VALUE_MATE_IN_MAX_PLY
|
||||
|
@ -472,8 +437,7 @@ void Thread::search() {
|
|||
if (!Threads.stop && !Threads.stopOnPonderhit)
|
||||
{
|
||||
// Stop the search if only one legal move is available, or if all
|
||||
// of the available time has been used, or if we matched an easyMove
|
||||
// from the previous search and just did a fast verification.
|
||||
// of the available time has been used
|
||||
const int F[] = { mainThread->failedLow,
|
||||
bestValue - mainThread->previousScore };
|
||||
int improvingFactor = std::max(229, std::min(715, 357 + 119 * F[0] - 6 * F[1]));
|
||||
|
@ -485,14 +449,17 @@ void Thread::search() {
|
|||
|
||||
double unstablePvFactor = 1 + mainThread->bestMoveChanges + thinkHard;
|
||||
|
||||
bool doEasyMove = rootMoves[0].pv[0] == easyMove
|
||||
&& !thinkHard
|
||||
&& mainThread->bestMoveChanges < 0.03
|
||||
&& Time.elapsed() > Time.optimum() * 5 / 44;
|
||||
// if the bestMove is stable over several iterations, reduce time for this move,
|
||||
// the longer the move has been stable, the more.
|
||||
// Use part of the gained time from a previous stable move for the current move.
|
||||
timeReduction = 1;
|
||||
for (int i : {3, 4, 5})
|
||||
if (lastBestMoveDepth * i < completedDepth && !thinkHard)
|
||||
timeReduction *= 1.3;
|
||||
unstablePvFactor *= std::pow(mainThread->previousTimeReduction, 0.51) / timeReduction;
|
||||
|
||||
if ( rootMoves.size() == 1
|
||||
|| Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 628
|
||||
|| (mainThread->easyMovePlayed = doEasyMove, doEasyMove))
|
||||
|| Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 628)
|
||||
{
|
||||
// If we are allowed to ponder do not stop the search now but
|
||||
// keep pondering until the GUI sends "ponderhit" or "stop".
|
||||
|
@ -502,21 +469,13 @@ void Thread::search() {
|
|||
Threads.stop = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rootMoves[0].pv.size() >= 3)
|
||||
EasyMove.update(rootPos, rootMoves[0].pv);
|
||||
else
|
||||
EasyMove.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!mainThread)
|
||||
return;
|
||||
|
||||
// Clear any candidate easy move that wasn't stable for the last search
|
||||
// iterations; the second condition prevents consecutive fast moves.
|
||||
if (EasyMove.stableCnt < 6 || mainThread->easyMovePlayed)
|
||||
EasyMove.clear();
|
||||
mainThread->previousTimeReduction = timeReduction;
|
||||
|
||||
// If skill level is enabled, swap best PV line with the sub-optimal one
|
||||
if (skill.enabled())
|
||||
|
|
|
@ -82,8 +82,8 @@ struct MainThread : public Thread {
|
|||
void search() override;
|
||||
void check_time();
|
||||
|
||||
bool easyMovePlayed, failedLow;
|
||||
double bestMoveChanges;
|
||||
bool failedLow;
|
||||
double bestMoveChanges, previousTimeReduction;
|
||||
Value previousScore;
|
||||
int callsCnt;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue