Equations for edges and corners.

This is a functional simplification that removes the large arrays in endgames.cpp.
It also fixes a recently introduced bug (960d59d541) in KNBvK,
now using flip_file() instead of ~.

One fen added to bench to increase endgame coverage.

STC
LLR: 2.94 (-2.94,2.94) {-1.50,0.50}
Total: 174724 W: 33325 L: 33404 D: 107995
Ptnml(0-2): 2503, 19607, 43181, 19608, 2463
http://tests.stockfishchess.org/tests/view/5e6448ffe42a5c3b3ca2e287

LTC
LLR: 2.95 (-2.94,2.94) {-1.50,0.50}
Total: 35640 W: 4679 L: 4621 D: 26340
Ptnml(0-2): 189, 2991, 11424, 3005, 211
http://tests.stockfishchess.org/tests/view/5e650b24e42a5c3b3ca2e2d8

closes https://github.com/official-stockfish/Stockfish/pull/2577

Bench: 5527957
This commit is contained in:
protonspring
2020-03-09 22:11:08 +01:00
committed by Joost VandeVondele
parent 37e3863927
commit 47be966d30
8 changed files with 24 additions and 38 deletions

View File

@@ -28,31 +28,17 @@ using std::string;
namespace {
// Table used to drive the king towards the edge of the board
// Used to drive the king towards the edge of the board
// in KX vs K and KQ vs KR endgames.
constexpr int PushToEdges[SQUARE_NB] = {
100, 90, 80, 70, 70, 80, 90, 100,
90, 70, 60, 50, 50, 60, 70, 90,
80, 60, 40, 30, 30, 40, 60, 80,
70, 50, 30, 20, 20, 30, 50, 70,
70, 50, 30, 20, 20, 30, 50, 70,
80, 60, 40, 30, 30, 40, 60, 80,
90, 70, 60, 50, 50, 60, 70, 90,
100, 90, 80, 70, 70, 80, 90, 100
};
inline int push_to_edge(Square s) {
int rd = edge_distance(rank_of(s)), fd = edge_distance(file_of(s));
return 90 - (7 * fd * fd / 2 + 7 * rd * rd / 2);
}
// Table used to drive the king towards a corner square of the
// right color in KBN vs K endgames.
constexpr int PushToCorners[SQUARE_NB] = {
6400, 6080, 5760, 5440, 5120, 4800, 4480, 4160,
6080, 5760, 5440, 5120, 4800, 4480, 4160, 4480,
5760, 5440, 4960, 4480, 4480, 4000, 4480, 4800,
5440, 5120, 4480, 3840, 3520, 4480, 4800, 5120,
5120, 4800, 4480, 3520, 3840, 4480, 5120, 5440,
4800, 4480, 4000, 4480, 4480, 4960, 5440, 5760,
4480, 4160, 4480, 4800, 5120, 5440, 5760, 6080,
4160, 4480, 4800, 5120, 5440, 5760, 6080, 6400
};
// Used to drive the king towards A1H8 corners in KBN vs K endgames.
inline int push_to_corner(Square s) {
return abs(7 - rank_of(s) - file_of(s));
}
// Drive a piece close to or away from another piece
inline int push_close(Square s1, Square s2) { return 140 - 20 * distance(s1, s2); }
@@ -126,7 +112,7 @@ Value Endgame<KXK>::operator()(const Position& pos) const {
Value result = pos.non_pawn_material(strongSide)
+ pos.count<PAWN>(strongSide) * PawnValueEg
+ PushToEdges[loserKSq]
+ push_to_edge(loserKSq)
+ push_close(winnerKSq, loserKSq);
if ( pos.count<QUEEN>(strongSide)
@@ -155,9 +141,9 @@ Value Endgame<KBNK>::operator()(const Position& pos) const {
// If our bishop does not attack A1/H8, we flip the enemy king square
// to drive to opposite corners (A8/H1).
Value result = VALUE_KNOWN_WIN
Value result = (VALUE_KNOWN_WIN + 3520)
+ push_close(winnerKSq, loserKSq)
+ PushToCorners[opposite_colors(bishopSq, SQ_A1) ? ~loserKSq : loserKSq];
+ 420 * push_to_corner(opposite_colors(bishopSq, SQ_A1) ? flip_file(loserKSq) : loserKSq);
assert(abs(result) < VALUE_TB_WIN_IN_MAX_PLY);
return strongSide == pos.side_to_move() ? result : -result;
@@ -240,7 +226,7 @@ Value Endgame<KRKB>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
Value result = Value(PushToEdges[pos.square<KING>(weakSide)]);
Value result = Value(push_to_edge(pos.square<KING>(weakSide)));
return strongSide == pos.side_to_move() ? result : -result;
}
@@ -255,7 +241,7 @@ Value Endgame<KRKN>::operator()(const Position& pos) const {
Square bksq = pos.square<KING>(weakSide);
Square bnsq = pos.square<KNIGHT>(weakSide);
Value result = Value(PushToEdges[bksq] + push_away(bksq, bnsq));
Value result = Value(push_to_edge(bksq) + push_away(bksq, bnsq));
return strongSide == pos.side_to_move() ? result : -result;
}
@@ -300,7 +286,7 @@ Value Endgame<KQKR>::operator()(const Position& pos) const {
Value result = QueenValueEg
- RookValueEg
+ PushToEdges[loserKSq]
+ push_to_edge(loserKSq)
+ push_close(winnerKSq, loserKSq);
return strongSide == pos.side_to_move() ? result : -result;
@@ -316,7 +302,7 @@ Value Endgame<KNNKP>::operator()(const Position& pos) const {
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
Value result = PawnValueEg
+ 2 * PushToEdges[pos.square<KING>(weakSide)]
+ 2 * push_to_edge(pos.square<KING>(weakSide))
- 10 * relative_rank(weakSide, pos.square<PAWN>(weakSide));
return strongSide == pos.side_to_move() ? result : -result;