Thanks for the explanations, Rein, Marco! I promise to study this some more when I want to do something with the endgame code again. I agree that for the coding of endgames, classes and Object Orient Programming seem the appropriate tool and it becomes clearer when to use the different methods by studying how this is done in Stockfish. But when they implemented all that in Pascal(or Delphi) it all quickly became very complicated and very abstract. No fun at all to read about and for things like numerical mathematics there did not seem much point in learning any of that, but this seems more suited and a good way to get better acquainted with OOP.
I can maybe add the way I implemented the same bishop code without using Marco's recommended way of fabricating a new function KBBPsK, but changing the KXK code so that this does not give VALUE_KNOWN_WIN anymore in the case of same colored bishops (and edge pawn(s) of the wrong color):
Code: Select all
/// Mate with KX vs K. This function is used to evaluate positions with
/// King and plenty of material vs a lone king. It simply gives the
/// attacking side a bonus for driving the defending king towards the edge
/// of the board, and for keeping the distance between the two kings small.
template<>
Value Endgame<KXK>::apply(const Position& pos) const {
assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO);
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
+ MateTable[loserKSq]
+ DistanceBonus[square_distance(winnerKSq, loserKSq)];
if ( pos.piece_count(strongerSide, QUEEN)
|| pos.piece_count(strongerSide, ROOK)
|| (pos.piece_count(strongerSide, BISHOP) == 2
&& opposite_colors(pos.piece_list(strongerSide, BISHOP)[0], pos.piece_list(strongerSide, BISHOP)[1])))
// TODO: check for more than two equal-colored bishops!
result += VALUE_KNOWN_WIN;
else if (pos.piece_count(strongerSide, BISHOP) == 2
&& !opposite_colors(pos.piece_list(strongerSide, BISHOP)[0], pos.piece_list(strongerSide, BISHOP)[1])
&& pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame)
{
result = VALUE_DRAW;
if (pos.piece_count(strongerSide, PAWN))
{
result = pos.non_pawn_material(strongerSide) + pos.piece_count(strongerSide, PAWN) * PawnValueEndgame;
Bitboard pawns = pos.pieces(PAWN, strongerSide);
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)
&& (pawns & ~file_bb(pawnFile)) == EmptyBoardBB)
{
Square bishopSq = pos.piece_list(strongerSide, BISHOP)[0];
Square queeningSq = relative_square(strongerSide, make_square(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
// frontmost pawn.
Rank rank;
if (strongerSide == WHITE)
{
for (rank = RANK_7; (rank_bb(rank) & pawns) == EmptyBoardBB; rank--) {}
assert(rank >= RANK_2 && rank <= RANK_7);
}
else
{
for (rank = RANK_2; (rank_bb(rank) & pawns) == EmptyBoardBB; rank++) {}
rank = Rank(rank ^ 7); // HACK to get the relative rank
assert(rank >= RANK_2 && rank <= RANK_7);
}
// If the defending king has distance 1 to the promotion square or
// is placed somewhere in front of the pawn, it's a draw.
if ( square_distance(kingSq, queeningSq) <= 1
|| relative_rank(strongerSide, kingSq) >= rank)
result = VALUE_DRAW + pos.piece_count(strongerSide, PAWN) * rank;
}
}
}
}
return strongerSide == pos.side_to_move() ? result : -result;
}
Maybe it can be done simpler but it seemed to me little enough code for a patch. Almost all of this code already existed for the KBPsK class. I think it will work in the Stockfish master branch without any changes. Note that there is a little change from the result as I had given in the post above where Rainbow Serpent just gave away the pawns; even if the theoretical result is a draw Stockfish will still try to improve the rank of the edge pawn(s) now, and give a smal plus for the stronger side, if he still has pawns. The same colored bishops are not counted though
If Stockfish has eight of them or two or just one makes no difference for the evaluation, only the rank of the pawn or pawns on the edge.
Thanks again, will go study classes a bit later!
Eelco
Small typo further in endgame.cpp:
Code: Select all
/// KBPsKScalingFunction scales endgames where the stronger side has king,
Added a s behind the P here as that seemed to be missing. (No functional change it was just a comment
)