mirror of
https://github.com/sockspls/badfish
synced 2025-07-11 19:49:14 +00:00
Wrap in a class Skill Level code
Note that the actual pickup is done in the class d'tor so to be sure it is always triggered, even in case of a sudden exit due to a 'stop' signal. No functional change.
This commit is contained in:
parent
9c2b3faec4
commit
e8e5b9f537
1 changed files with 36 additions and 34 deletions
|
@ -90,9 +90,7 @@ namespace {
|
||||||
size_t MultiPV, UCIMultiPV, PVIdx;
|
size_t MultiPV, UCIMultiPV, PVIdx;
|
||||||
TimeManager TimeMgr;
|
TimeManager TimeMgr;
|
||||||
int BestMoveChanges;
|
int BestMoveChanges;
|
||||||
int SkillLevel;
|
bool Chess960;
|
||||||
Move skillBest;
|
|
||||||
bool SkillLevelEnabled, Chess960;
|
|
||||||
Value DrawValue[COLOR_NB];
|
Value DrawValue[COLOR_NB];
|
||||||
History H;
|
History H;
|
||||||
|
|
||||||
|
@ -108,9 +106,24 @@ namespace {
|
||||||
Value value_to_tt(Value v, int ply);
|
Value value_to_tt(Value v, int ply);
|
||||||
Value value_from_tt(Value v, int ply);
|
Value value_from_tt(Value v, int ply);
|
||||||
bool connected_threat(const Position& pos, Move m, Move threat);
|
bool connected_threat(const Position& pos, Move m, Move threat);
|
||||||
Move do_skill_level();
|
|
||||||
string uci_pv(const Position& pos, int depth, Value alpha, Value beta);
|
string uci_pv(const Position& pos, int depth, Value alpha, Value beta);
|
||||||
|
|
||||||
|
struct Skill {
|
||||||
|
Skill(int l) : level(l), best(MOVE_NONE) {}
|
||||||
|
~Skill() {
|
||||||
|
if (enabled()) // Swap best PV line with the sub-optimal one
|
||||||
|
std::swap(RootMoves[0], *std::find(RootMoves.begin(),
|
||||||
|
RootMoves.end(), best ? best : pick_move()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enabled() const { return level < 20; }
|
||||||
|
bool time_to_pick(int depth) const { return depth == 1 + level; }
|
||||||
|
Move pick_move();
|
||||||
|
|
||||||
|
int level;
|
||||||
|
Move best;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
@ -210,15 +223,6 @@ void Search::think() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UCIMultiPV = Options["MultiPV"];
|
|
||||||
SkillLevel = Options["Skill Level"];
|
|
||||||
|
|
||||||
// Do we have to play with skill handicap? In this case enable MultiPV that
|
|
||||||
// we will use behind the scenes to retrieve a set of possible moves.
|
|
||||||
SkillLevelEnabled = (SkillLevel < 20);
|
|
||||||
skillBest = MOVE_NONE;
|
|
||||||
MultiPV = (SkillLevelEnabled ? std::max(UCIMultiPV, (size_t)4) : UCIMultiPV);
|
|
||||||
|
|
||||||
if (Options["Use Search Log"])
|
if (Options["Use Search Log"])
|
||||||
{
|
{
|
||||||
Log log(Options["Search Log Filename"]);
|
Log log(Options["Search Log Filename"]);
|
||||||
|
@ -248,15 +252,6 @@ void Search::think() {
|
||||||
Threads.set_timer(0); // Stop timer
|
Threads.set_timer(0); // Stop timer
|
||||||
Threads.sleep();
|
Threads.sleep();
|
||||||
|
|
||||||
// When using skills swap best PV line with the sub-optimal one
|
|
||||||
if (SkillLevelEnabled)
|
|
||||||
{
|
|
||||||
if (skillBest == MOVE_NONE) // Still unassigned ?
|
|
||||||
skillBest = do_skill_level();
|
|
||||||
|
|
||||||
std::swap(RootMoves[0], *std::find(RootMoves.begin(), RootMoves.end(), skillBest));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Options["Use Search Log"])
|
if (Options["Use Search Log"])
|
||||||
{
|
{
|
||||||
Time::point elapsed = Time::now() - SearchTime + 1;
|
Time::point elapsed = Time::now() - SearchTime + 1;
|
||||||
|
@ -304,6 +299,13 @@ namespace {
|
||||||
bestValue = delta = -VALUE_INFINITE;
|
bestValue = delta = -VALUE_INFINITE;
|
||||||
ss->currentMove = MOVE_NULL; // Hack to skip update gains
|
ss->currentMove = MOVE_NULL; // Hack to skip update gains
|
||||||
|
|
||||||
|
UCIMultiPV = Options["MultiPV"];
|
||||||
|
Skill skill(Options["Skill Level"]);
|
||||||
|
|
||||||
|
// Do we have to play with skill handicap? In this case enable MultiPV that
|
||||||
|
// we will use behind the scenes to retrieve a set of possible moves.
|
||||||
|
MultiPV = skill.enabled() ? std::max(UCIMultiPV, (size_t)4) : UCIMultiPV;
|
||||||
|
|
||||||
// Iterative deepening loop until requested to stop or target depth reached
|
// Iterative deepening loop until requested to stop or target depth reached
|
||||||
while (++depth <= MAX_PLY && !Signals.stop && (!Limits.depth || depth <= Limits.depth))
|
while (++depth <= MAX_PLY && !Signals.stop && (!Limits.depth || depth <= Limits.depth))
|
||||||
{
|
{
|
||||||
|
@ -359,13 +361,9 @@ namespace {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// In case of failing high/low increase aspiration window and
|
// In case of failing high/low increase aspiration window and
|
||||||
// research, otherwise sort multi-PV lines and exit the loop.
|
// research, otherwise exit the loop.
|
||||||
if (bestValue > alpha && bestValue < beta)
|
if (bestValue > alpha && bestValue < beta)
|
||||||
{
|
|
||||||
sort<RootMove>(RootMoves.begin(), RootMoves.begin() + PVIdx);
|
|
||||||
sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
// Give some update (without cluttering the UI) before to research
|
// Give some update (without cluttering the UI) before to research
|
||||||
if (Time::now() - SearchTime > 3000)
|
if (Time::now() - SearchTime > 3000)
|
||||||
|
@ -392,11 +390,15 @@ namespace {
|
||||||
|
|
||||||
assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
|
assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort the PV lines searched so far and update the GUI
|
||||||
|
sort<RootMove>(RootMoves.begin(), RootMoves.begin() + PVIdx);
|
||||||
|
sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skills: Do we need to pick now the best move ?
|
// Do we need to pick now the sub-optimal best move ?
|
||||||
if (SkillLevelEnabled && depth == 1 + SkillLevel)
|
if (skill.enabled() && skill.time_to_pick(depth))
|
||||||
skillBest = do_skill_level();
|
skill.pick_move();
|
||||||
|
|
||||||
if (Options["Use Search Log"])
|
if (Options["Use Search Log"])
|
||||||
{
|
{
|
||||||
|
@ -1437,9 +1439,9 @@ split_point_start: // At split points actual search starts from here
|
||||||
|
|
||||||
|
|
||||||
// When playing with strength handicap choose best move among the MultiPV set
|
// When playing with strength handicap choose best move among the MultiPV set
|
||||||
// using a statistical rule dependent on SkillLevel. Idea by Heinz van Saanen.
|
// using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
|
||||||
|
|
||||||
Move do_skill_level() {
|
Move Skill::pick_move() {
|
||||||
|
|
||||||
assert(MultiPV > 1);
|
assert(MultiPV > 1);
|
||||||
|
|
||||||
|
@ -1452,9 +1454,9 @@ split_point_start: // At split points actual search starts from here
|
||||||
// RootMoves are already sorted by score in descending order
|
// RootMoves are already sorted by score in descending order
|
||||||
size_t size = std::min(MultiPV, RootMoves.size());
|
size_t size = std::min(MultiPV, RootMoves.size());
|
||||||
int variance = std::min(RootMoves[0].score - RootMoves[size - 1].score, PawnValueMg);
|
int variance = std::min(RootMoves[0].score - RootMoves[size - 1].score, PawnValueMg);
|
||||||
int weakness = 120 - 2 * SkillLevel;
|
int weakness = 120 - 2 * level;
|
||||||
int max_s = -VALUE_INFINITE;
|
int max_s = -VALUE_INFINITE;
|
||||||
Move best = MOVE_NONE;
|
best = MOVE_NONE;
|
||||||
|
|
||||||
// Choose best move. For each move score we add two terms both dependent on
|
// Choose best move. For each move score we add two terms both dependent on
|
||||||
// weakness, one deterministic and bigger for weaker moves, and one random,
|
// weakness, one deterministic and bigger for weaker moves, and one random,
|
||||||
|
|
Loading…
Add table
Reference in a new issue