/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008 Marco Costalba
+ Copyright (C) 2008-2009 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include <cassert>
#include "bitbase.h"
+#include "bitcount.h"
#include "endgame.h"
-////
-//// Constants and variables
-////
-
-/// Evaluation functions
-
-// Generic "mate lone king" eval
-EvaluationFunction<KXK> EvaluateKXK(WHITE), EvaluateKKX(BLACK);
-
-// K and two minors vs K and one or two minors
-EvaluationFunction<KmmKm> EvaluateKmmKm(WHITE);
-
-EvaluationFunction<KBNK> EvaluateKBNK(WHITE), EvaluateKKBN(BLACK); // KBN vs K
-EvaluationFunction<KPK> EvaluateKPK(WHITE), EvaluateKKP(BLACK); // KP vs K
-EvaluationFunction<KRKP> EvaluateKRKP(WHITE), EvaluateKPKR(BLACK); // KR vs KP
-EvaluationFunction<KRKB> EvaluateKRKB(WHITE), EvaluateKBKR(BLACK); // KR vs KB
-EvaluationFunction<KRKN> EvaluateKRKN(WHITE), EvaluateKNKR(BLACK); // KR vs KN
-EvaluationFunction<KQKR> EvaluateKQKR(WHITE), EvaluateKRKQ(BLACK); // KQ vs KR
-EvaluationFunction<KBBKN> EvaluateKBBKN(WHITE), EvaluateKNKBB(BLACK); // KBB vs KN
-
-
-/// Scaling functions
-
-ScalingFunction<KBPK> ScaleKBPK(WHITE), ScaleKKBP(BLACK); // KBP vs K
-ScalingFunction<KQKRP> ScaleKQKRP(WHITE), ScaleKRPKQ(BLACK); // KQ vs KRP
-ScalingFunction<KRPKR> ScaleKRPKR(WHITE), ScaleKRKRP(BLACK); // KRP vs KR
-ScalingFunction<KRPPKRP> ScaleKRPPKRP(WHITE), ScaleKRPKRPP(BLACK); // KRPP vs KRP
-ScalingFunction<KPsK> ScaleKPsK(WHITE), ScaleKKPs(BLACK); // King and pawns vs king
-ScalingFunction<KBPKB> ScaleKBPKB(WHITE), ScaleKBKBP(BLACK); // KBP vs KB
-ScalingFunction<KBPKN> ScaleKBPKN(WHITE), ScaleKNKBP(BLACK); // KBP vs KN
-ScalingFunction<KNPK> ScaleKNPK(WHITE), ScaleKKNP(BLACK); // KNP vs K
-ScalingFunction<KPKP> ScaleKPKPw(WHITE), ScaleKPKPb(BLACK); // KPKP
-
-
////
//// Local definitions
////
return (strongerSide == pos.side_to_move() ? result : -result);
}
+
+/// K and two minors vs K and one or two minors or K and two knights against
+/// king alone are always draw.
template<>
-Value EvaluationFunction<KmmKm>::apply(const Position &pos) {
+Value EvaluationFunction<KmmKm>::apply(const Position&) {
return Value(0);
}
+template<>
+Value EvaluationFunction<KNNK>::apply(const Position&) {
+ return Value(0);
+}
/// KBPKScalingFunction scales endgames where the stronger side has king,
/// bishop and one or more pawns. It checks for draws with rook pawns and a
/// returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
/// will be used.
template<>
-ScaleFactor ScalingFunction<KBPK>::apply(const Position& pos) {
+ScaleFactor ScalingFunction<KBPsK>::apply(const Position& pos) {
assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
assert(pos.piece_count(strongerSide, BISHOP) == 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)
{
/// It tests for fortress draws with a rook on the third rank defended by
/// a pawn.
template<>
-ScaleFactor ScalingFunction<KQKRP>::apply(const Position& pos) {
+ScaleFactor ScalingFunction<KQKRPs>::apply(const Position& pos) {
assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
assert(pos.piece_count(strongerSide, QUEEN) == 1);
}
+/// KBPPKBScalingFunction scales KBPP vs KB endgames. It detects a few basic
+/// draws with opposite-colored bishops.
+template<>
+ScaleFactor ScalingFunction<KBPPKB>::apply(const Position& pos) {
+
+ assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
+ assert(pos.piece_count(strongerSide, BISHOP) == 1);
+ assert(pos.piece_count(strongerSide, PAWN) == 2);
+ assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
+ assert(pos.piece_count(weakerSide, BISHOP) == 1);
+ assert(pos.piece_count(weakerSide, PAWN) == 0);
+
+ Square wbsq = pos.piece_list(strongerSide, BISHOP, 0);
+ Square bbsq = pos.piece_list(weakerSide, BISHOP, 0);
+
+ if (square_color(wbsq) == square_color(bbsq))
+ // Not opposite-colored bishops, no scaling
+ return SCALE_FACTOR_NONE;
+
+ Square ksq = pos.king_square(weakerSide);
+ Square psq1 = pos.piece_list(strongerSide, PAWN, 0);
+ Square psq2 = pos.piece_list(strongerSide, PAWN, 1);
+ Rank r1 = square_rank(psq1);
+ Rank r2 = square_rank(psq2);
+ Square blockSq1, blockSq2;
+
+ if (relative_rank(strongerSide, psq1) > relative_rank(strongerSide, psq2))
+ {
+ blockSq1 = psq1 + pawn_push(strongerSide);
+ blockSq2 = make_square(square_file(psq2), square_rank(psq1));
+ }
+ else
+ {
+ blockSq1 = psq2 + pawn_push(strongerSide);
+ blockSq2 = make_square(square_file(psq1), square_rank(psq2));
+ }
+
+ switch (file_distance(psq1, psq2))
+ {
+ case 0:
+ // Both pawns are on the same file. Easy draw if defender firmly controls
+ // some square in the frontmost pawn's path.
+ if ( square_file(ksq) == square_file(blockSq1)
+ && relative_rank(strongerSide, ksq) >= relative_rank(strongerSide, blockSq1)
+ && square_color(ksq) != square_color(wbsq))
+ return ScaleFactor(0);
+ else
+ return SCALE_FACTOR_NONE;
+
+ case 1:
+ // Pawns on neighboring 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
+ && square_color(ksq) != square_color(wbsq)
+ && ( bbsq == blockSq2
+ || (pos.piece_attacks<BISHOP>(blockSq2) & pos.bishops(weakerSide))
+ || rank_distance(r1, r2) >= 2))
+ return ScaleFactor(0);
+ else if ( ksq == blockSq2
+ && square_color(ksq) != square_color(wbsq)
+ && ( bbsq == blockSq1
+ || (pos.piece_attacks<BISHOP>(blockSq1) & pos.bishops(weakerSide))))
+ return ScaleFactor(0);
+ else
+ return SCALE_FACTOR_NONE;
+
+ default:
+ // The pawns are not on the same file or adjacent files. No scaling.
+ return SCALE_FACTOR_NONE;
+ }
+}
+
+
/// KBPKNScalingFunction scales KBP vs KN endgames. There is a single rule:
/// If the defending king is somewhere along the path of the pawn, and the
/// square of the king is not of the same color as the stronger side's bishop,