X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fendgame.cpp;h=fd283ad9d975cc10fa9a10dc6faef7ed54eb6752;hp=cf38009fa2a0f16baf69d017581c38d339085bcd;hb=e304db9d1ecf6a2318708483c90fadecf4fac4ee;hpb=4a8c1b24702ddf577853d72962cee6735a0235da diff --git a/src/endgame.cpp b/src/endgame.cpp index cf38009f..fd283ad9 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -1,7 +1,7 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Copyright (C) 2004-2008 Tord Romstad (Glaurung author) - Copyright (C) 2008-2010 Marco Costalba, Joona Kiiski, Tord Romstad + Copyright (C) 2008-2012 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 @@ -20,19 +20,18 @@ #include #include +#include "bitboard.h" #include "bitcount.h" #include "endgame.h" -#include "pawns.h" +#include "movegen.h" using std::string; -extern uint32_t probe_kpk_bitbase(Square wksq, Square wpsq, Square bksq, Color stm); - namespace { // Table used to drive the defending king towards the edge of the board // in KX vs K and KQ vs KR endgames. - const int MateTable[64] = { + const int MateTable[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, @@ -45,7 +44,7 @@ namespace { // Table used to drive the defending king towards a corner square of the // right color in KBN vs K endgames. - const int KBNKMateTable[64] = { + const int KBNKMateTable[SQUARE_NB] = { 200, 190, 180, 170, 160, 150, 140, 130, 190, 180, 170, 160, 150, 140, 130, 140, 180, 170, 155, 140, 140, 125, 140, 150, @@ -60,34 +59,24 @@ namespace { // the two kings in basic endgames. const int DistanceBonus[8] = { 0, 0, 100, 80, 60, 40, 20, 10 }; - // Build corresponding key code for the opposite color: "KBPKN" -> "KNKBP" - const string swap_colors(const string& keyCode) { - - size_t idx = keyCode.find('K', 1); - return keyCode.substr(idx) + keyCode.substr(0, idx); - } + // Get the material key of a 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 to do the work for us. Note that the + // fen string could correspond to an illegal position. + Key key(const string& code, Color c) { - // Get the material key of a position out of the given endgame key code - // like "KBPKN". The trick here is to first build up a FEN string and then - // let a Position object to do the work for us. Note that the FEN string - // could correspond to an illegal position. - Key mat_key(const string& keyCode) { + assert(code.length() > 0 && code.length() < 8); + assert(code[0] == 'K'); - assert(keyCode.length() > 0 && keyCode.length() < 8); - assert(keyCode[0] == 'K'); + string sides[] = { code.substr(code.find('K', 1)), // Weaker + code.substr(0, code.find('K', 1)) }; // Stronger - string fen; - size_t i = 0; + std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower); - // First add white and then black pieces - do fen += keyCode[i]; while (keyCode[++i] != 'K'); - do fen += char(tolower(keyCode[i])); while (++i < keyCode.length()); + string fen = sides[0] + char('0' + int(8 - code.length())) + + sides[1] + "/8/8/8/8/8/8/8 w - - 0 10"; - // Add file padding and remaining empty ranks - fen += string(1, '0' + int(8 - keyCode.length())) + "/8/8/8/8/8/8/8 w - - 0 10"; - - // Build a Position out of the fen string and get its material key - return Position(fen, false, 0).material_key(); + return Position(fen, false, NULL).material_key(); } template @@ -96,10 +85,7 @@ namespace { } // namespace -/// Endgames member definitions - -template<> const Endgames::M1& Endgames::map() const { return m1; } -template<> const Endgames::M2& Endgames::map() const { return m2; } +/// Endgames members definitions Endgames::Endgames() { @@ -127,13 +113,10 @@ Endgames::~Endgames() { } template -void Endgames::add(const string& keyCode) { +void Endgames::add(const string& code) { - typedef typename eg_family::type T; - typedef typename Map::type M; - - const_cast(map()).insert(std::make_pair(mat_key(keyCode), new Endgame(WHITE))); - const_cast(map()).insert(std::make_pair(mat_key(swap_colors(keyCode)), new Endgame(BLACK))); + map((Endgame*)0)[key(code, WHITE)] = new Endgame(WHITE); + map((Endgame*)0)[key(code, BLACK)] = new Endgame(BLACK); } @@ -147,19 +130,26 @@ Value Endgame::operator()(const Position& pos) const { assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO); assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO); + // Stalemate detection with lone king + if ( pos.side_to_move() == weakerSide + && !pos.in_check() + && !MoveList(pos).size()) { + return VALUE_DRAW; + } + Square winnerKSq = pos.king_square(strongerSide); Square loserKSq = pos.king_square(weakerSide); Value result = pos.non_pawn_material(strongerSide) - + pos.piece_count(strongerSide, PAWN) * PawnValueEndgame + + pos.piece_count(strongerSide, PAWN) * PawnValueEg + MateTable[loserKSq] + DistanceBonus[square_distance(winnerKSq, loserKSq)]; if ( pos.piece_count(strongerSide, QUEEN) || pos.piece_count(strongerSide, ROOK) - || pos.piece_count(strongerSide, BISHOP) > 1) - // TODO: check for two equal-colored bishops! - result += VALUE_KNOWN_WIN; + || pos.bishop_pair(strongerSide)) { + result += VALUE_KNOWN_WIN; + } return strongerSide == pos.side_to_move() ? result : -result; } @@ -172,7 +162,7 @@ Value Endgame::operator()(const Position& pos) const { assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO); assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO); - assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame + BishopValueMidgame); + assert(pos.non_pawn_material(strongerSide) == KnightValueMg + BishopValueMg); assert(pos.piece_count(strongerSide, BISHOP) == 1); assert(pos.piece_count(strongerSide, KNIGHT) == 1); assert(pos.piece_count(strongerSide, PAWN) == 0); @@ -219,10 +209,10 @@ Value Endgame::operator()(const Position& pos) const { } else { - wksq = flip(pos.king_square(BLACK)); - bksq = flip(pos.king_square(WHITE)); - wpsq = flip(pos.piece_list(BLACK, PAWN)[0]); - stm = flip(pos.side_to_move()); + wksq = ~pos.king_square(BLACK); + bksq = ~pos.king_square(WHITE); + wpsq = ~pos.piece_list(BLACK, PAWN)[0]; + stm = ~pos.side_to_move(); } if (file_of(wpsq) >= FILE_E) @@ -232,12 +222,10 @@ Value Endgame::operator()(const Position& pos) const { wpsq = mirror(wpsq); } - if (!probe_kpk_bitbase(wksq, wpsq, bksq, stm)) + if (!Bitbases::probe_kpk(wksq, wpsq, bksq, stm)) return VALUE_DRAW; - Value result = VALUE_KNOWN_WIN - + PawnValueEndgame - + Value(rank_of(wpsq)); + Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(wpsq)); return strongerSide == pos.side_to_move() ? result : -result; } @@ -250,7 +238,7 @@ Value Endgame::operator()(const Position& pos) const { template<> Value Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); + assert(pos.non_pawn_material(strongerSide) == RookValueMg); assert(pos.piece_count(strongerSide, PAWN) == 0); assert(pos.non_pawn_material(weakerSide) == 0); assert(pos.piece_count(weakerSide, PAWN) == 1); @@ -265,24 +253,24 @@ Value Endgame::operator()(const Position& pos) const { if (strongerSide == BLACK) { - wksq = flip(wksq); - wrsq = flip(wrsq); - bksq = flip(bksq); - bpsq = flip(bpsq); + wksq = ~wksq; + wrsq = ~wrsq; + bksq = ~bksq; + bpsq = ~bpsq; } - Square queeningSq = make_square(file_of(bpsq), RANK_1); + Square queeningSq = file_of(bpsq) | RANK_1; Value result; // If the stronger side's king is in front of the pawn, it's a win if (wksq < bpsq && file_of(wksq) == file_of(bpsq)) - result = RookValueEndgame - Value(square_distance(wksq, bpsq)); + result = RookValueEg - Value(square_distance(wksq, bpsq)); // If the weaker side's king is too far from the pawn and the rook, // it's a win else if ( square_distance(bksq, bpsq) - (tempo ^ 1) >= 3 && square_distance(bksq, wrsq) >= 3) - result = RookValueEndgame - Value(square_distance(wksq, bpsq)); + result = RookValueEg - Value(square_distance(wksq, bpsq)); // If the pawn is far advanced and supported by the defending king, // the position is drawish @@ -307,9 +295,9 @@ Value Endgame::operator()(const Position& pos) const { template<> Value Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); + assert(pos.non_pawn_material(strongerSide) == RookValueMg); assert(pos.piece_count(strongerSide, PAWN) == 0); - assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame); + assert(pos.non_pawn_material(weakerSide) == BishopValueMg); assert(pos.piece_count(weakerSide, PAWN) == 0); assert(pos.piece_count(weakerSide, BISHOP) == 1); @@ -323,9 +311,9 @@ Value Endgame::operator()(const Position& pos) const { template<> Value Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); + assert(pos.non_pawn_material(strongerSide) == RookValueMg); assert(pos.piece_count(strongerSide, PAWN) == 0); - assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame); + assert(pos.non_pawn_material(weakerSide) == KnightValueMg); assert(pos.piece_count(weakerSide, PAWN) == 0); assert(pos.piece_count(weakerSide, KNIGHT) == 1); @@ -346,16 +334,16 @@ Value Endgame::operator()(const Position& pos) const { template<> Value Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame); + assert(pos.non_pawn_material(strongerSide) == QueenValueMg); assert(pos.piece_count(strongerSide, PAWN) == 0); - assert(pos.non_pawn_material(weakerSide) == RookValueMidgame); + assert(pos.non_pawn_material(weakerSide) == RookValueMg); assert(pos.piece_count(weakerSide, PAWN) == 0); Square winnerKSq = pos.king_square(strongerSide); Square loserKSq = pos.king_square(weakerSide); - Value result = QueenValueEndgame - - RookValueEndgame + Value result = QueenValueEg + - RookValueEg + MateTable[loserKSq] + DistanceBonus[square_distance(winnerKSq, loserKSq)]; @@ -366,12 +354,12 @@ template<> Value Endgame::operator()(const Position& pos) const { assert(pos.piece_count(strongerSide, BISHOP) == 2); - assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame); + assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMg); assert(pos.piece_count(weakerSide, KNIGHT) == 1); - assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame); + assert(pos.non_pawn_material(weakerSide) == KnightValueMg); assert(!pos.pieces(PAWN)); - Value result = BishopValueEndgame; + Value result = BishopValueEg; Square wksq = pos.king_square(strongerSide); Square bksq = pos.king_square(weakerSide); Square nsq = pos.piece_list(weakerSide, KNIGHT)[0]; @@ -383,7 +371,7 @@ Value Endgame::operator()(const Position& pos) const { result += Value(square_distance(bksq, nsq) * 32); // Bonus for restricting the knight's mobility - result += Value((8 - count_1s(pos.attacks_from(nsq))) * 8); + result += Value((8 - popcount(pos.attacks_from(nsq))) * 8); return strongerSide == pos.side_to_move() ? result : -result; } @@ -408,29 +396,29 @@ Value Endgame::operator()(const Position&) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame); + assert(pos.non_pawn_material(strongerSide) == BishopValueMg); assert(pos.piece_count(strongerSide, BISHOP) == 1); assert(pos.piece_count(strongerSide, PAWN) >= 1); // No assertions about the material of weakerSide, because we want draws to // be detected even when the weaker side has some pawns. - Bitboard pawns = pos.pieces(PAWN, strongerSide); + Bitboard pawns = pos.pieces(strongerSide, PAWN); File pawnFile = file_of(pos.piece_list(strongerSide, PAWN)[0]); // All pawns are on a single rook file ? - if ( (pawnFile == FILE_A || pawnFile == FILE_H) + if ( (pawnFile == FILE_A || pawnFile == FILE_H) && !(pawns & ~file_bb(pawnFile))) { Square bishopSq = pos.piece_list(strongerSide, BISHOP)[0]; - Square queeningSq = relative_square(strongerSide, make_square(pawnFile, RANK_8)); + Square queeningSq = relative_square(strongerSide, pawnFile | RANK_8); Square kingSq = pos.king_square(weakerSide); if ( opposite_colors(queeningSq, bishopSq) && abs(file_of(kingSq) - pawnFile) <= 1) { // The bishop has the wrong color, and the defending king is on the - // file of the pawn(s) or the neighboring file. Find the rank of the + // file of the pawn(s) or the adjacent file. Find the rank of the // frontmost pawn. Rank rank; if (strongerSide == WHITE) @@ -460,7 +448,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame); + assert(pos.non_pawn_material(strongerSide) == QueenValueMg); assert(pos.piece_count(strongerSide, QUEEN) == 1); assert(pos.piece_count(strongerSide, PAWN) == 0); assert(pos.piece_count(weakerSide, ROOK) == 1); @@ -469,12 +457,12 @@ ScaleFactor Endgame::operator()(const Position& pos) const { Square kingSq = pos.king_square(weakerSide); if ( relative_rank(weakerSide, kingSq) <= RANK_2 && relative_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4 - && (pos.pieces(ROOK, weakerSide) & rank_bb(relative_rank(weakerSide, RANK_3))) - && (pos.pieces(PAWN, weakerSide) & rank_bb(relative_rank(weakerSide, RANK_2))) - && (pos.attacks_from(kingSq) & pos.pieces(PAWN, weakerSide))) + && (pos.pieces(weakerSide, ROOK) & rank_bb(relative_rank(weakerSide, RANK_3))) + && (pos.pieces(weakerSide, PAWN) & rank_bb(relative_rank(weakerSide, RANK_2))) + && (pos.attacks_from(kingSq) & pos.pieces(weakerSide, PAWN))) { Square rsq = pos.piece_list(weakerSide, ROOK)[0]; - if (pos.attacks_from(rsq, strongerSide) & pos.pieces(PAWN, weakerSide)) + if (pos.attacks_from(rsq, strongerSide) & pos.pieces(weakerSide, PAWN)) return SCALE_FACTOR_DRAW; } return SCALE_FACTOR_NONE; @@ -490,9 +478,9 @@ ScaleFactor Endgame::operator()(const Position& pos) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); + assert(pos.non_pawn_material(strongerSide) == RookValueMg); assert(pos.piece_count(strongerSide, PAWN) == 1); - assert(pos.non_pawn_material(weakerSide) == RookValueMidgame); + assert(pos.non_pawn_material(weakerSide) == RookValueMg); assert(pos.piece_count(weakerSide, PAWN) == 0); Square wksq = pos.king_square(strongerSide); @@ -505,11 +493,11 @@ ScaleFactor Endgame::operator()(const Position& pos) const { // pawn is on the left half of the board. if (strongerSide == BLACK) { - wksq = flip(wksq); - wrsq = flip(wrsq); - wpsq = flip(wpsq); - bksq = flip(bksq); - brsq = flip(brsq); + wksq = ~wksq; + wrsq = ~wrsq; + wpsq = ~wpsq; + bksq = ~bksq; + brsq = ~brsq; } if (file_of(wpsq) > FILE_D) { @@ -522,7 +510,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { File f = file_of(wpsq); Rank r = rank_of(wpsq); - Square queeningSq = make_square(f, RANK_8); + Square queeningSq = f | RANK_8; int tempo = (pos.side_to_move() == strongerSide); // If the pawn is not too far advanced and the defending king defends the @@ -608,9 +596,9 @@ ScaleFactor Endgame::operator()(const Position& pos) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == RookValueMidgame); + assert(pos.non_pawn_material(strongerSide) == RookValueMg); assert(pos.piece_count(strongerSide, PAWN) == 2); - assert(pos.non_pawn_material(weakerSide) == RookValueMidgame); + assert(pos.non_pawn_material(weakerSide) == RookValueMg); assert(pos.piece_count(weakerSide, PAWN) == 1); Square wpsq1 = pos.piece_list(strongerSide, PAWN)[0]; @@ -652,15 +640,15 @@ ScaleFactor Endgame::operator()(const Position& pos) const { assert(pos.piece_count(weakerSide, PAWN) == 0); Square ksq = pos.king_square(weakerSide); - Bitboard pawns = pos.pieces(PAWN, strongerSide); + Bitboard pawns = pos.pieces(strongerSide, PAWN); // Are all pawns on the 'a' file? if (!(pawns & ~FileABB)) { // Does the defending king block the pawns? if ( square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1 - || ( file_of(ksq) == FILE_A - && !in_front_bb(strongerSide, ksq) & pawns)) + || ( file_of(ksq) == FILE_A + && !(in_front_bb(strongerSide, ksq) & pawns))) return SCALE_FACTOR_DRAW; } // Are all pawns on the 'h' file? @@ -668,8 +656,8 @@ ScaleFactor Endgame::operator()(const Position& pos) const { { // Does the defending king block the pawns? if ( square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1 - || ( file_of(ksq) == FILE_H - && !in_front_bb(strongerSide, ksq) & pawns)) + || ( file_of(ksq) == FILE_H + && !(in_front_bb(strongerSide, ksq) & pawns))) return SCALE_FACTOR_DRAW; } return SCALE_FACTOR_NONE; @@ -683,10 +671,10 @@ ScaleFactor Endgame::operator()(const Position& pos) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame); + assert(pos.non_pawn_material(strongerSide) == BishopValueMg); assert(pos.piece_count(strongerSide, BISHOP) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1); - assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame); + assert(pos.non_pawn_material(weakerSide) == BishopValueMg); assert(pos.piece_count(weakerSide, BISHOP) == 1); assert(pos.piece_count(weakerSide, PAWN) == 0); @@ -719,9 +707,9 @@ ScaleFactor Endgame::operator()(const Position& pos) const { return SCALE_FACTOR_DRAW; else { - Bitboard path = squares_in_front_of(strongerSide, pawnSq); + Bitboard path = forward_bb(strongerSide, pawnSq); - if (path & pos.pieces(KING, weakerSide)) + if (path & pos.pieces(weakerSide, KING)) return SCALE_FACTOR_DRAW; if ( (pos.attacks_from(weakerBishopSq) & path) @@ -738,10 +726,10 @@ ScaleFactor Endgame::operator()(const Position& pos) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame); + assert(pos.non_pawn_material(strongerSide) == BishopValueMg); assert(pos.piece_count(strongerSide, BISHOP) == 1); assert(pos.piece_count(strongerSide, PAWN) == 2); - assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame); + assert(pos.non_pawn_material(weakerSide) == BishopValueMg); assert(pos.piece_count(weakerSide, BISHOP) == 1); assert(pos.piece_count(weakerSide, PAWN) == 0); @@ -761,12 +749,12 @@ ScaleFactor Endgame::operator()(const Position& pos) const { if (relative_rank(strongerSide, psq1) > relative_rank(strongerSide, psq2)) { blockSq1 = psq1 + pawn_push(strongerSide); - blockSq2 = make_square(file_of(psq2), rank_of(psq1)); + blockSq2 = file_of(psq2) | rank_of(psq1); } else { blockSq1 = psq2 + pawn_push(strongerSide); - blockSq2 = make_square(file_of(psq1), rank_of(psq2)); + blockSq2 = file_of(psq1) | rank_of(psq2); } switch (file_distance(psq1, psq2)) @@ -782,20 +770,20 @@ ScaleFactor Endgame::operator()(const Position& pos) const { return SCALE_FACTOR_NONE; case 1: - // Pawns on neighboring files. Draw if defender firmly controls the square + // Pawns on adjacent files. Draw if defender firmly controls the square // in front of the frontmost pawn's path, and the square diagonally behind // this square on the file of the other pawn. if ( ksq == blockSq1 && opposite_colors(ksq, wbsq) && ( bbsq == blockSq2 - || (pos.attacks_from(blockSq2) & pos.pieces(BISHOP, weakerSide)) + || (pos.attacks_from(blockSq2) & pos.pieces(weakerSide, BISHOP)) || abs(r1 - r2) >= 2)) return SCALE_FACTOR_DRAW; else if ( ksq == blockSq2 && opposite_colors(ksq, wbsq) && ( bbsq == blockSq1 - || (pos.attacks_from(blockSq1) & pos.pieces(BISHOP, weakerSide)))) + || (pos.attacks_from(blockSq1) & pos.pieces(weakerSide, BISHOP)))) return SCALE_FACTOR_DRAW; else return SCALE_FACTOR_NONE; @@ -813,10 +801,10 @@ ScaleFactor Endgame::operator()(const Position& pos) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame); + assert(pos.non_pawn_material(strongerSide) == BishopValueMg); assert(pos.piece_count(strongerSide, BISHOP) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1); - assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame); + assert(pos.non_pawn_material(weakerSide) == KnightValueMg); assert(pos.piece_count(weakerSide, KNIGHT) == 1); assert(pos.piece_count(weakerSide, PAWN) == 0); @@ -840,7 +828,7 @@ ScaleFactor Endgame::operator()(const Position& pos) const { template<> ScaleFactor Endgame::operator()(const Position& pos) const { - assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame); + assert(pos.non_pawn_material(strongerSide) == KnightValueMg); assert(pos.piece_count(strongerSide, KNIGHT) == 1); assert(pos.piece_count(strongerSide, PAWN) == 1); assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO); @@ -881,10 +869,10 @@ ScaleFactor Endgame::operator()(const Position& pos) const { if (strongerSide == BLACK) { - wksq = flip(wksq); - bksq = flip(bksq); - wpsq = flip(wpsq); - stm = flip(stm); + wksq = ~wksq; + bksq = ~bksq; + wpsq = ~wpsq; + stm = ~stm; } if (file_of(wpsq) >= FILE_E) @@ -902,5 +890,5 @@ ScaleFactor Endgame::operator()(const Position& pos) const { // 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 probe_kpk_bitbase(wksq, wpsq, bksq, stm) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW; + return Bitbases::probe_kpk(wksq, wpsq, bksq, stm) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW; }