Rev 154 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 154 | Rev 169 | ||
---|---|---|---|
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-2018 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 81... | Line 81... | ||
81 | sq = ~sq; |
81 | sq = ~sq; |
82 | 82 | ||
83 | return sq; |
83 | return sq; |
84 | } |
84 | } |
85 | 85 | ||
86 | // Get the material key of Position out of the given endgame key code |
- | |
87 | // like "KBPKN". The trick here is to first forge an ad-hoc FEN string |
- | |
88 | // and then let a Position object do the work for us. |
- | |
89 | Key key(const string& code, Color c) { |
- | |
90 | - | ||
91 | assert(code.length() > 0 && code.length() < 8); |
- | |
92 | assert(code[0] == 'K'); |
- | |
93 | - | ||
94 | string sides[] = { code.substr(code.find('K', 1)), // Weak |
- | |
95 | code.substr(0, code.find('K', 1)) }; // Strong |
- | |
96 | - | ||
97 | std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower); |
- | |
98 | - | ||
99 | string fen = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/" |
- | |
100 | + sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10"; |
- | |
101 | - | ||
102 | StateInfo st; |
- | |
103 | return Position().set(fen, false, &st, nullptr).material_key(); |
- | |
104 | } |
- | |
105 | - | ||
106 | } // namespace |
86 | } // namespace |
107 | 87 | ||
108 | 88 | ||
109 | /// Endgames members definitions |
89 | /// Endgames members definitions |
110 | 90 | ||
111 | Endgames::Endgames() { |
91 | Endgames::Endgames() { |
112 | 92 | ||
Line 125... | Line 105... | ||
125 | add<KRPKB>("KRPKB"); |
105 | add<KRPKB>("KRPKB"); |
126 | add<KBPKB>("KBPKB"); |
106 | add<KBPKB>("KBPKB"); |
127 | add<KBPKN>("KBPKN"); |
107 | add<KBPKN>("KBPKN"); |
128 | add<KBPPKB>("KBPPKB"); |
108 | add<KBPPKB>("KBPPKB"); |
129 | add<KRPPKRP>("KRPPKRP"); |
109 | add<KRPPKRP>("KRPPKRP"); |
130 | } |
- | |
131 | - | ||
132 | - | ||
133 | template<EndgameType E, typename T> |
- | |
134 | void Endgames::add(const string& code) { |
- | |
135 | map<T>()[key(code, WHITE)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(WHITE)); |
- | |
136 | map<T>()[key(code, BLACK)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(BLACK)); |
- | |
137 | } |
110 | } |
138 | 111 | ||
139 | 112 | ||
140 | /// Mate with KX vs K. This function is used to evaluate positions with |
113 | /// Mate with KX vs K. This function is used to evaluate positions with |
141 | /// king and plenty of material vs a lone king. It simply gives the |
114 | /// king and plenty of material vs a lone king. It simply gives the |
Line 160... | Line 133... | ||
160 | + PushClose[distance(winnerKSq, loserKSq)]; |
133 | + PushClose[distance(winnerKSq, loserKSq)]; |
161 | 134 | ||
162 | if ( pos.count<QUEEN>(strongSide) |
135 | if ( pos.count<QUEEN>(strongSide) |
163 | || pos.count<ROOK>(strongSide) |
136 | || pos.count<ROOK>(strongSide) |
164 | ||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide)) |
137 | ||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide)) |
165 | ||(pos. |
138 | || ( (pos.pieces(strongSide, BISHOP) & ~DarkSquares) |
166 |
|
139 | && (pos.pieces(strongSide, BISHOP) & DarkSquares))) |
167 | result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1); |
140 | result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1); |
168 | 141 | ||
169 | return strongSide == pos.side_to_move() ? result : -result; |
142 | return strongSide == pos.side_to_move() ? result : -result; |
170 | } |
143 | } |
171 | 144 | ||
Line 549... | Line 522... | ||
549 | { |
522 | { |
550 | Square ksq = pos.square<KING>(weakSide); |
523 | Square ksq = pos.square<KING>(weakSide); |
551 | Square bsq = pos.square<BISHOP>(weakSide); |
524 | Square bsq = pos.square<BISHOP>(weakSide); |
552 | Square psq = pos.square<PAWN>(strongSide); |
525 | Square psq = pos.square<PAWN>(strongSide); |
553 | Rank rk = relative_rank(strongSide, psq); |
526 | Rank rk = relative_rank(strongSide, psq); |
554 |
|
527 | Direction push = pawn_push(strongSide); |
555 | 528 | ||
556 | // If the pawn is on the 5th rank and the pawn (currently) is on |
529 | // If the pawn is on the 5th rank and the pawn (currently) is on |
557 | // the same color square as the bishop then there is a chance of |
530 | // the same color square as the bishop then there is a chance of |
558 | // a fortress. Depending on the king position give a moderate |
531 | // a fortress. Depending on the king position give a moderate |
559 | // reduction or a stronger one if the defending king is near the |
532 | // reduction or a stronger one if the defending king is near the |
Line 623... | Line 596... | ||
623 | Square ksq = pos.square<KING>(weakSide); |
596 | Square ksq = pos.square<KING>(weakSide); |
624 | Bitboard pawns = pos.pieces(strongSide, PAWN); |
597 | Bitboard pawns = pos.pieces(strongSide, PAWN); |
625 | 598 | ||
626 | // If all pawns are ahead of the king, on a single rook file and |
599 | // If all pawns are ahead of the king, on a single rook file and |
627 | // the king is within one file of the pawns, it's a draw. |
600 | // the king is within one file of the pawns, it's a draw. |
628 | if ( !(pawns & |
601 | if ( !(pawns & ~forward_ranks_bb(weakSide, ksq)) |
629 | && !((pawns & ~FileABB) && (pawns & ~FileHBB)) |
602 | && !((pawns & ~FileABB) && (pawns & ~FileHBB)) |
630 | && distance<File>(ksq, lsb(pawns)) <= 1) |
603 | && distance<File>(ksq, lsb(pawns)) <= 1) |
631 | return SCALE_FACTOR_DRAW; |
604 | return SCALE_FACTOR_DRAW; |
632 | 605 | ||
633 | return SCALE_FACTOR_NONE; |
606 | return SCALE_FACTOR_NONE; |
Line 669... | Line 642... | ||
669 | // These rules are probably not perfect, but in practice they work |
642 | // These rules are probably not perfect, but in practice they work |
670 | // reasonably well. |
643 | // reasonably well. |
671 | 644 | ||
672 | if (relative_rank(strongSide, pawnSq) <= RANK_5) |
645 | if (relative_rank(strongSide, pawnSq) <= RANK_5) |
673 | return SCALE_FACTOR_DRAW; |
646 | return SCALE_FACTOR_DRAW; |
674 | else |
- | |
675 | { |
- | |
676 | Bitboard path = forward_bb(strongSide, pawnSq); |
- | |
677 | 647 | ||
- | 648 | Bitboard path = forward_file_bb(strongSide, pawnSq); |
|
- | 649 | ||
678 |
|
650 | if (path & pos.pieces(weakSide, KING)) |
679 |
|
651 | return SCALE_FACTOR_DRAW; |
680 | 652 | ||
681 |
|
653 | if ( (pos.attacks_from<BISHOP>(weakBishopSq) & path) |
682 |
|
654 | && distance(weakBishopSq, pawnSq) >= 3) |
683 |
|
655 | return SCALE_FACTOR_DRAW; |
684 | } |
- | |
685 | } |
656 | } |
686 | return SCALE_FACTOR_NONE; |
657 | return SCALE_FACTOR_NONE; |
687 | } |
658 | } |
688 | 659 | ||
689 | 660 | ||
Line 807... | Line 778... | ||
807 | Square bishopSq = pos.square<BISHOP>(weakSide); |
778 | Square bishopSq = pos.square<BISHOP>(weakSide); |
808 | Square weakKingSq = pos.square<KING>(weakSide); |
779 | Square weakKingSq = pos.square<KING>(weakSide); |
809 | 780 | ||
810 | // King needs to get close to promoting pawn to prevent knight from blocking. |
781 | // King needs to get close to promoting pawn to prevent knight from blocking. |
811 | // Rules for this are very tricky, so just approximate. |
782 | // Rules for this are very tricky, so just approximate. |
812 | if ( |
783 | if (forward_file_bb(strongSide, pawnSq) & pos.attacks_from<BISHOP>(bishopSq)) |
813 | return ScaleFactor(distance(weakKingSq, pawnSq)); |
784 | return ScaleFactor(distance(weakKingSq, pawnSq)); |
814 | 785 | ||
815 | return SCALE_FACTOR_NONE; |
786 | return SCALE_FACTOR_NONE; |
816 | } |
787 | } |
817 | 788 |