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-2015 Marco Costalba, Joona Kiiski, Tord Romstad
5 Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad
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
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Stockfish is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
32 // Table used to drive the king towards the edge of the board
33 // in KX vs K and KQ vs KR endgames.
34 const int PushToEdges[SQUARE_NB] = {
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 king towards a corner square of the
46 // right color in KBN vs K endgames.
47 const int PushToCorners[SQUARE_NB] = {
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 // Tables used to drive a piece towards or away from another piece
59 const int PushClose[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
60 const int PushAway [8] = { 0, 5, 20, 40, 60, 80, 90, 100 };
62 // Pawn Rank based scaling factors used in KRPPKRP endgame
63 const int KRPPKRPScaleFactors[RANK_NB] = { 0, 9, 10, 14, 21, 44, 0, 0 };
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;
71 // Map the square as if strongSide is white and strongSide's only pawn
72 // is on the left half of the board.
73 Square normalize(const Position& pos, Color strongSide, Square sq) {
75 assert(pos.count<PAWN>(strongSide) == 1);
77 if (file_of(pos.square<PAWN>(strongSide)) >= FILE_E)
78 sq = Square(sq ^ 7); // Mirror SQ_H1 -> SQ_A1
80 if (strongSide == BLACK)
89 /// Endgames members definitions
91 Endgames::Endgames() {
108 add<KBPPKB>("KBPPKB");
109 add<KRPPKRP>("KRPPKRP");
113 template<EndgameType E, typename T>
114 void Endgames::add(const string& code) {
116 map<T>()[Position().set(code, WHITE, &st).material_key()] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(WHITE));
117 map<T>()[Position().set(code, BLACK, &st).material_key()] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(BLACK));
121 /// Mate with KX vs K. This function is used to evaluate positions with
122 /// king and plenty of material vs a lone king. It simply gives the
123 /// attacking side a bonus for driving the defending king towards the edge
124 /// of the board, and for keeping the distance between the two kings small.
126 Value Endgame<KXK>::operator()(const Position& pos) const {
128 assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
129 assert(!pos.checkers()); // Eval is never called when in check
131 // Stalemate detection with lone king
132 if (pos.side_to_move() == weakSide && !MoveList<LEGAL>(pos).size())
135 Square winnerKSq = pos.square<KING>(strongSide);
136 Square loserKSq = pos.square<KING>(weakSide);
138 Value result = pos.non_pawn_material(strongSide)
139 + pos.count<PAWN>(strongSide) * PawnValueEg
140 + PushToEdges[loserKSq]
141 + PushClose[distance(winnerKSq, loserKSq)];
143 if ( pos.count<QUEEN>(strongSide)
144 || pos.count<ROOK>(strongSide)
145 ||(pos.count<BISHOP>(strongSide) && pos.count<KNIGHT>(strongSide))
146 ||(pos.count<BISHOP>(strongSide) > 1 && opposite_colors(pos.squares<BISHOP>(strongSide)[0],
147 pos.squares<BISHOP>(strongSide)[1])))
148 result = std::min(result + VALUE_KNOWN_WIN, VALUE_MATE_IN_MAX_PLY - 1);
150 return strongSide == pos.side_to_move() ? result : -result;
154 /// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the
155 /// defending king towards a corner square of the right color.
157 Value Endgame<KBNK>::operator()(const Position& pos) const {
159 assert(verify_material(pos, strongSide, KnightValueMg + BishopValueMg, 0));
160 assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
162 Square winnerKSq = pos.square<KING>(strongSide);
163 Square loserKSq = pos.square<KING>(weakSide);
164 Square bishopSq = pos.square<BISHOP>(strongSide);
166 // kbnk_mate_table() tries to drive toward corners A1 or H8. If we have a
167 // bishop that cannot reach the above squares, we flip the kings in order
168 // to drive the enemy toward corners A8 or H1.
169 if (opposite_colors(bishopSq, SQ_A1))
171 winnerKSq = ~winnerKSq;
172 loserKSq = ~loserKSq;
175 Value result = VALUE_KNOWN_WIN
176 + PushClose[distance(winnerKSq, loserKSq)]
177 + PushToCorners[loserKSq];
179 return strongSide == pos.side_to_move() ? result : -result;
183 /// KP vs K. This endgame is evaluated with the help of a bitbase.
185 Value Endgame<KPK>::operator()(const Position& pos) const {
187 assert(verify_material(pos, strongSide, VALUE_ZERO, 1));
188 assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
190 // Assume strongSide is white and the pawn is on files A-D
191 Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
192 Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
193 Square psq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
195 Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
197 if (!Bitbases::probe(wksq, psq, bksq, us))
200 Value result = VALUE_KNOWN_WIN + PawnValueEg + Value(rank_of(psq));
202 return strongSide == pos.side_to_move() ? result : -result;
206 /// KR vs KP. This is a somewhat tricky endgame to evaluate precisely without
207 /// a bitbase. The function below returns drawish scores when the pawn is
208 /// far advanced with support of the king, while the attacking king is far
211 Value Endgame<KRKP>::operator()(const Position& pos) const {
213 assert(verify_material(pos, strongSide, RookValueMg, 0));
214 assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
216 Square wksq = relative_square(strongSide, pos.square<KING>(strongSide));
217 Square bksq = relative_square(strongSide, pos.square<KING>(weakSide));
218 Square rsq = relative_square(strongSide, pos.square<ROOK>(strongSide));
219 Square psq = relative_square(strongSide, pos.square<PAWN>(weakSide));
221 Square queeningSq = make_square(file_of(psq), RANK_1);
224 // If the stronger side's king is in front of the pawn, it's a win
225 if (wksq < psq && file_of(wksq) == file_of(psq))
226 result = RookValueEg - distance(wksq, psq);
228 // If the weaker side's king is too far from the pawn and the rook,
230 else if ( distance(bksq, psq) >= 3 + (pos.side_to_move() == weakSide)
231 && distance(bksq, rsq) >= 3)
232 result = RookValueEg - distance(wksq, psq);
234 // If the pawn is far advanced and supported by the defending king,
235 // the position is drawish
236 else if ( rank_of(bksq) <= RANK_3
237 && distance(bksq, psq) == 1
238 && rank_of(wksq) >= RANK_4
239 && distance(wksq, psq) > 2 + (pos.side_to_move() == strongSide))
240 result = Value(80) - 8 * distance(wksq, psq);
243 result = Value(200) - 8 * ( distance(wksq, psq + SOUTH)
244 - distance(bksq, psq + SOUTH)
245 - distance(psq, queeningSq));
247 return strongSide == pos.side_to_move() ? result : -result;
251 /// KR vs KB. This is very simple, and always returns drawish scores. The
252 /// score is slightly bigger when the defending king is close to the edge.
254 Value Endgame<KRKB>::operator()(const Position& pos) const {
256 assert(verify_material(pos, strongSide, RookValueMg, 0));
257 assert(verify_material(pos, weakSide, BishopValueMg, 0));
259 Value result = Value(PushToEdges[pos.square<KING>(weakSide)]);
260 return strongSide == pos.side_to_move() ? result : -result;
264 /// KR vs KN. The attacking side has slightly better winning chances than
265 /// in KR vs KB, particularly if the king and the knight are far apart.
267 Value Endgame<KRKN>::operator()(const Position& pos) const {
269 assert(verify_material(pos, strongSide, RookValueMg, 0));
270 assert(verify_material(pos, weakSide, KnightValueMg, 0));
272 Square bksq = pos.square<KING>(weakSide);
273 Square bnsq = pos.square<KNIGHT>(weakSide);
274 Value result = Value(PushToEdges[bksq] + PushAway[distance(bksq, bnsq)]);
275 return strongSide == pos.side_to_move() ? result : -result;
279 /// KQ vs KP. In general, this is a win for the stronger side, but there are a
280 /// few important exceptions. A pawn on 7th rank and on the A,C,F or H files
281 /// with a king positioned next to it can be a draw, so in that case, we only
282 /// use the distance between the kings.
284 Value Endgame<KQKP>::operator()(const Position& pos) const {
286 assert(verify_material(pos, strongSide, QueenValueMg, 0));
287 assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
289 Square winnerKSq = pos.square<KING>(strongSide);
290 Square loserKSq = pos.square<KING>(weakSide);
291 Square pawnSq = pos.square<PAWN>(weakSide);
293 Value result = Value(PushClose[distance(winnerKSq, loserKSq)]);
295 if ( relative_rank(weakSide, pawnSq) != RANK_7
296 || distance(loserKSq, pawnSq) != 1
297 || !((FileABB | FileCBB | FileFBB | FileHBB) & pawnSq))
298 result += QueenValueEg - PawnValueEg;
300 return strongSide == pos.side_to_move() ? result : -result;
304 /// KQ vs KR. This is almost identical to KX vs K: We give the attacking
305 /// king a bonus for having the kings close together, and for forcing the
306 /// defending king towards the edge. If we also take care to avoid null move for
307 /// the defending side in the search, this is usually sufficient to win KQ vs KR.
309 Value Endgame<KQKR>::operator()(const Position& pos) const {
311 assert(verify_material(pos, strongSide, QueenValueMg, 0));
312 assert(verify_material(pos, weakSide, RookValueMg, 0));
314 Square winnerKSq = pos.square<KING>(strongSide);
315 Square loserKSq = pos.square<KING>(weakSide);
317 Value result = QueenValueEg
319 + PushToEdges[loserKSq]
320 + PushClose[distance(winnerKSq, loserKSq)];
322 return strongSide == pos.side_to_move() ? result : -result;
326 /// Some cases of trivial draws
327 template<> Value Endgame<KNNK>::operator()(const Position&) const { return VALUE_DRAW; }
330 /// KB and one or more pawns vs K. It checks for draws with rook pawns and
331 /// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW
332 /// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
335 ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
337 assert(pos.non_pawn_material(strongSide) == BishopValueMg);
338 assert(pos.count<PAWN>(strongSide) >= 1);
340 // No assertions about the material of weakSide, because we want draws to
341 // be detected even when the weaker side has some pawns.
343 Bitboard pawns = pos.pieces(strongSide, PAWN);
344 File pawnsFile = file_of(lsb(pawns));
346 // All pawns are on a single rook file?
347 if ( (pawnsFile == FILE_A || pawnsFile == FILE_H)
348 && !(pawns & ~file_bb(pawnsFile)))
350 Square bishopSq = pos.square<BISHOP>(strongSide);
351 Square queeningSq = relative_square(strongSide, make_square(pawnsFile, RANK_8));
352 Square kingSq = pos.square<KING>(weakSide);
354 if ( opposite_colors(queeningSq, bishopSq)
355 && distance(queeningSq, kingSq) <= 1)
356 return SCALE_FACTOR_DRAW;
359 // If all the pawns are on the same B or G file, then it's potentially a draw
360 if ( (pawnsFile == FILE_B || pawnsFile == FILE_G)
361 && !(pos.pieces(PAWN) & ~file_bb(pawnsFile))
362 && pos.non_pawn_material(weakSide) == 0
363 && pos.count<PAWN>(weakSide) >= 1)
365 // Get weakSide pawn that is closest to the home rank
366 Square weakPawnSq = backmost_sq(weakSide, pos.pieces(weakSide, PAWN));
368 Square strongKingSq = pos.square<KING>(strongSide);
369 Square weakKingSq = pos.square<KING>(weakSide);
370 Square bishopSq = pos.square<BISHOP>(strongSide);
372 // There's potential for a draw if our pawn is blocked on the 7th rank,
373 // the bishop cannot attack it or they only have one pawn left
374 if ( relative_rank(strongSide, weakPawnSq) == RANK_7
375 && (pos.pieces(strongSide, PAWN) & (weakPawnSq + pawn_push(weakSide)))
376 && (opposite_colors(bishopSq, weakPawnSq) || pos.count<PAWN>(strongSide) == 1))
378 int strongKingDist = distance(weakPawnSq, strongKingSq);
379 int weakKingDist = distance(weakPawnSq, weakKingSq);
381 // It's a draw if the weak king is on its back two ranks, within 2
382 // squares of the blocking pawn and the strong king is not
383 // closer. (I think this rule only fails in practically
384 // unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w
385 // and positions where qsearch will immediately correct the
386 // problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w)
387 if ( relative_rank(strongSide, weakKingSq) >= RANK_7
389 && weakKingDist <= strongKingDist)
390 return SCALE_FACTOR_DRAW;
394 return SCALE_FACTOR_NONE;
398 /// KQ vs KR and one or more pawns. It tests for fortress draws with a rook on
399 /// the third rank defended by a pawn.
401 ScaleFactor Endgame<KQKRPs>::operator()(const Position& pos) const {
403 assert(verify_material(pos, strongSide, QueenValueMg, 0));
404 assert(pos.count<ROOK>(weakSide) == 1);
405 assert(pos.count<PAWN>(weakSide) >= 1);
407 Square kingSq = pos.square<KING>(weakSide);
408 Square rsq = pos.square<ROOK>(weakSide);
410 if ( relative_rank(weakSide, kingSq) <= RANK_2
411 && relative_rank(weakSide, pos.square<KING>(strongSide)) >= RANK_4
412 && relative_rank(weakSide, rsq) == RANK_3
413 && ( pos.pieces(weakSide, PAWN)
414 & pos.attacks_from<KING>(kingSq)
415 & pos.attacks_from<PAWN>(rsq, strongSide)))
416 return SCALE_FACTOR_DRAW;
418 return SCALE_FACTOR_NONE;
422 /// KRP vs KR. This function knows a handful of the most important classes of
423 /// drawn positions, but is far from perfect. It would probably be a good idea
424 /// to add more knowledge in the future.
426 /// It would also be nice to rewrite the actual code for this function,
427 /// which is mostly copied from Glaurung 1.x, and isn't very pretty.
429 ScaleFactor Endgame<KRPKR>::operator()(const Position& pos) const {
431 assert(verify_material(pos, strongSide, RookValueMg, 1));
432 assert(verify_material(pos, weakSide, RookValueMg, 0));
434 // Assume strongSide is white and the pawn is on files A-D
435 Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
436 Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
437 Square wrsq = normalize(pos, strongSide, pos.square<ROOK>(strongSide));
438 Square wpsq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
439 Square brsq = normalize(pos, strongSide, pos.square<ROOK>(weakSide));
441 File f = file_of(wpsq);
442 Rank r = rank_of(wpsq);
443 Square queeningSq = make_square(f, RANK_8);
444 int tempo = (pos.side_to_move() == strongSide);
446 // If the pawn is not too far advanced and the defending king defends the
447 // queening square, use the third-rank defence.
449 && distance(bksq, queeningSq) <= 1
451 && (rank_of(brsq) == RANK_6 || (r <= RANK_3 && rank_of(wrsq) != RANK_6)))
452 return SCALE_FACTOR_DRAW;
454 // The defending side saves a draw by checking from behind in case the pawn
455 // has advanced to the 6th rank with the king behind.
457 && distance(bksq, queeningSq) <= 1
458 && rank_of(wksq) + tempo <= RANK_6
459 && (rank_of(brsq) == RANK_1 || (!tempo && distance<File>(brsq, wpsq) >= 3)))
460 return SCALE_FACTOR_DRAW;
463 && bksq == queeningSq
464 && rank_of(brsq) == RANK_1
465 && (!tempo || distance(wksq, wpsq) >= 2))
466 return SCALE_FACTOR_DRAW;
468 // White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
469 // and the black rook is behind the pawn.
472 && (bksq == SQ_H7 || bksq == SQ_G7)
473 && file_of(brsq) == FILE_A
474 && (rank_of(brsq) <= RANK_3 || file_of(wksq) >= FILE_D || rank_of(wksq) <= RANK_5))
475 return SCALE_FACTOR_DRAW;
477 // If the defending king blocks the pawn and the attacking king is too far
478 // away, it's a draw.
480 && bksq == wpsq + NORTH
481 && distance(wksq, wpsq) - tempo >= 2
482 && distance(wksq, brsq) - tempo >= 2)
483 return SCALE_FACTOR_DRAW;
485 // Pawn on the 7th rank supported by the rook from behind usually wins if the
486 // attacking king is closer to the queening square than the defending king,
487 // and the defending king cannot gain tempi by threatening the attacking rook.
490 && file_of(wrsq) == f
491 && wrsq != queeningSq
492 && (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
493 && (distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo))
494 return ScaleFactor(SCALE_FACTOR_MAX - 2 * distance(wksq, queeningSq));
496 // Similar to the above, but with the pawn further back
498 && file_of(wrsq) == f
500 && (distance(wksq, queeningSq) < distance(bksq, queeningSq) - 2 + tempo)
501 && (distance(wksq, wpsq + NORTH) < distance(bksq, wpsq + NORTH) - 2 + tempo)
502 && ( distance(bksq, wrsq) + tempo >= 3
503 || ( distance(wksq, queeningSq) < distance(bksq, wrsq) + tempo
504 && (distance(wksq, wpsq + NORTH) < distance(bksq, wrsq) + tempo))))
505 return ScaleFactor( SCALE_FACTOR_MAX
506 - 8 * distance(wpsq, queeningSq)
507 - 2 * distance(wksq, queeningSq));
509 // If the pawn is not far advanced and the defending king is somewhere in
510 // the pawn's path, it's probably a draw.
511 if (r <= RANK_4 && bksq > wpsq)
513 if (file_of(bksq) == file_of(wpsq))
514 return ScaleFactor(10);
515 if ( distance<File>(bksq, wpsq) == 1
516 && distance(wksq, bksq) > 2)
517 return ScaleFactor(24 - 2 * distance(wksq, bksq));
519 return SCALE_FACTOR_NONE;
523 ScaleFactor Endgame<KRPKB>::operator()(const Position& pos) const {
525 assert(verify_material(pos, strongSide, RookValueMg, 1));
526 assert(verify_material(pos, weakSide, BishopValueMg, 0));
528 // Test for a rook pawn
529 if (pos.pieces(PAWN) & (FileABB | FileHBB))
531 Square ksq = pos.square<KING>(weakSide);
532 Square bsq = pos.square<BISHOP>(weakSide);
533 Square psq = pos.square<PAWN>(strongSide);
534 Rank rk = relative_rank(strongSide, psq);
535 Square push = pawn_push(strongSide);
537 // If the pawn is on the 5th rank and the pawn (currently) is on
538 // the same color square as the bishop then there is a chance of
539 // a fortress. Depending on the king position give a moderate
540 // reduction or a stronger one if the defending king is near the
541 // corner but not trapped there.
542 if (rk == RANK_5 && !opposite_colors(bsq, psq))
544 int d = distance(psq + 3 * push, ksq);
546 if (d <= 2 && !(d == 0 && ksq == pos.square<KING>(strongSide) + 2 * push))
547 return ScaleFactor(24);
549 return ScaleFactor(48);
552 // When the pawn has moved to the 6th rank we can be fairly sure
553 // it's drawn if the bishop attacks the square in front of the
554 // pawn from a reasonable distance and the defending king is near
557 && distance(psq + 2 * push, ksq) <= 1
558 && (PseudoAttacks[BISHOP][bsq] & (psq + push))
559 && distance<File>(bsq, psq) >= 2)
560 return ScaleFactor(8);
563 return SCALE_FACTOR_NONE;
566 /// KRPP vs KRP. There is just a single rule: if the stronger side has no passed
567 /// pawns and the defending king is actively placed, the position is drawish.
569 ScaleFactor Endgame<KRPPKRP>::operator()(const Position& pos) const {
571 assert(verify_material(pos, strongSide, RookValueMg, 2));
572 assert(verify_material(pos, weakSide, RookValueMg, 1));
574 Square wpsq1 = pos.squares<PAWN>(strongSide)[0];
575 Square wpsq2 = pos.squares<PAWN>(strongSide)[1];
576 Square bksq = pos.square<KING>(weakSide);
578 // Does the stronger side have a passed pawn?
579 if (pos.pawn_passed(strongSide, wpsq1) || pos.pawn_passed(strongSide, wpsq2))
580 return SCALE_FACTOR_NONE;
582 Rank r = std::max(relative_rank(strongSide, wpsq1), relative_rank(strongSide, wpsq2));
584 if ( distance<File>(bksq, wpsq1) <= 1
585 && distance<File>(bksq, wpsq2) <= 1
586 && relative_rank(strongSide, bksq) > r)
588 assert(r > RANK_1 && r < RANK_7);
589 return ScaleFactor(KRPPKRPScaleFactors[r]);
591 return SCALE_FACTOR_NONE;
595 /// K and two or more pawns vs K. There is just a single rule here: If all pawns
596 /// are on the same rook file and are blocked by the defending king, it's a draw.
598 ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const {
600 assert(pos.non_pawn_material(strongSide) == VALUE_ZERO);
601 assert(pos.count<PAWN>(strongSide) >= 2);
602 assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
604 Square ksq = pos.square<KING>(weakSide);
605 Bitboard pawns = pos.pieces(strongSide, PAWN);
607 // If all pawns are ahead of the king, on a single rook file and
608 // the king is within one file of the pawns, it's a draw.
609 if ( !(pawns & ~in_front_bb(weakSide, rank_of(ksq)))
610 && !((pawns & ~FileABB) && (pawns & ~FileHBB))
611 && distance<File>(ksq, lsb(pawns)) <= 1)
612 return SCALE_FACTOR_DRAW;
614 return SCALE_FACTOR_NONE;
618 /// KBP vs KB. There are two rules: if the defending king is somewhere along the
619 /// path of the pawn, and the square of the king is not of the same color as the
620 /// stronger side's bishop, it's a draw. If the two bishops have opposite color,
621 /// it's almost always a draw.
623 ScaleFactor Endgame<KBPKB>::operator()(const Position& pos) const {
625 assert(verify_material(pos, strongSide, BishopValueMg, 1));
626 assert(verify_material(pos, weakSide, BishopValueMg, 0));
628 Square pawnSq = pos.square<PAWN>(strongSide);
629 Square strongBishopSq = pos.square<BISHOP>(strongSide);
630 Square weakBishopSq = pos.square<BISHOP>(weakSide);
631 Square weakKingSq = pos.square<KING>(weakSide);
633 // Case 1: Defending king blocks the pawn, and cannot be driven away
634 if ( file_of(weakKingSq) == file_of(pawnSq)
635 && relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
636 && ( opposite_colors(weakKingSq, strongBishopSq)
637 || relative_rank(strongSide, weakKingSq) <= RANK_6))
638 return SCALE_FACTOR_DRAW;
640 // Case 2: Opposite colored bishops
641 if (opposite_colors(strongBishopSq, weakBishopSq))
643 // We assume that the position is drawn in the following three situations:
645 // a. The pawn is on rank 5 or further back.
646 // b. The defending king is somewhere in the pawn's path.
647 // c. The defending bishop attacks some square along the pawn's path,
648 // and is at least three squares away from the pawn.
650 // These rules are probably not perfect, but in practice they work
653 if (relative_rank(strongSide, pawnSq) <= RANK_5)
654 return SCALE_FACTOR_DRAW;
656 Bitboard path = forward_bb(strongSide, pawnSq);
658 if (path & pos.pieces(weakSide, KING))
659 return SCALE_FACTOR_DRAW;
661 if ( (pos.attacks_from<BISHOP>(weakBishopSq) & path)
662 && distance(weakBishopSq, pawnSq) >= 3)
663 return SCALE_FACTOR_DRAW;
665 return SCALE_FACTOR_NONE;
669 /// KBPP vs KB. It detects a few basic draws with opposite-colored bishops
671 ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
673 assert(verify_material(pos, strongSide, BishopValueMg, 2));
674 assert(verify_material(pos, weakSide, BishopValueMg, 0));
676 Square wbsq = pos.square<BISHOP>(strongSide);
677 Square bbsq = pos.square<BISHOP>(weakSide);
679 if (!opposite_colors(wbsq, bbsq))
680 return SCALE_FACTOR_NONE;
682 Square ksq = pos.square<KING>(weakSide);
683 Square psq1 = pos.squares<PAWN>(strongSide)[0];
684 Square psq2 = pos.squares<PAWN>(strongSide)[1];
685 Rank r1 = rank_of(psq1);
686 Rank r2 = rank_of(psq2);
687 Square blockSq1, blockSq2;
689 if (relative_rank(strongSide, psq1) > relative_rank(strongSide, psq2))
691 blockSq1 = psq1 + pawn_push(strongSide);
692 blockSq2 = make_square(file_of(psq2), rank_of(psq1));
696 blockSq1 = psq2 + pawn_push(strongSide);
697 blockSq2 = make_square(file_of(psq1), rank_of(psq2));
700 switch (distance<File>(psq1, psq2))
703 // Both pawns are on the same file. It's an easy draw if the defender firmly
704 // controls some square in the frontmost pawn's path.
705 if ( file_of(ksq) == file_of(blockSq1)
706 && relative_rank(strongSide, ksq) >= relative_rank(strongSide, blockSq1)
707 && opposite_colors(ksq, wbsq))
708 return SCALE_FACTOR_DRAW;
710 return SCALE_FACTOR_NONE;
713 // Pawns on adjacent files. It's a draw if the defender firmly controls the
714 // square in front of the frontmost pawn's path, and the square diagonally
715 // behind this square on the file of the other pawn.
717 && opposite_colors(ksq, wbsq)
718 && ( bbsq == blockSq2
719 || (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(weakSide, BISHOP))
720 || distance(r1, r2) >= 2))
721 return SCALE_FACTOR_DRAW;
723 else if ( ksq == blockSq2
724 && opposite_colors(ksq, wbsq)
725 && ( bbsq == blockSq1
726 || (pos.attacks_from<BISHOP>(blockSq1) & pos.pieces(weakSide, BISHOP))))
727 return SCALE_FACTOR_DRAW;
729 return SCALE_FACTOR_NONE;
732 // The pawns are not on the same file or adjacent files. No scaling.
733 return SCALE_FACTOR_NONE;
738 /// KBP vs KN. There is a single rule: If the defending king is somewhere along
739 /// the path of the pawn, and the square of the king is not of the same color as
740 /// the stronger side's bishop, it's a draw.
742 ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
744 assert(verify_material(pos, strongSide, BishopValueMg, 1));
745 assert(verify_material(pos, weakSide, KnightValueMg, 0));
747 Square pawnSq = pos.square<PAWN>(strongSide);
748 Square strongBishopSq = pos.square<BISHOP>(strongSide);
749 Square weakKingSq = pos.square<KING>(weakSide);
751 if ( file_of(weakKingSq) == file_of(pawnSq)
752 && relative_rank(strongSide, pawnSq) < relative_rank(strongSide, weakKingSq)
753 && ( opposite_colors(weakKingSq, strongBishopSq)
754 || relative_rank(strongSide, weakKingSq) <= RANK_6))
755 return SCALE_FACTOR_DRAW;
757 return SCALE_FACTOR_NONE;
761 /// KNP vs K. There is a single rule: if the pawn is a rook pawn on the 7th rank
762 /// and the defending king prevents the pawn from advancing, the position is drawn.
764 ScaleFactor Endgame<KNPK>::operator()(const Position& pos) const {
766 assert(verify_material(pos, strongSide, KnightValueMg, 1));
767 assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
769 // Assume strongSide is white and the pawn is on files A-D
770 Square pawnSq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
771 Square weakKingSq = normalize(pos, strongSide, pos.square<KING>(weakSide));
773 if (pawnSq == SQ_A7 && distance(SQ_A8, weakKingSq) <= 1)
774 return SCALE_FACTOR_DRAW;
776 return SCALE_FACTOR_NONE;
780 /// KNP vs KB. If knight can block bishop from taking pawn, it's a win.
781 /// Otherwise the position is drawn.
783 ScaleFactor Endgame<KNPKB>::operator()(const Position& pos) const {
785 Square pawnSq = pos.square<PAWN>(strongSide);
786 Square bishopSq = pos.square<BISHOP>(weakSide);
787 Square weakKingSq = pos.square<KING>(weakSide);
789 // King needs to get close to promoting pawn to prevent knight from blocking.
790 // Rules for this are very tricky, so just approximate.
791 if (forward_bb(strongSide, pawnSq) & pos.attacks_from<BISHOP>(bishopSq))
792 return ScaleFactor(distance(weakKingSq, pawnSq));
794 return SCALE_FACTOR_NONE;
798 /// KP vs KP. This is done by removing the weakest side's pawn and probing the
799 /// KP vs K bitbase: If the weakest side has a draw without the pawn, it probably
800 /// has at least a draw with the pawn as well. The exception is when the stronger
801 /// side's pawn is far advanced and not on a rook file; in this case it is often
802 /// possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
804 ScaleFactor Endgame<KPKP>::operator()(const Position& pos) const {
806 assert(verify_material(pos, strongSide, VALUE_ZERO, 1));
807 assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
809 // Assume strongSide is white and the pawn is on files A-D
810 Square wksq = normalize(pos, strongSide, pos.square<KING>(strongSide));
811 Square bksq = normalize(pos, strongSide, pos.square<KING>(weakSide));
812 Square psq = normalize(pos, strongSide, pos.square<PAWN>(strongSide));
814 Color us = strongSide == pos.side_to_move() ? WHITE : BLACK;
816 // If the pawn has advanced to the fifth rank or further, and is not a
817 // rook pawn, it's too dangerous to assume that it's at least a draw.
818 if (rank_of(psq) >= RANK_5 && file_of(psq) != FILE_A)
819 return SCALE_FACTOR_NONE;
821 // Probe the KPK bitbase with the weakest side's pawn removed. If it's a draw,
822 // it's probably at least a draw even with the pawn.
823 return Bitbases::probe(wksq, psq, bksq, us) ? SCALE_FACTOR_NONE : SCALE_FACTOR_DRAW;