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 Marco Costalba
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/>.
32 //// Constants and variables
35 /// Evaluation functions
37 // Generic "mate lone king" eval
38 KXKEvaluationFunction EvaluateKXK = KXKEvaluationFunction(WHITE);
39 KXKEvaluationFunction EvaluateKKX = KXKEvaluationFunction(BLACK);
42 KBNKEvaluationFunction EvaluateKBNK = KBNKEvaluationFunction(WHITE);
43 KBNKEvaluationFunction EvaluateKKBN = KBNKEvaluationFunction(BLACK);
46 KPKEvaluationFunction EvaluateKPK = KPKEvaluationFunction(WHITE);
47 KPKEvaluationFunction EvaluateKKP = KPKEvaluationFunction(BLACK);
50 KRKPEvaluationFunction EvaluateKRKP = KRKPEvaluationFunction(WHITE);
51 KRKPEvaluationFunction EvaluateKPKR = KRKPEvaluationFunction(BLACK);
54 KRKBEvaluationFunction EvaluateKRKB = KRKBEvaluationFunction(WHITE);
55 KRKBEvaluationFunction EvaluateKBKR = KRKBEvaluationFunction(BLACK);
58 KRKNEvaluationFunction EvaluateKRKN = KRKNEvaluationFunction(WHITE);
59 KRKNEvaluationFunction EvaluateKNKR = KRKNEvaluationFunction(BLACK);
62 KQKREvaluationFunction EvaluateKQKR = KQKREvaluationFunction(WHITE);
63 KQKREvaluationFunction EvaluateKRKQ = KQKREvaluationFunction(BLACK);
66 KBBKNEvaluationFunction EvaluateKBBKN = KBBKNEvaluationFunction(WHITE);
67 KBBKNEvaluationFunction EvaluateKNKBB = KBBKNEvaluationFunction(BLACK);
69 // K and two minors vs K and one or two minors
70 KmmKmEvaluationFunction EvaluateKmmKm = KmmKmEvaluationFunction(WHITE);
76 KBPKScalingFunction ScaleKBPK = KBPKScalingFunction(WHITE);
77 KBPKScalingFunction ScaleKKBP = KBPKScalingFunction(BLACK);
80 KQKRPScalingFunction ScaleKQKRP = KQKRPScalingFunction(WHITE);
81 KQKRPScalingFunction ScaleKRPKQ = KQKRPScalingFunction(BLACK);
84 KRPKRScalingFunction ScaleKRPKR = KRPKRScalingFunction(WHITE);
85 KRPKRScalingFunction ScaleKRKRP = KRPKRScalingFunction(BLACK);
88 KRPPKRPScalingFunction ScaleKRPPKRP = KRPPKRPScalingFunction(WHITE);
89 KRPPKRPScalingFunction ScaleKRPKRPP = KRPPKRPScalingFunction(BLACK);
91 // King and pawns vs king
92 KPsKScalingFunction ScaleKPsK = KPsKScalingFunction(WHITE);
93 KPsKScalingFunction ScaleKKPs = KPsKScalingFunction(BLACK);
96 KBPKBScalingFunction ScaleKBPKB = KBPKBScalingFunction(WHITE);
97 KBPKBScalingFunction ScaleKBKBP = KBPKBScalingFunction(BLACK);
100 KBPKNScalingFunction ScaleKBPKN = KBPKNScalingFunction(WHITE);
101 KBPKNScalingFunction ScaleKNKBP = KBPKNScalingFunction(BLACK);
104 KNPKScalingFunction ScaleKNPK = KNPKScalingFunction(WHITE);
105 KNPKScalingFunction ScaleKKNP = KNPKScalingFunction(BLACK);
108 KPKPScalingFunction ScaleKPKPw = KPKPScalingFunction(WHITE);
109 KPKPScalingFunction ScaleKPKPb = KPKPScalingFunction(BLACK);
113 //// Local definitions
118 // Table used to drive the defending king towards the edge of the board
119 // in KX vs K and KQ vs KR endgames.
120 const uint8_t MateTable[64] = {
121 100, 90, 80, 70, 70, 80, 90, 100,
122 90, 70, 60, 50, 50, 60, 70, 90,
123 80, 60, 40, 30, 30, 40, 60, 80,
124 70, 50, 30, 20, 20, 30, 50, 70,
125 70, 50, 30, 20, 20, 30, 50, 70,
126 80, 60, 40, 30, 30, 40, 60, 80,
127 90, 70, 60, 50, 50, 60, 70, 90,
128 100, 90, 80, 70, 70, 80, 90, 100,
131 // Table used to drive the defending king towards a corner square of the
132 // right color in KBN vs K endgames.
133 const uint8_t KBNKMateTable[64] = {
134 200, 190, 180, 170, 160, 150, 140, 130,
135 190, 180, 170, 160, 150, 140, 130, 140,
136 180, 170, 155, 140, 140, 125, 140, 150,
137 170, 160, 140, 120, 110, 140, 150, 160,
138 160, 150, 140, 110, 120, 140, 160, 170,
139 150, 140, 125, 140, 140, 155, 170, 180,
140 140, 130, 140, 150, 160, 170, 180, 190,
141 130, 140, 150, 160, 170, 180, 190, 200
144 // The attacking side is given a descending bonus based on distance between
145 // the two kings in basic endgames.
146 const int DistanceBonus[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
148 // Bitbase for KP vs K
149 uint8_t KPKBitbase[24576];
151 // Penalty for big distance between king and knight for the defending king
152 // and knight in KR vs KN endgames.
153 const int KRKNKingKnightDistancePenalty[8] = { 0, 0, 4, 10, 20, 32, 48, 70 };
155 // Various inline functions for accessing the above arrays
156 inline Value mate_table(Square s) {
157 return Value(MateTable[s]);
160 inline Value kbnk_mate_table(Square s) {
161 return Value(KBNKMateTable[s]);
164 inline Value distance_bonus(int d) {
165 return Value(DistanceBonus[d]);
168 inline Value krkn_king_knight_distance_penalty(int d) {
169 return Value(KRKNKingKnightDistancePenalty[d]);
172 // Function for probing the KP vs K bitbase
173 int probe_kpk(Square wksq, Square wpsq, Square bksq, Color stm);
184 EndgameEvaluationFunction::EndgameEvaluationFunction(Color c) : strongerSide(c) {
185 weakerSide = opposite_color(strongerSide);
188 KXKEvaluationFunction::KXKEvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
189 KBNKEvaluationFunction::KBNKEvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
190 KPKEvaluationFunction::KPKEvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
191 KRKPEvaluationFunction::KRKPEvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
192 KRKBEvaluationFunction::KRKBEvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
193 KRKNEvaluationFunction::KRKNEvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
194 KQKREvaluationFunction::KQKREvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
195 KBBKNEvaluationFunction::KBBKNEvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
196 KmmKmEvaluationFunction::KmmKmEvaluationFunction(Color c) : EndgameEvaluationFunction(c) {}
199 ScalingFunction::ScalingFunction(Color c) : strongerSide(c) {
200 weakerSide = opposite_color(c);
203 KBPKScalingFunction::KBPKScalingFunction(Color c) : ScalingFunction(c) {}
204 KQKRPScalingFunction::KQKRPScalingFunction(Color c) : ScalingFunction(c) {}
205 KRPKRScalingFunction::KRPKRScalingFunction(Color c) : ScalingFunction(c) {}
206 KRPPKRPScalingFunction::KRPPKRPScalingFunction(Color c) : ScalingFunction(c) {}
207 KPsKScalingFunction::KPsKScalingFunction(Color c) : ScalingFunction(c) {}
208 KBPKBScalingFunction::KBPKBScalingFunction(Color c) : ScalingFunction(c) {}
209 KBPKNScalingFunction::KBPKNScalingFunction(Color c) : ScalingFunction(c) {}
210 KNPKScalingFunction::KNPKScalingFunction(Color c) : ScalingFunction(c) {}
211 KPKPScalingFunction::KPKPScalingFunction(Color c) : ScalingFunction(c) {}
214 /// Mate with KX vs K. This function is used to evaluate positions with
215 /// King and plenty of material vs a lone king. It simply gives the
216 /// attacking side a bonus for driving the defending king towards the edge
217 /// of the board, and for keeping the distance between the two kings small.
219 Value KXKEvaluationFunction::apply(const Position& pos) {
221 assert(pos.non_pawn_material(weakerSide) == Value(0));
222 assert(pos.piece_count(weakerSide, PAWN) == Value(0));
224 Square winnerKSq = pos.king_square(strongerSide);
225 Square loserKSq = pos.king_square(weakerSide);
227 Value result = pos.non_pawn_material(strongerSide)
228 + pos.piece_count(strongerSide, PAWN) * PawnValueEndgame
229 + mate_table(loserKSq)
230 + distance_bonus(square_distance(winnerKSq, loserKSq));
232 if ( pos.piece_count(strongerSide, QUEEN) > 0
233 || pos.piece_count(strongerSide, ROOK) > 0
234 || pos.piece_count(strongerSide, BISHOP) > 1)
235 // TODO: check for two equal-colored bishops!
236 result += VALUE_KNOWN_WIN;
238 return (strongerSide == pos.side_to_move() ? result : -result);
242 /// Mate with KBN vs K. This is similar to KX vs K, but we have to drive the
243 /// defending king towards a corner square of the right color.
245 Value KBNKEvaluationFunction::apply(const Position& pos) {
247 assert(pos.non_pawn_material(weakerSide) == Value(0));
248 assert(pos.piece_count(weakerSide, PAWN) == Value(0));
249 assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame + BishopValueMidgame);
250 assert(pos.piece_count(strongerSide, BISHOP) == 1);
251 assert(pos.piece_count(strongerSide, KNIGHT) == 1);
252 assert(pos.piece_count(strongerSide, PAWN) == 0);
254 Square winnerKSq = pos.king_square(strongerSide);
255 Square loserKSq = pos.king_square(weakerSide);
256 Square bishopSquare = pos.piece_list(strongerSide, BISHOP, 0);
258 if (square_color(bishopSquare) == BLACK)
260 winnerKSq = flop_square(winnerKSq);
261 loserKSq = flop_square(loserKSq);
264 Value result = VALUE_KNOWN_WIN
265 + distance_bonus(square_distance(winnerKSq, loserKSq))
266 + kbnk_mate_table(loserKSq);
268 return (strongerSide == pos.side_to_move() ? result : -result);
272 /// KP vs K. This endgame is evaluated with the help of a bitbase.
274 Value KPKEvaluationFunction::apply(const Position& pos) {
276 assert(pos.non_pawn_material(strongerSide) == Value(0));
277 assert(pos.non_pawn_material(weakerSide) == Value(0));
278 assert(pos.piece_count(strongerSide, PAWN) == 1);
279 assert(pos.piece_count(weakerSide, PAWN) == 0);
281 Square wksq, bksq, wpsq;
284 if (strongerSide == WHITE)
286 wksq = pos.king_square(WHITE);
287 bksq = pos.king_square(BLACK);
288 wpsq = pos.piece_list(WHITE, PAWN, 0);
289 stm = pos.side_to_move();
293 wksq = flip_square(pos.king_square(BLACK));
294 bksq = flip_square(pos.king_square(WHITE));
295 wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
296 stm = opposite_color(pos.side_to_move());
299 if (square_file(wpsq) >= FILE_E)
301 wksq = flop_square(wksq);
302 bksq = flop_square(bksq);
303 wpsq = flop_square(wpsq);
306 if (!probe_kpk(wksq, wpsq, bksq, stm))
309 Value result = VALUE_KNOWN_WIN
311 + Value(square_rank(wpsq));
313 return (strongerSide == pos.side_to_move() ? result : -result);
317 /// KR vs KP. This is a somewhat tricky endgame to evaluate precisely without
318 /// a bitbase. The function below returns drawish scores when the pawn is
319 /// far advanced with support of the king, while the attacking king is far
322 Value KRKPEvaluationFunction::apply(const Position& pos) {
324 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
325 assert(pos.piece_count(strongerSide, PAWN) == 0);
326 assert(pos.non_pawn_material(weakerSide) == 0);
327 assert(pos.piece_count(weakerSide, PAWN) == 1);
329 Square wksq, wrsq, bksq, bpsq;
330 int tempo = (pos.side_to_move() == strongerSide);
332 wksq = pos.king_square(strongerSide);
333 wrsq = pos.piece_list(strongerSide, ROOK, 0);
334 bksq = pos.king_square(weakerSide);
335 bpsq = pos.piece_list(weakerSide, PAWN, 0);
337 if (strongerSide == BLACK)
339 wksq = flip_square(wksq);
340 wrsq = flip_square(wrsq);
341 bksq = flip_square(bksq);
342 bpsq = flip_square(bpsq);
345 Square queeningSq = make_square(square_file(bpsq), RANK_1);
348 // If the stronger side's king is in front of the pawn, it's a win
349 if (wksq < bpsq && square_file(wksq) == square_file(bpsq))
350 result = RookValueEndgame - Value(square_distance(wksq, bpsq));
352 // If the weaker side's king is too far from the pawn and the rook,
354 else if ( square_distance(bksq, bpsq) - (tempo^1) >= 3
355 && square_distance(bksq, wrsq) >= 3)
356 result = RookValueEndgame - Value(square_distance(wksq, bpsq));
358 // If the pawn is far advanced and supported by the defending king,
359 // the position is drawish
360 else if ( square_rank(bksq) <= RANK_3
361 && square_distance(bksq, bpsq) == 1
362 && square_rank(wksq) >= RANK_4
363 && square_distance(wksq, bpsq) - tempo > 2)
364 result = Value(80 - square_distance(wksq, bpsq) * 8);
368 - Value(square_distance(wksq, bpsq + DELTA_S) * 8)
369 + Value(square_distance(bksq, bpsq + DELTA_S) * 8)
370 + Value(square_distance(bpsq, queeningSq) * 8);
372 return (strongerSide == pos.side_to_move() ? result : -result);
376 /// KR vs KB. This is very simple, and always returns drawish scores. The
377 /// score is slightly bigger when the defending king is close to the edge.
379 Value KRKBEvaluationFunction::apply(const Position& pos) {
381 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
382 assert(pos.piece_count(strongerSide, PAWN) == 0);
383 assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
384 assert(pos.piece_count(weakerSide, PAWN) == 0);
385 assert(pos.piece_count(weakerSide, BISHOP) == 1);
387 Value result = mate_table(pos.king_square(weakerSide));
388 return (pos.side_to_move() == strongerSide ? result : -result);
392 /// KR vs KN. The attacking side has slightly better winning chances than
393 /// in KR vs KB, particularly if the king and the knight are far apart.
395 Value KRKNEvaluationFunction::apply(const Position& pos) {
397 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
398 assert(pos.piece_count(strongerSide, PAWN) == 0);
399 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
400 assert(pos.piece_count(weakerSide, PAWN) == 0);
401 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
403 Square defendingKSq = pos.king_square(weakerSide);
404 Square nSq = pos.piece_list(weakerSide, KNIGHT, 0);
406 Value result = Value(10) + mate_table(defendingKSq) +
407 krkn_king_knight_distance_penalty(square_distance(defendingKSq, nSq));
409 return (strongerSide == pos.side_to_move())? result : -result;
413 /// KQ vs KR. This is almost identical to KX vs K: We give the attacking
414 /// king a bonus for having the kings close together, and for forcing the
415 /// defending king towards the edge. If we also take care to avoid null move
416 /// for the defending side in the search, this is usually sufficient to be
417 /// able to win KQ vs KR.
419 Value KQKREvaluationFunction::apply(const Position& pos) {
421 assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
422 assert(pos.piece_count(strongerSide, PAWN) == 0);
423 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
424 assert(pos.piece_count(weakerSide, PAWN) == 0);
426 Square winnerKSq = pos.king_square(strongerSide);
427 Square loserKSq = pos.king_square(weakerSide);
429 Value result = QueenValueEndgame
431 + mate_table(loserKSq)
432 + distance_bonus(square_distance(winnerKSq, loserKSq));
434 return (strongerSide == pos.side_to_move())? result : -result;
438 Value KBBKNEvaluationFunction::apply(const Position& pos) {
440 assert(pos.piece_count(strongerSide, BISHOP) == 2);
441 assert(pos.non_pawn_material(strongerSide) == 2*BishopValueMidgame);
442 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
443 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
444 assert(pos.pawns() == EmptyBoardBB);
446 Value result = BishopValueEndgame;
447 Square wksq = pos.king_square(strongerSide);
448 Square bksq = pos.king_square(weakerSide);
449 Square nsq = pos.piece_list(weakerSide, KNIGHT, 0);
451 // Bonus for attacking king close to defending king
452 result += distance_bonus(square_distance(wksq, bksq));
454 // Bonus for driving the defending king and knight apart
455 result += Value(square_distance(bksq, nsq) * 32);
457 // Bonus for restricting the knight's mobility
458 result += Value((8 - count_1s_max_15(pos.piece_attacks<KNIGHT>(nsq))) * 8);
460 return (strongerSide == pos.side_to_move() ? result : -result);
464 Value KmmKmEvaluationFunction::apply(const Position &pos) {
469 /// KBPKScalingFunction scales endgames where the stronger side has king,
470 /// bishop and one or more pawns. It checks for draws with rook pawns and a
471 /// bishop of the wrong color. If such a draw is detected, ScaleFactor(0) is
472 /// returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling
475 ScaleFactor KBPKScalingFunction::apply(const Position& pos) {
477 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
478 assert(pos.piece_count(strongerSide, BISHOP) == 1);
479 assert(pos.piece_count(strongerSide, PAWN) >= 1);
481 // No assertions about the material of weakerSide, because we want draws to
482 // be detected even when the weaker side has some pawns.
484 Bitboard pawns = pos.pawns(strongerSide);
485 File pawnFile = square_file(pos.piece_list(strongerSide, PAWN, 0));
487 // All pawns are on a single rook file ?
488 if ( (pawnFile == FILE_A || pawnFile == FILE_H)
489 && (pawns & ~file_bb(pawnFile)) == EmptyBoardBB)
491 Square bishopSq = pos.piece_list(strongerSide, BISHOP, 0);
492 Square queeningSq = relative_square(strongerSide, make_square(pawnFile, RANK_8));
493 Square kingSq = pos.king_square(weakerSide);
495 if ( square_color(queeningSq) != square_color(bishopSq)
496 && file_distance(square_file(kingSq), pawnFile) <= 1)
498 // The bishop has the wrong color, and the defending king is on the
499 // file of the pawn(s) or the neighboring file. Find the rank of the
503 if (strongerSide == WHITE)
505 for (rank = RANK_7; (rank_bb(rank) & pawns) == EmptyBoardBB; rank--) {}
506 assert(rank >= RANK_2 && rank <= RANK_7);
510 for(rank = RANK_2; (rank_bb(rank) & pawns) == EmptyBoardBB; rank++) {}
511 rank = Rank(rank^7); // HACK to get the relative rank
512 assert(rank >= RANK_2 && rank <= RANK_7);
514 // If the defending king has distance 1 to the promotion square or
515 // is placed somewhere in front of the pawn, it's a draw.
516 if ( square_distance(kingSq, queeningSq) <= 1
517 || relative_rank(strongerSide, kingSq) >= rank)
518 return ScaleFactor(0);
521 return SCALE_FACTOR_NONE;
525 /// KQKRPScalingFunction scales endgames where the stronger side has only
526 /// king and queen, while the weaker side has at least a rook and a pawn.
527 /// It tests for fortress draws with a rook on the third rank defended by
530 ScaleFactor KQKRPScalingFunction::apply(const Position& pos) {
532 assert(pos.non_pawn_material(strongerSide) == QueenValueMidgame);
533 assert(pos.piece_count(strongerSide, QUEEN) == 1);
534 assert(pos.piece_count(strongerSide, PAWN) == 0);
535 assert(pos.piece_count(weakerSide, ROOK) == 1);
536 assert(pos.piece_count(weakerSide, PAWN) >= 1);
538 Square kingSq = pos.king_square(weakerSide);
539 if ( relative_rank(weakerSide, kingSq) <= RANK_2
540 && relative_rank(weakerSide, pos.king_square(strongerSide)) >= RANK_4
541 && (pos.rooks(weakerSide) & relative_rank_bb(weakerSide, RANK_3))
542 && (pos.pawns(weakerSide) & relative_rank_bb(weakerSide, RANK_2))
543 && (pos.piece_attacks<KING>(kingSq) & pos.pawns(weakerSide)))
545 Square rsq = pos.piece_list(weakerSide, ROOK, 0);
546 if (pos.pawn_attacks(strongerSide, rsq) & pos.pawns(weakerSide))
547 return ScaleFactor(0);
549 return SCALE_FACTOR_NONE;
553 /// KRPKRScalingFunction scales KRP vs KR endgames. This function knows a
554 /// handful of the most important classes of drawn positions, but is far
555 /// from perfect. It would probably be a good idea to add more knowledge
558 /// It would also be nice to rewrite the actual code for this function,
559 /// which is mostly copied from Glaurung 1.x, and not very pretty.
561 ScaleFactor KRPKRScalingFunction::apply(const Position &pos) {
562 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
563 assert(pos.piece_count(strongerSide, PAWN) == 1);
564 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
565 assert(pos.piece_count(weakerSide, PAWN) == 0);
567 Square wksq = pos.king_square(strongerSide);
568 Square wrsq = pos.piece_list(strongerSide, ROOK, 0);
569 Square wpsq = pos.piece_list(strongerSide, PAWN, 0);
570 Square bksq = pos.king_square(weakerSide);
571 Square brsq = pos.piece_list(weakerSide, ROOK, 0);
573 // Orient the board in such a way that the stronger side is white, and the
574 // pawn is on the left half of the board:
575 if(strongerSide == BLACK) {
576 wksq = flip_square(wksq);
577 wrsq = flip_square(wrsq);
578 wpsq = flip_square(wpsq);
579 bksq = flip_square(bksq);
580 brsq = flip_square(brsq);
582 if(square_file(wpsq) > FILE_D) {
583 wksq = flop_square(wksq);
584 wrsq = flop_square(wrsq);
585 wpsq = flop_square(wpsq);
586 bksq = flop_square(bksq);
587 brsq = flop_square(brsq);
590 File f = square_file(wpsq);
591 Rank r = square_rank(wpsq);
592 Square queeningSq = make_square(f, RANK_8);
593 int tempo = (pos.side_to_move() == strongerSide);
595 // If the pawn is not too far advanced and the defending king defends the
596 // queening square, use the third-rank defence:
597 if(r <= RANK_5 && square_distance(bksq, queeningSq) <= 1 && wksq <= SQ_H5 &&
598 (square_rank(brsq) == RANK_6 || (r <= RANK_3 &&
599 square_rank(wrsq) != RANK_6)))
600 return ScaleFactor(0);
602 // The defending side saves a draw by checking from behind in case the pawn
603 // has advanced to the 6th rank with the king behind.
604 if(r == RANK_6 && square_distance(bksq, queeningSq) <= 1 &&
605 square_rank(wksq) + tempo <= RANK_6 &&
606 (square_rank(brsq) == RANK_1 ||
607 (!tempo && abs(square_file(brsq) - f) >= 3)))
608 return ScaleFactor(0);
610 if(r >= RANK_6 && bksq == queeningSq && square_rank(brsq) == RANK_1 &&
611 (!tempo || square_distance(wksq, wpsq) >= 2))
612 return ScaleFactor(0);
614 // White pawn on a7 and rook on a8 is a draw if black's king is on g7 or h7
615 // and the black rook is behind the pawn.
616 if(wpsq == SQ_A7 && wrsq == SQ_A8 && (bksq == SQ_H7 || bksq == SQ_G7) &&
617 square_file(brsq) == FILE_A &&
618 (square_rank(brsq) <= RANK_3 || square_file(wksq) >= FILE_D ||
619 square_rank(wksq) <= RANK_5))
620 return ScaleFactor(0);
622 // If the defending king blocks the pawn and the attacking king is too far
623 // away, it's a draw.
624 if(r <= RANK_5 && bksq == wpsq + DELTA_N &&
625 square_distance(wksq, wpsq) - tempo >= 2 &&
626 square_distance(wksq, brsq) - tempo >= 2)
627 return ScaleFactor(0);
629 // Pawn on the 7th rank supported by the rook from behind usually wins if the
630 // attacking king is closer to the queening square than the defending king,
631 // and the defending king cannot gain tempi by threatening the attacking
633 if(r == RANK_7 && f != FILE_A && square_file(wrsq) == f
634 && wrsq != queeningSq
635 && (square_distance(wksq, queeningSq) <
636 square_distance(bksq, queeningSq) - 2 + tempo)
637 && (square_distance(wksq, queeningSq) <
638 square_distance(bksq, wrsq) + tempo))
639 return ScaleFactor(SCALE_FACTOR_MAX
640 - 2 * square_distance(wksq, queeningSq));
642 // Similar to the above, but with the pawn further back:
643 if(f != FILE_A && square_file(wrsq) == f && wrsq < wpsq
644 && (square_distance(wksq, queeningSq) <
645 square_distance(bksq, queeningSq) - 2 + tempo)
646 && (square_distance(wksq, wpsq + DELTA_N) <
647 square_distance(bksq, wpsq + DELTA_N) - 2 + tempo)
648 && (square_distance(bksq, wrsq) + tempo >= 3
649 || (square_distance(wksq, queeningSq) <
650 square_distance(bksq, wrsq) + tempo
651 && (square_distance(wksq, wpsq + DELTA_N) <
652 square_distance(bksq, wrsq) + tempo))))
654 ScaleFactor(SCALE_FACTOR_MAX
655 - (8 * square_distance(wpsq, queeningSq) +
656 2 * square_distance(wksq, queeningSq)));
658 // If the pawn is not far advanced, and the defending king is somewhere in
659 // the pawn's path, it's probably a draw:
660 if(r <= RANK_4 && bksq > wpsq) {
661 if(square_file(bksq) == square_file(wpsq))
662 return ScaleFactor(10);
663 if(abs(square_file(bksq) - square_file(wpsq)) == 1
664 && square_distance(wksq, bksq) > 2)
665 return ScaleFactor(24 - 2 * square_distance(wksq, bksq));
668 return SCALE_FACTOR_NONE;
672 /// KRPPKRPScalingFunction scales KRPP vs KRP endgames. There is only a
673 /// single pattern: If the stronger side has no pawns and the defending king
674 /// is actively placed, the position is drawish.
676 ScaleFactor KRPPKRPScalingFunction::apply(const Position &pos) {
677 assert(pos.non_pawn_material(strongerSide) == RookValueMidgame);
678 assert(pos.piece_count(strongerSide, PAWN) == 2);
679 assert(pos.non_pawn_material(weakerSide) == RookValueMidgame);
680 assert(pos.piece_count(weakerSide, PAWN) == 1);
682 Square wpsq1 = pos.piece_list(strongerSide, PAWN, 0);
683 Square wpsq2 = pos.piece_list(strongerSide, PAWN, 1);
684 Square bksq = pos.king_square(weakerSide);
686 // Does the stronger side have a passed pawn?
687 if(pos.pawn_is_passed(strongerSide, wpsq1) ||
688 pos.pawn_is_passed(strongerSide, wpsq2))
689 return SCALE_FACTOR_NONE;
691 Rank r = Max(relative_rank(strongerSide, wpsq1), relative_rank(strongerSide, wpsq2));
693 if(file_distance(bksq, wpsq1) <= 1 && file_distance(bksq, wpsq2) <= 1
694 && relative_rank(strongerSide, bksq) > r) {
697 case RANK_2: return ScaleFactor(10);
698 case RANK_3: return ScaleFactor(10);
699 case RANK_4: return ScaleFactor(15);
700 case RANK_5: return ScaleFactor(20);
701 case RANK_6: return ScaleFactor(40);
702 default: assert(false);
706 return SCALE_FACTOR_NONE;
710 /// KPsKScalingFunction scales endgames with king and two or more pawns
711 /// against king. There is just a single rule here: If all pawns are on
712 /// the same rook file and are blocked by the defending king, it's a draw.
714 ScaleFactor KPsKScalingFunction::apply(const Position &pos) {
715 assert(pos.non_pawn_material(strongerSide) == Value(0));
716 assert(pos.piece_count(strongerSide, PAWN) >= 2);
717 assert(pos.non_pawn_material(weakerSide) == Value(0));
718 assert(pos.piece_count(weakerSide, PAWN) == 0);
720 Bitboard pawns = pos.pawns(strongerSide);
722 // Are all pawns on the 'a' file?
723 if((pawns & ~FileABB) == EmptyBoardBB) {
724 // Does the defending king block the pawns?
725 Square ksq = pos.king_square(weakerSide);
726 if(square_distance(ksq, relative_square(strongerSide, SQ_A8)) <= 1)
727 return ScaleFactor(0);
728 else if(square_file(ksq) == FILE_A &&
729 (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB)
730 return ScaleFactor(0);
732 return SCALE_FACTOR_NONE;
734 // Are all pawns on the 'h' file?
735 else if((pawns & ~FileHBB) == EmptyBoardBB) {
736 // Does the defending king block the pawns?
737 Square ksq = pos.king_square(weakerSide);
738 if(square_distance(ksq, relative_square(strongerSide, SQ_H8)) <= 1)
739 return ScaleFactor(0);
740 else if(square_file(ksq) == FILE_H &&
741 (in_front_bb(strongerSide, ksq) & pawns) == EmptyBoardBB)
742 return ScaleFactor(0);
744 return SCALE_FACTOR_NONE;
747 return SCALE_FACTOR_NONE;
751 /// KBPKBScalingFunction scales KBP vs KB endgames. There are two rules:
752 /// If the defending king is somewhere along the path of the pawn, and the
753 /// square of the king is not of the same color as the stronger side's bishop,
754 /// it's a draw. If the two bishops have opposite color, it's almost always
757 ScaleFactor KBPKBScalingFunction::apply(const Position &pos) {
758 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
759 assert(pos.piece_count(strongerSide, BISHOP) == 1);
760 assert(pos.piece_count(strongerSide, PAWN) == 1);
761 assert(pos.non_pawn_material(weakerSide) == BishopValueMidgame);
762 assert(pos.piece_count(weakerSide, BISHOP) == 1);
763 assert(pos.piece_count(weakerSide, PAWN) == 0);
765 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
766 Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
767 Square weakerBishopSq = pos.piece_list(weakerSide, BISHOP, 0);
768 Square weakerKingSq = pos.king_square(weakerSide);
770 // Case 1: Defending king blocks the pawn, and cannot be driven away.
771 if(square_file(weakerKingSq) == square_file(pawnSq)
772 && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
773 && (square_color(weakerKingSq) != square_color(strongerBishopSq)
774 || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
775 return ScaleFactor(0);
777 // Case 2: Opposite colored bishops.
778 if(square_color(strongerBishopSq) != square_color(weakerBishopSq)) {
780 // We assume that the position is drawn in the following three situations:
782 // a. The pawn is on rank 5 or further back.
783 // b. The defending king is somewhere in the pawn's path.
784 // c. The defending bishop attacks some square along the pawn's path,
785 // and is at least three squares away from the pawn.
787 // These rules are probably not perfect, but in practice they work
790 if(relative_rank(strongerSide, pawnSq) <= RANK_5)
791 return ScaleFactor(0);
794 ray_bb(pawnSq, (strongerSide == WHITE)? SIGNED_DIR_N : SIGNED_DIR_S);
795 if(ray & pos.kings(weakerSide))
796 return ScaleFactor(0);
797 if((pos.piece_attacks<BISHOP>(weakerBishopSq) & ray)
798 && square_distance(weakerBishopSq, pawnSq) >= 3)
799 return ScaleFactor(0);
802 return SCALE_FACTOR_NONE;
806 /// KBPKNScalingFunction scales KBP vs KN endgames. There is a single rule:
807 /// If the defending king is somewhere along the path of the pawn, and the
808 /// square of the king is not of the same color as the stronger side's bishop,
811 ScaleFactor KBPKNScalingFunction::apply(const Position &pos) {
812 assert(pos.non_pawn_material(strongerSide) == BishopValueMidgame);
813 assert(pos.piece_count(strongerSide, BISHOP) == 1);
814 assert(pos.piece_count(strongerSide, PAWN) == 1);
815 assert(pos.non_pawn_material(weakerSide) == KnightValueMidgame);
816 assert(pos.piece_count(weakerSide, KNIGHT) == 1);
817 assert(pos.piece_count(weakerSide, PAWN) == 0);
819 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
820 Square strongerBishopSq = pos.piece_list(strongerSide, BISHOP, 0);
821 Square weakerKingSq = pos.king_square(weakerSide);
823 if(square_file(weakerKingSq) == square_file(pawnSq)
824 && relative_rank(strongerSide, pawnSq) < relative_rank(strongerSide, weakerKingSq)
825 && (square_color(weakerKingSq) != square_color(strongerBishopSq)
826 || relative_rank(strongerSide, weakerKingSq) <= RANK_6))
827 return ScaleFactor(0);
829 return SCALE_FACTOR_NONE;
833 /// KNPKScalingFunction scales KNP vs K endgames. There is a single rule:
834 /// If the pawn is a rook pawn on the 7th rank and the defending king prevents
835 /// the pawn from advancing, the position is drawn.
837 ScaleFactor KNPKScalingFunction::apply(const Position &pos) {
838 assert(pos.non_pawn_material(strongerSide) == KnightValueMidgame);
839 assert(pos.piece_count(strongerSide, KNIGHT) == 1);
840 assert(pos.piece_count(strongerSide, PAWN) == 1);
841 assert(pos.non_pawn_material(weakerSide) == Value(0));
842 assert(pos.piece_count(weakerSide, PAWN) == 0);
844 Square pawnSq = pos.piece_list(strongerSide, PAWN, 0);
845 Square weakerKingSq = pos.king_square(weakerSide);
847 if(pawnSq == relative_square(strongerSide, SQ_A7) &&
848 square_distance(weakerKingSq, relative_square(strongerSide, SQ_A8)) <= 1)
849 return ScaleFactor(0);
851 if(pawnSq == relative_square(strongerSide, SQ_H7) &&
852 square_distance(weakerKingSq, relative_square(strongerSide, SQ_H8)) <= 1)
853 return ScaleFactor(0);
855 return SCALE_FACTOR_NONE;
859 /// KPKPScalingFunction scales KP vs KP endgames. This is done by removing
860 /// the weakest side's pawn and probing the KP vs K bitbase: If the weakest
861 /// side has a draw without the pawn, she probably has at least a draw with
862 /// the pawn as well. The exception is when the stronger side's pawn is far
863 /// advanced and not on a rook file; in this case it is often possible to win
864 /// (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).
866 ScaleFactor KPKPScalingFunction::apply(const Position &pos) {
867 assert(pos.non_pawn_material(strongerSide) == Value(0));
868 assert(pos.non_pawn_material(weakerSide) == Value(0));
869 assert(pos.piece_count(WHITE, PAWN) == 1);
870 assert(pos.piece_count(BLACK, PAWN) == 1);
872 Square wksq, bksq, wpsq;
875 if(strongerSide == WHITE) {
876 wksq = pos.king_square(WHITE);
877 bksq = pos.king_square(BLACK);
878 wpsq = pos.piece_list(WHITE, PAWN, 0);
879 stm = pos.side_to_move();
882 wksq = flip_square(pos.king_square(BLACK));
883 bksq = flip_square(pos.king_square(WHITE));
884 wpsq = flip_square(pos.piece_list(BLACK, PAWN, 0));
885 stm = opposite_color(pos.side_to_move());
888 if(square_file(wpsq) >= FILE_E) {
889 wksq = flop_square(wksq);
890 bksq = flop_square(bksq);
891 wpsq = flop_square(wpsq);
894 // If the pawn has advanced to the fifth rank or further, and is not a
895 // rook pawn, it's too dangerous to assume that it's at least a draw.
896 if(square_rank(wpsq) >= RANK_5 && square_file(wpsq) != FILE_A)
897 return SCALE_FACTOR_NONE;
899 // Probe the KPK bitbase with the weakest side's pawn removed. If it's a
900 // draw, it's probably at least a draw even with the pawn.
901 if(probe_kpk(wksq, wpsq, bksq, stm))
902 return SCALE_FACTOR_NONE;
904 return ScaleFactor(0);
908 /// init_bitbases() is called during program initialization, and simply loads
909 /// bitbases from disk into memory. At the moment, there is only the bitbase
910 /// for KP vs K, but we may decide to add other bitbases later.
912 void init_bitbases() {
913 generate_kpk_bitbase(KPKBitbase);
919 // Probe the KP vs K bitbase:
921 int probe_kpk(Square wksq, Square wpsq, Square bksq, Color stm) {
922 int wp = int(square_file(wpsq)) + (int(square_rank(wpsq)) - 1) * 4;
923 int index = int(stm) + 2*int(bksq) + 128*int(wksq) + 8192*wp;
925 assert(index >= 0 && index < 24576*8);
926 return KPKBitbase[index/8] & (1 << (index&7));