mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 00:33:09 +00:00
Better document how history works
Both with added comment and changing the API to reflect that only destination square and moved piece is important for history. No functional change. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
8df816f869
commit
436fa5c8fa
4 changed files with 50 additions and 44 deletions
|
@ -32,14 +32,13 @@
|
||||||
//// Functions
|
//// Functions
|
||||||
////
|
////
|
||||||
|
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
|
||||||
History::History() {
|
History::History() { clear(); }
|
||||||
this->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// History::clear() clears the history tables.
|
/// History::clear() clears the history tables
|
||||||
|
|
||||||
void History::clear() {
|
void History::clear() {
|
||||||
memset(history, 0, 2 * 8 * 64 * sizeof(int));
|
memset(history, 0, 2 * 8 * 64 * sizeof(int));
|
||||||
|
@ -48,55 +47,59 @@ void History::clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// History::success() registers a move as being successful. This is done
|
/// History::success() registers a move as being successful. This is done
|
||||||
/// whenever a non-capturing move causes a beta cutoff in the main search.
|
/// whenever a non-capturing move causes a beta cutoff in the main search.
|
||||||
/// The three parameters are the moving piece, the move itself, and the
|
/// The three parameters are the moving piece, the destination square, and
|
||||||
/// search depth.
|
/// the search depth.
|
||||||
|
|
||||||
|
void History::success(Piece p, Square to, Depth d) {
|
||||||
|
|
||||||
void History::success(Piece p, Move m, Depth d) {
|
|
||||||
assert(piece_is_ok(p));
|
assert(piece_is_ok(p));
|
||||||
assert(move_is_ok(m));
|
assert(square_is_ok(to));
|
||||||
|
|
||||||
history[p][move_to(m)] += int(d) * int(d);
|
history[p][to] += int(d) * int(d);
|
||||||
successCount[p][move_to(m)]++;
|
successCount[p][to]++;
|
||||||
|
|
||||||
// Prevent history overflow:
|
// Prevent history overflow
|
||||||
if(history[p][move_to(m)] >= HistoryMax)
|
if (history[p][to] >= HistoryMax)
|
||||||
for(int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
for(int j = 0; j < 64; j++)
|
for (int j = 0; j < 64; j++)
|
||||||
history[i][j] /= 2;
|
history[i][j] /= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// History::failure() registers a move as being unsuccessful. The function is
|
/// History::failure() registers a move as being unsuccessful. The function is
|
||||||
/// called for each non-capturing move which failed to produce a beta cutoff
|
/// called for each non-capturing move which failed to produce a beta cutoff
|
||||||
/// at a node where a beta cutoff was finally found.
|
/// at a node where a beta cutoff was finally found.
|
||||||
|
|
||||||
void History::failure(Piece p, Move m) {
|
void History::failure(Piece p, Square to) {
|
||||||
assert(piece_is_ok(p));
|
|
||||||
assert(move_is_ok(m));
|
|
||||||
|
|
||||||
failureCount[p][move_to(m)]++;
|
assert(piece_is_ok(p));
|
||||||
|
assert(square_is_ok(to));
|
||||||
|
|
||||||
|
failureCount[p][to]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// History::move_ordering_score() returns an integer value used to order the
|
/// History::move_ordering_score() returns an integer value used to order the
|
||||||
/// non-capturing moves in the MovePicker class.
|
/// non-capturing moves in the MovePicker class.
|
||||||
|
|
||||||
int History::move_ordering_score(Piece p, Move m) const {
|
int History::move_ordering_score(Piece p, Square to) const {
|
||||||
assert(piece_is_ok(p));
|
|
||||||
assert(move_is_ok(m));
|
|
||||||
|
|
||||||
return history[p][move_to(m)];
|
assert(piece_is_ok(p));
|
||||||
|
assert(square_is_ok(to));
|
||||||
|
|
||||||
|
return history[p][to];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// History::ok_to_prune() decides whether a move has been sufficiently
|
/// History::ok_to_prune() decides whether a move has been sufficiently
|
||||||
/// unsuccessful that it makes sense to prune it entirely.
|
/// unsuccessful that it makes sense to prune it entirely.
|
||||||
|
|
||||||
bool History::ok_to_prune(Piece p, Move m, Depth d) const {
|
bool History::ok_to_prune(Piece p, Square to, Depth d) const {
|
||||||
assert(piece_is_ok(p));
|
|
||||||
assert(move_is_ok(m));
|
|
||||||
|
|
||||||
return (int(d) * successCount[p][move_to(m)] < failureCount[p][move_to(m)]);
|
assert(piece_is_ok(p));
|
||||||
|
assert(square_is_ok(to));
|
||||||
|
|
||||||
|
return (int(d) * successCount[p][to] < failureCount[p][to]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,19 +34,22 @@
|
||||||
//// Types
|
//// Types
|
||||||
////
|
////
|
||||||
|
|
||||||
/// The History class stores statistics about how often different moves have
|
/// The History class stores statistics about how often different moves
|
||||||
/// been successful or unsuccessful during the current search. These
|
/// have been successful or unsuccessful during the current search. These
|
||||||
/// statistics are used for reduction and move ordering decisions.
|
/// statistics are used for reduction and move ordering decisions. History
|
||||||
|
/// entries are stored according only to moving piece and destination square,
|
||||||
|
/// in particular two moves with different origin but same destination and
|
||||||
|
/// same piece will be considered identical.
|
||||||
|
|
||||||
class History {
|
class History {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
History();
|
History();
|
||||||
void clear();
|
void clear();
|
||||||
void success(Piece p, Move m, Depth d);
|
void success(Piece p, Square to, Depth d);
|
||||||
void failure(Piece p, Move m);
|
void failure(Piece p, Square to);
|
||||||
int move_ordering_score(Piece p, Move m) const;
|
int move_ordering_score(Piece p, Square to) const;
|
||||||
bool ok_to_prune(Piece p, Move m, Depth d) const;
|
bool ok_to_prune(Piece p, Square to, Depth d) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int history[16][64]; // [piece][square]
|
int history[16][64]; // [piece][square]
|
||||||
|
@ -61,14 +64,14 @@ private:
|
||||||
|
|
||||||
/// HistoryMax controls how often the history counters will be scaled down:
|
/// HistoryMax controls how often the history counters will be scaled down:
|
||||||
/// When the history score for a move gets bigger than HistoryMax, all
|
/// When the history score for a move gets bigger than HistoryMax, all
|
||||||
/// entries in the table are divided by 2. It is difficult to guess what
|
/// entries in the table are divided by 2. It is difficult to guess what
|
||||||
/// the ideal value of this constant is. Scaling down the scores often has
|
/// the ideal value of this constant is. Scaling down the scores often has
|
||||||
/// the effect that parts of the search tree which have been searched
|
/// the effect that parts of the search tree which have been searched
|
||||||
/// recently have a bigger importance for move ordering than the moves which
|
/// recently have a bigger importance for move ordering than the moves which
|
||||||
/// have been searched a long time ago.
|
/// have been searched a long time ago.
|
||||||
///
|
///
|
||||||
/// Note that HistoryMax should probably be changed whenever the constant
|
/// Note that HistoryMax should probably be changed whenever the constant
|
||||||
/// OnePly in depth.h is changed. This is somewhat annoying. Perhaps it
|
/// OnePly in depth.h is changed. This is somewhat annoying. Perhaps it
|
||||||
/// would be better to scale down the history table at regular intervals?
|
/// would be better to scale down the history table at regular intervals?
|
||||||
|
|
||||||
const int HistoryMax = 50000;
|
const int HistoryMax = 50000;
|
||||||
|
|
|
@ -264,7 +264,7 @@ void MovePicker::score_noncaptures() {
|
||||||
else if (m == killer2)
|
else if (m == killer2)
|
||||||
hs = HistoryMax + 1;
|
hs = HistoryMax + 1;
|
||||||
else
|
else
|
||||||
hs = H.move_ordering_score(pos.piece_on(move_from(m)), m);
|
hs = H.move_ordering_score(pos.piece_on(move_from(m)), move_to(m));
|
||||||
|
|
||||||
// Ensure history is always preferred to pst
|
// Ensure history is always preferred to pst
|
||||||
if (hs > 0)
|
if (hs > 0)
|
||||||
|
@ -287,7 +287,7 @@ void MovePicker::score_evasions() {
|
||||||
int seeScore = pos.see(m);
|
int seeScore = pos.see(m);
|
||||||
moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
|
moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
|
||||||
} else
|
} else
|
||||||
moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
|
moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), move_to(m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2332,7 +2332,7 @@ namespace {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Case 4: Don't prune moves with good history.
|
// Case 4: Don't prune moves with good history.
|
||||||
if (!H.ok_to_prune(pos.piece_on(move_from(m)), m, d))
|
if (!H.ok_to_prune(pos.piece_on(mfrom), mto, d))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Case 5: If the moving piece in the threatened move is a slider, don't
|
// Case 5: If the moving piece in the threatened move is a slider, don't
|
||||||
|
@ -2379,13 +2379,13 @@ namespace {
|
||||||
void update_history(const Position& pos, Move m, Depth depth,
|
void update_history(const Position& pos, Move m, Depth depth,
|
||||||
Move movesSearched[], int moveCount) {
|
Move movesSearched[], int moveCount) {
|
||||||
|
|
||||||
H.success(pos.piece_on(move_from(m)), m, depth);
|
H.success(pos.piece_on(move_from(m)), move_to(m), depth);
|
||||||
|
|
||||||
for (int i = 0; i < moveCount - 1; i++)
|
for (int i = 0; i < moveCount - 1; i++)
|
||||||
{
|
{
|
||||||
assert(m != movesSearched[i]);
|
assert(m != movesSearched[i]);
|
||||||
if (ok_to_history(pos, movesSearched[i]))
|
if (ok_to_history(pos, movesSearched[i]))
|
||||||
H.failure(pos.piece_on(move_from(movesSearched[i])), movesSearched[i]);
|
H.failure(pos.piece_on(move_from(movesSearched[i])), move_to(movesSearched[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue