Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Sat, 18 Jul 2020 08:33:12 +0000 (10:33 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sat, 18 Jul 2020 08:33:12 +0000 (10:33 +0200)
bench: 5054568

1  2 
src/endgame.cpp

diff --cc src/endgame.cpp
@@@ -54,22 -54,9 +54,22 @@@ namespace 
       4160, 4480, 4800, 5120, 5440, 5760, 6080, 6400
    };
  
 +  // Table used to drive the king towards the edge of the board
 +  // in KSF vs K.
 +  constexpr int PushToOpposingSideEdges[SQUARE_NB] = {
 +     20, 10,  5,  0,  0,  5, 10,  20,
 +     20, 10,  5,  0,  0,  5, 10,  20,
 +     30, 20, 10,  0,  0, 10, 20,  30,
 +     50, 40, 20, 10, 10, 20, 40,  50,
 +     60, 50, 40, 30, 30, 40, 50,  60,
 +     70, 60, 50, 40, 40, 50, 60,  70,
 +     90, 70, 60, 50, 50, 60, 70,  90,
 +    100, 90, 80, 70, 70, 80, 90, 100
 +  };
 +
-   // Tables used to drive a piece towards or away from another piece
-   constexpr int PushClose[FILE_NB] = { 0, 0, 100, 80, 60, 40, 20, 10 };
-   constexpr int PushAway [FILE_NB] = { 0, 5, 20, 40, 60, 80, 90, 100 };
+   // Drive a piece close to or away from another piece
+   inline int push_close(Square s1, Square s2) { return 140 - 20 * distance(s1, s2); }
+   inline int push_away(Square s1, Square s2) { return 120 - push_close(s1, s2); }
  
    // Pawn Rank based scaling factors used in KRPPKRP endgame
    constexpr int KRPPKRPScaleFactors[RANK_NB] = { 0, 9, 10, 14, 21, 44, 0, 0 };
