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
- };
-
- // 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
- };
+ 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);
+ }
+
+ // 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); }
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)
// 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;
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;
}
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;
}
Value result = QueenValueEg
- RookValueEg
- + PushToEdges[loserKSq]
+ + push_to_edge(loserKSq)
+ push_close(winnerKSq, loserKSq);
return strongSide == pos.side_to_move() ? result : -result;
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;