Rev 169 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 169 | Rev 185 | ||
|---|---|---|---|
| Line 4... | Line 4... | ||
| 4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
4 | Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad |
| 5 | Copyright (C) 2015- |
5 | Copyright (C) 2015-2019 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad |
| 6 | 6 | ||
| 7 | Stockfish is free software: you can redistribute it and/or modify |
7 | Stockfish is free software: you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation, either version 3 of the License, or |
9 | the Free Software Foundation, either version 3 of the License, or |
| 10 | (at your option) any later version. |
10 | (at your option) any later version. |
| Line 29... | Line 29... | ||
| 29 | 29 | ||
| 30 | namespace { |
30 | namespace { |
| 31 | 31 | ||
| 32 | // Table used to drive the king towards the edge of the board |
32 | // Table used to drive the king towards the edge of the board |
| 33 | // in KX vs K and KQ vs KR endgames. |
33 | // in KX vs K and KQ vs KR endgames. |
| 34 |
|
34 | constexpr int PushToEdges[SQUARE_NB] = { |
| 35 | 100, 90, 80, 70, 70, 80, 90, 100, |
35 | 100, 90, 80, 70, 70, 80, 90, 100, |
| 36 | 90, 70, 60, 50, 50, 60, 70, 90, |
36 | 90, 70, 60, 50, 50, 60, 70, 90, |
| 37 | 80, 60, 40, 30, 30, 40, 60, 80, |
37 | 80, 60, 40, 30, 30, 40, 60, 80, |
| 38 | 70, 50, 30, 20, 20, 30, 50, 70, |
38 | 70, 50, 30, 20, 20, 30, 50, 70, |
| 39 | 70, 50, 30, 20, 20, 30, 50, 70, |
39 | 70, 50, 30, 20, 20, 30, 50, 70, |
| Line 42... | Line 42... | ||
| 42 | 100, 90, 80, 70, 70, 80, 90, 100 |
42 | 100, 90, 80, 70, 70, 80, 90, 100 |
| 43 | }; |
43 | }; |
| 44 | 44 | ||
| 45 | // Table used to drive the king towards a corner square of the |
45 | // Table used to drive the king towards a corner square of the |
| 46 | // right color in KBN vs K endgames. |
46 | // right color in KBN vs K endgames. |
| 47 |
|
47 | constexpr int PushToCorners[SQUARE_NB] = { |
| 48 | 200, 190, 180, 170, 160, 150, 140, 130, |
48 | 200, 190, 180, 170, 160, 150, 140, 130, |
| 49 | 190, 180, 170, 160, 150, 140, 130, 140, |
49 | 190, 180, 170, 160, 150, 140, 130, 140, |
| 50 | 180, 170, 155, 140, 140, 125, 140, 150, |
50 | 180, 170, 155, 140, 140, 125, 140, 150, |
| 51 | 170, 160, 140, 120, 110, 140, 150, 160, |
51 | 170, 160, 140, 120, 110, 140, 150, 160, |
| 52 | 160, 150, 140, 110, 120, 140, 160, 170, |
52 | 160, 150, 140, 110, 120, 140, 160, 170, |
| Line 54... | Line 54... | ||
| 54 | 140, 130, 140, 150, 160, 170, 180, 190, |
54 | 140, 130, 140, 150, 160, 170, 180, 190, |
| 55 | 130, 140, 150, 160, 170, 180, 190, 200 |
55 | 130, 140, 150, 160, 170, 180, 190, 200 |
| 56 | }; |
56 | }; |
| 57 | 57 | ||
| 58 | // Tables used to drive a piece towards or away from another piece |
58 | // Tables used to drive a piece towards or away from another piece |
| 59 |
|
59 | constexpr int PushClose[8] = { 0, 0, 100, 80, 60, 40, 20, 10 }; |
| 60 |
|
60 | constexpr int PushAway [8] = { 0, 5, 20, 40, 60, 80, 90, 100 }; |
| 61 | 61 | ||
| 62 | // Pawn Rank based scaling factors used in KRPPKRP endgame |
62 | // Pawn Rank based scaling factors used in KRPPKRP endgame |
| 63 |
|
63 | constexpr int KRPPKRPScaleFactors[RANK_NB] = { 0, 9, 10, 14, 21, 44, 0, 0 }; |
| 64 | 64 | ||
| 65 | #ifndef NDEBUG |
65 | #ifndef NDEBUG |
| 66 | bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) { |
66 | bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) { |
| 67 | return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == pawnsCnt; |
67 | return pos.non_pawn_material(c) == npm && pos.count<PAWN>(c) == pawnsCnt; |
| 68 | } |
68 | } |
| Line 82... | Line 82... | ||
| 82 | 82 | ||
| 83 | return sq; |
83 | return sq; |
| 84 | } |
84 | } |
| 85 | 85 | ||
| 86 | } // namespace |
86 | } // namespace |
| 87 | - | ||
| 88 | - | ||
| 89 | /// Endgames members definitions |
- | |
| 90 | - | ||
| 91 | Endgames::Endgames() { |
- | |
| 92 | - | ||
| 93 | add<KPK>("KPK"); |
- | |
| 94 | add<KNNK>("KNNK"); |
- | |
| 95 | add<KBNK>("KBNK"); |
- | |
| 96 | add<KRKP>("KRKP"); |
- | |
| 97 | add<KRKB>("KRKB"); |
- | |
| 98 | add<KRKN>("KRKN"); |
- | |
| 99 | add<KQKP>("KQKP"); |
- | |
| 100 | add<KQKR>("KQKR"); |
- | |
| 101 | - | ||
| 102 | add<KNPK>("KNPK"); |
- | |
| 103 | add<KNPKB>("KNPKB"); |
- | |
| 104 | add<KRPKR>("KRPKR"); |
- | |
| 105 | add<KRPKB>("KRPKB"); |
- | |
| 106 | add<KBPKB>("KBPKB"); |
- | |
| 107 | add<KBPKN>("KBPKN"); |
- | |
| 108 | add<KBPPKB>("KBPPKB"); |
- | |
| 109 | add<KRPPKRP>("KRPPKRP"); |
- | |
| 110 | } |
- | |
| 111 | 87 | ||
| 112 | 88 | ||
| 113 | /// Mate with KX vs K. This function is used to evaluate positions with |
89 | /// Mate with KX vs K. This function is used to evaluate positions with |
| 114 | /// king and plenty of material vs a lone king. It simply gives the |
90 | /// king and plenty of material vs a lone king. It simply gives the |
| 115 | /// attacking side a bonus for driving the defending king towards the edge |
91 | /// attacking side a bonus for driving the defending king towards the edge |
| Line 212... | Line 188... | ||
| 212 | 188 | ||
| 213 | Square queeningSq = make_square(file_of(psq), RANK_1); |
189 | Square queeningSq = make_square(file_of(psq), RANK_1); |
| 214 | Value result; |
190 | Value result; |
| 215 | 191 | ||
| 216 | // If the stronger side's king is in front of the pawn, it's a win |
192 | // If the stronger side's king is in front of the pawn, it's a win |
| 217 | if ( |
193 | if (forward_file_bb(WHITE, wksq) & psq) |
| 218 | result = RookValueEg - distance(wksq, psq); |
194 | result = RookValueEg - distance(wksq, psq); |
| 219 | 195 | ||
| 220 | // If the weaker side's king is too far from the pawn and the rook, |
196 | // If the weaker side's king is too far from the pawn and the rook, |
| 221 | // it's a win. |
197 | // it's a win. |
| 222 | else if ( distance(bksq, psq) >= 3 + (pos.side_to_move() == weakSide) |
198 | else if ( distance(bksq, psq) >= 3 + (pos.side_to_move() == weakSide) |
| Line 238... | Line 214... | ||
| 238 | 214 | ||
| 239 | return strongSide == pos.side_to_move() ? result : -result; |
215 | return strongSide == pos.side_to_move() ? result : -result; |
| 240 | } |
216 | } |
| 241 | 217 | ||
| 242 | 218 | ||
| 243 | /// KR vs KB. This is very simple, and always returns drawish scores. |
219 | /// KR vs KB. This is very simple, and always returns drawish scores. The |
| 244 | /// score is slightly bigger when the defending king is close to the edge. |
220 | /// score is slightly bigger when the defending king is close to the edge. |
| 245 | template<> |
221 | template<> |
| 246 | Value Endgame<KRKB>::operator()(const Position& pos) const { |
222 | Value Endgame<KRKB>::operator()(const Position& pos) const { |
| 247 | 223 | ||
| 248 | assert(verify_material(pos, strongSide, RookValueMg, 0)); |
224 | assert(verify_material(pos, strongSide, RookValueMg, 0)); |
| Line 629... | Line 605... | ||
| 629 | || relative_rank(strongSide, weakKingSq) <= RANK_6)) |
605 | || relative_rank(strongSide, weakKingSq) <= RANK_6)) |
| 630 | return SCALE_FACTOR_DRAW; |
606 | return SCALE_FACTOR_DRAW; |
| 631 | 607 | ||
| 632 | // Case 2: Opposite colored bishops |
608 | // Case 2: Opposite colored bishops |
| 633 | if (opposite_colors(strongBishopSq, weakBishopSq)) |
609 | if (opposite_colors(strongBishopSq, weakBishopSq)) |
| 634 | { |
- | |
| 635 | // We assume that the position is drawn in the following three situations: |
- | |
| 636 | // |
- | |
| 637 | // a. The pawn is on rank 5 or further back. |
- | |
| 638 | // b. The defending king is somewhere in the pawn's path. |
- | |
| 639 | // c. The defending bishop attacks some square along the pawn's path, |
- | |
| 640 | // and is at least three squares away from the pawn. |
- | |
| 641 | // |
- | |
| 642 | // These rules are probably not perfect, but in practice they work |
- | |
| 643 |
|
610 | return SCALE_FACTOR_DRAW; |
| 644 | 611 | ||
| 645 | if (relative_rank(strongSide, pawnSq) <= RANK_5) |
- | |
| 646 | return SCALE_FACTOR_DRAW; |
- | |
| 647 | - | ||
| 648 | Bitboard path = forward_file_bb(strongSide, pawnSq); |
- | |
| 649 | - | ||
| 650 | if (path & pos.pieces(weakSide, KING)) |
- | |
| 651 | return SCALE_FACTOR_DRAW; |
- | |
| 652 | - | ||
| 653 | if ( (pos.attacks_from<BISHOP>(weakBishopSq) & path) |
- | |
| 654 | && distance(weakBishopSq, pawnSq) >= 3) |
- | |
| 655 | return SCALE_FACTOR_DRAW; |
- | |
| 656 | } |
- | |
| 657 | return SCALE_FACTOR_NONE; |
612 | return SCALE_FACTOR_NONE; |
| 658 | } |
613 | } |
| 659 | 614 | ||
| 660 | 615 | ||
| 661 | /// KBPP vs KB. It detects a few basic draws with opposite-colored bishops |
616 | /// KBPP vs KB. It detects a few basic draws with opposite-colored bishops |