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/>.
26 extern uint32_t probe_kpk_bitbase(Square wksq, Square wpsq, Square bksq, Color stm);
30 // Table used to drive the defending king towards the edge of the board
31 // in KX vs K and KQ vs KR endgames.
32 const uint8_t MateTable[64] = {
33 100, 90, 80, 70, 70, 80, 90, 100,
34 90, 70, 60, 50, 50, 60, 70, 90,
35 80, 60, 40, 30, 30, 40, 60, 80,
36 70, 50, 30, 20, 20, 30, 50, 70,
37 70, 50, 30, 20, 20, 30, 50, 70,
38 80, 60, 40, 30, 30, 40, 60, 80,
39 90, 70, 60, 50, 50, 60, 70, 90,
40 100, 90, 80, 70, 70, 80, 90, 100,
43 // Table used to drive the defending king towards a corner square of the
44 // right color in KBN vs K endgames.
45 const uint8_t KBNKMateTable[64] = {
46 200, 190, 180, 170, 160, 150, 140, 130,
47 190, 180, 170, 160, 150, 140, 130, 140,
48 180, 170, 155, 140, 140, 125, 140, 150,
49 170, 160, 140, 120, 110, 140, 150, 160,
50 160, 150, 140, 110, 120, 140, 160, 170,
51 150, 140, 125, 140, 140, 155, 170, 180,
52 140, 130, 140, 150, 160, 170, 180, 190,
53 130, 140, 150, 160, 170, 180, 190, 200
56 // The attacking side is given a descending bonus based on distance between
57 // the two kings in basic endgames.
58 const int DistanceBonus[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
60 // Penalty for big distance between king and knight for the defending king
61 // and knight in KR vs KN endgames.
62 const int KRKNKingKnightDistancePenalty[8] = { 0, 0, 4, 10, 20, 32, 48, 70 };
64 // Various inline functions for accessing the above arrays
65 inline Value mate_table(Square s) {
66 return Value(MateTable[s]);
69 inline Value kbnk_mate_table(Square s) {
70 return Value(KBNKMateTable[s]);
73 inline Value distance_bonus(int d) {
74 return Value(DistanceBonus[d]);
77 inline Value krkn_king_knight_distance_penalty(int d) {
78 return Value(KRKNKingKnightDistancePenalty[d]);
84 /// Mate with KX vs K. This function is used to evaluate positions with
85 /// King and plenty of material vs a lone king. It simply gives the
86 /// attacking side a bonus for driving the defending king towards the edge
87 /// of the board, and for keeping the distance between the two kings small.
89 Value EvaluationFunction<KXK>::apply(const Position& pos) const {
91 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
92 assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO);
94 Square winnerKSq = pos.king_square(strongerSide);
95 Square loserKSq = pos.king_square(weakerSide);
97 Value result = pos.non_pawn_material(strongerSide)
98 + pos.piece_count(strongerSide, PAWN) * PawnValueEndgame
99 + mate_table(loserKSq)
100 + distance_bonus(square_distance(winnerKSq, loserKSq));
102 if ( pos.piece_count(strongerSide, QUEEN)
103 || pos.piece_count(strongerSide, ROOK)
104 || pos.piece_count(strongerSide, BISHOP) > 1)
105 // TODO: check for two equal-colored bishops!
106 result += VALUE_KNOWN_WIN;
108 return strongerSide == pos.side_to_move() ? result : -result;
112 /// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the
113 /// defending king towards a corner square of the right color.
115 Value EvaluationFunction<KBNK>::apply(const Position& pos) const {
117 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
118 assert(pos.piece_count(weakerSide, PAWN) == VALUE_ZERO);
119 assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame + BishopValueMidgame);
120 assert(pos.piece_count(strongerSide, BISHOP) == 1);
121 assert(pos.piece_count(strongerSide, KNIGHT) == 1);
122 assert(pos.piece_count(strongerSide, PAWN) == 0);
124 Square winnerKSq = pos.king_square(strongerSide);
125 Square loserKSq = pos.king_square(weakerSide);
126 Square bishopSquare = pos.piece_list(strongerSide, BISHOP, 0);
128 // kbnk_mate_table() tries to drive toward corners A1 or H8,
129 // if we have a bishop that cannot reach the above squares we
130 // mirror the kings so to drive enemy toward corners A8 or H1.
131 if (opposite_color_squares(bishopSquare, SQ_A1))
133 winnerKSq = flop_square(winnerKSq);
134 loserKSq = flop_square(loserKSq);
137 Value result = VALUE_KNOWN_WIN
138 + distance_bonus(square_distance(winnerKSq, loserKSq))
139 + kbnk_mate_table(loserKSq);
141 return strongerSide == pos.side_to_move() ? result : -result;
145 /// KP vs K. This endgame is evaluated with the help of a bitbase.
147 Value EvaluationFunction<KPK>::apply(const Position& pos) const {
149 assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
150 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
151 assert(pos.piece_count(strongerSide, PAWN) == 1);
152 assert(pos.piece_count(weakerSide, PAWN) == 0);
154 Square wksq, bksq, wpsq;
157 if (strongerSide == WHITE)
159 wksq = pos.king_square(WHITE);
160 bksq = pos.king_square(BLACK);
161 wpsq = pos.piece_list(WHITE, PAWN, 0);
162 stm = pos.side_to_move();
166 wksq = flip_square(pos.king_square(BLACK));
167 bksq = flip_square(pos.king_square(WHITE));
168 wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
169 stm = opposite_color(pos.side_to_move());
172 if (square_file(wpsq) >= FILE_E)
174 wksq = flop_square(wksq);
175 bksq = flop_square(bksq);
176 wpsq = flop_square(wpsq);
179 if (!probe_kpk_bitbase(wksq, wpsq, bksq, stm))
182 Value result = VALUE_KNOWN_WIN
184 + Value(square_rank(wpsq));
186 return strongerSide == pos.side_to_move() ? result : -result;
190 /// KR vs KP. This is a somewhat tricky endgame to evaluate precisely without
191 /// a bitbase. The function below returns drawish scores when the pawn is
192 /// far advanced with support of the king, while the attacking king is far
195 Value EvaluationFunction<KRKP>::apply(const Position& pos) const {
197 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
198 assert(pos.piece_count(strongerSide, PAWN) == 0);
199 assert(pos.non_pawn_material(weakerSide) == 0);
200 assert(pos.piece_count(weakerSide, PAWN) == 1);
202 Square wksq, wrsq, bksq, bpsq;
203 int tempo = (pos.side_to_move() == strongerSide);
205 wksq = pos.king_square(strongerSide);
206 wrsq = pos.piece_list(strongerSide, ROOK, 0);
207 bksq = pos.king_square(weakerSide);
208 bpsq = pos.piece_list(weakerSide, PAWN, 0);
210 if (strongerSide == BLACK)
212 wksq = flip_square(wksq);
213 wrsq = flip_square(wrsq);
214 bksq = flip_square(bksq);
215 bpsq = flip_square(bpsq);
218 Square queeningSq = make_square(square_file(bpsq), RANK_1);
221 // If the stronger side's king is in front of the pawn, it's a win
222 if (wksq < bpsq && square_file(wksq) == square_file(bpsq))
223 result = RookValueEndgame - Value(square_distance(wksq, bpsq));
225 // If the weaker side's king is too far from the pawn and the rook,
227 else if ( square_distance(bksq, bpsq) - (tempo ^ 1) >= 3
228 && square_distance(bksq, wrsq) >= 3)
229 result = RookValueEndgame - Value(square_distance(wksq, bpsq));
231 // If the pawn is far advanced and supported by the defending king,
232 // the position is drawish
233 else if ( square_rank(bksq) <= RANK_3
234 && square_distance(bksq, bpsq) == 1
235 && square_rank(wksq) >= RANK_4
236 && square_distance(wksq, bpsq) - tempo > 2)
237 result = Value(80 - square_distance(wksq, bpsq) * 8);
241 - Value(square_distance(wksq, bpsq + DELTA_S) * 8)
242 + Value(square_distance(bksq, bpsq + DELTA_S) * 8)
243 + Value(square_distance(bpsq, queeningSq) * 8);
245 return strongerSide == pos.side_to_move() ? result : -result;
249 /// KR vs KB. This is very simple, and always returns drawish scores. The
250 /// score is slightly bigger when the defending king is close to the edge.
252 Value EvaluationFunction<KRKB>::apply(const Position& pos) const {
254 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
255 assert(pos.piece_count(strongerSide, PAWN) == 0);
256 assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
257 assert(pos.piece_count(weakerSide, PAWN) == 0);
258 assert(pos.piece_count(weakerSide, BISHOP) == 1);
260 Value result = mate_table(pos.king_square(weakerSide));
261 return strongerSide == pos.side_to_move() ? result : -result;
265 /// KR vs KN. The attacking side has slightly better winning chances than
266 /// in KR vs KB, particularly if the king and the knight are far apart.
268 Value EvaluationFunction<KRKN>::apply(const Position& pos) const {
270 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
271 assert(pos.piece_count(strongerSide, PAWN) == 0);
272 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
273 assert(pos.piece_count(weakerSide, PAWN) == 0);
274 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
276 Square defendingKSq = pos.king_square(weakerSide);
277 Square nSq = pos.piece_list(weakerSide, KNIGHT, 0);
279 int d = square_distance(defendingKSq, nSq);
280 Value result = Value(10)
281 + mate_table(defendingKSq)
282 + krkn_king_knight_distance_penalty(d);
284 return strongerSide == pos.side_to_move() ? result : -result;
288 /// KQ vs KR. This is almost identical to KX vs K: We give the attacking
289 /// king a bonus for having the kings close together, and for forcing the
290 /// defending king towards the edge. If we also take care to avoid null move
291 /// for the defending side in the search, this is usually sufficient to be
292 /// able to win KQ vs KR.
294 Value EvaluationFunction<KQKR>::apply(const Position& pos) const {
296 assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
297 assert(pos.piece_count(strongerSide, PAWN) == 0);
298 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
299 assert(pos.piece_count(weakerSide, PAWN) == 0);
301 Square winnerKSq = pos.king_square(strongerSide);
302 Square loserKSq = pos.king_square(weakerSide);
304 Value result = QueenValueEndgame
306 + mate_table(loserKSq)
307 + distance_bonus(square_distance(winnerKSq, loserKSq));
309 return strongerSide == pos.side_to_move() ? result : -result;
313 Value EvaluationFunction<KBBKN>::apply(const Position& pos) const {
315 assert(pos.piece_count(strongerSide, BISHOP) == 2);
316 assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame);
317 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
318 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
319 assert(pos.pieces(PAWN) == EmptyBoardBB);
321 Value result = BishopValueEndgame;
322 Square wksq = pos.king_square(strongerSide);
323 Square bksq = pos.king_square(weakerSide);
324 Square nsq = pos.piece_list(weakerSide, KNIGHT, 0);
326 // Bonus for attacking king close to defending king
327 result += distance_bonus(square_distance(wksq, bksq));
329 // Bonus for driving the defending king and knight apart
330 result += Value(square_distance(bksq, nsq) * 32);
332 // Bonus for restricting the knight's mobility
333 result += Value((8 - count_1s<CNT32_MAX15>(pos.attacks_from<KNIGHT>(nsq))) * 8);
335 return strongerSide == pos.side_to_move() ? result : -result;
339 /// K and two minors vs K and one or two minors or K and two knights against
340 /// king alone are always draw.
342 Value EvaluationFunction<KmmKm>::apply(const Position&) const {
347 Value EvaluationFunction<KNNK>::apply(const Position&) const {
351 /// KBPKScalingFunction scales endgames where the stronger side has king,
352 /// bishop and one or more pawns. It checks for draws with rook pawns and a
353 /// bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_ZERO is
354 /// returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
357 ScaleFactor ScalingFunction<KBPsK>::apply(const Position& pos) const {
359 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
360 assert(pos.piece_count(strongerSide, BISHOP) == 1);
361 assert(pos.piece_count(strongerSide, PAWN) >= 1);
363 // No assertions about the material of weakerSide, because we want draws to
364 // be detected even when the weaker side has some pawns.
366 Bitboard pawns = pos.pieces(PAWN, strongerSide);
367 File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0));
369 // All pawns are on a single rook file ?
370 if ( (pawnFile == FILE_A || pawnFile == FILE_H)
371 && (pawns & ~file_bb(pawnFile)) == EmptyBoardBB)
373 Square bishopSq = pos.piece_list(strongerSide, BISHOP, 0);
374 Square queeningSq = relative_square(strongerSide, make_square(pawnFile, RANK_8));
375 Square kingSq = pos.king_square(weakerSide);
377 if ( opposite_color_squares(queeningSq, bishopSq)
378 && abs(square_file(kingSq) - pawnFile) <= 1)
380 // The bishop has the wrong color, and the defending king is on the
381 // file of the pawn(s) or the neighboring file. Find the rank of the
384 if (strongerSide == WHITE)
386 for (rank = RANK_7; (rank_bb(rank) & pawns) == EmptyBoardBB; rank--) {}
387 assert(rank >= RANK_2 && rank <= RANK_7);
391 for (rank = RANK_2; (rank_bb(rank) & pawns) == EmptyBoardBB; rank++) {}
392 rank = Rank(rank ^ 7); // HACK to get the relative rank
393 assert(rank >= RANK_2 && rank <= RANK_7);
395 // If the defending king has distance 1 to the promotion square or
396 // is placed somewhere in front of the pawn, it's a draw.
397 if ( square_distance(kingSq, queeningSq) <= 1
398 || relative_rank(strongerSide, kingSq) >= rank)
399 return SCALE_FACTOR_ZERO;
402 return SCALE_FACTOR_NONE;
406 /// KQKRPScalingFunction scales endgames where the stronger side has only
407 /// king and queen, while the weaker side has at least a rook and a pawn.
408 /// It tests for fortress draws with a rook on the third rank defended by
411 ScaleFactor ScalingFunction<KQKRPs>::apply(const Position& pos) const {
413 assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
414 assert(pos.piece_count(strongerSide, QUEEN) == 1);
415 assert(pos.piece_count(strongerSide, PAWN) == 0);
416 assert(pos.piece_count(weakerSide, ROOK) == 1);
417 assert(pos.piece_count(weakerSide, PAWN) >= 1);
419 Square kingSq = pos.king_square(weakerSide);
420 if ( relative_rank(weakerSide, kingSq) <= RANK_2
421 && relative_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4
422 && (pos.pieces(ROOK, weakerSide) & rank_bb(relative_rank(weakerSide, RANK_3)))
423 && (pos.pieces(PAWN, weakerSide) & rank_bb(relative_rank(weakerSide, RANK_2)))
424 && (pos.attacks_from<KING>(kingSq) & pos.pieces(PAWN, weakerSide)))
426 Square rsq = pos.piece_list(weakerSide, ROOK, 0);
427 if (pos.attacks_from<PAWN>(rsq, strongerSide) & pos.pieces(PAWN, weakerSide))
428 return SCALE_FACTOR_ZERO;
430 return SCALE_FACTOR_NONE;
434 /// KRPKRScalingFunction scales KRP vs KR endgames. This function knows a
435 /// handful of the most important classes of drawn positions, but is far
436 /// from perfect. It would probably be a good idea to add more knowledge
439 /// It would also be nice to rewrite the actual code for this function,
440 /// which is mostly copied from Glaurung 1.x, and not very pretty.
442 ScaleFactor ScalingFunction<KRPKR>::apply(const Position& pos) const {
444 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
445 assert(pos.piece_count(strongerSide, PAWN) == 1);
446 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
447 assert(pos.piece_count(weakerSide, PAWN) == 0);
449 Square wksq = pos.king_square(strongerSide);
450 Square wrsq = pos.piece_list(strongerSide, ROOK, 0);
451 Square wpsq = pos.piece_list(strongerSide, PAWN, 0);
452 Square bksq = pos.king_square(weakerSide);
453 Square brsq = pos.piece_list(weakerSide, ROOK, 0);
455 // Orient the board in such a way that the stronger side is white, and the
456 // pawn is on the left half of the board.
457 if (strongerSide == BLACK)
459 wksq = flip_square(wksq);
460 wrsq = flip_square(wrsq);
461 wpsq = flip_square(wpsq);
462 bksq = flip_square(bksq);
463 brsq = flip_square(brsq);
465 if (square_file(wpsq) > FILE_D)
467 wksq = flop_square(wksq);
468 wrsq = flop_square(wrsq);
469 wpsq = flop_square(wpsq);
470 bksq = flop_square(bksq);
471 brsq = flop_square(brsq);
474 File f = square_file(wpsq);
475 Rank r = square_rank(wpsq);
476 Square queeningSq = make_square(f, RANK_8);
477 int tempo = (pos.side_to_move() == strongerSide);
479 // If the pawn is not too far advanced and the defending king defends the
480 // queening square, use the third-rank defence.
482 && square_distance(bksq, queeningSq) <= 1
484 && (square_rank(brsq) == RANK_6 || (r <= RANK_3 && square_rank(wrsq) != RANK_6)))
485 return SCALE_FACTOR_ZERO;
487 // The defending side saves a draw by checking from behind in case the pawn
488 // has advanced to the 6th rank with the king behind.
490 && square_distance(bksq, queeningSq) <= 1
491 && square_rank(wksq) + tempo <= RANK_6
492 && (square_rank(brsq) == RANK_1 || (!tempo && abs(square_file(brsq) - f) >= 3)))
493 return SCALE_FACTOR_ZERO;
496 && bksq == queeningSq
497 && square_rank(brsq) == RANK_1
498 && (!tempo || square_distance(wksq, wpsq) >= 2))
499 return SCALE_FACTOR_ZERO;
501 // White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
502 // and the black rook is behind the pawn.
505 && (bksq == SQ_H7 || bksq == SQ_G7)
506 && square_file(brsq) == FILE_A
507 && (square_rank(brsq) <= RANK_3 || square_file(wksq) >= FILE_D || square_rank(wksq) <= RANK_5))
508 return SCALE_FACTOR_ZERO;
510 // If the defending king blocks the pawn and the attacking king is too far
511 // away, it's a draw.
513 && bksq == wpsq + DELTA_N
514 && square_distance(wksq, wpsq) - tempo >= 2
515 && square_distance(wksq, brsq) - tempo >= 2)
516 return SCALE_FACTOR_ZERO;
518 // Pawn on the 7th rank supported by the rook from behind usually wins if the
519 // attacking king is closer to the queening square than the defending king,
520 // and the defending king cannot gain tempi by threatening the attacking rook.
523 && square_file(wrsq) == f
524 && wrsq != queeningSq
525 && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
526 && (square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo))
527 return ScaleFactor(SCALE_FACTOR_MAX - 2 * square_distance(wksq, queeningSq));
529 // Similar to the above, but with the pawn further back
531 && square_file(wrsq) == f
533 && (square_distance(wksq, queeningSq) < square_distance(bksq, queeningSq) - 2 + tempo)
534 && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wpsq + DELTA_N) - 2 + tempo)
535 && ( square_distance(bksq, wrsq) + tempo >= 3
536 || ( square_distance(wksq, queeningSq) < square_distance(bksq, wrsq) + tempo
537 && (square_distance(wksq, wpsq + DELTA_N) < square_distance(bksq, wrsq) + tempo))))
538 return ScaleFactor( SCALE_FACTOR_MAX
539 - 8 * square_distance(wpsq, queeningSq)
540 - 2 * square_distance(wksq, queeningSq));
542 // If the pawn is not far advanced, and the defending king is somewhere in
543 // the pawn's path, it's probably a draw.
544 if (r <= RANK_4 && bksq > wpsq)
546 if (square_file(bksq) == square_file(wpsq))
547 return ScaleFactor(10);
548 if ( abs(square_file(bksq) - square_file(wpsq)) == 1
549 && square_distance(wksq, bksq) > 2)
550 return ScaleFactor(24 - 2 * square_distance(wksq, bksq));
552 return SCALE_FACTOR_NONE;
556 /// KRPPKRPScalingFunction scales KRPP vs KRP endgames. There is only a
557 /// single pattern: If the stronger side has no pawns and the defending king
558 /// is actively placed, the position is drawish.
560 ScaleFactor ScalingFunction<KRPPKRP>::apply(const Position& pos) const {
562 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
563 assert(pos.piece_count(strongerSide, PAWN) == 2);
564 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
565 assert(pos.piece_count(weakerSide, PAWN) == 1);
567 Square wpsq1 = pos.piece_list(strongerSide, PAWN, 0);
568 Square wpsq2 = pos.piece_list(strongerSide, PAWN, 1);
569 Square bksq = pos.king_square(weakerSide);
571 // Does the stronger side have a passed pawn?
572 if ( pos.pawn_is_passed(strongerSide, wpsq1)
573 || pos.pawn_is_passed(strongerSide, wpsq2))
574 return SCALE_FACTOR_NONE;
576 Rank r = Max(relative_rank(strongerSide, wpsq1), relative_rank(strongerSide, wpsq2));
578 if ( file_distance(bksq, wpsq1) <= 1
579 && file_distance(bksq, wpsq2) <= 1
580 && relative_rank(strongerSide, bksq) > r)
583 case RANK_2: return ScaleFactor(10);
584 case RANK_3: return ScaleFactor(10);
585 case RANK_4: return ScaleFactor(15);
586 case RANK_5: return ScaleFactor(20);
587 case RANK_6: return ScaleFactor(40);
588 default: assert(false);
591 return SCALE_FACTOR_NONE;
595 /// KPsKScalingFunction scales endgames with king and two or more pawns
596 /// against king. There is just a single rule here: If all pawns are on
597 /// the same rook file and are blocked by the defending king, it's a draw.
599 ScaleFactor ScalingFunction<KPsK>::apply(const Position& pos) const {
601 assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
602 assert(pos.piece_count(strongerSide, PAWN) >= 2);
603 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
604 assert(pos.piece_count(weakerSide, PAWN) == 0);
606 Square ksq = pos.king_square(weakerSide);
607 Bitboard pawns = pos.pieces(PAWN, strongerSide);
609 // Are all pawns on the 'a' file?
610 if ((pawns & ~FileABB) == EmptyBoardBB)
612 // Does the defending king block the pawns?
613 if ( square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1
614 || ( square_file(ksq) == FILE_A
615 && (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB))
616 return SCALE_FACTOR_ZERO;
618 // Are all pawns on the 'h' file?
619 else if ((pawns & ~FileHBB) == EmptyBoardBB)
621 // Does the defending king block the pawns?
622 if ( square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1
623 || ( square_file(ksq) == FILE_H
624 && (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB))
625 return SCALE_FACTOR_ZERO;
627 return SCALE_FACTOR_NONE;
631 /// KBPKBScalingFunction scales KBP vs KB endgames. There are two rules:
632 /// If the defending king is somewhere along the path of the pawn, and the
633 /// square of the king is not of the same color as the stronger side's bishop,
634 /// it's a draw. If the two bishops have opposite color, it's almost always
637 ScaleFactor ScalingFunction<KBPKB>::apply(const Position& pos) const {
639 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
640 assert(pos.piece_count(strongerSide, BISHOP) == 1);
641 assert(pos.piece_count(strongerSide, PAWN) == 1);
642 assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
643 assert(pos.piece_count(weakerSide, BISHOP) == 1);
644 assert(pos.piece_count(weakerSide, PAWN) == 0);
646 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
647 Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
648 Square weakerBishopSq = pos.piece_list(weakerSide, BISHOP, 0);
649 Square weakerKingSq = pos.king_square(weakerSide);
651 // Case 1: Defending king blocks the pawn, and cannot be driven away
652 if ( square_file(weakerKingSq) == square_file(pawnSq)
653 && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
654 && ( opposite_color_squares(weakerKingSq, strongerBishopSq)
655 || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
656 return SCALE_FACTOR_ZERO;
658 // Case 2: Opposite colored bishops
659 if (opposite_color_squares(strongerBishopSq, weakerBishopSq))
661 // We assume that the position is drawn in the following three situations:
663 // a. The pawn is on rank 5 or further back.
664 // b. The defending king is somewhere in the pawn's path.
665 // c. The defending bishop attacks some square along the pawn's path,
666 // and is at least three squares away from the pawn.
668 // These rules are probably not perfect, but in practice they work
671 if (relative_rank(strongerSide, pawnSq) <= RANK_5)
672 return SCALE_FACTOR_ZERO;
675 Bitboard path = squares_in_front_of(strongerSide, pawnSq);
677 if (path & pos.pieces(KING, weakerSide))
678 return SCALE_FACTOR_ZERO;
680 if ( (pos.attacks_from<BISHOP>(weakerBishopSq) & path)
681 && square_distance(weakerBishopSq, pawnSq) >= 3)
682 return SCALE_FACTOR_ZERO;
685 return SCALE_FACTOR_NONE;
689 /// KBPPKBScalingFunction scales KBPP vs KB endgames. It detects a few basic
690 /// draws with opposite-colored bishops.
692 ScaleFactor ScalingFunction<KBPPKB>::apply(const Position& pos) const {
694 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
695 assert(pos.piece_count(strongerSide, BISHOP) == 1);
696 assert(pos.piece_count(strongerSide, PAWN) == 2);
697 assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
698 assert(pos.piece_count(weakerSide, BISHOP) == 1);
699 assert(pos.piece_count(weakerSide, PAWN) == 0);
701 Square wbsq = pos.piece_list(strongerSide, BISHOP, 0);
702 Square bbsq = pos.piece_list(weakerSide, BISHOP, 0);
704 if (!opposite_color_squares(wbsq, bbsq))
705 return SCALE_FACTOR_NONE;
707 Square ksq = pos.king_square(weakerSide);
708 Square psq1 = pos.piece_list(strongerSide, PAWN, 0);
709 Square psq2 = pos.piece_list(strongerSide, PAWN, 1);
710 Rank r1 = square_rank(psq1);
711 Rank r2 = square_rank(psq2);
712 Square blockSq1, blockSq2;
714 if (relative_rank(strongerSide, psq1) > relative_rank(strongerSide, psq2))
716 blockSq1 = psq1 + pawn_push(strongerSide);
717 blockSq2 = make_square(square_file(psq2), square_rank(psq1));
721 blockSq1 = psq2 + pawn_push(strongerSide);
722 blockSq2 = make_square(square_file(psq1), square_rank(psq2));
725 switch (file_distance(psq1, psq2))
728 // Both pawns are on the same file. Easy draw if defender firmly controls
729 // some square in the frontmost pawn's path.
730 if ( square_file(ksq) == square_file(blockSq1)
731 && relative_rank(strongerSide, ksq) >= relative_rank(strongerSide, blockSq1)
732 && opposite_color_squares(ksq, wbsq))
733 return SCALE_FACTOR_ZERO;
735 return SCALE_FACTOR_NONE;
738 // Pawns on neighboring files. Draw if defender firmly controls the square
739 // in front of the frontmost pawn's path, and the square diagonally behind
740 // this square on the file of the other pawn.
742 && opposite_color_squares(ksq, wbsq)
743 && ( bbsq == blockSq2
744 || (pos.attacks_from<BISHOP>(blockSq2) & pos.pieces(BISHOP, weakerSide))
745 || abs(r1 - r2) >= 2))
746 return SCALE_FACTOR_ZERO;
748 else if ( ksq == blockSq2
749 && opposite_color_squares(ksq, wbsq)
750 && ( bbsq == blockSq1
751 || (pos.attacks_from<BISHOP>(blockSq1) & pos.pieces(BISHOP, weakerSide))))
752 return SCALE_FACTOR_ZERO;
754 return SCALE_FACTOR_NONE;
757 // The pawns are not on the same file or adjacent files. No scaling.
758 return SCALE_FACTOR_NONE;
763 /// KBPKNScalingFunction scales KBP vs KN endgames. There is a single rule:
764 /// If the defending king is somewhere along the path of the pawn, and the
765 /// square of the king is not of the same color as the stronger side's bishop,
768 ScaleFactor ScalingFunction<KBPKN>::apply(const Position& pos) const {
770 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
771 assert(pos.piece_count(strongerSide, BISHOP) == 1);
772 assert(pos.piece_count(strongerSide, PAWN) == 1);
773 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
774 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
775 assert(pos.piece_count(weakerSide, PAWN) == 0);
777 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
778 Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
779 Square weakerKingSq = pos.king_square(weakerSide);
781 if ( square_file(weakerKingSq) == square_file(pawnSq)
782 && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
783 && ( opposite_color_squares(weakerKingSq, strongerBishopSq)
784 || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
785 return SCALE_FACTOR_ZERO;
787 return SCALE_FACTOR_NONE;
791 /// KNPKScalingFunction scales KNP vs K endgames. There is a single rule:
792 /// If the pawn is a rook pawn on the 7th rank and the defending king prevents
793 /// the pawn from advancing, the position is drawn.
795 ScaleFactor ScalingFunction<KNPK>::apply(const Position& pos) const {
797 assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame);
798 assert(pos.piece_count(strongerSide, KNIGHT) == 1);
799 assert(pos.piece_count(strongerSide, PAWN) == 1);
800 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
801 assert(pos.piece_count(weakerSide, PAWN) == 0);
803 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
804 Square weakerKingSq = pos.king_square(weakerSide);
806 if ( pawnSq == relative_square(strongerSide, SQ_A7)
807 && square_distance(weakerKingSq, relative_square(strongerSide, SQ_A8)) <= 1)
808 return SCALE_FACTOR_ZERO;
810 if ( pawnSq == relative_square(strongerSide, SQ_H7)
811 && square_distance(weakerKingSq, relative_square(strongerSide, SQ_H8)) <= 1)
812 return SCALE_FACTOR_ZERO;
814 return SCALE_FACTOR_NONE;
818 /// KPKPScalingFunction scales KP vs KP endgames. This is done by removing
819 /// the weakest side's pawn and probing the KP vs K bitbase: If the weakest
820 /// side has a draw without the pawn, she probably has at least a draw with
821 /// the pawn as well. The exception is when the stronger side's pawn is far
822 /// advanced and not on a rook file; in this case it is often possible to win
823 /// (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
825 ScaleFactor ScalingFunction<KPKP>::apply(const Position& pos) const {
827 assert(pos.non_pawn_material(strongerSide) == VALUE_ZERO);
828 assert(pos.non_pawn_material(weakerSide) == VALUE_ZERO);
829 assert(pos.piece_count(WHITE, PAWN) == 1);
830 assert(pos.piece_count(BLACK, PAWN) == 1);
832 Square wksq, bksq, wpsq;
835 if (strongerSide == WHITE)
837 wksq = pos.king_square(WHITE);
838 bksq = pos.king_square(BLACK);
839 wpsq = pos.piece_list(WHITE, PAWN, 0);
840 stm = pos.side_to_move();
844 wksq = flip_square(pos.king_square(BLACK));
845 bksq = flip_square(pos.king_square(WHITE));
846 wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
847 stm = opposite_color(pos.side_to_move());
850 if (square_file(wpsq) >= FILE_E)
852 wksq = flop_square(wksq);
853 bksq = flop_square(bksq);
854 wpsq = flop_square(wpsq);
857 // If the pawn has advanced to the fifth rank or further, and is not a
858 // rook pawn, it's too dangerous to assume that it's at least a draw.
859 if ( square_rank(wpsq) >= RANK_5
860 && square_file(wpsq) != FILE_A)
861 return SCALE_FACTOR_NONE;
863 // Probe the KPK bitbase with the weakest side's pawn removed. If it's a
864 // draw, it's probably at least a draw even with the pawn.
865 return probe_kpk_bitbase(wksq, wpsq, bksq, stm) ? SCALE_FACTOR_NONE : SCALE_FACTOR_ZERO;