/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2013 Marco Costalba, Joona Kiiski, Tord Romstad
+ Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad
+ Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, 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
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
};
// Table used to drive the king towards a corner square of the
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 num_pawns) {
- return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == num_pawns;
+ bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
+ return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == pawnsCnt;
}
#endif
assert(pos.count<PAWN>(strongSide) == 1);
- if (file_of(pos.list<PAWN>(strongSide)[0]) >= FILE_E)
+ if (file_of(pos.square<PAWN>(strongSide)) >= FILE_E)
sq = Square(sq ^ 7); // Mirror SQ_H1 -> SQ_A1
if (strongSide == BLACK)
// Get the material key of Position out of the given endgame key code
// like "KBPKN". The trick here is to first forge an ad-hoc FEN string
- // and then let a Position object do the work for us. Note that the
- // FEN string could correspond to an illegal position.
+ // and then let a Position object do the work for us.
Key key(const string& code, Color c) {
assert(code.length() > 0 && code.length() < 8);
std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
- string fen = sides[0] + char('0' + int(8 - code.length()))
- + sides[1] + "/8/8/8/8/8/8/8 w - - 0 10";
+ string fen = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/"
+ + sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10";
- return Position(fen, false, NULL).material_key();
+ return Position(fen, false, nullptr).material_key();
}
- template<typename M>
- void delete_endgame(const typename M::value_type& p) { delete p.second; }
-
} // namespace
add<KRKN>("KRKN");
add<KQKP>("KQKP");
add<KQKR>("KQKR");
- add<KBBKN>("KBBKN");
add<KNPK>("KNPK");
add<KNPKB>("KNPKB");
add<KRPPKRP>("KRPPKRP");
}
-Endgames::~Endgames() {
-
- for_each(m1.begin(), m1.end(), delete_endgame<M1>);
- for_each(m2.begin(), m2.end(), delete_endgame<M2>);
-}
-template<EndgameType E>
+template<EndgameType E, typename T>
void Endgames::add(const string& code) {
-
- map((Endgame<E>*)0)[key(code, WHITE)] = new Endgame<E>(WHITE);
- map((Endgame<E>*)0)[key(code, BLACK)] = new Endgame<E>(BLACK);
+ map<T>()[key(code, WHITE)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(WHITE));
+ map<T>()[key(code, BLACK)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(BLACK));
}
if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
return VALUE_DRAW;
- Square winnerKSq = pos.king_square(strongSide);
- Square loserKSq = pos.king_square(weakSide);
+ Square winnerKSq = pos.square<KING>(strongSide);
+ Square loserKSq = pos.square<KING>(weakSide);
Value result = pos.non_pawn_material(strongSide)
+ pos.count<PAWN>(strongSide) * PawnValueEg
+ PushToEdges[loserKSq]
- + PushClose[square_distance(winnerKSq, loserKSq)];
+ + PushClose[distance(winnerKSq, loserKSq)];
if ( pos.count<QUEEN>(strongSide)
|| pos.count<ROOK>(strongSide)
- || pos.bishop_pair(strongSide))
- result += VALUE_KNOWN_WIN;
+ ||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
+ ||(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);
return strongSide == pos.side_to_move() ? result : -result;
}
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
}
Value result = VALUE_KNOWN_WIN
- + PushClose[square_distance(winnerKSq, loserKSq)]
+ + PushClose[distance(winnerKSq, loserKSq)]
+ PushToCorners[loserKSq];
return strongSide == pos.side_to_move() ? result : -result;
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));
Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
- if (!Bitbases::probe_kpk(wksq, psq, bksq, us))
+ if (!Bitbases::probe(wksq, psq, bksq, us))
return VALUE_DRAW;
Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(psq));
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));
- Square queeningSq = file_of(psq) | RANK_1;
+ Square queeningSq = make_square(file_of(psq), RANK_1);
Value result;
// If the stronger side's king is in front of the pawn, it's a win
if (wksq < psq && file_of(wksq) == file_of(psq))
- result = RookValueEg - Value(square_distance(wksq, psq));
+ result = RookValueEg - distance(wksq, psq);
// If the weaker side's king is too far from the pawn and the rook,
// it's a win.
- else if ( square_distance(bksq, psq) >= 3 + (pos.side_to_move() == weakSide)
- && square_distance(bksq, rsq) >= 3)
- result = RookValueEg - Value(square_distance(wksq, psq));
+ else if ( distance(bksq, psq) >= 3 + (pos.side_to_move() == weakSide)
+ && distance(bksq, rsq) >= 3)
+ result = RookValueEg - distance(wksq, psq);
// If the pawn is far advanced and supported by the defending king,
// the position is drawish
else if ( rank_of(bksq) <= RANK_3
- && square_distance(bksq, psq) == 1
+ && distance(bksq, psq) == 1
&& rank_of(wksq) >= RANK_4
- && square_distance(wksq, psq) > 2 + (pos.side_to_move() == strongSide))
- result = Value(80 - square_distance(wksq, psq) * 8);
+ && distance(wksq, psq) > 2 + (pos.side_to_move() == strongSide))
+ result = Value(80) - 8 * distance(wksq, psq);
else
- result = Value(200)
- - Value(square_distance(wksq, psq + DELTA_S) * 8)
- + Value(square_distance(bksq, psq + DELTA_S) * 8)
- + Value(square_distance(psq, queeningSq) * 8);
+ result = Value(200) - 8 * ( distance(wksq, psq + DELTA_S)
+ - distance(bksq, psq + DELTA_S)
+ - distance(psq, queeningSq));
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.king_square(weakSide)]);
+ Value result = Value(PushToEdges[pos.square<KING>(weakSide)]);
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.king_square(weakSide);
- Square bnsq = pos.list<KNIGHT>(weakSide)[0];
- Value result = Value(PushToEdges[bksq] + PushAway[square_distance(bksq, bnsq)]);
+ Square bksq = pos.square<KING>(weakSide);
+ Square bnsq = pos.square<KNIGHT>(weakSide);
+ 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));
- 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);
- Value result = Value(PushClose[square_distance(winnerKSq, loserKSq)]);
+ Value result = Value(PushClose[distance(winnerKSq, loserKSq)]);
if ( relative_rank(weakSide, pawnSq) != RANK_7
- || square_distance(loserKSq, pawnSq) != 1
+ || distance(loserKSq, pawnSq) != 1
|| !((FileABB | FileCBB | FileFBB | FileHBB) & pawnSq))
result += QueenValueEg - PawnValueEg;
assert(verify_material(pos, strongSide, QueenValueMg, 0));
assert(verify_material(pos, weakSide, RookValueMg, 0));
- Square winnerKSq = pos.king_square(strongSide);
- Square loserKSq = pos.king_square(weakSide);
+ Square winnerKSq = pos.square<KING>(strongSide);
+ Square loserKSq = pos.square<KING>(weakSide);
Value result = QueenValueEg
- RookValueEg
+ PushToEdges[loserKSq]
- + PushClose[square_distance(winnerKSq, loserKSq)];
-
- return strongSide == pos.side_to_move() ? result : -result;
-}
-
-
-/// KBB vs KN. This is almost always a win. We try to push the enemy king to a corner
-/// and away from his knight. For a reference of this difficult endgame see:
-/// en.wikipedia.org/wiki/Chess_endgame#Effect_of_tablebases_on_endgame_theory
-
-template<>
-Value Endgame<KBBKN>::operator()(const Position& pos) const {
-
- assert(verify_material(pos, strongSide, 2 * BishopValueMg, 0));
- assert(verify_material(pos, weakSide, KnightValueMg, 0));
-
- Square winnerKSq = pos.king_square(strongSide);
- Square loserKSq = pos.king_square(weakSide);
- Square knightSq = pos.list<KNIGHT>(weakSide)[0];
-
- Value result = VALUE_KNOWN_WIN
- + PushToCorners[loserKSq]
- + PushClose[square_distance(winnerKSq, loserKSq)]
- + PushAway[square_distance(loserKSq, knightSq)];
+ + PushClose[distance(winnerKSq, loserKSq)];
return strongSide == pos.side_to_move() ? result : -result;
}
/// Some cases of trivial draws
template<> Value Endgame<KNNK>::operator()(const Position&) const { return VALUE_DRAW; }
-template<> Value Endgame<KmmKm>::operator()(const Position&) const { return VALUE_DRAW; }
/// KB and one or more pawns vs K. It checks for draws with rook pawns and
// be detected even when the weaker side has some pawns.
Bitboard pawns = pos.pieces(strongSide, PAWN);
- File pawnFile = file_of(pos.list<PAWN>(strongSide)[0]);
+ File pawnsFile = file_of(lsb(pawns));
- // 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, 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)
- && square_distance(queeningSq, kingSq) <= 1)
+ && distance(queeningSq, kingSq) <= 1)
return SCALE_FACTOR_DRAW;
}
// If all the pawns are on the same B or G file, then it's potentially a draw
- if ( (pawnFile == FILE_B || pawnFile == FILE_G)
- && !(pos.pieces(PAWN) & ~file_bb(pawnFile))
+ if ( (pawnsFile == FILE_B || pawnsFile == FILE_G)
+ && !(pos.pieces(PAWN) & ~file_bb(pawnsFile))
&& 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
&& (pos.pieces(strongSide, PAWN) & (weakPawnSq + pawn_push(weakSide)))
&& (opposite_colors(bishopSq, weakPawnSq) || pos.count<PAWN>(strongSide) == 1))
{
- int strongKingDist = square_distance(weakPawnSq, strongKingSq);
- int weakKingDist = square_distance(weakPawnSq, weakKingSq);
+ int strongKingDist = distance(weakPawnSq, strongKingSq);
+ int weakKingDist = distance(weakPawnSq, weakKingSq);
// It's a draw if the weak king is on its back two ranks, within 2
// squares of the blocking pawn and the strong king is not
assert(pos.count<ROOK>(weakSide) == 1);
assert(pos.count<PAWN>(weakSide) >= 1);
- Square kingSq = pos.king_square(weakSide);
- Square rsq = pos.list<ROOK>(weakSide)[0];
+ Square kingSq = pos.square<KING>(weakSide);
+ Square rsq = pos.square<ROOK>(weakSide);
if ( relative_rank(weakSide, kingSq) <= RANK_2
- && relative_rank(weakSide, pos.king_square(strongSide)) >= RANK_4
+ && relative_rank(weakSide, pos.square<KING>(strongSide)) >= RANK_4
&& 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
- 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));
File f = file_of(wpsq);
Rank r = rank_of(wpsq);
- Square queeningSq = f | RANK_8;
+ Square queeningSq = make_square(f, RANK_8);
int tempo = (pos.side_to_move() == strongSide);
// If the pawn is not too far advanced and the defending king defends the
// queening square, use the third-rank defence.
if ( r <= RANK_5
- && square_distance(bksq, queeningSq) <= 1
+ && distance(bksq, queeningSq) <= 1
&& wksq <= SQ_H5
&& (rank_of(brsq) == RANK_6 || (r <= RANK_3 && rank_of(wrsq) != RANK_6)))
return SCALE_FACTOR_DRAW;
// The defending side saves a draw by checking from behind in case the pawn
// has advanced to the 6th rank with the king behind.
if ( r == RANK_6
- && square_distance(bksq, queeningSq) <= 1
+ && distance(bksq, queeningSq) <= 1
&& rank_of(wksq) + tempo <= RANK_6
- && (rank_of(brsq) == RANK_1 || (!tempo && abs(file_of(brsq) - f) >= 3)))
+ && (rank_of(brsq) == RANK_1 || (!tempo && distance<File>(brsq, wpsq) >= 3)))
return SCALE_FACTOR_DRAW;
if ( r >= RANK_6
&& bksq == queeningSq
&& rank_of(brsq) == RANK_1
- && (!tempo || square_distance(wksq, wpsq) >= 2))
+ && (!tempo || distance(wksq, wpsq) >= 2))
return SCALE_FACTOR_DRAW;
// White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
// away, it's a draw.
if ( r <= RANK_5
&& bksq == wpsq + DELTA_N
- && square_distance(wksq, wpsq) - tempo >= 2
- && square_distance(wksq, brsq) - tempo >= 2)
+ && distance(wksq, wpsq) - tempo >= 2
+ && distance(wksq, brsq) - tempo >= 2)
return SCALE_FACTOR_DRAW;
// Pawn on the 7th rank supported by the rook from behind usually wins if the
&& f != FILE_A
&& file_of(wrsq) == f
&& wrsq != queeningSq
- && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
- && (square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo))
- return ScaleFactor(SCALE_FACTOR_MAX - 2 * square_distance(wksq, queeningSq));
+ && (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
+ && (distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo))
+ return ScaleFactor(SCALE_FACTOR_MAX - 2 * distance(wksq, queeningSq));
// Similar to the above, but with the pawn further back
if ( f != FILE_A
&& file_of(wrsq) == f
&& wrsq < wpsq
- && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
- && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wpsq + DELTA_N) - 2 + tempo)
- && ( square_distance(bksq, wrsq) + tempo >= 3
- || ( square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo
- && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wrsq) + tempo))))
+ && (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
+ && (distance(wksq, wpsq + DELTA_N) < distance(bksq, wpsq + DELTA_N) - 2 + tempo)
+ && ( distance(bksq, wrsq) + tempo >= 3
+ || ( distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo
+ && (distance(wksq, wpsq + DELTA_N) < distance(bksq, wrsq) + tempo))))
return ScaleFactor( SCALE_FACTOR_MAX
- - 8 * square_distance(wpsq, queeningSq)
- - 2 * square_distance(wksq, queeningSq));
+ - 8 * distance(wpsq, queeningSq)
+ - 2 * distance(wksq, queeningSq));
// If the pawn is not far advanced and the defending king is somewhere in
// the pawn's path, it's probably a draw.
{
if (file_of(bksq) == file_of(wpsq))
return ScaleFactor(10);
- if ( abs(file_of(bksq) - file_of(wpsq)) == 1
- && square_distance(wksq, bksq) > 2)
- return ScaleFactor(24 - 2 * square_distance(wksq, bksq));
+ if ( distance<File>(bksq, wpsq) == 1
+ && distance(wksq, bksq) > 2)
+ return ScaleFactor(24 - 2 * distance(wksq, bksq));
}
return SCALE_FACTOR_NONE;
}
// Test for a rook pawn
if (pos.pieces(PAWN) & (FileABB | FileHBB))
{
- 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);
// corner but not trapped there.
if (rk == RANK_5 && !opposite_colors(bsq, psq))
{
- int d = square_distance(psq + 3 * push, ksq);
+ int d = distance(psq + 3 * push, ksq);
- if (d <= 2 && !(d == 0 && ksq == pos.king_square(strongSide) + 2 * push))
+ if (d <= 2 && !(d == 0 && ksq == pos.square<KING>(strongSide) + 2 * push))
return ScaleFactor(24);
else
return ScaleFactor(48);
// pawn from a reasonable distance and the defending king is near
// the corner
if ( rk == RANK_6
- && square_distance(psq + 2 * push, ksq) <= 1
+ && distance(psq + 2 * push, ksq) <= 1
&& (PseudoAttacks[BISHOP][bsq] & (psq + push))
- && file_distance(bsq, psq) >= 2)
+ && distance<File>(bsq, psq) >= 2)
return ScaleFactor(8);
}
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))
Rank r = std::max(relative_rank(strongSide, wpsq1), relative_rank(strongSide, wpsq2));
- if ( file_distance(bksq, wpsq1) <= 1
- && file_distance(bksq, wpsq2) <= 1
+ if ( distance<File>(bksq, wpsq1) <= 1
+ && 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]);
}
return SCALE_FACTOR_NONE;
}
assert(pos.count<PAWN>(strongSide) >= 2);
assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
- Square ksq = pos.king_square(weakSide);
+ Square ksq = pos.square<KING>(weakSide);
Bitboard pawns = pos.pieces(strongSide, PAWN);
- Square psq = pos.list<PAWN>(strongSide)[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))
- && file_distance(ksq, psq) <= 1)
+ && distance<File>(ksq, lsb(pawns)) <= 1)
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
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)
return SCALE_FACTOR_DRAW;
if ( (pos.attacks_from<BISHOP>(weakBishopSq) & path)
- && square_distance(weakBishopSq, pawnSq) >= 3)
+ && distance(weakBishopSq, pawnSq) >= 3)
return SCALE_FACTOR_DRAW;
}
}
assert(verify_material(pos, strongSide, BishopValueMg, 2));
assert(verify_material(pos, weakSide, BishopValueMg, 0));
- Square wbsq = pos.list<BISHOP>(strongSide)[0];
- Square bbsq = pos.list<BISHOP>(weakSide)[0];
+ Square wbsq = pos.square<BISHOP>(strongSide);
+ Square bbsq = pos.square<BISHOP>(weakSide);
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];
Rank r1 = rank_of(psq1);
Rank r2 = rank_of(psq2);
Square blockSq1, blockSq2;
if (relative_rank(strongSide, psq1) > relative_rank(strongSide, psq2))
{
blockSq1 = psq1 + pawn_push(strongSide);
- blockSq2 = file_of(psq2) | rank_of(psq1);
+ blockSq2 = make_square(file_of(psq2), rank_of(psq1));
}
else
{
blockSq1 = psq2 + pawn_push(strongSide);
- blockSq2 = file_of(psq1) | rank_of(psq2);
+ blockSq2 = make_square(file_of(psq1), rank_of(psq2));
}
- switch (file_distance(psq1, psq2))
+ switch (distance<File>(psq1, psq2))
{
case 0:
// Both pawns are on the same file. It's an easy draw if the defender firmly
&& opposite_colors(ksq, wbsq)
&& ( bbsq == blockSq2
|| (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(weakSide, BISHOP))
- || abs(r1 - r2) >= 2))
+ || distance(r1, r2) >= 2))
return SCALE_FACTOR_DRAW;
else if ( ksq == blockSq2
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)
/// KNP vs K. There is a single rule: if the pawn is a rook pawn on the 7th rank
-/// and the defending king prevents the pawn from advancing the position is drawn.
+/// and the defending king prevents the pawn from advancing, the position is drawn.
template<>
ScaleFactor Endgame<KNPK>::operator()(const Position& pos) const {
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 && square_distance(SQ_A8, weakKingSq) <= 1)
+ if (pawnSq == SQ_A7 && distance(SQ_A8, weakKingSq) <= 1)
return SCALE_FACTOR_DRAW;
return SCALE_FACTOR_NONE;
template<>
ScaleFactor Endgame<KNPKB>::operator()(const Position& pos) const {
- 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.
if (forward_bb(strongSide, pawnSq) & pos.attacks_from<BISHOP>(bishopSq))
- return ScaleFactor(square_distance(weakKingSq, pawnSq));
+ return ScaleFactor(distance(weakKingSq, pawnSq));
return SCALE_FACTOR_NONE;
}
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));
Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
// 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.
- return Bitbases::probe_kpk(wksq, psq, bksq, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
+ return Bitbases::probe(wksq, psq, bksq, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;
}