2 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
3 Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
4 Copyright (C) 2008-2010 Marco Costalba, Joona Kiiski, Tord Romstad
6 Stockfish is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 Stockfish is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 extern uint32_t probe_kpk_bitbase(Square wksq, Square wpsq, Square bksq, Color stm);
32 // Table used to drive the defending king towards the edge of the board
33 // in KX vs K and KQ vs KR endgames.
34 const uint8_t MateTable[64] = {
35 100, 90, 80, 70, 70, 80, 90, 100,
36 90, 70, 60, 50, 50, 60, 70, 90,
37 80, 60, 40, 30, 30, 40, 60, 80,
38 70, 50, 30, 20, 20, 30, 50, 70,
39 70, 50, 30, 20, 20, 30, 50, 70,
40 80, 60, 40, 30, 30, 40, 60, 80,
41 90, 70, 60, 50, 50, 60, 70, 90,
42 100, 90, 80, 70, 70, 80, 90, 100,
45 // Table used to drive the defending king towards a corner square of the
46 // right color in KBN vs K endgames.
47 const uint8_t KBNKMateTable[64] = {
48 200, 190, 180, 170, 160, 150, 140, 130,
49 190, 180, 170, 160, 150, 140, 130, 140,
50 180, 170, 155, 140, 140, 125, 140, 150,
51 170, 160, 140, 120, 110, 140, 150, 160,
52 160, 150, 140, 110, 120, 140, 160, 170,
53 150, 140, 125, 140, 140, 155, 170, 180,
54 140, 130, 140, 150, 160, 170, 180, 190,
55 130, 140, 150, 160, 170, 180, 190, 200
58 // The attacking side is given a descending bonus based on distance between
59 // the two kings in basic endgames.
60 const int DistanceBonus[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
62 // Penalty for big distance between king and knight for the defending king
63 // and knight in KR vs KN endgames.
64 const int KRKNKingKnightDistancePenalty[8] = { 0, 0, 4, 10, 20, 32, 48, 70 };
66 // Various inline functions for accessing the above arrays
67 inline Value mate_table(Square s) {
68 return Value(MateTable[s]);
71 inline Value kbnk_mate_table(Square s) {
72 return Value(KBNKMateTable[s]);
75 inline Value distance_bonus(int d) {
76 return Value(DistanceBonus[d]);
79 inline Value krkn_king_knight_distance_penalty(int d) {
80 return Value(KRKNKingKnightDistancePenalty[d]);
83 // Build corresponding key for the opposite color: "KBPKN" -> "KNKBP"
84 const string swapColors(const string& keyCode) {
86 size_t idx = keyCode.find('K', 1);
87 return keyCode.substr(idx) + keyCode.substr(0, idx);
90 // Build up a fen string with the given pieces, note that the fen string
91 // could be of an illegal position.
92 Key buildKey(const string& keyCode) {
94 assert(keyCode.length() > 0 && keyCode.length() < 8);
95 assert(keyCode[0] == 'K');
100 for (size_t i = 0; i < keyCode.length(); i++)
102 if (keyCode[i] == 'K')
105 fen += char(upcase ? toupper(keyCode[i]) : tolower(keyCode[i]));
107 fen += char(8 - keyCode.length() + '0');
108 fen += "/8/8/8/8/8/8/8 w - -";
109 return Position(fen, false, 0).get_material_key();
112 typedef EndgameBase<Value> EF;
113 typedef EndgameBase<ScaleFactor> SF;
118 /// Endgames member definitions
120 template<> const Endgames::EFMap& Endgames::get<EF>() const { return maps.first; }
121 template<> const Endgames::SFMap& Endgames::get<SF>() const { return maps.second; }
123 Endgames::Endgames() {
125 add<Endgame<Value, KNNK> >("KNNK");
126 add<Endgame<Value, KPK> >("KPK");
127 add<Endgame<Value, KBNK> >("KBNK");
128 add<Endgame<Value, KRKP> >("KRKP");
129 add<Endgame<Value, KRKB> >("KRKB");
130 add<Endgame<Value, KRKN> >("KRKN");
131 add<Endgame<Value, KQKR> >("KQKR");
132 add<Endgame<Value, KBBKN> >("KBBKN");
134 add<Endgame<ScaleFactor, KNPK> >("KNPK");
135 add<Endgame<ScaleFactor, KRPKR> >("KRPKR");
136 add<Endgame<ScaleFactor, KBPKB> >("KBPKB");
137 add<Endgame<ScaleFactor, KBPPKB> >("KBPPKB");
138 add<Endgame<ScaleFactor, KBPKN> >("KBPKN");
139 add<Endgame<ScaleFactor, KRPPKRP> >("KRPPKRP");
142 Endgames::~Endgames() {
144 for (EFMap::const_iterator it = get<EF>().begin(); it != get<EF>().end(); ++it)
147 for (SFMap::const_iterator it = get<SF>().begin(); it != get<SF>().end(); ++it)
152 void Endgames::add(const string& keyCode) {
154 typedef typename T::Base F;
155 typedef std::map<Key, F*> M;
157 const_cast<M&>(get<F>()).insert(std::pair<Key, F*>(buildKey(keyCode), new T(WHITE)));
158 const_cast<M&>(get<F>()).insert(std::pair<Key, F*>(buildKey(swapColors(keyCode)), new T(BLACK)));
162 T* Endgames::get(Key key) const {
164 typename std::map<Key, T*>::const_iterator it = get<T>().find(key);
165 return it != get<T>().end() ? it->second : NULL;
168 // Explicit template instantiations
169 template EF* Endgames::get<EF>(Key key) const;
170 template SF* Endgames::get<SF>(Key key) const;
173 /// Mate with KX vs K. This function is used to evaluate positions with
174 /// King and plenty of material vs a lone king. It simply gives the
175 /// attacking side a bonus for driving the defending king towards the edge
176 /// of the board, and for keeping the distance between the two kings small.
178 Value Endgame<Value, KXK>::apply(const Position& pos) const {
180 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
181 assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO);
183 Square winnerKSq = pos.king_square(strongerSide);
184 Square loserKSq = pos.king_square(weakerSide);
186 Value result = pos.non_pawn_material(strongerSide)
187 + pos.piece_count(strongerSide, PAWN) * PawnValueEndgame
188 + mate_table(loserKSq)
189 + distance_bonus(square_distance(winnerKSq, loserKSq));
191 if ( pos.piece_count(strongerSide, QUEEN)
192 || pos.piece_count(strongerSide, ROOK)
193 || pos.piece_count(strongerSide, BISHOP) > 1)
194 // TODO: check for two equal-colored bishops!
195 result += VALUE_KNOWN_WIN;
197 return strongerSide == pos.side_to_move() ? result : -result;
201 /// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the
202 /// defending king towards a corner square of the right color.
204 Value Endgame<Value, KBNK>::apply(const Position& pos) const {
206 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
207 assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO);
208 assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame + BishopValueMidgame);
209 assert(pos.piece_count(strongerSide, BISHOP) == 1);
210 assert(pos.piece_count(strongerSide, KNIGHT) == 1);
211 assert(pos.piece_count(strongerSide, PAWN) == 0);
213 Square winnerKSq = pos.king_square(strongerSide);
214 Square loserKSq = pos.king_square(weakerSide);
215 Square bishopSquare = pos.piece_list(strongerSide, BISHOP, 0);
217 // kbnk_mate_table() tries to drive toward corners A1 or H8,
218 // if we have a bishop that cannot reach the above squares we
219 // mirror the kings so to drive enemy toward corners A8 or H1.
220 if (opposite_color_squares(bishopSquare, SQ_A1))
222 winnerKSq = flop_square(winnerKSq);
223 loserKSq = flop_square(loserKSq);
226 Value result = VALUE_KNOWN_WIN
227 + distance_bonus(square_distance(winnerKSq, loserKSq))
228 + kbnk_mate_table(loserKSq);
230 return strongerSide == pos.side_to_move() ? result : -result;
234 /// KP vs K. This endgame is evaluated with the help of a bitbase.
236 Value Endgame<Value, KPK>::apply(const Position& pos) const {
238 assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
239 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
240 assert(pos.piece_count(strongerSide, PAWN) == 1);
241 assert(pos.piece_count(weakerSide, PAWN) == 0);
243 Square wksq, bksq, wpsq;
246 if (strongerSide == WHITE)
248 wksq = pos.king_square(WHITE);
249 bksq = pos.king_square(BLACK);
250 wpsq = pos.piece_list(WHITE, PAWN, 0);
251 stm = pos.side_to_move();
255 wksq = flip_square(pos.king_square(BLACK));
256 bksq = flip_square(pos.king_square(WHITE));
257 wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
258 stm = opposite_color(pos.side_to_move());
261 if (square_file(wpsq) >= FILE_E)
263 wksq = flop_square(wksq);
264 bksq = flop_square(bksq);
265 wpsq = flop_square(wpsq);
268 if (!probe_kpk_bitbase(wksq, wpsq, bksq, stm))
271 Value result = VALUE_KNOWN_WIN
273 + Value(square_rank(wpsq));
275 return strongerSide == pos.side_to_move() ? result : -result;
279 /// KR vs KP. This is a somewhat tricky endgame to evaluate precisely without
280 /// a bitbase. The function below returns drawish scores when the pawn is
281 /// far advanced with support of the king, while the attacking king is far
284 Value Endgame<Value, KRKP>::apply(const Position& pos) const {
286 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
287 assert(pos.piece_count(strongerSide, PAWN) == 0);
288 assert(pos.non_pawn_material(weakerSide) == 0);
289 assert(pos.piece_count(weakerSide, PAWN) == 1);
291 Square wksq, wrsq, bksq, bpsq;
292 int tempo = (pos.side_to_move() == strongerSide);
294 wksq = pos.king_square(strongerSide);
295 wrsq = pos.piece_list(strongerSide, ROOK, 0);
296 bksq = pos.king_square(weakerSide);
297 bpsq = pos.piece_list(weakerSide, PAWN, 0);
299 if (strongerSide == BLACK)
301 wksq = flip_square(wksq);
302 wrsq = flip_square(wrsq);
303 bksq = flip_square(bksq);
304 bpsq = flip_square(bpsq);
307 Square queeningSq = make_square(square_file(bpsq), RANK_1);
310 // If the stronger side's king is in front of the pawn, it's a win
311 if (wksq < bpsq && square_file(wksq) == square_file(bpsq))
312 result = RookValueEndgame - Value(square_distance(wksq, bpsq));
314 // If the weaker side's king is too far from the pawn and the rook,
316 else if ( square_distance(bksq, bpsq) - (tempo ^ 1) >= 3
317 && square_distance(bksq, wrsq) >= 3)
318 result = RookValueEndgame - Value(square_distance(wksq, bpsq));
320 // If the pawn is far advanced and supported by the defending king,
321 // the position is drawish
322 else if ( square_rank(bksq) <= RANK_3
323 && square_distance(bksq, bpsq) == 1
324 && square_rank(wksq) >= RANK_4
325 && square_distance(wksq, bpsq) - tempo > 2)
326 result = Value(80 - square_distance(wksq, bpsq) * 8);
330 - Value(square_distance(wksq, bpsq + DELTA_S) * 8)
331 + Value(square_distance(bksq, bpsq + DELTA_S) * 8)
332 + Value(square_distance(bpsq, queeningSq) * 8);
334 return strongerSide == pos.side_to_move() ? result : -result;
338 /// KR vs KB. This is very simple, and always returns drawish scores. The
339 /// score is slightly bigger when the defending king is close to the edge.
341 Value Endgame<Value, KRKB>::apply(const Position& pos) const {
343 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
344 assert(pos.piece_count(strongerSide, PAWN) == 0);
345 assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
346 assert(pos.piece_count(weakerSide, PAWN) == 0);
347 assert(pos.piece_count(weakerSide, BISHOP) == 1);
349 Value result = mate_table(pos.king_square(weakerSide));
350 return strongerSide == pos.side_to_move() ? result : -result;
354 /// KR vs KN. The attacking side has slightly better winning chances than
355 /// in KR vs KB, particularly if the king and the knight are far apart.
357 Value Endgame<Value, KRKN>::apply(const Position& pos) const {
359 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
360 assert(pos.piece_count(strongerSide, PAWN) == 0);
361 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
362 assert(pos.piece_count(weakerSide, PAWN) == 0);
363 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
365 Square defendingKSq = pos.king_square(weakerSide);
366 Square nSq = pos.piece_list(weakerSide, KNIGHT, 0);
368 int d = square_distance(defendingKSq, nSq);
369 Value result = Value(10)
370 + mate_table(defendingKSq)
371 + krkn_king_knight_distance_penalty(d);
373 return strongerSide == pos.side_to_move() ? result : -result;
377 /// KQ vs KR. This is almost identical to KX vs K: We give the attacking
378 /// king a bonus for having the kings close together, and for forcing the
379 /// defending king towards the edge. If we also take care to avoid null move
380 /// for the defending side in the search, this is usually sufficient to be
381 /// able to win KQ vs KR.
383 Value Endgame<Value, KQKR>::apply(const Position& pos) const {
385 assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
386 assert(pos.piece_count(strongerSide, PAWN) == 0);
387 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
388 assert(pos.piece_count(weakerSide, PAWN) == 0);
390 Square winnerKSq = pos.king_square(strongerSide);
391 Square loserKSq = pos.king_square(weakerSide);
393 Value result = QueenValueEndgame
395 + mate_table(loserKSq)
396 + distance_bonus(square_distance(winnerKSq, loserKSq));
398 return strongerSide == pos.side_to_move() ? result : -result;
402 Value Endgame<Value, KBBKN>::apply(const Position& pos) const {
404 assert(pos.piece_count(strongerSide, BISHOP) == 2);
405 assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame);
406 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
407 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
408 assert(pos.pieces(PAWN) == EmptyBoardBB);
410 Value result = BishopValueEndgame;
411 Square wksq = pos.king_square(strongerSide);
412 Square bksq = pos.king_square(weakerSide);
413 Square nsq = pos.piece_list(weakerSide, KNIGHT, 0);
415 // Bonus for attacking king close to defending king
416 result += distance_bonus(square_distance(wksq, bksq));
418 // Bonus for driving the defending king and knight apart
419 result += Value(square_distance(bksq, nsq) * 32);
421 // Bonus for restricting the knight's mobility
422 result += Value((8 - count_1s<CNT32_MAX15>(pos.attacks_from<KNIGHT>(nsq))) * 8);
424 return strongerSide == pos.side_to_move() ? result : -result;
428 /// K and two minors vs K and one or two minors or K and two knights against
429 /// king alone are always draw.
431 Value Endgame<Value, KmmKm>::apply(const Position&) const {
436 Value Endgame<Value, KNNK>::apply(const Position&) const {
440 /// KBPKScalingFunction scales endgames where the stronger side has king,
441 /// bishop and one or more pawns. It checks for draws with rook pawns and a
442 /// bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_ZERO is
443 /// returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
446 ScaleFactor Endgame<ScaleFactor, KBPsK>::apply(const Position& pos) const {
448 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
449 assert(pos.piece_count(strongerSide, BISHOP) == 1);
450 assert(pos.piece_count(strongerSide, PAWN) >= 1);
452 // No assertions about the material of weakerSide, because we want draws to
453 // be detected even when the weaker side has some pawns.
455 Bitboard pawns = pos.pieces(PAWN, strongerSide);
456 File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0));
458 // All pawns are on a single rook file ?
459 if ( (pawnFile == FILE_A || pawnFile == FILE_H)
460 && (pawns & ~file_bb(pawnFile)) == EmptyBoardBB)
462 Square bishopSq = pos.piece_list(strongerSide, BISHOP, 0);
463 Square queeningSq = relative_square(strongerSide, make_square(pawnFile, RANK_8));
464 Square kingSq = pos.king_square(weakerSide);
466 if ( opposite_color_squares(queeningSq, bishopSq)
467 && abs(square_file(kingSq) - pawnFile) <= 1)
469 // The bishop has the wrong color, and the defending king is on the
470 // file of the pawn(s) or the neighboring file. Find the rank of the
473 if (strongerSide == WHITE)
475 for (rank = RANK_7; (rank_bb(rank) & pawns) == EmptyBoardBB; rank--) {}
476 assert(rank >= RANK_2 && rank <= RANK_7);
480 for (rank = RANK_2; (rank_bb(rank) & pawns) == EmptyBoardBB; rank++) {}
481 rank = Rank(rank ^ 7); // HACK to get the relative rank
482 assert(rank >= RANK_2 && rank <= RANK_7);
484 // If the defending king has distance 1 to the promotion square or
485 // is placed somewhere in front of the pawn, it's a draw.
486 if ( square_distance(kingSq, queeningSq) <= 1
487 || relative_rank(strongerSide, kingSq) >= rank)
488 return SCALE_FACTOR_ZERO;
491 return SCALE_FACTOR_NONE;
495 /// KQKRPScalingFunction scales endgames where the stronger side has only
496 /// king and queen, while the weaker side has at least a rook and a pawn.
497 /// It tests for fortress draws with a rook on the third rank defended by
500 ScaleFactor Endgame<ScaleFactor, KQKRPs>::apply(const Position& pos) const {
502 assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
503 assert(pos.piece_count(strongerSide, QUEEN) == 1);
504 assert(pos.piece_count(strongerSide, PAWN) == 0);
505 assert(pos.piece_count(weakerSide, ROOK) == 1);
506 assert(pos.piece_count(weakerSide, PAWN) >= 1);
508 Square kingSq = pos.king_square(weakerSide);
509 if ( relative_rank(weakerSide, kingSq) <= RANK_2
510 && relative_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4
511 && (pos.pieces(ROOK, weakerSide) & rank_bb(relative_rank(weakerSide, RANK_3)))
512 && (pos.pieces(PAWN, weakerSide) & rank_bb(relative_rank(weakerSide, RANK_2)))
513 && (pos.attacks_from<KING>(kingSq) & pos.pieces(PAWN, weakerSide)))
515 Square rsq = pos.piece_list(weakerSide, ROOK, 0);
516 if (pos.attacks_from<PAWN>(rsq, strongerSide) & pos.pieces(PAWN, weakerSide))
517 return SCALE_FACTOR_ZERO;
519 return SCALE_FACTOR_NONE;
523 /// KRPKRScalingFunction scales KRP vs KR endgames. This function knows a
524 /// handful of the most important classes of drawn positions, but is far
525 /// from perfect. It would probably be a good idea to add more knowledge
528 /// It would also be nice to rewrite the actual code for this function,
529 /// which is mostly copied from Glaurung 1.x, and not very pretty.
531 ScaleFactor Endgame<ScaleFactor, KRPKR>::apply(const Position& pos) const {
533 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
534 assert(pos.piece_count(strongerSide, PAWN) == 1);
535 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
536 assert(pos.piece_count(weakerSide, PAWN) == 0);
538 Square wksq = pos.king_square(strongerSide);
539 Square wrsq = pos.piece_list(strongerSide, ROOK, 0);
540 Square wpsq = pos.piece_list(strongerSide, PAWN, 0);
541 Square bksq = pos.king_square(weakerSide);
542 Square brsq = pos.piece_list(weakerSide, ROOK, 0);
544 // Orient the board in such a way that the stronger side is white, and the
545 // pawn is on the left half of the board.
546 if (strongerSide == BLACK)
548 wksq = flip_square(wksq);
549 wrsq = flip_square(wrsq);
550 wpsq = flip_square(wpsq);
551 bksq = flip_square(bksq);
552 brsq = flip_square(brsq);
554 if (square_file(wpsq) > FILE_D)
556 wksq = flop_square(wksq);
557 wrsq = flop_square(wrsq);
558 wpsq = flop_square(wpsq);
559 bksq = flop_square(bksq);
560 brsq = flop_square(brsq);
563 File f = square_file(wpsq);
564 Rank r = square_rank(wpsq);
565 Square queeningSq = make_square(f, RANK_8);
566 int tempo = (pos.side_to_move() == strongerSide);
568 // If the pawn is not too far advanced and the defending king defends the
569 // queening square, use the third-rank defence.
571 && square_distance(bksq, queeningSq) <= 1
573 && (square_rank(brsq) == RANK_6 || (r <= RANK_3 && square_rank(wrsq) != RANK_6)))
574 return SCALE_FACTOR_ZERO;
576 // The defending side saves a draw by checking from behind in case the pawn
577 // has advanced to the 6th rank with the king behind.
579 && square_distance(bksq, queeningSq) <= 1
580 && square_rank(wksq) + tempo <= RANK_6
581 && (square_rank(brsq) == RANK_1 || (!tempo && abs(square_file(brsq) - f) >= 3)))
582 return SCALE_FACTOR_ZERO;
585 && bksq == queeningSq
586 && square_rank(brsq) == RANK_1
587 && (!tempo || square_distance(wksq, wpsq) >= 2))
588 return SCALE_FACTOR_ZERO;
590 // White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
591 // and the black rook is behind the pawn.
594 && (bksq == SQ_H7 || bksq == SQ_G7)
595 && square_file(brsq) == FILE_A
596 && (square_rank(brsq) <= RANK_3 || square_file(wksq) >= FILE_D || square_rank(wksq) <= RANK_5))
597 return SCALE_FACTOR_ZERO;
599 // If the defending king blocks the pawn and the attacking king is too far
600 // away, it's a draw.
602 && bksq == wpsq + DELTA_N
603 && square_distance(wksq, wpsq) - tempo >= 2
604 && square_distance(wksq, brsq) - tempo >= 2)
605 return SCALE_FACTOR_ZERO;
607 // Pawn on the 7th rank supported by the rook from behind usually wins if the
608 // attacking king is closer to the queening square than the defending king,
609 // and the defending king cannot gain tempi by threatening the attacking rook.
612 && square_file(wrsq) == f
613 && wrsq != queeningSq
614 && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
615 && (square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo))
616 return ScaleFactor(SCALE_FACTOR_MAX - 2 * square_distance(wksq, queeningSq));
618 // Similar to the above, but with the pawn further back
620 && square_file(wrsq) == f
622 && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
623 && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wpsq + DELTA_N) - 2 + tempo)
624 && ( square_distance(bksq, wrsq) + tempo >= 3
625 || ( square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo
626 && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wrsq) + tempo))))
627 return ScaleFactor( SCALE_FACTOR_MAX
628 - 8 * square_distance(wpsq, queeningSq)
629 - 2 * square_distance(wksq, queeningSq));
631 // If the pawn is not far advanced, and the defending king is somewhere in
632 // the pawn's path, it's probably a draw.
633 if (r <= RANK_4 && bksq > wpsq)
635 if (square_file(bksq) == square_file(wpsq))
636 return ScaleFactor(10);
637 if ( abs(square_file(bksq) - square_file(wpsq)) == 1
638 && square_distance(wksq, bksq) > 2)
639 return ScaleFactor(24 - 2 * square_distance(wksq, bksq));
641 return SCALE_FACTOR_NONE;
645 /// KRPPKRPScalingFunction scales KRPP vs KRP endgames. There is only a
646 /// single pattern: If the stronger side has no pawns and the defending king
647 /// is actively placed, the position is drawish.
649 ScaleFactor Endgame<ScaleFactor, KRPPKRP>::apply(const Position& pos) const {
651 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
652 assert(pos.piece_count(strongerSide, PAWN) == 2);
653 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
654 assert(pos.piece_count(weakerSide, PAWN) == 1);
656 Square wpsq1 = pos.piece_list(strongerSide, PAWN, 0);
657 Square wpsq2 = pos.piece_list(strongerSide, PAWN, 1);
658 Square bksq = pos.king_square(weakerSide);
660 // Does the stronger side have a passed pawn?
661 if ( pos.pawn_is_passed(strongerSide, wpsq1)
662 || pos.pawn_is_passed(strongerSide, wpsq2))
663 return SCALE_FACTOR_NONE;
665 Rank r = Max(relative_rank(strongerSide, wpsq1), relative_rank(strongerSide, wpsq2));
667 if ( file_distance(bksq, wpsq1) <= 1
668 && file_distance(bksq, wpsq2) <= 1
669 && relative_rank(strongerSide, bksq) > r)
672 case RANK_2: return ScaleFactor(10);
673 case RANK_3: return ScaleFactor(10);
674 case RANK_4: return ScaleFactor(15);
675 case RANK_5: return ScaleFactor(20);
676 case RANK_6: return ScaleFactor(40);
677 default: assert(false);
680 return SCALE_FACTOR_NONE;
684 /// KPsKScalingFunction scales endgames with king and two or more pawns
685 /// against king. There is just a single rule here: If all pawns are on
686 /// the same rook file and are blocked by the defending king, it's a draw.
688 ScaleFactor Endgame<ScaleFactor, KPsK>::apply(const Position& pos) const {
690 assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
691 assert(pos.piece_count(strongerSide, PAWN) >= 2);
692 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
693 assert(pos.piece_count(weakerSide, PAWN) == 0);
695 Square ksq = pos.king_square(weakerSide);
696 Bitboard pawns = pos.pieces(PAWN, strongerSide);
698 // Are all pawns on the 'a' file?
699 if ((pawns & ~FileABB) == EmptyBoardBB)
701 // Does the defending king block the pawns?
702 if ( square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1
703 || ( square_file(ksq) == FILE_A
704 && (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB))
705 return SCALE_FACTOR_ZERO;
707 // Are all pawns on the 'h' file?
708 else if ((pawns & ~FileHBB) == EmptyBoardBB)
710 // Does the defending king block the pawns?
711 if ( square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1
712 || ( square_file(ksq) == FILE_H
713 && (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB))
714 return SCALE_FACTOR_ZERO;
716 return SCALE_FACTOR_NONE;
720 /// KBPKBScalingFunction scales KBP vs KB endgames. There are two rules:
721 /// If the defending king is somewhere along the path of the pawn, and the
722 /// square of the king is not of the same color as the stronger side's bishop,
723 /// it's a draw. If the two bishops have opposite color, it's almost always
726 ScaleFactor Endgame<ScaleFactor, KBPKB>::apply(const Position& pos) const {
728 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
729 assert(pos.piece_count(strongerSide, BISHOP) == 1);
730 assert(pos.piece_count(strongerSide, PAWN) == 1);
731 assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
732 assert(pos.piece_count(weakerSide, BISHOP) == 1);
733 assert(pos.piece_count(weakerSide, PAWN) == 0);
735 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
736 Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
737 Square weakerBishopSq = pos.piece_list(weakerSide, BISHOP, 0);
738 Square weakerKingSq = pos.king_square(weakerSide);
740 // Case 1: Defending king blocks the pawn, and cannot be driven away
741 if ( square_file(weakerKingSq) == square_file(pawnSq)
742 && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
743 && ( opposite_color_squares(weakerKingSq, strongerBishopSq)
744 || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
745 return SCALE_FACTOR_ZERO;
747 // Case 2: Opposite colored bishops
748 if (opposite_color_squares(strongerBishopSq, weakerBishopSq))
750 // We assume that the position is drawn in the following three situations:
752 // a. The pawn is on rank 5 or further back.
753 // b. The defending king is somewhere in the pawn's path.
754 // c. The defending bishop attacks some square along the pawn's path,
755 // and is at least three squares away from the pawn.
757 // These rules are probably not perfect, but in practice they work
760 if (relative_rank(strongerSide, pawnSq) <= RANK_5)
761 return SCALE_FACTOR_ZERO;
764 Bitboard path = squares_in_front_of(strongerSide, pawnSq);
766 if (path & pos.pieces(KING, weakerSide))
767 return SCALE_FACTOR_ZERO;
769 if ( (pos.attacks_from<BISHOP>(weakerBishopSq) & path)
770 && square_distance(weakerBishopSq, pawnSq) >= 3)
771 return SCALE_FACTOR_ZERO;
774 return SCALE_FACTOR_NONE;
778 /// KBPPKBScalingFunction scales KBPP vs KB endgames. It detects a few basic
779 /// draws with opposite-colored bishops.
781 ScaleFactor Endgame<ScaleFactor, KBPPKB>::apply(const Position& pos) const {
783 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
784 assert(pos.piece_count(strongerSide, BISHOP) == 1);
785 assert(pos.piece_count(strongerSide, PAWN) == 2);
786 assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
787 assert(pos.piece_count(weakerSide, BISHOP) == 1);
788 assert(pos.piece_count(weakerSide, PAWN) == 0);
790 Square wbsq = pos.piece_list(strongerSide, BISHOP, 0);
791 Square bbsq = pos.piece_list(weakerSide, BISHOP, 0);
793 if (!opposite_color_squares(wbsq, bbsq))
794 return SCALE_FACTOR_NONE;
796 Square ksq = pos.king_square(weakerSide);
797 Square psq1 = pos.piece_list(strongerSide, PAWN, 0);
798 Square psq2 = pos.piece_list(strongerSide, PAWN, 1);
799 Rank r1 = square_rank(psq1);
800 Rank r2 = square_rank(psq2);
801 Square blockSq1, blockSq2;
803 if (relative_rank(strongerSide, psq1) > relative_rank(strongerSide, psq2))
805 blockSq1 = psq1 + pawn_push(strongerSide);
806 blockSq2 = make_square(square_file(psq2), square_rank(psq1));
810 blockSq1 = psq2 + pawn_push(strongerSide);
811 blockSq2 = make_square(square_file(psq1), square_rank(psq2));
814 switch (file_distance(psq1, psq2))
817 // Both pawns are on the same file. Easy draw if defender firmly controls
818 // some square in the frontmost pawn's path.
819 if ( square_file(ksq) == square_file(blockSq1)
820 && relative_rank(strongerSide, ksq) >= relative_rank(strongerSide, blockSq1)
821 && opposite_color_squares(ksq, wbsq))
822 return SCALE_FACTOR_ZERO;
824 return SCALE_FACTOR_NONE;
827 // Pawns on neighboring files. Draw if defender firmly controls the square
828 // in front of the frontmost pawn's path, and the square diagonally behind
829 // this square on the file of the other pawn.
831 && opposite_color_squares(ksq, wbsq)
832 && ( bbsq == blockSq2
833 || (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(BISHOP, weakerSide))
834 || abs(r1 - r2) >= 2))
835 return SCALE_FACTOR_ZERO;
837 else if ( ksq == blockSq2
838 && opposite_color_squares(ksq, wbsq)
839 && ( bbsq == blockSq1
840 || (pos.attacks_from<BISHOP>(blockSq1) & pos.pieces(BISHOP, weakerSide))))
841 return SCALE_FACTOR_ZERO;
843 return SCALE_FACTOR_NONE;
846 // The pawns are not on the same file or adjacent files. No scaling.
847 return SCALE_FACTOR_NONE;
852 /// KBPKNScalingFunction scales KBP vs KN endgames. There is a single rule:
853 /// If the defending king is somewhere along the path of the pawn, and the
854 /// square of the king is not of the same color as the stronger side's bishop,
857 ScaleFactor Endgame<ScaleFactor, KBPKN>::apply(const Position& pos) const {
859 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
860 assert(pos.piece_count(strongerSide, BISHOP) == 1);
861 assert(pos.piece_count(strongerSide, PAWN) == 1);
862 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
863 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
864 assert(pos.piece_count(weakerSide, PAWN) == 0);
866 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
867 Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
868 Square weakerKingSq = pos.king_square(weakerSide);
870 if ( square_file(weakerKingSq) == square_file(pawnSq)
871 && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
872 && ( opposite_color_squares(weakerKingSq, strongerBishopSq)
873 || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
874 return SCALE_FACTOR_ZERO;
876 return SCALE_FACTOR_NONE;
880 /// KNPKScalingFunction scales KNP vs K endgames. There is a single rule:
881 /// If the pawn is a rook pawn on the 7th rank and the defending king prevents
882 /// the pawn from advancing, the position is drawn.
884 ScaleFactor Endgame<ScaleFactor, KNPK>::apply(const Position& pos) const {
886 assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame);
887 assert(pos.piece_count(strongerSide, KNIGHT) == 1);
888 assert(pos.piece_count(strongerSide, PAWN) == 1);
889 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
890 assert(pos.piece_count(weakerSide, PAWN) == 0);
892 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
893 Square weakerKingSq = pos.king_square(weakerSide);
895 if ( pawnSq == relative_square(strongerSide, SQ_A7)
896 && square_distance(weakerKingSq, relative_square(strongerSide, SQ_A8)) <= 1)
897 return SCALE_FACTOR_ZERO;
899 if ( pawnSq == relative_square(strongerSide, SQ_H7)
900 && square_distance(weakerKingSq, relative_square(strongerSide, SQ_H8)) <= 1)
901 return SCALE_FACTOR_ZERO;
903 return SCALE_FACTOR_NONE;
907 /// KPKPScalingFunction scales KP vs KP endgames. This is done by removing
908 /// the weakest side's pawn and probing the KP vs K bitbase: If the weakest
909 /// side has a draw without the pawn, she probably has at least a draw with
910 /// the pawn as well. The exception is when the stronger side's pawn is far
911 /// advanced and not on a rook file; in this case it is often possible to win
912 /// (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
914 ScaleFactor Endgame<ScaleFactor, KPKP>::apply(const Position& pos) const {
916 assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
917 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
918 assert(pos.piece_count(WHITE, PAWN) == 1);
919 assert(pos.piece_count(BLACK, PAWN) == 1);
921 Square wksq, bksq, wpsq;
924 if (strongerSide == WHITE)
926 wksq = pos.king_square(WHITE);
927 bksq = pos.king_square(BLACK);
928 wpsq = pos.piece_list(WHITE, PAWN, 0);
929 stm = pos.side_to_move();
933 wksq = flip_square(pos.king_square(BLACK));
934 bksq = flip_square(pos.king_square(WHITE));
935 wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
936 stm = opposite_color(pos.side_to_move());
939 if (square_file(wpsq) >= FILE_E)
941 wksq = flop_square(wksq);
942 bksq = flop_square(bksq);
943 wpsq = flop_square(wpsq);
946 // If the pawn has advanced to the fifth rank or further, and is not a
947 // rook pawn, it's too dangerous to assume that it's at least a draw.
948 if ( square_rank(wpsq) >= RANK_5
949 && square_file(wpsq) != FILE_A)
950 return SCALE_FACTOR_NONE;
952 // Probe the KPK bitbase with the weakest side's pawn removed. If it's a
953 // draw, it's probably at least a draw even with the pawn.
954 return probe_kpk_bitbase(wksq, wpsq, bksq, stm) ? SCALE_FACTOR_NONE : SCALE_FACTOR_ZERO;