@@@ -157,8 -129,8 +157,8 @@@ Value Endgame<KXK>::operator()(const Po
  
    Value result =  pos.non_pawn_material(strongSide)
                  + pos.count<PAWN>(strongSide) * PawnValueEg
 -                + PushToEdges[loserKSq]
 +                + PushToEdges[map_to_standard_board(pos, loserKSq)]
-                 + PushClose[distance(winnerKSq, loserKSq)];
+                 + push_close(winnerKSq, loserKSq);
  
    if (   pos.count<QUEEN>(strongSide)
        || pos.count<ROOK>(strongSide)
@@@ -194,8 -159,8 +194,8 @@@ Value Endgame<KBNK>::operator()(const P
    // to drive to opposite corners (A8/H1).
  
    Value result =  VALUE_KNOWN_WIN
-                 + PushClose[distance(winnerKSq, loserKSq)]
+                 + push_close(winnerKSq, loserKSq)
 -                + PushToCorners[opposite_colors(bishopSq, SQ_A1) ? ~loserKSq : loserKSq];
 +                + PushToCorners[map_to_standard_board(pos, relative_square(opposite_colors(bishopSq, SQ_A1) ? BLACK : WHITE, loserKSq, pos.max_rank()))];
  
    assert(abs(result) < VALUE_TB_WIN_IN_MAX_PLY);
    return strongSide == pos.side_to_move() ? result : -result;
@@@ -304,7 -258,7 +304,7 @@@ Value Endgame<KRKN>::operator()(const P
  
    Square bksq = pos.square<KING>(weakSide);
    Square bnsq = pos.square<KNIGHT>(weakSide);
-   Value result = Value(PushToEdges[map_to_standard_board(pos, bksq)] + PushAway[distance(bksq, bnsq)]);
 -  Value result = Value(PushToEdges[bksq] + push_away(bksq, bnsq));
++  Value result = Value(PushToEdges[map_to_standard_board(pos, bksq)] + push_away(bksq, bnsq));
    return strongSide == pos.side_to_move() ? result : -result;
  }
  
@@@ -349,8 -303,8 +349,8 @@@ Value Endgame<KQKR>::operator()(const P
  
    Value result =  QueenValueEg
                  - RookValueEg
 -                + PushToEdges[loserKSq]
 +                + PushToEdges[map_to_standard_board(pos, loserKSq)]
-                 + PushClose[distance(winnerKSq, loserKSq)];
+                 + push_close(winnerKSq, loserKSq);
  
    return strongSide == pos.side_to_move() ? result : -result;
  }
@@@ -376,169 -330,6 +376,169 @@@ Value Endgame<KNNKP>::operator()(const 
  template<> Value Endgame<KNNK>::operator()(const Position&) const { return VALUE_DRAW; }
  
  
 +/// KFsPs vs K.
 +template<>
 +Value Endgame<KFsPsK>::operator()(const Position& pos) const {
 +
 +  assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
 +
 +  Square winnerKSq = pos.square<KING>(strongSide);
 +  Square loserKSq = pos.square<KING>(weakSide);
 +
 +  Value result =  pos.non_pawn_material(strongSide)
 +                + pos.count<PAWN>(strongSide) * PawnValueEg
 +                + PushToEdges[map_to_standard_board(pos, loserKSq)]
-                 + PushClose[distance(winnerKSq, loserKSq)];
++                + push_close(winnerKSq, loserKSq);
 +
 +  if (   pos.count<FERS>(strongSide) >= 3
 +      && ( DarkSquares & pos.pieces(strongSide, FERS))
 +      && (~DarkSquares & pos.pieces(strongSide, FERS)))
 +      result = std::min(result + VALUE_KNOWN_WIN, VALUE_TB_WIN_IN_MAX_PLY - 1);
 +  else if (pos.count<FERS>(strongSide) + pos.count<PAWN>(strongSide) < 3)
 +      return VALUE_DRAW;
 +  else
 +  {
 +      bool dark  =  DarkSquares & pos.pieces(strongSide, FERS);
 +      bool light = ~DarkSquares & pos.pieces(strongSide, FERS);
 +
 +      // Determine the color of ferzes from promoting pawns
 +      Bitboard b = pos.pieces(strongSide, PAWN);
 +      while (b && (!dark || !light))
 +      {
 +          if (file_of(pop_lsb(&b)) % 2 != relative_rank(strongSide, pos.promotion_rank(), pos.max_rank()) % 2)
 +              light = true;
 +          else
 +              dark = true;
 +      }
 +      if (!dark || !light)
 +          return VALUE_DRAW; // we can not checkmate with same colored ferzes
 +  }
 +
 +  return strongSide == pos.side_to_move() ? result : -result;
 +}
 +
 +
 +/// Mate with KNS vs K.
 +template<>
 +Value Endgame<KNSK>::operator()(const Position& pos) const {
 +
 +  assert(verify_material(pos, strongSide, KnightValueMg + SilverValueMg, 0));
 +  assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
 +
 +  Square winnerKSq = pos.square<KING>(strongSide);
 +  Square loserKSq = pos.square<KING>(weakSide);
 +
 +  Value result =  VALUE_KNOWN_WIN
-                 + PushClose[distance(winnerKSq, loserKSq)]
++                + push_close(winnerKSq, loserKSq)
 +                + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))];
 +
 +  return strongSide == pos.side_to_move() ? result : -result;
 +}
 +
 +
 +/// KNF vs K. Can only be won if the weaker side's king
 +/// is close to a corner of the same color as the fers.
 +template<>
 +Value Endgame<KNFK>::operator()(const Position& pos) const {
 +
 +  assert(verify_material(pos, strongSide, KnightValueMg + FersValueMg, 0));
 +  assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
 +
 +  Square winnerKSq = pos.square<KING>(strongSide);
 +  Square loserKSq = pos.square<KING>(weakSide);
 +  Square fersSq = pos.square<FERS>(strongSide);
 +
 +  // tries to drive toward corners A1 or H8. If we have a
 +  // fers that cannot reach the above squares, we flip the kings in order
 +  // to drive the enemy toward corners A8 or H1.
 +  if (opposite_colors(fersSq, SQ_A1))
 +  {
 +      winnerKSq = relative_square(BLACK, winnerKSq, pos.max_rank());
 +      loserKSq  = relative_square(BLACK, loserKSq, pos.max_rank());
 +  }
 +
-   Value result =  Value(PushClose[distance(winnerKSq, loserKSq)])
++  Value result =  Value(push_close(winnerKSq, loserKSq))
 +                + (PushToCorners[map_to_standard_board(pos, loserKSq)] - 3000) / 10;
 +
 +  return strongSide == pos.side_to_move() ? result : -result;
 +}
 +
 +
 +/// KNSFKR vs K.
 +template<>
 +Value Endgame<KNSFKR>::operator()(const Position& pos) const {
 +
 +  assert(verify_material(pos, strongSide, KnightValueMg + SilverValueMg + FersValueMg, 0));
 +  assert(verify_material(pos, weakSide, RookValueMg, 0));
 +
 +  Square winnerKSq = pos.square<KING>(strongSide);
 +  Square loserKSq = pos.square<KING>(weakSide);
 +
 +  Value result =  KnightValueEg + SilverValueEg + FersValueEg - RookValueEg
-                 + PushClose[distance(winnerKSq, loserKSq)]
++                + push_close(winnerKSq, loserKSq)
 +                + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))];
 +
 +  return strongSide == pos.side_to_move() ? result : -result;
 +}
 +
 +
 +/// Mate with KSF vs K.
 +template<>
 +Value Endgame<KSFK>::operator()(const Position& pos) const {
 +
 +  assert(verify_material(pos, strongSide, SilverValueMg + FersValueMg, 0));
 +  assert(verify_material(pos, weakSide, VALUE_ZERO, 0));
 +
 +  Square winnerKSq = pos.square<KING>(strongSide);
 +  Square loserKSq = pos.square<KING>(weakSide);
 +
 +  Value result =  VALUE_KNOWN_WIN
-                 + PushClose[distance(winnerKSq, loserKSq)]
++                + push_close(winnerKSq, loserKSq)
 +                + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))];
 +
 +  return strongSide == pos.side_to_move() ? result : -result;
 +}
 +
 +
 +/// Mate with KSF vs KF.
 +template<>
 +Value Endgame<KSFKF>::operator()(const Position& pos) const {
 +
 +  assert(verify_material(pos, strongSide, SilverValueMg + FersValueMg, 0));
 +  assert(verify_material(pos, weakSide, FersValueMg, 0));
 +
 +  Square winnerKSq = pos.square<KING>(strongSide);
 +  Square loserKSq = pos.square<KING>(weakSide);
 +  Square fersSq = pos.square<FERS>(weakSide);
 +
 +  Value result =  SilverValueEg
-                 + PushClose[distance(winnerKSq, loserKSq)]
-                 + PushAway[distance(fersSq, loserKSq)]
++                + push_close(winnerKSq, loserKSq)
++                + push_away(fersSq, loserKSq)
 +                + PushToOpposingSideEdges[map_to_standard_board(pos, relative_square(strongSide, loserKSq, pos.max_rank()))];
 +
 +  return strongSide == pos.side_to_move() ? result : -result;
 +}
 +
 +
 +/// KR vs KS
 +template<>
 +Value Endgame<KRKS>::operator()(const Position& pos) const {
 +
 +  assert(verify_material(pos, strongSide, RookValueMg, 0));
 +  assert(verify_material(pos, weakSide, SilverValueMg, 0));
 +
 +  Square winnerKSq = pos.square<KING>(strongSide);
 +  Square loserKSq = pos.square<KING>(weakSide);
 +
 +  Value result =  RookValueEg
 +                - SilverValueEg
 +                + PushToEdges[map_to_standard_board(pos, loserKSq)]
-                 + PushClose[distance(winnerKSq, loserKSq)];
++                + push_close(winnerKSq, loserKSq);
 +
 +  return strongSide == pos.side_to_move() ? result : -result;
 +}
 +
 +
  /// KB and one or more pawns vs K. It checks for draws with rook pawns and
  /// a bishop of the wrong color. If such a draw is detected, SCALE_FACTOR_DRAW
  /// is returned. If not, the return value is SCALE_FACTOR_NONE, i.e. no scaling