// Used to drive the king towards the edge of the board
// in KX vs K and KQ vs KR endgames.
+ // Values range from 27 (center squares) to 90 (in the corners)
- inline int push_to_edge(Square s) {
- int rd = edge_distance(rank_of(s)), fd = edge_distance(file_of(s));
+ inline int push_to_edge(Square s, const Position& pos) {
+ int rd = edge_distance(rank_of(s), pos.max_rank()), fd = edge_distance(file_of(s), pos.max_file());
return 90 - (7 * fd * fd / 2 + 7 * rd * rd / 2);
}
// Used to drive the king towards A1H8 corners in KBN vs K endgames.
- // Values range from 0 on A8H1 diagonal to 7 in A1H8 corners
- inline int push_to_corner(Square s) {
- return abs(7 - rank_of(s) - file_of(s));
++ // Values range from 0 on A8H1 diagonal to 7 in A1H8 corners.
+ inline int push_to_corner(Square s, const Position& pos) {
+ return abs((pos.max_file() + pos.max_rank()) / 2 - rank_of(s) - file_of(s));
+ }
+
- // Used to drive the king towards the edge of the board
- // in KSF vs K.
++ // Used to drive the king towards the edge of the board in KSF vs K.
+ inline int push_to_opposing_edge(Square s, const Position& pos) {
+ int rd = rank_of(s), fd = edge_distance(file_of(s), pos.max_file());
+ return 20 - (7 * fd * fd / 2 - 7 * rd * rd / 4);
}
// Drive a piece close to or away from another piece
Value result = pos.non_pawn_material(strongSide)
+ pos.count<PAWN>(strongSide) * PawnValueEg
- + push_to_edge(loserKSq, pos)
- + push_close(winnerKSq, loserKSq);
- + push_to_edge(weakKing)
++ + push_to_edge(weakKing, pos)
+ + push_close(strongKing, weakKing);
if ( pos.count<QUEEN>(strongSide)
|| pos.count<ROOK>(strongSide)
// to drive to opposite corners (A8/H1).
Value result = (VALUE_KNOWN_WIN + 3520)
- + push_close(winnerKSq, loserKSq)
- + 420 * push_to_corner(opposite_colors(bishopSq, SQ_A1) ? flip_file(loserKSq, pos.max_file()) : loserKSq, pos);
+ + push_close(strongKing, weakKing)
- + 420 * push_to_corner(opposite_colors(strongBishop, SQ_A1) ? flip_file(weakKing) : weakKing);
++ + 420 * push_to_corner(opposite_colors(strongBishop, SQ_A1) ? flip_file(weakKing, pos.max_file()) : weakKing, pos);
assert(abs(result) < VALUE_TB_WIN_IN_MAX_PLY);
return strongSide == pos.side_to_move() ? result : -result;
Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
- Value result;
- if ( pos.promotion_rank() == RANK_8
- && RANK_MAX == RANK_8
- && pos.promotion_piece_types().find(QUEEN) != pos.promotion_piece_types().end())
++ // Non-standard promotion, evaluation unclear
++ if ( pos.promotion_rank() != RANK_8
++ || RANK_MAX != RANK_8
++ || pos.promotion_piece_types().find(QUEEN) == pos.promotion_piece_types().end())
+ {
- if (!Bitbases::probe(wksq, psq, bksq, us))
- return VALUE_DRAW;
-
- result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(psq));
- }
- else
- {
- // Non-standard promotion, evaluation unclear
- result = PawnValueEg + Value(rank_of(psq));
++ Value result = PawnValueEg + Value(rank_of(strongPawn));
++ return strongSide == pos.side_to_move() ? result : -result;
+ }
+
+ if (!Bitbases::probe(strongKing, strongPawn, weakKing, us))
+ return VALUE_DRAW;
+
+ Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(strongPawn));
+
return strongSide == pos.side_to_move() ? result : -result;
}
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
- Square bksq = pos.square<KING>(weakSide);
- Square bnsq = pos.square<KNIGHT>(weakSide);
- Value result = Value(push_to_edge(bksq, pos) + push_away(bksq, bnsq));
+ Square weakKing = pos.square<KING>(weakSide);
+ Square weakKnight = pos.square<KNIGHT>(weakSide);
- Value result = Value(push_to_edge(weakKing) + push_away(weakKing, weakKnight));
++ Value result = Value(push_to_edge(weakKing, pos) + push_away(weakKing, weakKnight));
return strongSide == pos.side_to_move() ? result : -result;
}
Value result = QueenValueEg
- RookValueEg
- + push_to_edge(loserKSq, pos)
- + push_close(winnerKSq, loserKSq);
- + push_to_edge(weakKing)
++ + push_to_edge(weakKing, pos)
+ + push_close(strongKing, weakKing);
return strongSide == pos.side_to_move() ? result : -result;
}
assert(verify_material(pos, strongSide, 2 * KnightValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
+ Square weakKing = pos.square<KING>(weakSide);
+ Square weakPawn = pos.square<PAWN>(weakSide);
+
Value result = PawnValueEg
- + 2 * push_to_edge(pos.square<KING>(weakSide), pos)
- - 10 * relative_rank(weakSide, pos.square<PAWN>(weakSide));
- + 2 * push_to_edge(weakKing)
++ + 2 * push_to_edge(weakKing, pos)
+ - 10 * relative_rank(weakSide, weakPawn);
return strongSide == pos.side_to_move() ? result : -result;
}
// Probe the KPK bitbase with the weakest side's pawn removed. If it's a draw,
// it's probably at least a draw even with the pawn.
- if ( pos.promotion_rank() == RANK_8
- && RANK_MAX == RANK_8
- && pos.promotion_piece_types().find(QUEEN) != pos.promotion_piece_types().end())
- return Bitbases::probe(wksq, psq, bksq, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
- else
++ if ( pos.promotion_rank() != RANK_8
++ || RANK_MAX != RANK_8
++ || pos.promotion_piece_types().find(QUEEN) == pos.promotion_piece_types().end())
+ return SCALE_FACTOR_NONE;
++
+ return Bitbases::probe(strongKing, strongPawn, weakKing, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
}