Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
70, 50, 30, 20, 20, 30, 50, 70,
80, 60, 40, 30, 30, 40, 60, 80,
90, 70, 60, 50, 50, 60, 70, 90,
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,
+ 100, 90, 80, 70, 70, 80, 90, 100
const int PushClose[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
const int PushAway [8] = { 0, 5, 20, 40, 60, 80, 90, 100 };
const int PushClose[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
const int PushAway [8] = { 0, 5, 20, 40, 60, 80, 90, 100 };
+ // Pawn Rank based scaling factors used in KRPPKRP endgame
+ const int KRPPKRPScaleFactors[RANK_NB] = { 0, 9, 10, 14, 21, 44, 0, 0 };
+
#ifndef NDEBUG
bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == pawnsCnt;
#ifndef NDEBUG
bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == pawnsCnt;
if ( pos.count<QUEEN>(strongSide)
|| pos.count<ROOK>(strongSide)
||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
if ( pos.count<QUEEN>(strongSide)
|| pos.count<ROOK>(strongSide)
||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
- ||(pos.count<BISHOP>(strongSide) > 1 && opposite_colors(pos.list<BISHOP>(strongSide)[0],
- pos.list<BISHOP>(strongSide)[1])))
- result += VALUE_KNOWN_WIN;
+ ||(pos.count<BISHOP>(strongSide) > 1 && opposite_colors(pos.squares<BISHOP>(strongSide)[0],
+ pos.squares<BISHOP>(strongSide)[1])))
+ result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1);
assert(verify_material(pos, strongSide, KnightValueMg + BishopValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
assert(verify_material(pos, strongSide, KnightValueMg + BishopValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
- Square winnerKSq = pos.king_square(strongSide);
- Square loserKSq = pos.king_square(weakSide);
- Square bishopSq = pos.list<BISHOP>(strongSide)[0];
+ Square winnerKSq = pos.square<KING>(strongSide);
+ Square loserKSq = pos.square<KING>(weakSide);
+ Square bishopSq = pos.square<BISHOP>(strongSide);
// kbnk_mate_table() tries to drive toward corners A1 or H8. If we have a
// bishop that cannot reach the above squares, we flip the kings in order
// kbnk_mate_table() tries to drive toward corners A1 or H8. If we have a
// bishop that cannot reach the above squares, we flip the kings in order
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
// Assume strongSide is white and the pawn is on files A-D
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
// Assume strongSide is white and the pawn is on files A-D
- Square wksq = normalize(pos, strongSide, pos.king_square(strongSide));
- Square bksq = normalize(pos, strongSide, pos.king_square(weakSide));
- Square psq = normalize(pos, strongSide, pos.list<PAWN>(strongSide)[0]);
+ Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
+ Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
+ Square psq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
- Square wksq = relative_square(strongSide, pos.king_square(strongSide));
- Square bksq = relative_square(strongSide, pos.king_square(weakSide));
- Square rsq = relative_square(strongSide, pos.list<ROOK>(strongSide)[0]);
- Square psq = relative_square(strongSide, pos.list<PAWN>(weakSide)[0]);
+ Square wksq = relative_square(strongSide, pos.square<KING>(strongSide));
+ Square bksq = relative_square(strongSide, pos.square<KING>(weakSide));
+ Square rsq = relative_square(strongSide, pos.square<ROOK>(strongSide));
+ Square psq = relative_square(strongSide, pos.square<PAWN>(weakSide));
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
assert(verify_material(pos, strongSide, RookValueMg, 0));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
Value result = Value(PushToEdges[bksq] + PushAway[distance(bksq, bnsq)]);
return strongSide == pos.side_to_move() ? result : -result;
}
Value result = Value(PushToEdges[bksq] + PushAway[distance(bksq, bnsq)]);
return strongSide == pos.side_to_move() ? result : -result;
}
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
- Square winnerKSq = pos.king_square(strongSide);
- Square loserKSq = pos.king_square(weakSide);
- Square pawnSq = pos.list<PAWN>(weakSide)[0];
+ Square winnerKSq = pos.square<KING>(strongSide);
+ Square loserKSq = pos.square<KING>(weakSide);
+ Square pawnSq = pos.square<PAWN>(weakSide);
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, RookValueMg, 0));
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, RookValueMg, 0));
// be detected even when the weaker side has some pawns.
Bitboard pawns = pos.pieces(strongSide, PAWN);
// be detected even when the weaker side has some pawns.
Bitboard pawns = pos.pieces(strongSide, PAWN);
- // All pawns are on a single rook file ?
- if ( (pawnFile == FILE_A || pawnFile == FILE_H)
- && !(pawns & ~file_bb(pawnFile)))
+ // All pawns are on a single rook file?
+ if ( (pawnsFile == FILE_A || pawnsFile == FILE_H)
+ && !(pawns & ~file_bb(pawnsFile)))
- Square bishopSq = pos.list<BISHOP>(strongSide)[0];
- Square queeningSq = relative_square(strongSide, make_square(pawnFile, RANK_8));
- Square kingSq = pos.king_square(weakSide);
+ Square bishopSq = pos.square<BISHOP>(strongSide);
+ Square queeningSq = relative_square(strongSide, make_square(pawnsFile, RANK_8));
+ Square kingSq = pos.square<KING>(weakSide);
if ( opposite_colors(queeningSq, bishopSq)
&& distance(queeningSq, kingSq) <= 1)
if ( opposite_colors(queeningSq, bishopSq)
&& distance(queeningSq, kingSq) <= 1)
&& pos.non_pawn_material(weakSide) == 0
&& pos.count<PAWN>(weakSide) >= 1)
{
// Get weakSide pawn that is closest to the home rank
Square weakPawnSq = backmost_sq(weakSide, pos.pieces(weakSide, PAWN));
&& pos.non_pawn_material(weakSide) == 0
&& pos.count<PAWN>(weakSide) >= 1)
{
// Get weakSide pawn that is closest to the home rank
Square weakPawnSq = backmost_sq(weakSide, pos.pieces(weakSide, PAWN));
- Square strongKingSq = pos.king_square(strongSide);
- Square weakKingSq = pos.king_square(weakSide);
- Square bishopSq = pos.list<BISHOP>(strongSide)[0];
+ Square strongKingSq = pos.square<KING>(strongSide);
+ Square weakKingSq = pos.square<KING>(weakSide);
+ Square bishopSq = pos.square<BISHOP>(strongSide);
// There's potential for a draw if our pawn is blocked on the 7th rank,
// the bishop cannot attack it or they only have one pawn left
// There's potential for a draw if our pawn is blocked on the 7th rank,
// the bishop cannot attack it or they only have one pawn left
&& relative_rank(weakSide, rsq) == RANK_3
&& ( pos.pieces(weakSide, PAWN)
& pos.attacks_from<KING>(kingSq)
&& relative_rank(weakSide, rsq) == RANK_3
&& ( pos.pieces(weakSide, PAWN)
& pos.attacks_from<KING>(kingSq)
assert(verify_material(pos, weakSide, RookValueMg, 0));
// Assume strongSide is white and the pawn is on files A-D
assert(verify_material(pos, weakSide, RookValueMg, 0));
// Assume strongSide is white and the pawn is on files A-D
- Square wksq = normalize(pos, strongSide, pos.king_square(strongSide));
- Square bksq = normalize(pos, strongSide, pos.king_square(weakSide));
- Square wrsq = normalize(pos, strongSide, pos.list<ROOK>(strongSide)[0]);
- Square wpsq = normalize(pos, strongSide, pos.list<PAWN>(strongSide)[0]);
- Square brsq = normalize(pos, strongSide, pos.list<ROOK>(weakSide)[0]);
+ Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
+ Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
+ Square wrsq = normalize(pos, strongSide, pos.square<ROOK>(strongSide));
+ Square wpsq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
+ Square brsq = normalize(pos, strongSide, pos.square<ROOK>(weakSide));
if ( r == RANK_6
&& distance(bksq, queeningSq) <= 1
&& rank_of(wksq) + tempo <= RANK_6
if ( r == RANK_6
&& distance(bksq, queeningSq) <= 1
&& rank_of(wksq) + tempo <= RANK_6
- Square ksq = pos.king_square(weakSide);
- Square bsq = pos.list<BISHOP>(weakSide)[0];
- Square psq = pos.list<PAWN>(strongSide)[0];
+ Square ksq = pos.square<KING>(weakSide);
+ Square bsq = pos.square<BISHOP>(weakSide);
+ Square psq = pos.square<PAWN>(strongSide);
Rank rk = relative_rank(strongSide, psq);
Square push = pawn_push(strongSide);
Rank rk = relative_rank(strongSide, psq);
Square push = pawn_push(strongSide);
assert(verify_material(pos, strongSide, RookValueMg, 2));
assert(verify_material(pos, weakSide, RookValueMg, 1));
assert(verify_material(pos, strongSide, RookValueMg, 2));
assert(verify_material(pos, weakSide, RookValueMg, 1));
- Square wpsq1 = pos.list<PAWN>(strongSide)[0];
- Square wpsq2 = pos.list<PAWN>(strongSide)[1];
- Square bksq = pos.king_square(weakSide);
+ Square wpsq1 = pos.squares<PAWN>(strongSide)[0];
+ Square wpsq2 = pos.squares<PAWN>(strongSide)[1];
+ Square bksq = pos.square<KING>(weakSide);
// Does the stronger side have a passed pawn?
if (pos.pawn_passed(strongSide, wpsq1) || pos.pawn_passed(strongSide, wpsq2))
// Does the stronger side have a passed pawn?
if (pos.pawn_passed(strongSide, wpsq1) || pos.pawn_passed(strongSide, wpsq2))
&& distance<File>(bksq, wpsq2) <= 1
&& relative_rank(strongSide, bksq) > r)
{
&& distance<File>(bksq, wpsq2) <= 1
&& relative_rank(strongSide, bksq) > r)
{
- switch (r) {
- case RANK_2: return ScaleFactor(10);
- case RANK_3: return ScaleFactor(10);
- case RANK_4: return ScaleFactor(15);
- case RANK_5: return ScaleFactor(20);
- case RANK_6: return ScaleFactor(40);
- default: assert(false);
- }
+ assert(r > RANK_1 && r < RANK_7);
+ return ScaleFactor(KRPPKRPScaleFactors[r]);
assert(pos.count<PAWN>(strongSide) >= 2);
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
assert(pos.count<PAWN>(strongSide) >= 2);
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
// If all pawns are ahead of the king, on a single rook file and
// the king is within one file of the pawns, it's a draw.
if ( !(pawns & ~in_front_bb(weakSide, rank_of(ksq)))
&& !((pawns & ~FileABB) && (pawns & ~FileHBB))
// If all pawns are ahead of the king, on a single rook file and
// the king is within one file of the pawns, it's a draw.
if ( !(pawns & ~in_front_bb(weakSide, rank_of(ksq)))
&& !((pawns & ~FileABB) && (pawns & ~FileHBB))
assert(verify_material(pos, strongSide, BishopValueMg, 1));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
assert(verify_material(pos, strongSide, BishopValueMg, 1));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
- Square pawnSq = pos.list<PAWN>(strongSide)[0];
- Square strongBishopSq = pos.list<BISHOP>(strongSide)[0];
- Square weakBishopSq = pos.list<BISHOP>(weakSide)[0];
- Square weakKingSq = pos.king_square(weakSide);
+ Square pawnSq = pos.square<PAWN>(strongSide);
+ Square strongBishopSq = pos.square<BISHOP>(strongSide);
+ Square weakBishopSq = pos.square<BISHOP>(weakSide);
+ Square weakKingSq = pos.square<KING>(weakSide);
// Case 1: Defending king blocks the pawn, and cannot be driven away
if ( file_of(weakKingSq) == file_of(pawnSq)
// Case 1: Defending king blocks the pawn, and cannot be driven away
if ( file_of(weakKingSq) == file_of(pawnSq)
assert(verify_material(pos, strongSide, BishopValueMg, 2));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
assert(verify_material(pos, strongSide, BishopValueMg, 2));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
if (!opposite_colors(wbsq, bbsq))
return SCALE_FACTOR_NONE;
if (!opposite_colors(wbsq, bbsq))
return SCALE_FACTOR_NONE;
- Square ksq = pos.king_square(weakSide);
- Square psq1 = pos.list<PAWN>(strongSide)[0];
- Square psq2 = pos.list<PAWN>(strongSide)[1];
+ Square ksq = pos.square<KING>(weakSide);
+ Square psq1 = pos.squares<PAWN>(strongSide)[0];
+ Square psq2 = pos.squares<PAWN>(strongSide)[1];
assert(verify_material(pos, strongSide, BishopValueMg, 1));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
assert(verify_material(pos, strongSide, BishopValueMg, 1));
assert(verify_material(pos, weakSide, KnightValueMg, 0));
- Square pawnSq = pos.list<PAWN>(strongSide)[0];
- Square strongBishopSq = pos.list<BISHOP>(strongSide)[0];
- Square weakKingSq = pos.king_square(weakSide);
+ Square pawnSq = pos.square<PAWN>(strongSide);
+ Square strongBishopSq = pos.square<BISHOP>(strongSide);
+ Square weakKingSq = pos.square<KING>(weakSide);
if ( file_of(weakKingSq) == file_of(pawnSq)
&& relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
if ( file_of(weakKingSq) == file_of(pawnSq)
&& relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
// Assume strongSide is white and the pawn is on files A-D
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
// Assume strongSide is white and the pawn is on files A-D
- Square pawnSq = normalize(pos, strongSide, pos.list<PAWN>(strongSide)[0]);
- Square weakKingSq = normalize(pos, strongSide, pos.king_square(weakSide));
+ Square pawnSq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
+ Square weakKingSq = normalize(pos, strongSide, pos.square<KING>(weakSide));
if (pawnSq == SQ_A7 && distance(SQ_A8, weakKingSq) <= 1)
return SCALE_FACTOR_DRAW;
if (pawnSq == SQ_A7 && distance(SQ_A8, weakKingSq) <= 1)
return SCALE_FACTOR_DRAW;
- Square pawnSq = pos.list<PAWN>(strongSide)[0];
- Square bishopSq = pos.list<BISHOP>(weakSide)[0];
- Square weakKingSq = pos.king_square(weakSide);
+ Square pawnSq = pos.square<PAWN>(strongSide);
+ Square bishopSq = pos.square<BISHOP>(weakSide);
+ Square weakKingSq = pos.square<KING>(weakSide);
// King needs to get close to promoting pawn to prevent knight from blocking.
// Rules for this are very tricky, so just approximate.
// King needs to get close to promoting pawn to prevent knight from blocking.
// Rules for this are very tricky, so just approximate.
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
// Assume strongSide is white and the pawn is on files A-D
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
// Assume strongSide is white and the pawn is on files A-D
- Square wksq = normalize(pos, strongSide, pos.king_square(strongSide));
- Square bksq = normalize(pos, strongSide, pos.king_square(weakSide));
- Square psq = normalize(pos, strongSide, pos.list<PAWN>(strongSide)[0]);
+ Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
+ Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
+ Square psq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));